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:
authorYimingWu <xp8110@outlook.com>2020-05-16 18:08:40 +0300
committerYimingWu <xp8110@outlook.com>2020-05-16 18:08:40 +0300
commitcd54abd2c1316136753f7bbe227bd762a5f9e7d9 (patch)
tree69f2a4a1a5013acc78213bb4f3fe888912380ea4 /release/scripts/startup/bl_ui
parentf7770cb97bb9d19d0806f67da9377129fd4d09b0 (diff)
parenteaf7d36d66e551c3262d69f472b4028aeccb7e97 (diff)
Merge remote-tracking branch 'origin/master' into temp-lanpr-review
Diffstat (limited to 'release/scripts/startup/bl_ui')
-rw-r--r--release/scripts/startup/bl_ui/__init__.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py42
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py44
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py12
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py12
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_data_hair.py78
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py50
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py849
-rw-r--r--release/scripts/startup/bl_ui/properties_data_pointcloud.py78
-rw-r--r--release/scripts/startup/bl_ui/properties_data_shaderfx.py44
-rw-r--r--release/scripts/startup/bl_ui/properties_data_volume.py174
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py664
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_material_gpencil.py92
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py71
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py57
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py156
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py39
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py41
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py359
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py75
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py94
-rw-r--r--release/scripts/startup/bl_ui/properties_workspace.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py4
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py4
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py57
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py40
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py6
-rw-r--r--release/scripts/startup/bl_ui/space_image.py20
-rw-r--r--release/scripts/startup/bl_ui/space_node.py18
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py53
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py117
-rw-r--r--release/scripts/startup/bl_ui/space_text.py21
-rw-r--r--release/scripts/startup/bl_ui/space_time.py1
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py116
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py314
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py67
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py471
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py806
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py778
46 files changed, 3748 insertions, 2225 deletions
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 8fc59ca493a..36df0256c3d 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -35,14 +35,17 @@ _modules = [
"properties_data_curve",
"properties_data_empty",
"properties_data_gpencil",
+ "properties_data_hair",
"properties_data_light",
"properties_data_lattice",
"properties_data_mesh",
"properties_data_metaball",
"properties_data_modifier",
+ "properties_data_pointcloud",
"properties_data_shaderfx",
"properties_data_lightprobe",
"properties_data_speaker",
+ "properties_data_volume",
"properties_mask_common",
"properties_material",
"properties_material_gpencil",
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index d44af702d46..05abfa02500 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -84,17 +84,12 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
layout.prop(arm, "display_type", text="Display As")
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
- col = flow.column()
+ col = layout.column(heading="Show")
col.prop(arm, "show_names", text="Names")
- col = flow.column()
col.prop(arm, "show_axes", text="Axes")
- col = flow.column()
col.prop(arm, "show_bone_custom_shapes", text="Shapes")
- col = flow.column()
col.prop(arm, "show_group_colors", text="Group Colors")
if ob:
- col = flow.column()
col.prop(ob, "show_in_front", text="In Front")
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index c50b9414667..aca358870c8 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -268,18 +268,43 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
col = layout.column()
col.prop(bone, "hide", text="Hide")
+
+
+class BONE_PT_display_custom_shape(BoneButtonsPanel, Panel):
+ bl_label = "Custom Shape"
+ bl_parent_id = "BONE_PT_display"
+
+ @classmethod
+ def poll(cls, context):
+ return context.bone
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ bone = context.bone
+ pchan = None
+
+ if ob and bone:
+ pchan = ob.pose.bones[bone.name]
+ elif bone is None:
+ bone = context.edit_bone
+
+ if bone and pchan:
+ col = layout.column()
+ col.prop(pchan, "custom_shape")
+
sub = col.column()
sub.active = bool(pchan and pchan.custom_shape)
+ sub.separator()
+ sub.prop(pchan, "custom_shape_scale", text="Scale")
+ sub.prop_search(pchan, "custom_shape_transform",
+ ob.pose, "bones", text="Override Transform")
+ sub.prop(pchan, "use_custom_shape_bone_size")
+ sub.separator()
sub.prop(bone, "show_wire", text="Wireframe")
- if pchan:
- col = layout.column()
- col.prop(pchan, "custom_shape")
- if pchan.custom_shape:
- col.prop(pchan, "use_custom_shape_bone_size", text="Bone Size")
- col.prop(pchan, "custom_shape_scale", text="Scale")
- col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones")
-
class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
bl_label = "Inverse Kinematics"
@@ -431,6 +456,7 @@ classes = (
BONE_PT_inverse_kinematics,
BONE_PT_deform,
BONE_PT_display,
+ BONE_PT_display_custom_shape,
BONE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 957b119e9ba..62e1bcdfce4 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -360,8 +360,9 @@ class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
col.prop(bg, "rotation")
col.prop(bg, "scale")
- col.prop(bg, "use_flip_x")
- col.prop(bg, "use_flip_y")
+ col = box.column(heading="Flip")
+ col.prop(bg, "use_flip_x", text="X")
+ col.prop(bg, "use_flip_y", text="Y")
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
@@ -377,21 +378,12 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
col = layout.column(align=True)
- col.separator()
-
col.prop(cam, "display_size", text="Size")
- col.separator()
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column(heading="Show")
col.prop(cam, "show_limits", text="Limits")
- col = flow.column()
col.prop(cam, "show_mist", text="Mist")
- col = flow.column()
col.prop(cam, "show_sensor", text="Sensor")
- col = flow.column()
col.prop(cam, "show_name", text="Name")
@@ -407,24 +399,20 @@ class DATA_PT_camera_display_composition_guides(CameraButtonsPanel, Panel):
cam = context.camera
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
+ layout.prop(cam, "show_composition_thirds")
- col = flow.column()
+ col = layout.column(heading="Center", align=True)
col.prop(cam, "show_composition_center")
- col = flow.column()
- col.prop(cam, "show_composition_center_diagonal")
- col = flow.column()
- col.prop(cam, "show_composition_thirds")
- col = flow.column()
- col.prop(cam, "show_composition_golden")
- col = flow.column()
- col.prop(cam, "show_composition_golden_tria_a")
- col = flow.column()
- col.prop(cam, "show_composition_golden_tria_b")
- col = flow.column()
- col.prop(cam, "show_composition_harmony_tri_a")
- col = flow.column()
- col.prop(cam, "show_composition_harmony_tri_b")
+ col.prop(cam, "show_composition_center_diagonal", text="Diagonal")
+
+ col = layout.column(heading="Golden", align=True)
+ col.prop(cam, "show_composition_golden", text="Ratio")
+ col.prop(cam, "show_composition_golden_tria_a", text="Triangle A")
+ col.prop(cam, "show_composition_golden_tria_b", text="Triangle B")
+
+ col = layout.column(heading="Harmony", align=True)
+ col.prop(cam, "show_composition_harmony_tri_a", text="Triangle A")
+ col.prop(cam, "show_composition_harmony_tri_b", text="Triangle B")
class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index b694062dfc5..7e7488f4cf1 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -276,23 +276,23 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
col.prop(act_spline, "use_smooth")
else:
- sub = col.column(align=True)
- sub.prop(act_spline, "use_cyclic_u")
+ sub = col.column(heading="Cyclic", align=True)
+ sub.prop(act_spline, "use_cyclic_u", text="U")
if is_surf:
sub.prop(act_spline, "use_cyclic_v", text="V")
if act_spline.type == 'NURBS':
- sub = col.column(align=True)
+ sub = col.column(heading="Bezier", align=True)
# sub.active = (not act_spline.use_cyclic_u)
- sub.prop(act_spline, "use_bezier_u", text="Bezier U")
+ sub.prop(act_spline, "use_bezier_u", text="U")
if is_surf:
subsub = sub.column()
subsub.active = (not act_spline.use_cyclic_v)
subsub.prop(act_spline, "use_bezier_v", text="V")
- sub = col.column(align=True)
- sub.prop(act_spline, "use_endpoint_u", text="Endpoint U")
+ sub = col.column(heading="Endpoint", align=True)
+ sub.prop(act_spline, "use_endpoint_u", text="U")
if is_surf:
subsub = sub.column()
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index 88fdaae0433..1523f69536f 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -49,11 +49,15 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
col.prop(ob, "empty_image_offset", text="Y", index=1)
col = layout.column()
- col.row().prop(ob, "empty_image_depth", text="Depth", expand=True)
+ depth_row = col.row()
+ depth_row.enabled = not ob.show_in_front
+ depth_row.prop(ob, "empty_image_depth", text="Depth", expand=True)
col.row().prop(ob, "empty_image_side", text="Side", expand=True)
- col.prop(ob, "show_empty_image_orthographic", text="Display Orthographic")
- col.prop(ob, "show_empty_image_perspective", text="Display Perspective")
- col.prop(ob, "show_empty_image_only_axis_aligned")
+
+ col = layout.column(heading="Show in", align=True)
+ col.prop(ob, "show_empty_image_orthographic", text="Orthographic")
+ col.prop(ob, "show_empty_image_perspective", text="Perspective")
+ col.prop(ob, "show_empty_image_only_axis_aligned", text="Only Axis Aligned")
class DATA_PT_empty_alpha(DataButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
index 883673ffd7a..4ed5264549f 100644
--- a/release/scripts/startup/bl_ui/properties_data_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -22,6 +22,7 @@ from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_grease_pencil_common import (
+ GreasePencilLayerMasksPanel,
GreasePencilLayerAdjustmentsPanel,
GreasePencilLayerRelationsPanel,
GreasePencilLayerDisplayPanel,
@@ -116,7 +117,7 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- #layout.use_property_split = True
+ # layout.use_property_split = True
layout.use_property_decorate = False
gpd = context.gpencil
@@ -166,7 +167,6 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
col = layout.column(align=True)
if gpl:
-
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = True
@@ -178,6 +178,15 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
col = layout.row(align=True)
col.prop(gpl, "opacity", text="Opacity", slider=True)
+ col = layout.row(align=True)
+ col.prop(gpl, "use_lights")
+
+
+class DATA_PT_gpencil_layer_masks(LayerDataButtonsPanel, GreasePencilLayerMasksPanel, Panel):
+ bl_label = "Masks"
+ bl_parent_id = 'DATA_PT_gpencil_layers'
+ bl_options = {'DEFAULT_CLOSED'}
+
class DATA_PT_gpencil_layer_adjustments(LayerDataButtonsPanel, GreasePencilLayerAdjustmentsPanel, Panel):
bl_label = "Adjustments"
@@ -264,7 +273,7 @@ class DATA_PT_gpencil_onion_skinning_display(DataButtonsPanel, Panel):
col.prop(gpd, "use_onion_fade", text="Fade")
sub = layout.column()
sub.active = gpd.onion_mode in {'RELATIVE', 'SELECTED'}
- sub.prop(gpd, "use_onion_loop", text="Loop")
+ sub.prop(gpd, "use_onion_loop", text="Show Start Frame")
class GPENCIL_MT_gpencil_vertex_group(Menu):
@@ -364,9 +373,6 @@ class DATA_PT_gpencil_strokes(DataButtonsPanel, Panel):
sub.active = gpd.stroke_thickness_space == 'WORLDSPACE'
sub.prop(gpd, "pixel_factor", text="Thickness Scale")
- layout.prop(gpd, "use_force_fill_recalc", text="Force Fill Update")
- layout.prop(gpd, "use_adaptive_uv", text="Adaptive UVs")
-
class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
bl_label = "Viewport Display"
@@ -381,8 +387,6 @@ class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
gpl = gpd.layers.active
layout.prop(gpd, "edit_line_color", text="Edit Line Color")
- if gpl:
- layout.prop(gpd, "show_stroke_direction", text="Show Stroke Directions")
class DATA_PT_gpencil_canvas(DataButtonsPanel, Panel):
@@ -411,6 +415,7 @@ class DATA_PT_custom_props_gpencil(DataButtonsPanel, PropertyPanel, Panel):
_context_path = "object.data"
_property_type = bpy.types.GreasePencil
+
###############################
@@ -420,6 +425,7 @@ classes = (
DATA_PT_gpencil_onion_skinning,
DATA_PT_gpencil_onion_skinning_custom_colors,
DATA_PT_gpencil_onion_skinning_display,
+ DATA_PT_gpencil_layer_masks,
DATA_PT_gpencil_layer_adjustments,
DATA_PT_gpencil_layer_relations,
DATA_PT_gpencil_layer_display,
@@ -437,5 +443,6 @@ classes = (
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
+
for cls in classes:
register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_hair.py b/release/scripts/startup/bl_ui/properties_data_hair.py
new file mode 100644
index 00000000000..6017765b83d
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_hair.py
@@ -0,0 +1,78 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Panel, UIList
+from rna_prop_ui import PropertyPanel
+
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return hasattr(context, 'hair') and context.hair and (engine in cls.COMPAT_ENGINES)
+
+
+class DATA_PT_context_hair(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ hair = context.hair
+ space = context.space_data
+
+ if ob:
+ layout.template_ID(ob, "data")
+ elif hair:
+ layout.template_ID(space, "pin_id")
+
+
+class DATA_PT_hair(DataButtonsPanel, Panel):
+ bl_label = "Hair"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+ hair = context.hair
+ pass
+
+class DATA_PT_custom_props_hair(DataButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+ _context_path = "object.data"
+ _property_type = bpy.types.Hair if hasattr(bpy.types, "Hair") else None
+
+
+classes = (
+ DATA_PT_context_hair,
+ DATA_PT_hair,
+ DATA_PT_custom_props_hair,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 3edce6b3b52..425c94dfdcd 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -55,9 +55,12 @@ class MESH_MT_vertex_group_context_menu(Menu):
layout.operator("object.vertex_group_remove", text="Delete All Unlocked Groups").all_unlocked = True
layout.operator("object.vertex_group_remove", text="Delete All Groups").all = True
layout.separator()
- layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All").action = 'LOCK'
- layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="UnLock All").action = 'UNLOCK'
- layout.operator("object.vertex_group_lock", text="Lock Invert All").action = 'INVERT'
+ props = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
+ props.action, props.mask = 'LOCK', 'ALL'
+ props = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="UnLock All")
+ props.action, props.mask = 'UNLOCK', 'ALL'
+ props = layout.operator("object.vertex_group_lock", text="Lock Invert All")
+ props.action, props.mask = 'INVERT', 'ALL'
class MESH_MT_shape_key_context_menu(Menu):
@@ -187,27 +190,20 @@ class DATA_PT_normals(MeshButtonsPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
- pass
-
-
-class DATA_PT_normals_auto_smooth(MeshButtonsPanel, Panel):
- bl_label = "Auto Smooth"
- bl_parent_id = "DATA_PT_normals"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- def draw_header(self, context):
- mesh = context.mesh
-
- self.layout.prop(mesh, "use_auto_smooth", text="")
-
- def draw(self, context):
layout = self.layout
layout.use_property_split = True
mesh = context.mesh
- layout.active = mesh.use_auto_smooth and not mesh.has_custom_normals
- layout.prop(mesh, "auto_smooth_angle", text="Angle")
+ col = layout.column(align=False, heading="Auto Smooth")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(mesh, "use_auto_smooth", text="")
+ sub = sub.row(align=True)
+ sub.active = mesh.use_auto_smooth and not mesh.has_custom_normals
+ sub.prop(mesh, "auto_smooth_angle", text="")
+ row.prop_decorator(mesh, "auto_smooth_angle")
class DATA_PT_texture_space(MeshButtonsPanel, Panel):
@@ -482,8 +478,11 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
col.prop(mesh, "remesh_voxel_adaptivity")
col.prop(mesh, "use_remesh_fix_poles")
col.prop(mesh, "use_remesh_smooth_normals")
- col.prop(mesh, "use_remesh_preserve_volume")
- col.prop(mesh, "use_remesh_preserve_paint_mask")
+
+ col = layout.column(heading="Preserve")
+ col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
+ col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
+ col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
col.operator("object.voxel_remesh", text="Voxel Remesh")
else:
col.operator("object.quadriflow_remesh", text="QuadriFlow Remesh")
@@ -511,12 +510,12 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
else:
col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD')
- col = layout.column()
+ col = layout.column(heading="Store")
col.enabled = obj is not None and obj.mode != 'EDIT'
- col.prop(me, "use_customdata_vertex_bevel")
- col.prop(me, "use_customdata_edge_bevel")
- col.prop(me, "use_customdata_edge_crease")
+ 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_edge_crease", text="Edge Crease")
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
@@ -540,7 +539,6 @@ classes = (
DATA_PT_vertex_colors,
DATA_PT_face_maps,
DATA_PT_normals,
- DATA_PT_normals_auto_smooth,
DATA_PT_texture_space,
DATA_PT_remesh,
DATA_PT_customdata,
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 197566f16f3..75e9a320130 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -170,7 +170,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.limit_method == 'ANGLE':
layout.prop(md, "angle_limit")
elif md.limit_method == 'VGROUP':
- layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = layout.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
layout.label(text="Face Strength Mode:")
layout.row().prop(md, "face_strength_mode", expand=True)
@@ -316,7 +318,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "object", text="")
col = split.column()
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
layout.label(text="Deformation Axis:")
layout.row().prop(md, "deform_axis", expand=True)
@@ -381,7 +385,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="Space:")
col.prop(md, "space", text="")
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
col = split.column(align=True)
col.active = has_texture
@@ -390,6 +396,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.texture_coords == 'OBJECT':
col.label(text="Object:")
col.prop(md, "texture_coords_object", text="")
+ obj = md.texture_coords_object
+ if obj and obj.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "texture_coords_bone", obj.data, "bones", text="")
elif md.texture_coords == 'UV' and ob.type == 'MESH':
col.label(text="UV Map:")
col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
@@ -419,7 +429,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
sub = col.column()
sub.active = bool(md.vertex_group)
sub.prop(md, "protect")
@@ -450,7 +462,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop_search(md, "subtarget", md.object.data, "bones", text="")
col = split.column()
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
layout.separator()
@@ -484,13 +498,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.prop(md, "iterations")
- row = layout.row()
- row.active = not is_bind
- row.label(text="Anchors Vertex Group:")
-
- row = layout.row()
+ row = layout.row(align=True)
row.enabled = not is_bind
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop_search(md, "vertex_group", ob, "vertex_groups")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
layout.separator()
@@ -519,7 +530,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "use_normalized")
layout.label(text="Vertex Group:")
- layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = layout.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
def LATTICE(self, layout, ob, md):
split = layout.split()
@@ -530,7 +543,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
layout.separator()
layout.prop(md, "strength", slider=True)
@@ -640,6 +655,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row = layout.row()
row.prop(md, "use_mirror_u", text="Flip U")
row.prop(md, "use_mirror_v", text="Flip V")
+ row = layout.row()
+ row.prop(md, "use_mirror_udim", text="Flip UDIM")
col = layout.column(align=True)
@@ -654,26 +671,53 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "offset_v")
def MULTIRES(self, layout, ob, md):
- layout.row().prop(md, "subdivision_type", expand=True)
+ # Changing some of the properties can not be done once there is an
+ # actual displacement stored for this multires modifier. This check
+ # will disallow those properties from change.
+ # This is a bit stupid check but should be sufficient for the usual
+ # multires usage. It might become less strict and only disallow
+ # modifications if there is CD_MDISPS layer, or if there is actual
+ # non-zero displacement but such checks will be too slow to be done
+ # on every redraw.
+ have_displacement = (md.total_levels != 0)
+
+ row = layout.row()
+ row.enabled = not have_displacement
+ row.prop(md, "subdivision_type", expand=True)
split = layout.split()
col = split.column()
col.prop(md, "levels", text="Preview")
- # TODO(sergey): Expose it again after T58473 is solved.
- # col.prop(md, "sculpt_levels", text="Sculpt")
+ col.prop(md, "sculpt_levels", text="Sculpt")
col.prop(md, "render_levels", text="Render")
- col.prop(md, "quality")
+
+ row = col.row()
+ row.enabled = not have_displacement
+ row.prop(md, "quality")
col = split.column()
col.enabled = ob.mode != 'EDIT'
- col.operator("object.multires_subdivide", text="Subdivide")
+ op = col.operator("object.multires_subdivide", text="Subdivide")
+ op.mode = 'CATMULL_CLARK'
+
+ op = col.operator("object.multires_subdivide", text="Subdivide Simple")
+ op.mode = 'SIMPLE'
+
+ op = col.operator("object.multires_subdivide", text="Subdivide Linear")
+ op.mode = 'LINEAR'
+
col.operator("object.multires_higher_levels_delete", text="Delete Higher")
+ col.operator("object.multires_unsubdivide", text="Unsubdivide")
col.operator("object.multires_reshape", text="Reshape")
col.operator("object.multires_base_apply", text="Apply Base")
+ col.operator("object.multires_rebuild_subdiv", text="Rebuild Subdivisions")
col.prop(md, "uv_smooth", text="")
col.prop(md, "show_only_control_edges")
- col.prop(md, "use_creases")
+
+ row = col.row()
+ row.enabled = not have_displacement
+ row.prop(md, "use_creases")
layout.separator()
@@ -714,6 +758,19 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "size")
col.prop(md, "spatial_size")
+ layout.separator()
+
+ layout.prop(md, "spectrum")
+
+ if md.spectrum in {'TEXEL_MARSEN_ARSLOE', 'JONSWAP'}:
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "sharpen_peak_jonswap")
+
+ col = split.column()
+ col.prop(md, "fetch_jonswap")
+
layout.label(text="Waves:")
split = layout.split()
@@ -963,7 +1020,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "factor")
col.prop(md, "iterations")
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
def SOFT_BODY(self, layout, _ob, _md):
layout.label(text="Settings are inside the Physics tab")
@@ -998,12 +1057,23 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
sub = col.row()
sub.active = bool(md.vertex_group)
sub.prop(md, "thickness_vertex_group", text="Factor")
+ if solidify_mode == 'NON_MANIFOLD':
+ sub = col.row()
+ sub.active = bool(md.vertex_group)
+ sub.prop(md, "use_flat_faces")
if solidify_mode == 'EXTRUDE':
col.label(text="Crease:")
col.prop(md, "edge_crease_inner", text="Inner")
col.prop(md, "edge_crease_outer", text="Outer")
col.prop(md, "edge_crease_rim", text="Rim")
+ col.label(text="Bevel:")
+ col.prop(md, "bevel_convex")
+ else:
+ col.label(text="Bevel:")
+ col.prop(md, "bevel_convex")
+ col.separator()
+ col.prop(md, "nonmanifold_merge_threshold")
col = split.column()
@@ -1031,6 +1101,17 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.active = md.use_rim
row.prop(md, "material_offset_rim", text="Rim")
+ col.separator()
+
+ row = col.row(align=True)
+ row.label(text="Shell Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "shell_vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.label(text="Rim Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "rim_vertex_group", ob, "vertex_groups", text="")
+
def SUBSURF(self, layout, ob, md):
from bpy import context
layout.row().prop(md, "subdivision_type", expand=True)
@@ -1089,13 +1170,24 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.label(text="Settings are inside the Physics tab")
def SURFACE_DEFORM(self, layout, _ob, md):
- col = layout.column()
+ split = layout.split()
+ col = split.column()
col.active = not md.is_bound
- col.prop(md, "target")
- col.prop(md, "falloff")
+ col.label(text="Target:")
+ col.prop(md, "target", text="")
- layout.separator()
+ col = split.column()
+ col.label(text="Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", _ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "falloff")
+ col = split.column()
+ col.prop(md, "strength")
col = layout.column()
@@ -1132,12 +1224,30 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="From:")
col.prop(md, "object_from", text="")
- col.prop(md, "use_volume_preserve")
-
col = split.column()
col.label(text="To:")
col.prop(md, "object_to", text="")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+
+ split = layout.split()
+ col = split.column()
+ obj = md.object_from
+ if obj and obj.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "bone_from", obj.data, "bones", text="")
+
+ col = split.column()
+ obj = md.object_to
+ if obj and obj.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "bone_to", obj.data, "bones", text="")
+
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "use_volume_preserve")
+ col = split.column()
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
col = layout.column()
@@ -1163,6 +1273,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.texture_coords == 'OBJECT':
layout.prop(md, "texture_coords_object", text="Object")
+ obj = md.texture_coords_object
+ if obj and obj.type == 'ARMATURE':
+ layout.prop_search(md, "texture_coords_bone", obj.data, "bones", text="Bone")
elif md.texture_coords == 'UV' and ob.type == 'MESH':
layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
@@ -1202,7 +1315,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.separator()
layout.prop(md, "start_position_object")
- layout.prop_search(md, "vertex_group", ob, "vertex_groups")
+ row = layout.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
split = layout.split(factor=0.33)
col = split.column()
col.label(text="Texture")
@@ -1213,6 +1328,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
elif md.texture_coords == 'OBJECT':
layout.prop(md, "texture_coords_object")
+ obj = md.texture_coords_object
+ if obj and obj.type == 'ARMATURE':
+ layout.prop_search(md, "texture_coords_bone", obj.data, "bones")
layout.separator()
@@ -1234,17 +1352,22 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.prop(md, "mode")
row = layout.row()
- row.prop(md, "octree_depth")
- row.prop(md, "scale")
+ if md.mode == 'VOXEL':
+ layout.prop(md, "voxel_size")
+ layout.prop(md, "adaptivity")
+ else:
+ row.prop(md, "octree_depth")
+ row.prop(md, "scale")
- if md.mode == 'SHARP':
- layout.prop(md, "sharpness")
+ if md.mode == 'SHARP':
+ layout.prop(md, "sharpness")
+
+ layout.prop(md, "use_remove_disconnected")
+ row = layout.row()
+ row.active = md.use_remove_disconnected
+ row.prop(md, "threshold")
layout.prop(md, "use_smooth_shade")
- layout.prop(md, "use_remove_disconnected")
- row = layout.row()
- row.active = md.use_remove_disconnected
- row.prop(md, "threshold")
@staticmethod
def vertex_weight_mask(layout, ob, md):
@@ -1257,7 +1380,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if not md.mask_texture:
split = layout.split(factor=0.4)
split.label(text="Vertex Group Mask:")
- split.prop_search(md, "mask_vertex_group", ob, "vertex_groups", text="")
+ row = split.row(align=True)
+ row.prop_search(md, "mask_vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_mask_vertex_group", text="", icon='ARROW_LEFTRIGHT')
if not md.mask_vertex_group:
split = layout.split(factor=0.4)
@@ -1276,6 +1401,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.mask_tex_mapping == 'OBJECT':
layout.prop(md, "mask_tex_map_object", text="Object")
+ obj = md.mask_tex_map_object
+ if obj and obj.type == 'ARMATURE':
+ layout.prop_search(md, "mask_tex_map_bone", obj.data, "bones", text="Bone")
elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_layers")
@@ -1303,7 +1431,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.separator()
- layout.prop(md, "falloff_type")
+ row = layout.row(align=True)
+ row.prop(md, "falloff_type")
+ row.prop(md, "invert_falloff", text="", icon='ARROW_LEFTRIGHT')
if md.falloff_type == 'CURVE':
layout.template_curve_mapping(md, "map_curve")
@@ -1361,7 +1491,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "max_dist")
layout.separator()
- layout.prop(md, "falloff_type")
+ row = layout.row(align=True)
+ row.prop(md, "falloff_type")
+ row.prop(md, "invert_falloff", text="", icon='ARROW_LEFTRIGHT')
# Common mask options
layout.separator()
@@ -1442,10 +1574,25 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop_search(md, "bone_to", obj.data, "bones", text="")
split = layout.split()
+ col = split.column()
+ col.label(text="Offset:")
+ col.prop(md, "offset", text="")
+
+ col = split.column()
+ col.label(text="Scale:")
+ col.prop(md, "scale", text="")
+
+ col = split.column()
+ col.label(text="Rotate:")
+ col.prop(md, "rotation", text="")
+
+ split = layout.split()
col = split.column()
col.label(text="Vertex Group:")
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
col = split.column()
col.label(text="UV Map:")
@@ -1486,7 +1633,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def WELD(self, layout, ob, md):
layout.prop(md, "merge_threshold", text="Distance")
layout.prop(md, "max_interactions")
- layout.prop_search(md, "vertex_group", ob, "vertex_groups")
+ row = layout.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
def DATA_TRANSFER(self, layout, ob, md):
row = layout.row(align=True)
@@ -1641,7 +1790,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.prop(md, "factor", text="Factor")
layout.prop(md, "iterations")
-
+ layout.prop(md, "scale")
row = layout.row()
row.prop(md, "smooth_type")
@@ -1677,6 +1826,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "thresh", text="Threshold")
col.prop(md, "face_influence")
+ def SIMULATION(self, layout, ob, md):
+ layout.prop(md, "simulation")
+ layout.prop(md, "data_path")
+
class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
bl_label = "Modifiers"
@@ -1710,132 +1863,110 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
# ...to avoid lengthy if statements
# so each type must have a function here.
- def GP_NOISE(self, layout, ob, md):
+ def gpencil_masking(self, layout, ob, md, use_vertex, use_curve=False):
gpd = ob.data
- split = layout.split()
-
- col = split.column()
- row = col.row(align=True)
- row.prop(md, "factor")
- row.prop(md, "random", text="", icon='TIME', toggle=True)
- row = col.row()
- row.enabled = md.random
- row.prop(md, "step")
- row = col.row()
- row.enabled = md.random
- row.prop(md, "seed")
- col.prop(md, "full_stroke")
- col.prop(md, "move_extreme")
-
- row = layout.row(align=True)
- row.label(text="Affect:")
- row = layout.row(align=True)
- row.prop(md, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
- row.prop(md, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
- row.prop(md, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
- row.prop(md, "use_edit_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
+ layout.separator()
+ layout.label(text="Influence Filters:")
- col = layout.column()
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
+ split = layout.split(factor=0.25)
- col = layout.column()
- col.separator()
+ col1 = split.column()
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
+ col1.label(text="Layer:")
+ col1.label(text="Material:")
+ if use_vertex:
+ col1.label(text="Vertex Group:")
- col = layout.column()
- col.separator()
+ col2 = split.column()
- col.label(text="Layer:")
- row = col.row(align=True)
+ split = col2.split(factor=0.6)
+ row = split.row(align=True)
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
+
+ row = split.row(align=True)
row.prop(md, "layer_pass", text="Pass")
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
- def GP_SMOOTH(self, layout, ob, md):
- gpd = ob.data
- col = layout.column()
- col.prop(md, "factor")
- col.prop(md, "step")
+ split = col2.split(factor=0.6)
- col.label(text="Affect:")
- row = col.row(align=True)
- row.prop(md, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
- row.prop(md, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
- row.prop(md, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
- row.prop(md, "use_edit_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
-
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
+ row = split.row(align=True)
- col = layout.column()
- col.separator()
+ valid = md.material in (slot.material for slot in ob.material_slots) or md.material is None
+ if valid:
+ icon = 'SHADING_TEXTURE'
+ else:
+ icon = 'ERROR'
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
+ row.alert = not valid
+ row.prop_search(md, "material", gpd, "materials", text="", icon=icon)
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
+
+ row = split.row(align=True)
row.prop(md, "pass_index", text="Pass")
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
- col = layout.column()
- col.separator()
+ if use_vertex:
+ row = col2.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ if use_curve:
+ col = layout.column()
+ col.separator()
+ col.prop(md, "use_custom_curve")
+ if md.use_custom_curve:
+ col.template_curve_mapping(md, "curve")
- def GP_SUBDIV(self, layout, ob, md):
- gpd = ob.data
+ def GP_NOISE(self, layout, ob, md):
split = layout.split()
col = split.column()
row = col.row(align=True)
- row.prop(md, "level")
- row.prop(md, "simple", text="", icon='PARTICLE_POINT')
+ row.prop(md, "factor", text="Position")
+ row = col.row(align=True)
+ row.prop(md, "factor_strength", text="Strength")
+ row = col.row(align=True)
+ row.prop(md, "factor_thickness", text="Thickness")
+ row = col.row(align=True)
+ row.prop(md, "factor_uvs", text="UV")
- col = layout.column()
col.separator()
-
- col.label(text="Material:")
row = col.row(align=True)
+ row.prop(md, "random", text="", icon='TIME', toggle=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
+ subrow = row.row(align=True)
+ subrow.enabled = md.random
+ subrow.prop(md, "step")
+ subrow.prop(md, "seed")
- col = layout.column()
col.separator()
+ col.prop(md, "noise_scale")
+
+ self.gpencil_masking(layout, ob, md, True, True)
- col.label(text="Layer:")
+ def GP_SMOOTH(self, layout, ob, md):
+ col = layout.column()
+ col.prop(md, "factor")
+ col.prop(md, "step", text="Repeat")
+
+ col.label(text="Affect:")
row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ row.prop(md, "use_edit_position", text="Position", toggle=True)
+ row.prop(md, "use_edit_strength", text="Strength", toggle=True)
+ row.prop(md, "use_edit_thickness", text="Thickness", toggle=True)
+ row.prop(md, "use_edit_uv", text="UV", toggle=True)
+
+ self.gpencil_masking(layout, ob, md, True, True)
+
+ def GP_SUBDIV(self, layout, ob, md):
+ layout.row().prop(md, "subdivision_type", expand=True)
+ split = layout.split()
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "level", text="Subdivisions")
+
+ self.gpencil_masking(layout, ob, md, False)
def GP_SIMPLIFY(self, layout, ob, md):
gpd = ob.data
@@ -1857,108 +1988,70 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
elif md.mode == 'MERGE':
col.prop(md, "distance")
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, False)
def GP_THICK(self, layout, ob, md):
- gpd = ob.data
- split = layout.split()
-
- col = split.column()
- row = col.row(align=True)
- row.prop(md, "thickness", text="Thickness Factor")
+ col = layout.column()
col.prop(md, "normalize_thickness")
- if not md.normalize_thickness:
- split = layout.split()
- col = split.column()
- col.prop(md, "use_custom_curve")
+ if md.normalize_thickness:
+ col.prop(md, "thickness")
+ else:
+ col.prop(md, "thickness_factor")
- if md.use_custom_curve:
- col.template_curve_mapping(md, "curve")
+ self.gpencil_masking(layout, ob, md, True, True)
+ def GP_TEXTURE(self, layout, ob, md):
col = layout.column()
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
- col = layout.column()
- col.separator()
+ col.prop(md, "mode")
+ if md.mode in {'STROKE', 'STROKE_AND_FILL'}:
+ col.label(text="Stroke Texture:")
+ col.prop(md, "fit_method")
+ col.prop(md, "uv_offset")
+ col.prop(md, "uv_scale")
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
+ if md.mode == 'STROKE_AND_FILL':
+ col.separator()
- col = layout.column()
- col.separator()
+ if md.mode in {'FILL', 'STROKE_AND_FILL'}:
+ col.label(text="Fill Texture:")
+ col.prop(md, "fill_rotation", text="Rotation")
+ col.prop(md, "fill_offset", text="Location")
+ col.prop(md, "fill_scale", text="Scale")
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, True)
def GP_TINT(self, layout, ob, md):
- gpd = ob.data
- split = layout.split()
+ layout.row().prop(md, "tint_type", expand=True)
- col = split.column()
- col.prop(md, "color")
- col.prop(md, "factor")
+ if md.tint_type == 'UNIFORM':
+ col = layout.column()
+ col.prop(md, "color")
- row = layout.row()
- row.prop(md, "create_materials")
- row.prop(md, "modify_color")
+ col.separator()
+ col.prop(md, "factor")
- col = layout.column()
- col.separator()
+ if md.tint_type == 'GRADIENT':
+ col = layout.column()
+ col.label(text="Colors:")
+ col.template_color_ramp(md, "colors")
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
+ col.separator()
+
+ col.label(text="Object:")
+ col.prop(md, "object", text="")
+
+ col.separator()
+ row = col.row(align=True)
+ row.prop(md, "radius")
+ row.prop(md, "factor")
- col = layout.column()
col.separator()
+ col.prop(md, "vertex_mode")
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, True, True)
def GP_TIME(self, layout, ob, md):
gpd = ob.data
@@ -2004,7 +2097,6 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
def GP_COLOR(self, layout, ob, md):
- gpd = ob.data
split = layout.split()
col = split.column()
@@ -2014,134 +2106,71 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "value", text="V", slider=True)
row = layout.row()
- row.prop(md, "create_materials")
row.prop(md, "modify_color")
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, False, True)
def GP_OPACITY(self, layout, ob, md):
- gpd = ob.data
split = layout.split()
col = split.column()
- col.label(text="Opacity:")
- col.prop(md, "factor")
+ col.prop(md, "modify_color")
- row = layout.row()
- row.prop(md, "opacity_mode", text="Mode")
-
- if md.opacity_mode == 'MATERIAL':
- row = layout.row()
- row.prop(md, "create_materials")
- row.prop(md, "modify_color", text="Change")
+ if md.modify_color == 'HARDNESS':
+ col.prop(md, "hardness")
+ show = False
else:
- col = layout.column()
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
+ col.prop(md, "normalize_opacity")
+ if md.normalize_opacity is True:
+ text="Strength"
+ else:
+ text="Opacity Factor"
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ col.prop(md, "factor", text=text)
+ show = True
+ self.gpencil_masking(layout, ob, md, show, show)
def GP_ARRAY(self, layout, ob, md):
- gpd = ob.data
-
col = layout.column()
col.prop(md, "count")
split = layout.split()
col = split.column()
- col.label(text="Offset:")
- col.prop(md, "offset", text="")
- col.prop(md, "offset_object", text="Object")
+ col.prop(md, "use_constant_offset", text="Constant Offset")
+ subcol = col.column()
+ subcol.enabled = md.use_constant_offset
+ subcol.prop(md, "constant_offset", text="")
+
+ col.prop(md, "use_object_offset")
+ subcol = col.column()
+ subcol.enabled = md.use_object_offset
+ subcol.prop(md, "offset_object", text="")
col = split.column()
- col.label(text="Shift:")
- col.prop(md, "shift", text="")
+ col.prop(md, "use_relative_offset", text="Relative Offset")
+ subcol = col.column()
+ subcol.enabled = md.use_relative_offset
+ subcol.prop(md, "relative_offset", text="")
split = layout.split()
col = split.column()
- col.label(text="Rotation:")
- col.prop(md, "rotation", text="")
- col.separator()
- row = col.row(align=True)
- row.prop(md, "random_rot", text="", icon='TIME', toggle=True)
- row.prop(md, "rot_factor", text="")
+ col.label(text="Random Offset:")
+ col.prop(md, "random_offset", text="")
col = split.column()
- col.label(text="Scale:")
- col.prop(md, "scale", text="")
- col.separator()
- row = col.row(align=True)
- row.prop(md, "random_scale", text="", icon='TIME', toggle=True)
- row.prop(md, "scale_factor", text="")
-
- col = layout.column()
- col.prop(md, "replace_material", text="Material")
- col.prop(md, "keep_on_top", text="Keep original stroke on top")
+ col.label(text="Random Rotation:")
+ col.prop(md, "random_rotation", text="")
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
+ col = split.column()
+ col.label(text="Random Scale:")
+ col.prop(md, "random_scale", text="")
col = layout.column()
+ col.prop(md, "seed")
col.separator()
+ col.prop(md, "replace_material", text="Material Override")
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, False)
def GP_BUILD(self, layout, ob, md):
gpd = ob.data
@@ -2168,18 +2197,31 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
sub.prop(md, "frame_start", text="Start")
sub.prop(md, "frame_end", text="End")
- col = layout.column()
- col.separator()
- col.label(text="Layer:")
- row = col.row(align=True)
+ col.prop(md, "use_percentage")
+ sub = col.column(align=True)
+ sub.active = md.use_percentage
+ sub.prop(md, "percentage_factor")
+
+ layout.label(text="Influence Filters:")
+
+ split = layout.split(factor=0.25)
+
+ col1 = split.column()
+
+ col1.label(text="Layer:")
+
+ col2 = split.column()
+
+ split = col2.split(factor=0.6)
+ row = split.row(align=True)
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
+
+ row = split.row(align=True)
row.prop(md, "layer_pass", text="Pass")
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
def GP_LATTICE(self, layout, ob, md):
- gpd = ob.data
split = layout.split()
col = split.column()
@@ -2188,70 +2230,20 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
layout.prop(md, "strength", slider=True)
- col = layout.column()
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, True)
def GP_MIRROR(self, layout, ob, md):
- gpd = ob.data
-
row = layout.row(align=True)
row.prop(md, "x_axis")
row.prop(md, "y_axis")
row.prop(md, "z_axis")
- layout.label(text="Object:")
+ layout.label(text="Mirror Object:")
layout.prop(md, "object", text="")
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, False)
def GP_HOOK(self, layout, ob, md):
- gpd = ob.data
split = layout.split()
col = split.column()
@@ -2281,71 +2273,16 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "use_falloff_uniform")
- col = layout.column()
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, True)
def GP_OFFSET(self, layout, ob, md):
- gpd = ob.data
- col = layout.column()
-
- col.prop(md, "location")
- col.prop(md, "scale")
- col.prop(md, "rotation")
-
- col = layout.column()
- col.separator()
- col.label(text="Vertex Group:")
- row = col.row(align=True)
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
+ split = layout.split()
- col = layout.column()
- col.separator()
+ split.column().prop(md, "location")
+ split.column().prop(md, "rotation")
+ split.column().prop(md, "scale")
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, True)
def GP_ARMATURE(self, layout, ob, md):
split = layout.split()
@@ -2371,50 +2308,23 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
def GP_MULTIPLY(self, layout, ob, md):
- gpd = ob.data
col = layout.column()
- col.prop(md, "duplications")
+ col.prop(md, "duplicates")
subcol = col.column()
- subcol.enabled = md.duplications > 0
+ subcol.enabled = md.duplicates > 0
subcol.prop(md, "distance")
subcol.prop(md, "offset", slider=True)
subcol.separator()
- subcol.prop(md, "enable_fading")
- if md.enable_fading:
+ subcol.prop(md, "use_fade")
+ if md.use_fade:
subcol.prop(md, "fading_center")
subcol.prop(md, "fading_thickness", slider=True)
subcol.prop(md, "fading_opacity", slider=True)
- subcol.separator()
-
- col.prop(md, "enable_angle_splitting")
- if md.enable_angle_splitting:
- col.prop(md, "split_angle")
-
- col = layout.column()
- col.separator()
-
- col.label(text="Material:")
- row = col.row(align=True)
- row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
- row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "pass_index", text="Pass")
- row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
-
- col = layout.column()
- col.separator()
-
- col.label(text="Layer:")
- row = col.row(align=True)
- row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
- row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
- row = layout.row(align=True)
- row.prop(md, "layer_pass", text="Pass")
- row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
+ self.gpencil_masking(layout, ob, md, False)
classes = (
@@ -2424,5 +2334,6 @@ classes = (
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
+
for cls in classes:
register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_pointcloud.py b/release/scripts/startup/bl_ui/properties_data_pointcloud.py
new file mode 100644
index 00000000000..10ebdea3155
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_pointcloud.py
@@ -0,0 +1,78 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Panel, UIList
+from rna_prop_ui import PropertyPanel
+
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return hasattr(context, 'pointcloud') and context.pointcloud and (engine in cls.COMPAT_ENGINES)
+
+
+class DATA_PT_context_pointcloud(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ pointcloud = context.pointcloud
+ space = context.space_data
+
+ if ob:
+ layout.template_ID(ob, "data")
+ elif pointcloud:
+ layout.template_ID(space, "pin_id")
+
+
+class DATA_PT_pointcloud(DataButtonsPanel, Panel):
+ bl_label = "Point Cloud"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+ pointcloud = context.pointcloud
+ pass
+
+class DATA_PT_custom_props_pointcloud(DataButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+ _context_path = "object.data"
+ _property_type = bpy.types.PointCloud if hasattr(bpy.types, "PointCloud") else None
+
+
+classes = (
+ DATA_PT_context_pointcloud,
+ DATA_PT_pointcloud,
+ DATA_PT_custom_props_pointcloud,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_shaderfx.py b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
index fce86446dfc..1d4bf37b282 100644
--- a/release/scripts/startup/bl_ui/properties_data_shaderfx.py
+++ b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
@@ -56,27 +56,30 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
def FX_BLUR(self, layout, fx):
- layout.prop(fx, "factor", text="Factor")
+ layout.prop(fx, "use_dof_mode", text="Use Depth of Field")
+ layout.separator()
+
+ col = layout.column()
+ col.enabled = not fx.use_dof_mode
+ col.prop(fx, "size", text="Size")
+ col.separator()
+ col.prop(fx, "rotation")
+
layout.prop(fx, "samples", text="Samples")
- layout.separator()
- layout.prop(fx, "use_dof_mode")
- if fx.use_dof_mode:
- layout.prop(fx, "coc")
def FX_COLORIZE(self, layout, fx):
layout.prop(fx, "mode", text="Mode")
- if fx.mode == 'BITONE':
+ if fx.mode == 'DUOTONE':
layout.prop(fx, "low_color", text="Low Color")
if fx.mode == 'CUSTOM':
layout.prop(fx, "low_color", text="Color")
- if fx.mode == 'BITONE':
+ if fx.mode == 'DUOTONE':
layout.prop(fx, "high_color", text="High Color")
- if fx.mode in {'BITONE', 'CUSTOM', 'TRANSPARENT'}:
- layout.prop(fx, "factor")
+ layout.prop(fx, "factor")
def FX_WAVE(self, layout, fx):
row = layout.row(align=True)
@@ -95,7 +98,7 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
layout.prop(fx, "rim_color")
layout.prop(fx, "mask_color")
- layout.prop(fx, "mode")
+ layout.prop(fx, "mode", text="Blend")
layout.prop(fx, "blur")
layout.prop(fx, "samples")
@@ -111,7 +114,7 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
layout.prop(fx, "samples")
layout.separator()
- layout.prop(fx, "use_object", text="Use Object As Pivot")
+ layout.prop(fx, "use_object", text="Use Object as Pivot")
if fx.use_object:
row = layout.row()
row.prop(fx, "object", text="Object")
@@ -127,16 +130,21 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
def FX_GLOW(self, layout, fx):
layout.prop(fx, "mode")
- layout.prop(fx, "glow_color")
if fx.mode == 'LUMINANCE':
layout.prop(fx, "threshold")
else:
layout.prop(fx, "select_color")
+ layout.prop(fx, "glow_color")
layout.separator()
- layout.prop(fx, "radius")
+ layout.prop(fx, "blend_mode", text="Blend")
+ layout.prop(fx, "opacity")
+
+ layout.prop(fx, "size")
+ layout.prop(fx, "rotation")
layout.prop(fx, "samples")
- layout.prop(fx, "use_alpha_mode", text="Use Alpha Mode")
+
+ layout.prop(fx, "use_glow_under", text="Glow Under")
def FX_SWIRL(self, layout, fx):
layout.prop(fx, "object", text="Object")
@@ -144,18 +152,10 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
layout.prop(fx, "radius")
layout.prop(fx, "angle")
- layout.prop(fx, "use_transparent")
-
def FX_FLIP(self, layout, fx):
layout.prop(fx, "flip_horizontal")
layout.prop(fx, "flip_vertical")
- def FX_LIGHT(self, layout, fx):
- layout.prop(fx, "object", text="Object")
-
- layout.prop(fx, "energy")
- layout.prop(fx, "ambient")
-
classes = (
DATA_PT_shader_fx,
diff --git a/release/scripts/startup/bl_ui/properties_data_volume.py b/release/scripts/startup/bl_ui/properties_data_volume.py
new file mode 100644
index 00000000000..b10bb808edd
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_volume.py
@@ -0,0 +1,174 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Panel, UIList
+from rna_prop_ui import PropertyPanel
+
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return context.volume and (engine in cls.COMPAT_ENGINES)
+
+
+class DATA_PT_context_volume(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ volume = context.volume
+ space = context.space_data
+
+ if ob:
+ layout.template_ID(ob, "data")
+ elif volume:
+ layout.template_ID(space, "pin_id")
+
+
+class DATA_PT_volume_file(DataButtonsPanel, Panel):
+ bl_label = "OpenVDB File"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ volume = context.volume
+ volume.grids.load()
+
+ layout.prop(volume, "filepath", text="")
+
+ if len(volume.filepath):
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ col = layout.column(align=True)
+ col.prop(volume, "is_sequence")
+ if volume.is_sequence:
+ col.prop(volume, "frame_duration", text="Frames")
+ col.prop(volume, "frame_start", text="Start")
+ col.prop(volume, "frame_offset", text="Offset")
+ col.prop(volume, "sequence_mode", text="Mode")
+
+ error_msg = volume.grids.error_message
+ if len(error_msg):
+ layout.separator()
+ col = layout.column(align=True)
+ col.label(text="Failed to load volume:")
+ col.label(text=error_msg)
+
+
+class VOLUME_UL_grids(UIList):
+ def draw_item(self, context, layout, data, grid, icon, active_data, active_propname, index):
+ name = grid.name
+ data_type = grid.bl_rna.properties['data_type'].enum_items[grid.data_type]
+
+ layout.label(text=name)
+ row = layout.row()
+ row.alignment = 'RIGHT'
+ row.active = False
+ row.label(text=data_type.name)
+
+
+class DATA_PT_volume_grids(DataButtonsPanel, Panel):
+ bl_label = "Grids"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ volume = context.volume
+ volume.grids.load()
+
+ layout.template_list("VOLUME_UL_grids", "grids", volume, "grids", volume.grids, "active_index", rows=3)
+
+
+class DATA_PT_volume_render(DataButtonsPanel, Panel):
+ bl_label = "Render"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ volume = context.volume
+ render = volume.render
+
+ col = layout.column(align=True)
+ col.prop(render, "space")
+
+ if scene.render.engine == 'CYCLES':
+ col.prop(render, "step_size")
+
+ col = layout.column(align=True)
+ col.prop(render, "clipping")
+
+
+class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ volume = context.volume
+ display = volume.display
+
+ col = layout.column(align=True)
+ col.prop(display, "wireframe_type")
+ sub = col.row()
+ sub.active = display.wireframe_type in {'BOXES', 'POINTS'}
+ sub.prop(display, "wireframe_detail", text="Detail")
+
+ layout.prop(display, "density")
+
+
+class DATA_PT_custom_props_volume(DataButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+ _context_path = "object.data"
+ _property_type = bpy.types.Volume
+
+
+classes = (
+ DATA_PT_context_volume,
+ DATA_PT_volume_grids,
+ DATA_PT_volume_file,
+ DATA_PT_volume_viewport_display,
+ DATA_PT_volume_render,
+ DATA_PT_custom_props_volume,
+ VOLUME_UL_grids,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index 5fc03e59f9d..f70789ebeed 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -126,6 +126,7 @@ class VIEWLAYER_PT_freestyle(ViewLayerFreestyleButtonsPanel, Panel):
row = layout.row()
layout.prop(freestyle, "mode", text="Control Mode")
layout.prop(freestyle, "use_view_map_cache", text="View Map Cache")
+ layout.prop(freestyle, "as_render_pass", text="As Render Pass")
layout.label(text="Edge Detection Options:")
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 2001f46820f..64eda42c87a 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, UIList
+from bpy.types import Menu, UIList, Operator
from bpy.app.translations import pgettext_iface as iface_
@@ -44,38 +44,6 @@ def gpencil_stroke_placement_settings(context, layout):
row.prop_enum(tool_settings, propname, 'CURSOR', text="Cursor")
-def gpencil_active_brush_settings_simple(context, layout):
- tool_settings = context.tool_settings
- brush = tool_settings.gpencil_paint.brush
- if brush is None:
- layout.label(text="No Active Brush")
- return
-
- col = layout.column()
- col.label(text="Active Brush: ")
-
- row = col.row(align=True)
- row.operator_context = 'EXEC_REGION_WIN'
- row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA')
- row.prop(brush, "name", text="")
-
- col.prop(brush, "size", slider=True)
- row = col.row(align=True)
- row.prop(brush, "use_random_pressure", text="", icon='RNDCURVE')
- row.prop(brush, "pen_sensitivity_factor", slider=True)
- row.prop(brush, "use_pressure", text="", icon='STYLUS_PRESSURE')
- row = col.row(align=True)
- row.prop(brush, "use_random_strength", text="", icon='RNDCURVE')
- row.prop(brush, "strength", slider=True)
- row.prop(brush, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
- row = col.row(align=True)
- row.prop(brush, "jitter", slider=True)
- row.prop(brush, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
- row = col.row()
- row.prop(brush, "angle", slider=True)
- row.prop(brush, "angle_factor", text="Factor", slider=True)
-
-
# XXX: To be replaced with active tools
class AnnotationDrawingToolsPanel:
# subclass must set
@@ -108,11 +76,6 @@ class AnnotationDrawingToolsPanel:
sub.operator("gpencil.blank_frame_add", icon='FILE_NEW')
sub.operator("gpencil.active_frames_delete_all", icon='X', text="Delete Frame(s)")
- #sub = col.column(align=True)
- #sub.prop(context.tool_settings, "use_gpencil_draw_additive", text="Additive Drawing")
- #sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing")
- #sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back")
-
col.separator()
col.separator()
@@ -121,12 +84,9 @@ class AnnotationDrawingToolsPanel:
col.label(text="Data Source:")
row = col.row(align=True)
if is_3d_view:
- row.prop(context.tool_settings, "grease_pencil_source", expand=True)
+ row.prop(context.tool_settings, "annotation_source", expand=True)
elif is_clip_editor:
- row.prop(context.space_data, "grease_pencil_source", expand=True)
-
- # col.separator()
- # col.separator()
+ row.prop(context.space_data, "annotation_source", expand=True)
gpencil_stroke_placement_settings(context, col)
@@ -136,29 +96,33 @@ class GreasePencilSculptOptionsPanel:
@classmethod
def poll(cls, context):
- settings = context.tool_settings.gpencil_sculpt
- tool = settings.sculpt_tool
+ tool_settings = context.scene.tool_settings
+ settings = tool_settings.gpencil_sculpt_paint
+ brush = settings.brush
+ tool = brush.gpencil_sculpt_tool
- return bool(tool in {'SMOOTH', 'RANDOMIZE', 'SMOOTH'})
+ return bool(tool in {'SMOOTH', 'RANDOMIZE'})
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
- settings = context.tool_settings.gpencil_sculpt
- tool = settings.sculpt_tool
+ tool_settings = context.scene.tool_settings
+ settings = tool_settings.gpencil_sculpt_paint
brush = settings.brush
+ gp_settings = brush.gpencil_settings
+ tool = brush.gpencil_sculpt_tool
if tool in {'SMOOTH', 'RANDOMIZE'}:
- layout.prop(settings, "use_edit_position", text="Affect Position")
- layout.prop(settings, "use_edit_strength", text="Affect Strength")
- layout.prop(settings, "use_edit_thickness", text="Affect Thickness")
+ layout.prop(gp_settings, "use_edit_position", text="Affect Position")
+ layout.prop(gp_settings, "use_edit_strength", text="Affect Strength")
+ layout.prop(gp_settings, "use_edit_thickness", text="Affect Thickness")
if tool == 'SMOOTH':
- layout.prop(brush, "use_edit_pressure")
+ layout.prop(gp_settings, "use_edit_pressure")
- layout.prop(settings, "use_edit_uv", text="Affect UV")
+ layout.prop(gp_settings, "use_edit_uv", text="Affect UV")
# GP Object Tool Settings
@@ -174,7 +138,7 @@ class GreasePencilDisplayPanel:
if context.mode == 'PAINT_GPENCIL':
return brush.gpencil_tool != 'ERASE'
else:
- # GP Sculpt and Weight Paint always have Brush Tip panel.
+ # GP Sculpt, Vertex and Weight Paint always have Brush Tip panel.
return True
return False
@@ -182,16 +146,18 @@ class GreasePencilDisplayPanel:
if self.is_popover:
return
+ tool_settings = context.tool_settings
if context.mode == 'PAINT_GPENCIL':
- brush = context.tool_settings.gpencil_paint.brush
- gp_settings = brush.gpencil_settings
-
- self.layout.prop(gp_settings, "use_cursor", text="")
- elif context.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
- settings = context.tool_settings.gpencil_sculpt
- brush = settings.brush
-
- self.layout.prop(brush, "use_cursor", text="")
+ settings = tool_settings.gpencil_paint
+ elif context.mode == 'SCULPT_GPENCIL':
+ settings = tool_settings.gpencil_sculpt_paint
+ elif context.mode == 'WEIGHT_GPENCIL':
+ settings = tool_settings.gpencil_weight_paint
+ elif context.mode == 'VERTEX_GPENCIL':
+ settings = tool_settings.gpencil_vertex_paint
+ brush = settings.brush
+ if brush:
+ self.layout.prop(settings, "show_brush", text="")
def draw(self, context):
layout = self.layout
@@ -199,279 +165,101 @@ class GreasePencilDisplayPanel:
layout.use_property_decorate = False
tool_settings = context.tool_settings
- ob = context.active_object
+ if context.mode == 'PAINT_GPENCIL':
+ settings = tool_settings.gpencil_paint
+ elif context.mode == 'SCULPT_GPENCIL':
+ settings = tool_settings.gpencil_sculpt_paint
+ elif context.mode == 'WEIGHT_GPENCIL':
+ settings = tool_settings.gpencil_weight_paint
+ elif context.mode == 'VERTEX_GPENCIL':
+ settings = tool_settings.gpencil_vertex_paint
+ brush = settings.brush
+ gp_settings = brush.gpencil_settings
+ ob = context.active_object
if ob.mode == 'PAINT_GPENCIL':
- brush = tool_settings.gpencil_paint.brush
- gp_settings = brush.gpencil_settings
if self.is_popover:
row = layout.row(align=True)
- row.prop(gp_settings, "use_cursor", text="")
+ row.prop(settings, "show_brush", text="")
row.label(text="Display Cursor")
col = layout.column(align=True)
- col.active = gp_settings.use_cursor
+ col.active = settings.show_brush
if brush.gpencil_tool == 'DRAW':
col.prop(gp_settings, "show_lasso", text="Show Fill Color While Drawing")
- if brush.gpencil_tool == 'FILL':
- col.prop(brush, "cursor_color_add", text="Cursor Color")
-
- elif ob.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
- settings = tool_settings.gpencil_sculpt
- brush = settings.brush
- tool = settings.sculpt_tool
-
- if self.is_popover:
- row = layout.row(align=True)
- row.prop(brush, "use_cursor", text="")
- row.label(text="Display Cursor")
-
+ elif ob.mode == 'SCULPT_GPENCIL':
col = layout.column(align=True)
- col.active = brush.use_cursor
+ col.active = settings.show_brush
col.prop(brush, "cursor_color_add", text="Cursor Color")
- if tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
- col.prop(brush, "cursor_color_sub", text="Inverse Cursor Color")
-
-
-class GPENCIL_MT_pie_tool_palette(Menu):
- """A pie menu for quick access to Grease Pencil tools"""
- bl_label = "Grease Pencil Tools"
-
- def draw(self, context):
- layout = self.layout
-
- pie = layout.menu_pie()
- gpd = context.gpencil_data
-
- # W - Drawing Types
- col = pie.column()
- col.operator("gpencil.draw", text="Draw", icon='GREASEPENCIL').mode = 'DRAW'
- col.operator("gpencil.draw", text="Straight Lines", icon='LINE_DATA').mode = 'DRAW_STRAIGHT'
- col.operator("gpencil.draw", text="Poly", icon='MESH_DATA').mode = 'DRAW_POLY'
-
- # E - Eraser
- # XXX: needs a dedicated icon...
- col = pie.column()
- col.operator("gpencil.draw", text="Eraser", icon='FORCE_CURVE').mode = 'ERASER'
-
- # E - "Settings" Palette is included here too, since it needs to be in a stable position...
- if gpd and gpd.layers.active:
- col.separator()
- col.operator(
- "wm.call_menu_pie",
- text="Settings...",
- icon='SCRIPTWIN').name = "GPENCIL_MT_pie_settings_palette"
-
- # Editing tools
- if gpd:
- if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes:
- # S - Exit Edit Mode
- pie.operator("gpencil.editmode_toggle", text="Exit Edit Mode", icon='EDIT')
-
- # N - Transforms
- col = pie.column()
- row = col.row(align=True)
- row.operator("transform.translate", icon='MAN_TRANS')
- row.operator("transform.rotate", icon='MAN_ROT')
- row.operator("transform.resize", text="Scale", icon='MAN_SCALE')
- row = col.row(align=True)
- row.label(text="Proportional Edit:")
- row.prop(context.tool_settings, "use_proportional_edit", text="", icon_only=True)
- row.prop(context.tool_settings, "proportional_edit_falloff", text="", icon_only=True)
-
- # NW - Select (Non-Modal)
- col = pie.column()
- col.operator("gpencil.select_all", text="Select All", icon='PARTICLE_POINT')
- col.operator("gpencil.select_all", text="Select Inverse", icon='BLANK1')
- col.operator("gpencil.select_linked", text="Select Linked", icon='LINKED')
- col.operator("gpencil.palettecolor_select", text="Select Color", icon='COLOR')
-
- # NE - Select (Modal)
- col = pie.column()
- col.operator("gpencil.select_box", text="Box Select", icon='BORDER_RECT')
- col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY')
- col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO')
- col.operator("gpencil.select_alternate", text="Alternate Select", icon='BORDER_LASSO')
-
- # SW - Edit Tools
- col = pie.column()
- col.operator("gpencil.duplicate_move", icon='PARTICLE_PATH', text="Duplicate")
- col.operator("gpencil.delete", icon='X', text="Delete...")
-
- # SE - More Tools
- pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_MT_pie_tools_more"
- else:
- # Toggle Edit Mode
- pie.operator("gpencil.editmode_toggle", text="Enable Stroke Editing", icon='EDIT')
+ if brush.gpencil_sculpt_tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
+ col.prop(brush, "cursor_color_subtract", text="Inverse Cursor Color")
+ elif ob.mode == 'WEIGHT_GPENCIL':
+ col = layout.column(align=True)
+ col.active = settings.show_brush
-class GPENCIL_MT_pie_settings_palette(Menu):
- """A pie menu for quick access to Grease Pencil settings"""
- bl_label = "Grease Pencil Settings"
+ col.prop(brush, "cursor_color_add", text="Cursor Color")
- @classmethod
- def poll(cls, context):
- return bool(context.gpencil_data and context.active_gpencil_layer)
+ elif ob.mode == 'VERTEX_GPENCIL':
+ row = layout.row(align=True)
+ row.prop(settings, "show_brush", text="")
+ row.label(text="Display Cursor")
- def draw(self, context):
- layout = self.layout
- pie = layout.menu_pie()
- gpd = context.gpencil_data
- gpl = context.active_gpencil_layer
- palcolor = None # context.active_gpencil_palettecolor
-
- is_editmode = bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
-
- # W - Stroke draw settings
- col = pie.column(align=True)
- if palcolor is not None:
- col.enabled = not palcolor.lock
- col.label(text="Stroke")
- col.prop(palcolor, "color", text="")
- col.prop(palcolor, "alpha", text="", slider=True)
-
- # E - Fill draw settings
- col = pie.column(align=True)
- if palcolor is not None:
- col.enabled = not palcolor.lock
- col.label(text="Fill")
- col.prop(palcolor, "fill_color", text="")
- col.prop(palcolor, "fill_alpha", text="", slider=True)
-
- # S Brush settings
- gpencil_active_brush_settings_simple(context, pie)
-
- # N - Active Layer
- col = pie.column()
- col.label(text="Active Layer: ")
-
- row = col.row()
- row.operator_context = 'EXEC_REGION_WIN'
- row.operator_menu_enum("gpencil.layer_change", "layer", text="", icon='GREASEPENCIL')
- row.prop(gpl, "info", text="")
- row.operator("gpencil.layer_remove", text="", icon='X')
-
- row = col.row()
- row.prop(gpl, "lock")
- row.prop(gpl, "hide")
- col.prop(gpl, "use_onion_skinning")
-
- # NW/NE/SW/SE - These operators are only available in editmode
- # as they require strokes to be selected to work
- if is_editmode:
- # NW - Move stroke Down
- col = pie.column(align=True)
- col.label(text="Arrange Strokes")
- col.operator("gpencil.stroke_arrange", text="Send to Back").direction = 'BOTTOM'
- col.operator("gpencil.stroke_arrange", text="Send Backward").direction = 'DOWN'
-
- # NE - Move stroke Up
- col = pie.column(align=True)
- col.label(text="Arrange Strokes")
- col.operator("gpencil.stroke_arrange", text="Bring to Front").direction = 'TOP'
- col.operator("gpencil.stroke_arrange", text="Bring Forward").direction = 'UP'
-
- # SW - Move stroke to color
- col = pie.column(align=True)
- col.operator("gpencil.stroke_change_color", text="Move to Color")
-
- # SE - Join strokes
- col = pie.column(align=True)
- col.label(text="Join Strokes")
- row = col.row()
- row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
- row.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
- col.operator("gpencil.stroke_flip", text="Flip Direction")
-
- col.prop(gpd, "show_stroke_direction", text="Show Drawing Direction")
-
-
-class GPENCIL_MT_pie_tools_more(Menu):
- """A pie menu for accessing more Grease Pencil tools"""
- bl_label = "More Grease Pencil Tools"
+class GreasePencilBrushFalloff:
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- gpd = context.gpencil_data
- return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
-
- def draw(self, _context):
- layout = self.layout
-
- pie = layout.menu_pie()
- # gpd = context.gpencil_data
-
- col = pie.column(align=True)
- col.operator("gpencil.copy", text="Copy", icon='COPYDOWN')
- col.operator("gpencil.paste", text="Paste", icon='PASTEDOWN').type = 'ACTIVE'
- col.operator("gpencil.paste", text="Paste by Layer").type = 'LAYER'
-
- col = pie.column(align=True)
- col.operator("gpencil.select_more", icon='ADD')
- col.operator("gpencil.select_less", icon='REMOVE')
-
- pie.operator("transform.mirror", icon='MOD_MIRROR')
- pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM')
- pie.operator("transform.shear", icon='MOD_TRIANGULATE')
- pie.operator("transform.tosphere", icon='MOD_MULTIRES')
-
- pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...")
- pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_MT_pie_tool_palette"
-
+ ts = context.tool_settings
+ settings = None
+ if context.mode == 'PAINT_GPENCIL':
+ settings = ts.gpencil_paint
+ if context.mode == 'SCULPT_GPENCIL':
+ settings = ts.gpencil_sculpt_paint
+ elif context.mode == 'WEIGHT_GPENCIL':
+ settings = ts.gpencil_weight_paint
+ elif context.mode == 'VERTEX_GPENCIL':
+ settings = ts.gpencil_vertex_paint
-class GPENCIL_MT_pie_sculpt(Menu):
- """A pie menu for accessing Grease Pencil stroke sculpt settings"""
- bl_label = "Grease Pencil Sculpt"
-
- @classmethod
- def poll(cls, context):
- gpd = context.gpencil_data
- return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
+ return (settings and settings.brush and settings.brush.curve)
def draw(self, context):
layout = self.layout
+ ts = context.tool_settings
+ settings = None
+ if context.mode == 'PAINT_GPENCIL':
+ settings = ts.gpencil_paint
+ if context.mode == 'SCULPT_GPENCIL':
+ settings = ts.gpencil_sculpt_paint
+ elif context.mode == 'WEIGHT_GPENCIL':
+ settings = ts.gpencil_weight_paint
+ elif context.mode == 'VERTEX_GPENCIL':
+ settings = ts.gpencil_vertex_paint
+
+ if settings:
+ brush = settings.brush
- pie = layout.menu_pie()
-
- settings = context.tool_settings.gpencil_sculpt
- brush = settings.brush
-
- # W - Launch Sculpt Mode
- col = pie.column()
- # col.label(text="Tool:")
- col.prop(settings, "sculpt_tool", text="")
- col.operator("gpencil.sculpt_paint", text="Sculpt", icon='SCULPTMODE_HLT')
-
- # E - Common Settings
- col = pie.column(align=True)
- col.prop(brush, "size", slider=True)
- row = col.row(align=True)
- row.prop(brush, "strength", slider=True)
- # row.prop(brush, "use_pressure_strength", text="", icon_only=True)
- col.prop(brush, "use_falloff")
- if settings.sculpt_tool in {'SMOOTH', 'RANDOMIZE'}:
+ col = layout.column(align=True)
row = col.row(align=True)
- row.prop(settings, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
- row.prop(settings, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
- row.prop(settings, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
+ row.prop(brush, "curve_preset", text="")
- # S - Change Brush Type Shortcuts
- row = pie.row()
- row.prop_enum(settings, "tool", value='GRAB')
- row.prop_enum(settings, "tool", value='PUSH')
- row.prop_enum(settings, "tool", value='CLONE')
+ if brush.curve_preset == 'CUSTOM':
+ layout.template_curve_mapping(brush, "curve", brush=True)
- # N - Change Brush Type Shortcuts
- row = pie.row()
- row.prop_enum(settings, "tool", value='SMOOTH')
- row.prop_enum(settings, "tool", value='THICKNESS')
- row.prop_enum(settings, "tool", value='STRENGTH')
- row.prop_enum(settings, "tool", value='RANDOMIZE')
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
+ row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
+ row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
+ row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
+ row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
+ row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
class GPENCIL_MT_snap(Menu):
@@ -512,9 +300,64 @@ class GPENCIL_MT_move_to_layer(Menu):
layout.separator()
+ layout.operator("gpencil.move_to_layer", text="New Layer", icon='ADD').layer = -1
+
+
+class GPENCIL_MT_layer_active(Menu):
+ bl_label = "Change Active Layer"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator_context = 'INVOKE_REGION_WIN'
+
+ gpd = context.gpencil_data
+ if gpd:
+ gpl_active = context.active_gpencil_layer
+ tot_layers = len(gpd.layers)
+ i = tot_layers - 1
+ while i >= 0:
+ gpl = gpd.layers[i]
+ if gpl.info == gpl_active.info:
+ icon = 'GREASEPENCIL'
+ else:
+ icon = 'NONE'
+ layout.operator("gpencil.layer_active", text=gpl.info, icon=icon).layer = i
+ i -= 1
+
+ layout.separator()
+
layout.operator("gpencil.layer_add", text="New Layer", icon='ADD')
+class GPENCIL_MT_material_active(Menu):
+ bl_label = "Change Active Material"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ tool_settings = context.scene.tool_settings
+ mode = tool_settings.gpencil_paint.color_mode
+ if mode != 'MATERIAL':
+ return False
+
+ if ob is None or len(ob.material_slots) == 0:
+ return False
+
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ ob = context.active_object
+ mat_active = ob.active_material
+
+ for slot in ob.material_slots:
+ mat = slot.material
+ if mat:
+ icon = mat.id_data.preview.icon_id
+ layout.operator("gpencil.material_set", text=mat.name, icon_value=icon).slot = mat.name
+
+
class GPENCIL_MT_gpencil_draw_delete(Menu):
bl_label = "Delete"
@@ -602,7 +445,7 @@ class AnnotationDataPanel:
# Owner selector.
if context.space_data.type == 'CLIP_EDITOR':
- layout.row().prop(context.space_data, "grease_pencil_source", expand=True)
+ layout.row().prop(context.space_data, "annotation_source", expand=True)
layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.annotation_add", unlink="gpencil.data_unlink")
@@ -674,7 +517,7 @@ class AnnotationOnionSkin:
if gpl is None:
return False
- return True
+ return True
def draw_header(self, context):
gpl = context.active_annotation_layer
@@ -702,30 +545,6 @@ class AnnotationOnionSkin:
sub.prop(gpl, "annotation_onion_after_range", text="After")
-class GreasePencilToolsPanel:
- # For use in "2D" Editors without their own toolbar
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Grease Pencil Settings"
- bl_region_type = 'UI'
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, _context):
- # XXX - disabled in 2.8 branch.
- # return (context.gpencil_data is not None)
- return False
-
- def draw(self, context):
- layout = self.layout
-
- gpencil_active_brush_settings_simple(context, layout)
-
- layout.separator()
-
- gpencil_stroke_placement_settings(context, layout)
-
-
class GreasePencilMaterialsPanel:
# Mix-in, use for properties editor and top-bar.
def draw(self, context):
@@ -759,7 +578,7 @@ class GreasePencilMaterialsPanel:
col.separator()
- col.menu("GPENCIL_MT_color_context_menu", icon='DOWNARROW_HLT', text="")
+ col.menu("GPENCIL_MT_material_context_menu", icon='DOWNARROW_HLT', text="")
if is_sortable:
col.separator()
@@ -770,8 +589,8 @@ class GreasePencilMaterialsPanel:
col.separator()
sub = col.column(align=True)
- sub.operator("gpencil.color_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
- sub.operator("gpencil.color_isolate", icon='LOCKED', text="").affect_visibility = False
+ sub.operator("gpencil.material_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
+ sub.operator("gpencil.material_isolate", icon='LOCKED', text="").affect_visibility = False
if show_full_ui:
row = layout.row()
@@ -786,8 +605,8 @@ class GreasePencilMaterialsPanel:
if ob.data.use_stroke_edit_mode:
row = layout.row(align=True)
row.operator("gpencil.stroke_change_color", text="Assign")
- row.operator("gpencil.color_select", text="Select").deselect = False
- row.operator("gpencil.color_select", text="Deselect").deselect = True
+ row.operator("gpencil.material_select", text="Select").deselect = False
+ row.operator("gpencil.material_select", text="Deselect").deselect = True
# stroke color
ma = None
if is_view3d and brush is not None:
@@ -800,11 +619,7 @@ class GreasePencilMaterialsPanel:
if ma is not None and ma.grease_pencil is not None:
gpcolor = ma.grease_pencil
- if (
- gpcolor.stroke_style == 'SOLID' or
- gpcolor.use_stroke_pattern or
- gpcolor.use_stroke_texture_mix
- ):
+ if gpcolor.stroke_style == 'SOLID':
row = layout.row()
row.prop(gpcolor, "color", text="Stroke Color")
@@ -813,6 +628,44 @@ class GreasePencilMaterialsPanel:
row.template_ID(space, "pin_id")
+class GreasePencilVertexcolorPanel:
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ ts = context.scene.tool_settings
+ is_vertex = context.mode == 'VERTEX_GPENCIL'
+ gpencil_paint = ts.gpencil_vertex_paint if is_vertex else ts.gpencil_paint
+ brush = gpencil_paint.brush
+ gp_settings = brush.gpencil_settings
+ tool = brush.gpencil_vertex_tool if is_vertex else brush.gpencil_tool
+
+ ob = context.object
+
+ if ob:
+ col = layout.column()
+ col.template_color_picker(brush, "color", value_slider=True)
+
+ sub_row = layout.row(align=True)
+ sub_row.prop(brush, "color", text="")
+ sub_row.prop(brush, "secondary_color", text="")
+
+ sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="")
+
+ row = layout.row(align=True)
+ row.template_ID(gpencil_paint, "palette", new="palette.new")
+ if gpencil_paint.palette:
+ layout.template_palette(gpencil_paint, "palette", color=True)
+
+ if tool in {'DRAW', 'FILL'} and is_vertex is False:
+ row = layout.row(align=True)
+ row.prop(gp_settings, "vertex_mode", text="Mode")
+ row = layout.row(align=True)
+ row.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor")
+
+
class GPENCIL_UL_layer(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# assert(isinstance(item, bpy.types.GPencilLayer)
@@ -830,9 +683,10 @@ class GPENCIL_UL_layer(UIList):
row.prop(gpl, "info", text="", emboss=False)
row = layout.row(align=True)
- row.prop(gpl, "mask_layer", text="",
- icon='MOD_MASK' if gpl.mask_layer else 'LAYER_ACTIVE',
- emboss=False)
+
+ icon_mask = 'MOD_MASK' if gpl.use_mask_layer else 'LAYER_ACTIVE'
+
+ row.prop(gpl, "use_mask_layer", text="", icon=icon_mask, emboss=False)
subrow = row.row(align=True)
subrow.prop(
@@ -868,16 +722,12 @@ class GreasePencilSimplifyPanel:
layout.active = rd.simplify_gpencil
col = layout.column()
- col.prop(rd, "simplify_gpencil_onplay", text="Playback Only")
- col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
- col.prop(rd, "simplify_gpencil_shader_fx", text="ShaderFX")
- col.prop(rd, "simplify_gpencil_blend", text="Layers Blending")
- col.prop(rd, "simplify_gpencil_tint", text="Layers Tinting")
-
+ col.prop(rd, "simplify_gpencil_onplay")
col.prop(rd, "simplify_gpencil_view_fill")
- sub = col.column()
- sub.active = rd.simplify_gpencil_view_fill
- sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
+ col.prop(rd, "simplify_gpencil_modifier")
+ col.prop(rd, "simplify_gpencil_shader_fx")
+ col.prop(rd, "simplify_gpencil_tint")
+ col.prop(rd, "simplify_gpencil_antialiasing")
class GreasePencilLayerAdjustmentsPanel:
@@ -913,6 +763,65 @@ class GreasePencilLayerAdjustmentsPanel:
col.prop(gpl, "lock_material")
+class GPENCIL_UL_masks(UIList):
+ def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
+ mask = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ row = layout.row(align=True)
+ row.prop(mask, "name", text="", emboss=False, icon_value=icon)
+ row.prop(mask, "invert", text="", emboss=False)
+ row.prop(mask, "hide", text="", emboss=False)
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.prop(mask, "name", text="", emboss=False, icon_value=icon)
+
+
+class GPENCIL_MT_layer_mask_menu(Menu):
+ bl_label = "Layer Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ ob = context.object
+ gpd = ob.data
+ gpl_active = gpd.layers.active
+ done = False
+ for gpl in gpd.layers:
+ if gpl != gpl_active and gpl.info not in gpl_active.mask_layers:
+ done = True
+ layout.operator("gpencil.layer_mask_add", text=gpl.info).name=gpl.info
+
+ if done is False:
+ layout.label(text="No layers to add")
+
+
+class GreasePencilLayerMasksPanel:
+ def draw_header(self, context):
+ ob = context.active_object
+ gpd = ob.data
+ gpl = gpd.layers.active
+
+ self.layout.prop(gpl, "use_mask_layer", text="")
+
+ def draw(self, context):
+ ob = context.active_object
+ gpd = ob.data
+ gpl = gpd.layers.active
+
+ layout = self.layout
+ layout.enabled = gpl.use_mask_layer
+
+ if gpl:
+ rows = 4
+ row = layout.row()
+ col = row.column()
+ col.template_list("GPENCIL_UL_masks", "", gpl, "mask_layers", gpl.mask_layers,
+ "active_mask_index", rows=rows, sort_lock=True)
+
+ col2 = row.column(align=True)
+ col2.menu("GPENCIL_MT_layer_mask_menu", icon='ADD', text="")
+ col2.operator("gpencil.layer_mask_remove", icon='REMOVE', text="")
+
+
class GreasePencilLayerRelationsPanel:
def draw(self, context):
@@ -952,20 +861,59 @@ class GreasePencilLayerDisplayPanel:
col.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
-classes = (
- GPENCIL_MT_pie_tool_palette,
- GPENCIL_MT_pie_settings_palette,
- GPENCIL_MT_pie_tools_more,
- GPENCIL_MT_pie_sculpt,
+class GreasePencilFlipTintColors(Operator):
+ bl_label = "Flip Colors"
+ bl_idname = "gpencil.tint_flip"
+ bl_description = "Switch Tint colors"
+ def execute(self, context):
+ try:
+ ts = context.tool_settings
+ settings = None
+ if context.mode == 'PAINT_GPENCIL':
+ settings = ts.gpencil_paint
+ if context.mode == 'SCULPT_GPENCIL':
+ settings = ts.gpencil_sculpt_paint
+ elif context.mode == 'WEIGHT_GPENCIL':
+ settings = ts.gpencil_weight_paint
+ elif context.mode == 'VERTEX_GPENCIL':
+ settings = ts.gpencil_vertex_paint
+
+ brush = settings.brush
+ if brush is not None:
+ color = brush.color
+ secondary_color = brush.secondary_color
+
+ orig_prim = color.hsv
+ orig_sec = secondary_color.hsv
+
+ color.hsv = orig_sec
+ secondary_color.hsv = orig_prim
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ utils_core.error_handlers(self, "gpencil.tint_flip", e,
+ "Flip Colors could not be completed")
+
+ return {'CANCELLED'}
+
+
+classes = (
GPENCIL_MT_snap,
GPENCIL_MT_cleanup,
GPENCIL_MT_move_to_layer,
+ GPENCIL_MT_layer_active,
+ GPENCIL_MT_material_active,
GPENCIL_MT_gpencil_draw_delete,
+ GPENCIL_MT_layer_mask_menu,
GPENCIL_UL_annotation_layer,
GPENCIL_UL_layer,
+ GPENCIL_UL_masks,
+
+ GreasePencilFlipTintColors,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 0849437b680..6aaec9940e8 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -74,7 +74,7 @@ class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
_context_path = "material"
_property_type = bpy.types.Material
@@ -172,10 +172,11 @@ class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
layout.prop(mat, "use_nodes", icon='NODETREE')
layout.separator()
+ layout.use_property_split = True
+
if mat.use_nodes:
panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Surface")
else:
- layout.use_property_split = True
layout.prop(mat, "diffuse_color", text="Base Color")
layout.prop(mat, "metallic")
layout.prop(mat, "specular_intensity", text="Specular")
@@ -197,6 +198,8 @@ class EEVEE_MATERIAL_PT_volume(MaterialButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
mat = context.material
panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Volume")
diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py
index 4f419ec1f18..5d10a2cef4a 100644
--- a/release/scripts/startup/bl_ui/properties_material_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py
@@ -27,26 +27,31 @@ from bl_ui.properties_grease_pencil_common import (
)
-class GPENCIL_MT_color_context_menu(Menu):
+class GPENCIL_MT_material_context_menu(Menu):
bl_label = "Material Specials"
def draw(self, _context):
layout = self.layout
- layout.operator("gpencil.color_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
- layout.operator("gpencil.color_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
+ layout.operator("gpencil.material_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
+ layout.operator("gpencil.material_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
layout.separator()
- layout.operator("gpencil.color_lock_all", icon='LOCKED', text="Lock All")
- layout.operator("gpencil.color_unlock_all", icon='UNLOCKED', text="UnLock All")
+ layout.operator("gpencil.material_lock_all", icon='LOCKED', text="Lock All")
+ layout.operator("gpencil.material_unlock_all", icon='UNLOCKED', text="UnLock All")
- layout.operator("gpencil.stroke_lock_color", text="Lock Unselected")
+ layout.operator("gpencil.material_lock_unused", text="Lock Unselected")
layout.operator("gpencil.lock_layer", text="Lock Unused")
layout.separator()
layout.operator("object.material_slot_remove_unused")
+ layout.operator("gpencil.stroke_merge_material", text="Merge Similar")
+
+ layout.separator()
+ layout.operator("gpencil.material_to_vertex_color", text="Convert Materials to Vertex Color")
+ layout.operator("gpencil.extract_palette_vertex", text="Extract Palette from Vertex Color")
class GPENCIL_UL_matslots(UIList):
@@ -142,27 +147,25 @@ class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel):
col.prop(gpcolor, "stroke_style", text="Style")
+ row = col.row()
+ row.prop(gpcolor, "color", text="Base Color")
+
if gpcolor.stroke_style == 'TEXTURE':
row = col.row()
row.enabled = not gpcolor.lock
col = row.column(align=True)
col.template_ID(gpcolor, "stroke_image", open="image.open")
+
+ if gpcolor.stroke_style == 'TEXTURE':
+ row = col.row()
+ row.prop(gpcolor, "mix_stroke_factor", text="Blend", slider=True)
if gpcolor.mode == 'LINE':
col.prop(gpcolor, "pixel_size", text="UV Factor")
- col.prop(gpcolor, "use_stroke_pattern", text="Use As Stencil Mask")
- if gpcolor.use_stroke_pattern is False:
- col.prop(gpcolor, "use_stroke_texture_mix", text="Mix Color")
- if gpcolor.use_stroke_texture_mix is True:
- col.prop(gpcolor, "mix_stroke_factor", text="Factor")
-
- if (gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern or gpcolor.use_stroke_texture_mix):
- col.prop(gpcolor, "color", text="Color")
-
if gpcolor.mode in {'DOTS', 'BOX'}:
col.prop(gpcolor, "alignment_mode")
- if gpcolor.mode == 'LINE' and gpcolor.stroke_style != 'TEXTURE':
+ if gpcolor.mode == 'LINE':
col.prop(gpcolor, "use_overlap_strokes")
@@ -188,55 +191,37 @@ class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel):
col.enabled = not gpcolor.lock
col.prop(gpcolor, "fill_style", text="Style")
- if gpcolor.fill_style == 'GRADIENT':
- col.prop(gpcolor, "gradient_type")
-
- if gpcolor.fill_style != 'TEXTURE':
- col.prop(gpcolor, "fill_color", text="Color")
+ if gpcolor.fill_style == 'SOLID':
+ col.prop(gpcolor, "fill_color", text="Base Color")
- if gpcolor.fill_style in {'GRADIENT', 'CHECKER'}:
- col.prop(gpcolor, "mix_color", text="Secondary Color")
+ elif gpcolor.fill_style == 'GRADIENT':
+ col.prop(gpcolor, "gradient_type")
- if gpcolor.fill_style == 'GRADIENT':
- col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
+ col.prop(gpcolor, "fill_color", text="Base Color")
+ col.prop(gpcolor, "mix_color", text="Secondary Color")
+ col.prop(gpcolor, "mix_factor", text="Blend", slider=True)
+ col.prop(gpcolor, "flip", text="Flip Colors")
- if gpcolor.fill_style in {'GRADIENT', 'CHECKER'}:
- col.prop(gpcolor, "flip", text="Flip Colors")
+ col.prop(gpcolor, "texture_offset", text="Location")
- col.prop(gpcolor, "pattern_shift", text="Location")
- col.prop(gpcolor, "pattern_scale", text="Scale")
+ row = col.row()
+ row.enabled = gpcolor.gradient_type == 'LINEAR'
+ row.prop(gpcolor, "texture_angle", text="Rotation")
- if gpcolor.gradient_type == 'RADIAL' and gpcolor.fill_style not in {'SOLID', 'CHECKER'}:
- col.prop(gpcolor, "pattern_radius", text="Radius")
- else:
- if gpcolor.fill_style != 'SOLID':
- col.prop(gpcolor, "pattern_angle", text="Angle")
+ col.prop(gpcolor, "texture_scale", text="Scale")
- if gpcolor.fill_style == 'CHECKER':
- col.prop(gpcolor, "pattern_gridsize", text="Box Size")
+ elif gpcolor.fill_style == 'TEXTURE':
+ col.prop(gpcolor, "fill_color", text="Base Color")
- # Texture
- if gpcolor.fill_style == 'TEXTURE' or (gpcolor.use_fill_texture_mix is True and gpcolor.fill_style == 'SOLID'):
col.template_ID(gpcolor, "fill_image", open="image.open")
- if gpcolor.fill_style == 'TEXTURE':
- col.prop(gpcolor, "use_fill_pattern", text="Use as Stencil Mask")
- if gpcolor.use_fill_pattern is True:
- col.prop(gpcolor, "fill_color", text="Color")
+ col.prop(gpcolor, "mix_factor", text="Blend", slider=True)
- col.prop(gpcolor, "texture_offset", text="Offset")
+ col.prop(gpcolor, "texture_offset", text="Location")
+ col.prop(gpcolor, "texture_angle", text="Rotation")
col.prop(gpcolor, "texture_scale", text="Scale")
- col.prop(gpcolor, "texture_angle")
- col.prop(gpcolor, "texture_opacity")
col.prop(gpcolor, "texture_clamp", text="Clip Image")
- if gpcolor.use_fill_pattern is False:
- col.prop(gpcolor, "use_fill_texture_mix", text="Mix with Color")
-
- if gpcolor.use_fill_texture_mix is True:
- col.prop(gpcolor, "fill_color", text="Mix Color")
- col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
-
class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel):
bl_label = "Preview"
@@ -278,7 +263,7 @@ class MATERIAL_PT_gpencil_material_presets(PresetPanel, Panel):
classes = (
GPENCIL_UL_matslots,
- GPENCIL_MT_color_context_menu,
+ GPENCIL_MT_material_context_menu,
MATERIAL_PT_gpencil_slots,
MATERIAL_PT_gpencil_preview,
MATERIAL_PT_gpencil_material_presets,
@@ -291,5 +276,6 @@ classes = (
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
+
for cls in classes:
register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index bb020084b03..8ce53ed30eb 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -212,45 +212,31 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
obj = context.object
obj_type = obj.type
- is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'})
+ is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'VOLUME', 'HAIR', 'POINTCLOUD'})
is_wire = (obj_type in {'CAMERA', 'EMPTY'})
is_empty_image = (obj_type == 'EMPTY' and obj.empty_display_type == 'IMAGE')
is_dupli = (obj.instance_type != 'NONE')
is_gpencil = (obj_type == 'GPENCIL')
- col = flow.column()
+ col = layout.column(heading="Show")
col.prop(obj, "show_name", text="Name")
-
- col = flow.column()
col.prop(obj, "show_axis", text="Axis")
# Makes no sense for cameras, armatures, etc.!
# but these settings do apply to dupli instances
if is_geometry or is_dupli:
- col = flow.column()
col.prop(obj, "show_wire", text="Wireframe")
if obj_type == 'MESH' or is_dupli:
- col = flow.column()
col.prop(obj, "show_all_edges", text="All Edges")
-
- col = flow.column()
if is_geometry:
col.prop(obj, "show_texture_space", text="Texture Space")
- col = flow.column()
col.prop(obj.display, "show_shadows", text="Shadow")
-
- col = flow.column()
col.prop(obj, "show_in_front", text="In Front")
# if obj_type == 'MESH' or is_empty_image:
# col.prop(obj, "show_transparent", text="Transparency")
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
if is_wire:
# wire objects only use the max. display type for duplis
col.active = is_dupli
@@ -258,28 +244,17 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
if is_geometry or is_dupli or is_empty_image or is_gpencil:
# Only useful with object having faces/materials...
- col = flow.column()
col.prop(obj, "color")
-
-class OBJECT_PT_display_bounds(ObjectButtonsPanel, Panel):
- bl_label = "Bounds"
- bl_parent_id = "OBJECT_PT_display"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw_header(self, context):
-
- obj = context.object
-
- self.layout.prop(obj, "show_bounds", text="")
-
- def draw(self, context):
- layout = self.layout
- obj = context.object
- layout.use_property_split = True
-
- layout.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
- layout.prop(obj, "display_bounds_type", text="Shape")
+ col = layout.column(align=False, heading="Bounds")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(obj, "show_bounds", text="")
+ sub = sub.row(align=True)
+ sub.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
+ sub.prop(obj, "display_bounds_type", text="")
+ row.prop_decorator(obj, "display_bounds_type")
class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
@@ -295,7 +270,6 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
row.prop(ob, "instance_type", expand=True)
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
if ob.instance_type == 'VERTS':
layout.prop(ob, "use_instance_vertices_rotation", text="Align to Vertex Normal")
@@ -305,9 +279,9 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
col.prop(ob, "instance_collection", text="Collection")
if ob.instance_type != 'NONE' or ob.particle_systems:
- col = flow.column(align=True)
- col.prop(ob, "show_instancer_for_viewport")
- col.prop(ob, "show_instancer_for_render")
+ col = layout.column(heading="Show Instancer", align=True)
+ col.prop(ob, "show_instancer_for_viewport", text="Viewport")
+ col.prop(ob, "show_instancer_for_render", text="Render")
class OBJECT_PT_instancing_size(ObjectButtonsPanel, Panel):
@@ -385,16 +359,18 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
layout = self.layout
ob = context.object
- col = flow.column()
- col.prop(ob, "hide_viewport", text="Show in Viewports", toggle=False, invert_checkbox=True)
- col = flow.column()
- col.prop(ob, "hide_render", text="Show in Renders", toggle=False, invert_checkbox=True)
- col = flow.column()
- col.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
+ layout.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
+
+ col = layout.column(heading="Show in")
+ col.prop(ob, "hide_viewport", text="Viewports", toggle=False, invert_checkbox=True)
+ col.prop(ob, "hide_render", text="Renders", toggle=False, invert_checkbox=True)
+
+ if context.object.type == 'GPENCIL':
+ col = layout.column(heading="Grease Pencil")
+ col.prop(ob, "use_grease_pencil_lights", toggle=False)
class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
@@ -415,7 +391,6 @@ classes = (
OBJECT_PT_motion_paths,
OBJECT_PT_motion_paths_display,
OBJECT_PT_display,
- OBJECT_PT_display_bounds,
OBJECT_PT_visibility,
OBJECT_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index 748961bb40f..e859798c085 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -94,14 +94,14 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel):
return args
@staticmethod
- def draw_framerate(layout, sub, rd):
+ def draw_framerate(layout, rd):
if RENDER_PT_dimensions._preset_class is None:
RENDER_PT_dimensions._preset_class = bpy.types.RENDER_MT_framerate_presets
args = rd.fps, rd.fps_base, RENDER_PT_dimensions._preset_class.bl_label
fps_label_text, show_framerate = RENDER_PT_dimensions._draw_framerate_label(*args)
- sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
+ layout.menu("RENDER_MT_framerate_presets", text=fps_label_text)
if show_framerate:
col = layout.column(align=True)
@@ -136,10 +136,8 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel):
col.prop(scene, "frame_end", text="End")
col.prop(scene, "frame_step", text="Step")
- col = layout.split()
- col.alignment = 'RIGHT'
- col.label(text="Frame Rate")
- self.draw_framerate(layout, col, rd)
+ col = layout.column(heading="Frame Rate")
+ self.draw_framerate(col, rd)
class RENDER_PT_frame_remapping(RenderOutputButtonsPanel, Panel):
@@ -171,10 +169,8 @@ class RENDER_PT_post_processing(RenderOutputButtonsPanel, Panel):
rd = context.scene.render
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
+ col = layout.column(heading="Pipeline")
col.prop(rd, "use_compositing")
- col = flow.column()
col.prop(rd, "use_sequencer")
layout.prop(rd, "dither_intensity", text="Dither", slider=True)
@@ -192,44 +188,23 @@ class RENDER_PT_stamp(RenderOutputButtonsPanel, Panel):
rd = context.scene.render
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ if rd.use_sequencer:
+ layout.prop(rd, "metadata_input")
- col = flow.column()
+ col = layout.column(heading="Include")
col.prop(rd, "use_stamp_date", text="Date")
- col = flow.column()
col.prop(rd, "use_stamp_time", text="Time")
-
- col = flow.column()
col.prop(rd, "use_stamp_render_time", text="Render Time")
- col = flow.column()
col.prop(rd, "use_stamp_frame", text="Frame")
- col = flow.column()
col.prop(rd, "use_stamp_frame_range", text="Frame Range")
- col = flow.column()
col.prop(rd, "use_stamp_memory", text="Memory")
- col = flow.column()
col.prop(rd, "use_stamp_hostname", text="Hostname")
-
- col = flow.column()
col.prop(rd, "use_stamp_camera", text="Camera")
- col = flow.column()
col.prop(rd, "use_stamp_lens", text="Lens")
-
- col = flow.column()
col.prop(rd, "use_stamp_scene", text="Scene")
- col = flow.column()
col.prop(rd, "use_stamp_marker", text="Marker")
-
- col = flow.column()
col.prop(rd, "use_stamp_filename", text="Filename")
- col = flow.column()
- col.prop(rd, "use_stamp_sequencer_strip", text="Strip Name")
-
- if rd.use_sequencer:
- col = flow.column()
- col.prop(rd, "use_stamp_strip_meta", text="Use Strip Metadata")
-
class RENDER_PT_stamp_note(RenderOutputButtonsPanel, Panel):
bl_label = "Note"
@@ -293,21 +268,17 @@ class RENDER_PT_output(RenderOutputButtonsPanel, Panel):
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
- col.active = not rd.is_movie_format
- col.prop(rd, "use_overwrite")
- col = flow.column()
- col.active = not rd.is_movie_format
- col.prop(rd, "use_placeholder")
- col = flow.column()
+ col = layout.column(heading="Saving")
col.prop(rd, "use_file_extension")
- col = flow.column()
col.prop(rd, "use_render_cache")
layout.template_image_settings(image_settings, color_management=False)
+ if not rd.is_movie_format:
+ col = layout.column(heading="Image Sequence")
+ col.prop(rd, "use_overwrite")
+ col.prop(rd, "use_placeholder")
+
class RENDER_PT_output_views(RenderOutputButtonsPanel, Panel):
bl_label = "Views"
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index a9e8cae3c8b..92d421f63a8 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -89,8 +89,12 @@ class UnifiedPaintPanel:
# Grease Pencil settings
elif mode == 'PAINT_GPENCIL':
return tool_settings.gpencil_paint
- elif mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
- return tool_settings.gpencil_sculpt
+ elif mode == 'SCULPT_GPENCIL':
+ return tool_settings.gpencil_sculpt_paint
+ elif mode == 'WEIGHT_GPENCIL':
+ return tool_settings.gpencil_weight_paint
+ elif mode == 'VERTEX_GPENCIL':
+ return tool_settings.gpencil_vertex_paint
return None
@staticmethod
@@ -211,7 +215,7 @@ class ClonePanel(BrushPanel):
settings = cls.paint_settings(context)
mode = cls.get_brush_mode(context)
- if mode in {'PAINT_TEXTURE', 'PAINT_2D'}:
+ if mode == 'PAINT_TEXTURE':
brush = settings.brush
return brush.image_tool == 'CLONE'
return False
@@ -536,6 +540,7 @@ def brush_settings(layout, context, brush, popover=False):
# normal_radius_factor
layout.prop(brush, "normal_radius_factor", slider=True)
+ layout.prop(brush, "hardness", slider=True)
# auto_smooth_factor and use_inverse_smooth_pressure
if capabilities.has_auto_smooth:
@@ -582,10 +587,12 @@ def brush_settings(layout, context, brush, popover=False):
slider=True,
)
- layout.prop(brush, "use_plane_trim", text="Plane Trim")
- row = layout.row()
- row.active = brush.use_plane_trim
- row.prop(brush, "plane_trim", slider=True, text="Distance")
+ row = layout.row(heading="Plane Trim")
+ row.prop(brush, "use_plane_trim", text="")
+ sub = row.row()
+ sub.active = brush.use_plane_trim
+ sub.prop(brush, "plane_trim", slider=True, text="")
+
layout.separator()
# height
@@ -595,19 +602,14 @@ def brush_settings(layout, context, brush, popover=False):
# use_persistent, set_persistent_base
if capabilities.has_persistence:
ob = context.sculpt_object
- do_persistent = True
-
- # not supported yet for this case
- for md in ob.modifiers:
- if md.type == 'MULTIRES':
- do_persistent = False
- break
+ layout.separator()
+ layout.prop(brush, "use_persistent")
+ layout.operator("sculpt.set_persistent_base")
+ layout.separator()
- if do_persistent:
- layout.separator()
- layout.prop(brush, "use_persistent")
- layout.operator("sculpt.set_persistent_base")
- layout.separator()
+ if brush.sculpt_tool == 'CLAY_STRIPS':
+ row = layout.row()
+ row.prop(brush, "tip_roundness")
if brush.sculpt_tool == 'ELASTIC_DEFORM':
layout.separator()
@@ -617,17 +619,35 @@ def brush_settings(layout, context, brush, popover=False):
if brush.sculpt_tool == 'POSE':
layout.separator()
+ layout.prop(brush, "pose_origin_type")
layout.prop(brush, "pose_offset")
layout.prop(brush, "pose_smooth_iterations")
layout.prop(brush, "pose_ik_segments")
+ layout.prop(brush, "use_pose_ik_anchored")
layout.separator()
-
+
+ if brush.sculpt_tool == 'CLOTH':
+ layout.separator()
+ layout.prop(brush, "cloth_sim_limit")
+ layout.prop(brush, "cloth_sim_falloff")
+ layout.separator()
+ layout.prop(brush, "cloth_deform_type")
+ layout.prop(brush, "cloth_force_falloff_type")
+ layout.separator()
+ layout.prop(brush, "cloth_mass")
+ layout.prop(brush, "cloth_damping")
+ layout.separator()
+
if brush.sculpt_tool == 'SCRAPE':
row = layout.row()
+ row.prop(brush, "area_radius_factor", slider=True)
+ row = layout.row()
row.prop(brush, "invert_to_scrape_fill", text="Invert to Fill")
if brush.sculpt_tool == 'FILL':
row = layout.row()
+ row.prop(brush, "area_radius_factor", slider=True)
+ row = layout.row()
row.prop(brush, "invert_to_scrape_fill", text="Invert to Scrape")
if brush.sculpt_tool == 'GRAB':
@@ -639,6 +659,14 @@ def brush_settings(layout, context, brush, popover=False):
col.prop(brush, "use_multiplane_scrape_dynamic")
col.prop(brush, "show_multiplane_scrape_planes_preview")
+ if brush.sculpt_tool == 'SMOOTH':
+ col = layout.column()
+ col.prop(brush, "smooth_deform_type")
+ if brush.smooth_deform_type == 'SURFACE':
+ col.prop(brush, "surface_smooth_shape_preservation")
+ col.prop(brush, "surface_smooth_current_vertex")
+ col.prop(brush, "surface_smooth_iterations")
+
if brush.sculpt_tool == 'MASK':
layout.row().prop(brush, "mask_tool", expand=True)
@@ -782,14 +810,27 @@ def brush_settings_advanced(layout, context, brush, popover=False):
use_accumulate = capabilities.has_accumulate
use_frontface = True
+ col = layout.column(heading="Auto-Masking", align=True)
+
# topology automasking
- layout.prop(brush, "use_automasking_topology")
+ col.prop(brush, "use_automasking_topology", text="Topology")
+
+ # face masks automasking
+ col.prop(brush, "use_automasking_face_sets", text="Face Sets")
+
+ # boundary edges/face sets automasking
+ col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary")
+ col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
+ col.prop(brush, "automasking_boundary_edges_propagation_steps")
+
+ layout.separator()
# sculpt plane settings
if capabilities.has_sculpt_plane:
layout.prop(brush, "sculpt_plane")
- layout.prop(brush, "use_original_normal")
- layout.prop(brush, "use_original_plane")
+ col = layout.column(heading="Use Original", align=True)
+ col.prop(brush, "use_original_normal", text="Normal")
+ col.prop(brush, "use_original_plane", text="Plane")
layout.separator()
# 3D and 2D Texture Paint.
@@ -858,7 +899,7 @@ def draw_color_settings(context, layout, brush, color_type=False):
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
row.separator()
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
- row.prop(ups, "use_unified_color", text="", icon='WORLD')
+ row.prop(ups, "use_unified_color", text="", icon='BRUSHES_ALL')
# Gradient
elif brush.color_type == 'GRADIENT':
layout.template_color_ramp(brush, "gradient", expand=True)
@@ -994,8 +1035,12 @@ def brush_basic_texpaint_settings(layout, context, brush, *, compact=False):
def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False):
+ tool_settings = context.tool_settings
+ settings = tool_settings.gpencil_paint
gp_settings = brush.gpencil_settings
tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
+ if gp_settings is None:
+ return
# Brush details
if brush.gpencil_tool == 'ERASE':
@@ -1016,7 +1061,7 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
row.prop(gp_settings, "eraser_thickness_factor")
row = layout.row(align=True)
- row.prop(gp_settings, "use_cursor", text="Display Cursor")
+ row.prop(settings, "show_brush", text="Display Cursor")
# FIXME: tools must use their own UI drawing!
elif brush.gpencil_tool == 'FILL':
@@ -1027,14 +1072,29 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
row = layout.row(align=True)
row.prop(gp_settings, "fill_simplify_level", text="Simplify")
- else: # brush.gpencil_tool == 'DRAW':
+ else: # brush.gpencil_tool == 'DRAW/TINT':
row = layout.row(align=True)
row.prop(brush, "size", text="Radius")
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+
+ if gp_settings.use_pressure and context.area.type == 'PROPERTIES':
+ col = layout.column()
+ col.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True,
+ use_negative_slope=True)
+
row = layout.row(align=True)
row.prop(gp_settings, "pen_strength", slider=True)
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_strength_pressure and context.area.type == 'PROPERTIES':
+ col = layout.column()
+ col.template_curve_mapping(gp_settings, "curve_strength", brush=True,
+ use_negative_slope=True)
+
+ if brush.gpencil_tool == 'TINT':
+ row = layout.row(align=True)
+ row.prop(gp_settings, "vertex_mode", text="Mode")
+
# FIXME: tools must use their own UI drawing!
if tool.idname in {
"builtin.arc",
@@ -1047,7 +1107,7 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
settings = context.tool_settings.gpencil_sculpt
if compact:
row = layout.row(align=True)
- row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA')
+ row.prop(settings, "use_thickness_curve", text="", icon='SPHERECURVE')
sub = row.row(align=True)
sub.active = settings.use_thickness_curve
sub.popover(
@@ -1064,50 +1124,66 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
def brush_basic_gpencil_sculpt_settings(layout, context, brush, *, compact=False):
- tool_settings = context.tool_settings
- settings = tool_settings.gpencil_sculpt
- tool = settings.sculpt_tool
+ gp_settings = brush.gpencil_settings
+ tool = brush.gpencil_sculpt_tool
row = layout.row(align=True)
row.prop(brush, "size", slider=True)
sub = row.row(align=True)
sub.enabled = tool not in {'GRAB', 'CLONE'}
- sub.prop(brush, "use_pressure_radius", text="")
+ sub.prop(gp_settings, "use_pressure", text="")
row = layout.row(align=True)
row.prop(brush, "strength", slider=True)
row.prop(brush, "use_pressure_strength", text="")
- layout.prop(brush, "use_falloff")
-
if compact:
if tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
row.separator()
- row.prop(brush, "direction", expand=True, text="")
+ row.prop(gp_settings, "direction", expand=True, text="")
else:
use_property_split_prev = layout.use_property_split
layout.use_property_split = False
if tool in {'THICKNESS', 'STRENGTH'}:
- layout.row().prop(brush, "direction", expand=True)
+ layout.row().prop(gp_settings, "direction", expand=True)
elif tool == 'PINCH':
row = layout.row(align=True)
- row.prop_enum(brush, "direction", value='ADD', text="Pinch")
- row.prop_enum(brush, "direction", value='SUBTRACT', text="Inflate")
+ row.prop_enum(gp_settings, "direction", value='ADD', text="Pinch")
+ row.prop_enum(gp_settings, "direction", value='SUBTRACT', text="Inflate")
elif tool == 'TWIST':
row = layout.row(align=True)
- row.prop_enum(brush, "direction", value='ADD', text="CCW")
- row.prop_enum(brush, "direction", value='SUBTRACT', text="CW")
+ row.prop_enum(gp_settings, "direction", value='ADD', text="CCW")
+ row.prop_enum(gp_settings, "direction", value='SUBTRACT', text="CW")
layout.use_property_split = use_property_split_prev
def brush_basic_gpencil_weight_settings(layout, _context, brush, *, compact=False):
+ gp_settings = brush.gpencil_settings
layout.prop(brush, "size", slider=True)
row = layout.row(align=True)
row.prop(brush, "strength", slider=True)
row.prop(brush, "use_pressure_strength", text="")
+
layout.prop(brush, "weight", slider=True)
- layout.prop(brush, "use_falloff")
+
+
+def brush_basic_gpencil_vertex_settings(layout, _context, brush, *, compact=False):
+ gp_settings = brush.gpencil_settings
+
+ # Brush details
+ row = layout.row(align=True)
+ row.prop(brush, "size", text="Radius")
+ row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+
+ if brush.gpencil_vertex_tool in {'DRAW', 'BLUR', 'SMEAR'}:
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_strength", slider=True)
+ row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+
+ if brush.gpencil_vertex_tool in {'DRAW', 'REPLACE'}:
+ row = layout.row(align=True)
+ row.prop(gp_settings, "vertex_mode", text="Mode")
classes = (
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 3384032e332..cc8fa511e42 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -136,13 +136,13 @@ class PARTICLE_UL_particle_systems(bpy.types.UIList):
if md:
row.prop(
md,
- "show_viewport",
+ "show_render",
emboss=False,
icon_only=True,
)
row.prop(
md,
- "show_render",
+ "show_viewport",
emboss=False,
icon_only=True,
)
@@ -413,6 +413,38 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
box.label(text="Error: %.5f .. %.5f (avg. %.5f)" % (result.min_error, result.max_error, result.avg_error))
+class PARTICLE_PT_hair_dynamics_collision(ParticleButtonsPanel, Panel):
+ bl_label = "Collisions"
+ bl_parent_id = "PARTICLE_PT_hair_dynamics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.particle_system.cloth is not None
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ cloth_md = psys.cloth
+ cloth_collision = cloth_md.collision_settings
+
+ layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.prop(cloth_collision, "collision_quality", text="Quality")
+
+ layout.separator()
+
+ col = layout.column()
+ col.prop(cloth_collision, "distance_min", slider=True, text="Distance")
+ col.prop(cloth_collision, "impulse_clamp")
+ col.prop(cloth_collision, "collection")
+
+
class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel):
bl_label = "Structure"
bl_parent_id = "PARTICLE_PT_hair_dynamics"
@@ -607,7 +639,7 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
col.separator()
col.prop(part, "phase_factor", slider=True)
- col.prop(part, "phase_factor_random", text="Randomize Phase ", slider=True)
+ col.prop(part, "phase_factor_random", text="Randomize Phase", slider=True)
if part.type != 'HAIR':
col.prop(part, "use_dynamic_rotation")
@@ -1986,6 +2018,7 @@ classes = (
PARTICLE_PT_emission,
PARTICLE_PT_emission_source,
PARTICLE_PT_hair_dynamics,
+ PARTICLE_PT_hair_dynamics_collision,
PARTICLE_PT_hair_dynamics_structure,
PARTICLE_PT_hair_dynamics_volume,
PARTICLE_PT_cache,
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index d9713cb8608..0bf667482c4 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -230,7 +230,7 @@ class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
col.prop(cloth, "uniform_pressure_force")
col = flow.column()
- col.prop(cloth, "use_pressure_volume", text="Custom volume")
+ col.prop(cloth, "use_pressure_volume", text="Custom Volume")
col = flow.column()
col.active = cloth.use_pressure_volume
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 5397020a521..0cd99efcca9 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -227,7 +227,7 @@ def point_cache_ui(self, cache, enabled, cachetype):
col.operator("ptcache.bake", text="Bake").bake = True
sub = col.row()
- sub.enabled = (cache.is_frame_skip or cache.is_outdated) and enabled
+ sub.enabled = enabled
sub.operator("ptcache.bake", text="Calculate To Frame").bake = False
sub = col.column()
@@ -310,8 +310,10 @@ def basic_force_field_settings_ui(self, field):
else:
col.prop(field, "flow")
- col.prop(field, "apply_to_location", text="Affect Location")
- col.prop(field, "apply_to_rotation", text="Affect Rotation")
+ sub = col.column(heading="Affect")
+
+ sub.prop(field, "apply_to_location", text="Location")
+ sub.prop(field, "apply_to_rotation", text="Rotation")
col = flow.column()
sub = col.column(align=True)
@@ -336,26 +338,29 @@ def basic_force_field_falloff_ui(self, field):
if not field or field.type == 'NONE':
return
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
-
- col = flow.column()
+ col = layout.column()
col.prop(field, "z_direction")
col.prop(field, "falloff_power", text="Power")
- col = flow.column()
- col.prop(field, "use_min_distance", text="Use Minimum")
-
- sub = col.column(align=True)
+ col = layout.column(align=False, heading="Min Distance")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(field, "use_min_distance", text="")
+ sub = sub.row(align=True)
sub.active = field.use_min_distance
- sub.prop(field, "distance_min", text="Min Distance")
-
- col = flow.column()
- col.prop(field, "use_max_distance", text="Use Maximum")
-
- sub = col.column(align=True)
+ sub.prop(field, "distance_min", text="")
+ row.prop_decorator(field, "distance_min")
+
+ col = layout.column(align=False, heading="Max Distance")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(field, "use_max_distance", text="")
+ sub = sub.row(align=True)
sub.active = field.use_max_distance
- sub.prop(field, "distance_max", text="Max Distance")
-
+ sub.prop(field, "distance_max", text="")
+ row.prop_decorator(field, "distance_max")
classes = (
PHYSICS_PT_add,
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 00dc068a51a..d1ff1dc9f5e 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -123,7 +123,7 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel):
col.prop(field, "use_object_coords")
col.prop(field, "use_2d_force")
- elif field.type == 'SMOKE_FLOW':
+ elif field.type == 'FLUID_FLOW':
col = flow.column()
col.prop(field, "strength")
col.prop(field, "flow")
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 28c9895f53b..4b0791a63e6 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -19,20 +19,18 @@
# <pep8 compliant>
import bpy
-from bpy.types import (
- Panel,
- Menu,
-)
+from bpy.types import Menu, Panel
+from bl_ui.utils import PresetPanel
from .properties_physics_common import (
effector_weights_ui,
)
-class FLUID_MT_presets(Menu):
+class FLUID_PT_presets(PresetPanel, Panel):
bl_label = "Fluid Presets"
preset_subdir = "fluid"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "fluid.preset_add"
class PhysicButtonsPanel:
@@ -162,9 +160,6 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
if md.fluid_type == 'DOMAIN':
domain = md.domain_settings
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = not self.check_domain_has_unbaked_guide(domain)
-
is_baking_any = domain.is_cache_baking_any
has_baked_data = domain.has_cache_baked_data
@@ -176,16 +171,17 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
flow.enabled = not is_baking_any and not has_baked_data
col = flow.column()
+ col.enabled = not domain.has_cache_baked_guide
col.prop(domain, "resolution_max", text="Resolution Divisions")
col.prop(domain, "time_scale", text="Time Scale")
col.prop(domain, "cfl_condition", text="CFL Number")
col = flow.column()
col.prop(domain, "use_adaptive_timesteps")
- col1 = col.column(align=True)
- col1.enabled = domain.use_adaptive_timesteps
- col1.prop(domain, "timesteps_max", text="Timesteps Maximum")
- col1.prop(domain, "timesteps_min", text="Minimum")
+ sub = col.column(align=True)
+ sub.active = domain.use_adaptive_timesteps
+ sub.prop(domain, "timesteps_max", text="Timesteps Maximum")
+ sub.prop(domain, "timesteps_min", text="Minimum")
col.separator()
@@ -196,12 +192,25 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
sub.prop(domain, "gravity", text="Using Scene Gravity", icon='SCENE_DATA')
else:
col.prop(domain, "gravity", text="Gravity")
- # TODO (sebbas): Clipping var useful for manta openvdb caching?
- # col.prop(domain, "clipping", text="Empty Space")
+
+ col = flow.column()
+ if PhysicButtonsPanel.poll_gas_domain(context):
+ col.prop(domain, "clipping", text="Empty Space")
+ col.prop(domain, "delete_in_obstacle", text="Delete In Obstacle")
if domain.cache_type == 'MODULAR':
col.separator()
+
+ # Deactivate bake operator if guides are enabled but not baked yet.
+ note_flag = True
+ if self.check_domain_has_unbaked_guide(domain) and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Guides: Bake Guides or disable them")
+
split = layout.split()
+ split.enabled = note_flag
bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end)
if domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete:
@@ -227,8 +236,8 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
col = grid.column()
col.prop(flow, "flow_behavior", expand=False)
- if flow.flow_behavior in {'INFLOW'}:
- col.prop(flow, "use_inflow", text="Use Inflow")
+ if flow.flow_behavior in {'INFLOW', 'OUTFLOW'}:
+ col.prop(flow, "use_inflow", text="Use Flow")
col.prop(flow, "subframes", text="Sampling Substeps")
@@ -256,16 +265,19 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
row = layout.row()
row.prop(effector_settings, "effector_type")
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ grid = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
+ col = grid.column()
+ col.prop(effector_settings, "subframes", text="Sampling Substeps")
+ col.prop(effector_settings, "surface_distance", text="Surface Thickness")
+ col = grid.column()
+
+ col.prop(effector_settings, "use_effector", text="Use Effector")
col.prop(effector_settings, "use_plane_init", text="Is Planar")
- col.prop(effector_settings, "surface_distance", text="Surface Thickness")
if effector_settings.effector_type == 'GUIDE':
col.prop(effector_settings, "velocity_factor", text="Velocity Factor")
- col = flow.column()
col.prop(effector_settings, "guide_mode", text="Guide Mode")
@@ -309,8 +321,8 @@ class PHYSICS_PT_borders(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
- bl_label = "Smoke"
- bl_parent_id = 'PHYSICS_PT_settings'
+ bl_label = "Gas"
+ bl_parent_id = 'PHYSICS_PT_fluid'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
@@ -354,10 +366,13 @@ class PHYSICS_PT_smoke_dissolve(PhysicButtonsPanel, Panel):
return (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
- md = context.fluid
- domain = md.domain_settings
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
- self.layout.prop(domain, "use_dissolve_smoke", text="")
+ is_baking_any = domain.is_cache_baking_any
+
+ self.layout.enabled = not is_baking_any
+ self.layout.prop(md, "use_dissolve_smoke", text="")
def draw(self, context):
layout = self.layout
@@ -383,7 +398,7 @@ class PHYSICS_PT_smoke_dissolve(PhysicButtonsPanel, Panel):
class PHYSICS_PT_fire(PhysicButtonsPanel, Panel):
bl_label = "Fire"
- bl_parent_id = 'PHYSICS_PT_settings'
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -409,20 +424,22 @@ class PHYSICS_PT_fire(PhysicButtonsPanel, Panel):
col = flow.column()
col.prop(domain, "burning_rate", text="Reaction Speed")
- col = flow.column(align=True)
- col.prop(domain, "flame_smoke", text="Flame Smoke")
- col.prop(domain, "flame_vorticity", text="Vorticity")
+ row = col.row()
+ sub = row.column(align=True)
+ sub.prop(domain, "flame_smoke", text="Flame Smoke")
+ sub.prop(domain, "flame_vorticity", text="Vorticity")
+
col = flow.column(align=True)
col.prop(domain, "flame_max_temp", text="Temperature Maximum")
col.prop(domain, "flame_ignition", text="Minimum")
- col = flow.column()
- col.prop(domain, "flame_smoke_color", text="Flame Color")
+ row = col.row()
+ row.prop(domain, "flame_smoke_color", text="Flame Color")
class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
bl_label = "Liquid"
- bl_parent_id = 'PHYSICS_PT_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ bl_parent_id = 'PHYSICS_PT_fluid'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -433,6 +450,11 @@ class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
def draw_header(self, context):
md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+
+ is_baking_any = domain.is_cache_baking_any
+
+ self.layout.enabled = not is_baking_any
self.layout.prop(md, "use_flip_particles", text="")
def draw(self, context):
@@ -445,32 +467,32 @@ class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
is_baking_any = domain.is_cache_baking_any
has_baked_data = domain.has_cache_baked_data
+ layout.enabled = not is_baking_any and not has_baked_data
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
- col0 = col.column()
- col0.enabled = not is_baking_any and not has_baked_data
- col0.prop(domain, "simulation_method", expand=False)
- col0.prop(domain, "flip_ratio", text="FLIP Ratio")
- col0.prop(domain, "particle_radius", text="Particle Radius")
-
- col1 = flow.column(align=True)
- col1.enabled = not is_baking_any and not has_baked_data
- col1.prop(domain, "particle_max", text="Particles Maximum")
- col1.prop(domain, "particle_min", text="Minimum")
-
- col1 = flow.column()
- col1.enabled = not is_baking_any and not has_baked_data
- col1.prop(domain, "particle_number", text="Particle Sampling")
- col1.prop(domain, "particle_band_width", text="Narrow Band Width")
- col1.prop(domain, "particle_randomness", text="Particle Randomness")
-
- col2 = flow.column()
- col2.enabled = not is_baking_any and not has_baked_data
- col2.prop(domain, "use_fractions", text="Fractional Obstacles")
- col3 = col2.column()
- col3.enabled = domain.use_fractions and col2.enabled
- col3.prop(domain, "fractions_threshold", text="Obstacle-Fluid Threshold")
+ col.prop(domain, "simulation_method", expand=False)
+ col.prop(domain, "flip_ratio", text="FLIP Ratio")
+ col = col.column(align=True)
+ col.prop(domain, "particle_radius", text="Particle Radius")
+ col.prop(domain, "particle_number", text="Sampling")
+ col.prop(domain, "particle_randomness", text="Randomness")
+
+ col = flow.column()
+ col = col.column(align=True)
+ col.prop(domain, "particle_max", text="Particles Maximum")
+ col.prop(domain, "particle_min", text="Minimum")
+
+ col.separator()
+
+ col = col.column()
+ col.prop(domain, "particle_band_width", text="Narrow Band Width")
+
+ col = col.column()
+ col.prop(domain, "use_fractions", text="Fractional Obstacles")
+ sub = col.column()
+ sub.active = domain.use_fractions
+ sub.prop(domain, "fractions_threshold", text="Obstacle-Fluid Threshold")
class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel):
@@ -518,7 +540,7 @@ class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel):
class PHYSICS_PT_flow_initial_velocity(PhysicButtonsPanel, Panel):
bl_label = "Initial Velocity"
bl_parent_id = 'PHYSICS_PT_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -609,15 +631,21 @@ class PHYSICS_PT_flow_texture(PhysicButtonsPanel, Panel):
class PHYSICS_PT_adaptive_domain(PhysicButtonsPanel, Panel):
bl_label = "Adaptive Domain"
- bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_parent_id = 'PHYSICS_PT_settings'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
if not PhysicButtonsPanel.poll_gas_domain(context):
return False
+ md = context.fluid
+ domain = md.domain_settings
+ # Effector guides require a fixed domain size
+ if domain.use_guide and domain.guide_source == 'EFFECTOR':
+ return False
+
return (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
@@ -655,7 +683,7 @@ class PHYSICS_PT_adaptive_domain(PhysicButtonsPanel, Panel):
class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
bl_label = "Noise"
- bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -678,9 +706,7 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
layout.use_property_split = True
domain = context.fluid.domain_settings
-
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = domain.use_noise and not self.check_domain_has_unbaked_guide(domain)
+ layout.active = domain.use_noise
is_baking_any = domain.is_cache_baking_any
has_baked_noise = domain.has_cache_baked_noise
@@ -701,8 +727,16 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+ # Deactivate bake operator if data has not been baked yet.
+ note_flag = True
+ if domain.use_noise and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Data: Bake Data first")
+
split = layout.split()
- split.enabled = domain.has_cache_baked_data
+ split.enabled = domain.has_cache_baked_data and note_flag
bake_incomplete = (domain.cache_frame_pause_noise < domain.cache_frame_end)
if domain.has_cache_baked_noise and not domain.is_cache_baking_noise and bake_incomplete:
@@ -721,7 +755,7 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
bl_label = "Mesh"
- bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -744,9 +778,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
layout.use_property_split = True
domain = context.fluid.domain_settings
-
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = domain.use_mesh and not self.check_domain_has_unbaked_guide(domain)
+ layout.active = domain.use_mesh
is_baking_any = domain.is_cache_baking_any
has_baked_mesh = domain.has_cache_baked_mesh
@@ -780,8 +812,16 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+ # Deactivate bake operator if data has not been baked yet.
+ note_flag = True
+ if domain.use_mesh and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Data: Bake Data first")
+
split = layout.split()
- split.enabled = domain.has_cache_baked_data
+ split.enabled = domain.has_cache_baked_data and note_flag
bake_incomplete = (domain.cache_frame_pause_mesh < domain.cache_frame_end)
if domain.has_cache_baked_mesh and not domain.is_cache_baking_mesh and bake_incomplete:
@@ -800,9 +840,9 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
bl_label = "Particles"
- bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -817,9 +857,6 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = not self.check_domain_has_unbaked_guide(domain)
-
is_baking_any = domain.is_cache_baking_any
has_baked_particles = domain.has_cache_baked_particles
using_particles = domain.use_spray_particles or domain.use_foam_particles or domain.use_bubble_particles
@@ -829,36 +866,37 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
sndparticle_combined_export = domain.sndparticle_combined_export
col = flow.column()
- col.enabled = sndparticle_combined_export in {'OFF', 'FOAM + BUBBLES'}
- col.prop(domain, "use_spray_particles", text="Spray")
- col = flow.column()
- col.enabled = sndparticle_combined_export in {'OFF', 'SPRAY + BUBBLES'}
- col.prop(domain, "use_foam_particles", text="Foam")
- col = flow.column()
- col.enabled = sndparticle_combined_export in {'OFF', 'SPRAY + FOAM'}
- col.prop(domain, "use_bubble_particles", text="Bubbles")
+ row = col.row()
+ row.enabled = sndparticle_combined_export in {'OFF', 'FOAM + BUBBLES'}
+ row.prop(domain, "use_spray_particles", text="Spray")
+ row.prop(domain, "use_foam_particles", text="Foam")
+ row.prop(domain, "use_bubble_particles", text="Bubbles")
+
+ col.separator()
+
+ col.prop(domain, "sndparticle_combined_export")
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- flow.enabled = not is_baking_any and not has_baked_particles and using_particles
+ flow.enabled = not is_baking_any and not has_baked_particles
+ flow.active = using_particles
col = flow.column()
- col.prop(domain, "sndparticle_combined_export")
col.prop(domain, "particle_scale", text="Upres Factor")
col.separator()
col = flow.column(align=True)
- col.prop(domain, "sndparticle_tau_max_wc", text="Wave Crest Potential Maximum")
- col.prop(domain, "sndparticle_tau_min_wc", text="Minimum")
+ col.prop(domain, "sndparticle_potential_max_wavecrest", text="Wave Crest Potential Maximum")
+ col.prop(domain, "sndparticle_potential_min_wavecrest", text="Minimum")
col.separator()
col = flow.column(align=True)
- col.prop(domain, "sndparticle_tau_max_ta", text="Trapped Air Potential Maximum")
- col.prop(domain, "sndparticle_tau_min_ta", text="Minimum")
+ col.prop(domain, "sndparticle_potential_max_trappedair", text="Trapped Air Potential Maximum")
+ col.prop(domain, "sndparticle_potential_min_trappedair", text="Minimum")
col.separator()
col = flow.column(align=True)
- col.prop(domain, "sndparticle_tau_max_k", text="Kinetic Energy Potential Maximum")
- col.prop(domain, "sndparticle_tau_min_k", text="Minimum")
+ col.prop(domain, "sndparticle_potential_max_energy", text="Kinetic Energy Potential Maximum")
+ col.prop(domain, "sndparticle_potential_min_energy", text="Minimum")
col.separator()
col = flow.column(align=True)
@@ -867,18 +905,18 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
col.separator()
col = flow.column(align=True)
- col.prop(domain, "sndparticle_k_wc", text="Wave Crest Particle Sampling")
- col.prop(domain, "sndparticle_k_ta", text="Trapped Air Particle Sampling")
+ col.prop(domain, "sndparticle_sampling_wavecrest", text="Wave Crest Particle Sampling")
+ col.prop(domain, "sndparticle_sampling_trappedair", text="Trapped Air Particle Sampling")
col.separator()
col = flow.column(align=True)
- col.prop(domain, "sndparticle_l_max", text="Particle Life Maximum")
- col.prop(domain, "sndparticle_l_min", text="Minimum")
+ col.prop(domain, "sndparticle_life_max", text="Particle Life Maximum")
+ col.prop(domain, "sndparticle_life_min", text="Minimum")
col.separator()
col = flow.column(align=True)
- col.prop(domain, "sndparticle_k_b", text="Bubble Buoyancy")
- col.prop(domain, "sndparticle_k_d", text="Bubble Drag")
+ col.prop(domain, "sndparticle_bubble_buoyancy", text="Bubble Buoyancy")
+ col.prop(domain, "sndparticle_bubble_drag", text="Bubble Drag")
col.separator()
col = flow.column()
@@ -887,8 +925,17 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+ # Deactivate bake operator if data has not been baked yet.
+ note_flag = True
+ if using_particles and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Data: Bake Data first")
+
split = layout.split()
split.enabled = (
+ note_flag and
domain.has_cache_baked_data and
(domain.use_spray_particles or
domain.use_bubble_particles or
@@ -913,7 +960,7 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
bl_label = "Diffusion"
- bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -925,14 +972,23 @@ class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
return (context.engine in cls.COMPAT_ENGINES)
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+ is_baking_any = domain.is_cache_baking_any
+ has_baked_any = domain.has_cache_baked_any
+ self.layout.enabled = not is_baking_any and not has_baked_any
+ self.layout.prop(md, "use_diffusion", text="")
+
+ def draw_header_preset(self, _context):
+ FLUID_PT_presets.draw_panel_header(self.layout)
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
domain = context.fluid.domain_settings
-
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = not self.check_domain_has_unbaked_guide(domain)
+ layout.active = domain.use_diffusion
is_baking_any = domain.is_cache_baking_any
has_baked_any = domain.has_cache_baked_any
@@ -941,22 +997,11 @@ class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
flow.enabled = not is_baking_any and not has_baked_any and not has_baked_data
- row = flow.row()
-
- col = row.column()
- col.label(text="Viscosity Presets:")
- col.menu("FLUID_MT_presets", text=bpy.types.FLUID_MT_presets.bl_label)
-
- col = row.column(align=True)
- col.operator("fluid.preset_add", text="", icon='ADD')
- col.operator("fluid.preset_add", text="", icon='REMOVE').remove_active = True
-
col = flow.column(align=True)
col.prop(domain, "viscosity_base", text="Base")
col.prop(domain, "viscosity_exponent", text="Exponent", slider=True)
col = flow.column()
- col.prop(domain, "domain_size", text="Real World Size")
col.prop(domain, "surface_tension", text="Surface Tension")
@@ -964,7 +1009,7 @@ class PHYSICS_PT_guide(PhysicButtonsPanel, Panel):
bl_label = "Guides"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -1018,7 +1063,8 @@ class PHYSICS_PT_guide(PhysicButtonsPanel, Panel):
col = split.column()
col.operator("fluid.free_guides", text="Free")
elif not domain.has_cache_baked_guide and domain.is_cache_baking_guide:
- split.operator("fluid.pause_bake", text="Pause Guides")
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking Guides - ESC to pause")
elif not domain.has_cache_baked_guide and not domain.is_cache_baking_guide:
split.operator("fluid.bake_guides", text="Bake Guides")
else:
@@ -1072,7 +1118,10 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
is_baking_any = domain.is_cache_baking_any
- has_baked_any = domain.has_cache_baked_any
+ has_baked_data = domain.has_cache_baked_data
+ has_baked_noise = domain.has_cache_baked_noise
+ has_baked_mesh = domain.has_cache_baked_mesh
+ has_baked_particles = domain.has_cache_baked_particles
col = layout.column()
col.prop(domain, "cache_directory", text="")
@@ -1086,29 +1135,37 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
col.prop(domain, "cache_type", expand=False)
col.enabled = not is_baking_any
- col = flow.column(align=True)
col.separator()
+ row = col.row()
+ col = row.column(align=True)
col.prop(domain, "cache_frame_start", text="Frame Start")
col.prop(domain, "cache_frame_end", text="End")
- col.enabled = not is_baking_any
+ row.enabled = not is_baking_any
col.separator()
col = flow.column()
- col.enabled = not is_baking_any and not has_baked_any
- col.prop(domain, "cache_data_format", text="Data File Format")
+ row = col.row()
+ row.enabled = not is_baking_any and not has_baked_data
+ row.prop(domain, "cache_data_format", text="Data File Format")
if md.domain_settings.domain_type in {'GAS'}:
if domain.use_noise:
- col.prop(domain, "cache_noise_format", text="Noise File Format")
+ row = col.row()
+ row.enabled = not is_baking_any and not has_baked_noise
+ row.prop(domain, "cache_noise_format", text="Noise File Format")
if md.domain_settings.domain_type in {'LIQUID'}:
# File format for all particle systemes (FLIP and secondary)
- col.prop(domain, "cache_particle_format", text="Particle File Format")
+ row = col.row()
+ row.enabled = not is_baking_any and not has_baked_particles and not has_baked_data
+ row.prop(domain, "cache_particle_format", text="Particle File Format")
if domain.use_mesh:
- col.prop(domain, "cache_mesh_format", text="Mesh File Format")
+ row = col.row()
+ row.enabled = not is_baking_any and not has_baked_mesh
+ row.prop(domain, "cache_mesh_format", text="Mesh File Format")
if domain.cache_type == 'FINAL':
@@ -1132,7 +1189,8 @@ class PHYSICS_PT_export(PhysicButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- if not PhysicButtonsPanel.poll_fluid_domain(context):
+ # Only show the advanced panel to advanced users who know Mantaflow's birthday :)
+ if not PhysicButtonsPanel.poll_fluid_domain(context) or bpy.app.debug_value != 3001:
return False
return (context.engine in cls.COMPAT_ENGINES)
@@ -1186,35 +1244,31 @@ class PHYSICS_PT_viewport_display(PhysicButtonsPanel, Panel):
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
domain = context.fluid.domain_settings
-
- col = flow.column()
- col.prop(domain, "display_thickness")
-
- col.separator()
-
- col.prop(domain, "slice_method", text="Slicing")
-
slice_method = domain.slice_method
axis_slice_method = domain.axis_slice_method
do_axis_slicing = (slice_method == 'AXIS_ALIGNED')
do_full_slicing = (axis_slice_method == 'FULL')
- col = col.column()
- col.enabled = do_axis_slicing
- col.prop(domain, "axis_slice_method")
+ col = flow.column(align=False)
+ col.prop(domain, "display_thickness")
+ col.prop(domain, "display_interpolation")
+ col.separator()
col = flow.column()
- sub = col.column()
- sub.enabled = not do_full_slicing and do_axis_slicing
- sub.prop(domain, "slice_axis")
- sub.prop(domain, "slice_depth")
+ col.prop(domain, "slice_method", text="Slicing")
- row = col.row()
- row.enabled = do_full_slicing or not do_axis_slicing
- row.prop(domain, "slice_per_voxel")
+ col = col.column()
+ col.active = do_axis_slicing
+ col.prop(domain, "axis_slice_method")
- col.prop(domain, "display_interpolation")
+ if not do_full_slicing and do_axis_slicing:
+ col.prop(domain, "slice_axis")
+ col.prop(domain, "slice_depth")
+
+ col = col.column()
+ col.active = do_full_slicing or not do_axis_slicing
+ col.prop(domain, "slice_per_voxel")
class PHYSICS_PT_viewport_display_color(PhysicButtonsPanel, Panel):
@@ -1237,8 +1291,7 @@ class PHYSICS_PT_viewport_display_color(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
col = layout.column()
- col.enabled = domain.use_color_ramp
-
+ col.active = domain.use_color_ramp
col.prop(domain, "coba_field")
col.use_property_split = False
@@ -1269,33 +1322,33 @@ class PHYSICS_PT_viewport_display_debug(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
col = flow.column()
- col.enabled = domain.show_velocity
+ col.active = domain.show_velocity
col.prop(domain, "vector_display_type", text="Display As")
col.prop(domain, "vector_scale")
classes = (
- FLUID_MT_presets,
+ FLUID_PT_presets,
PHYSICS_PT_fluid,
PHYSICS_PT_settings,
PHYSICS_PT_borders,
+ PHYSICS_PT_adaptive_domain,
PHYSICS_PT_smoke,
PHYSICS_PT_smoke_dissolve,
+ PHYSICS_PT_noise,
PHYSICS_PT_fire,
PHYSICS_PT_liquid,
- PHYSICS_PT_flow_source,
- PHYSICS_PT_flow_initial_velocity,
- PHYSICS_PT_flow_texture,
- PHYSICS_PT_adaptive_domain,
- PHYSICS_PT_noise,
- PHYSICS_PT_mesh,
- PHYSICS_PT_particles,
PHYSICS_PT_diffusion,
+ PHYSICS_PT_particles,
+ PHYSICS_PT_mesh,
PHYSICS_PT_guide,
PHYSICS_PT_collections,
PHYSICS_PT_cache,
PHYSICS_PT_export,
PHYSICS_PT_field_weights,
+ PHYSICS_PT_flow_source,
+ PHYSICS_PT_flow_initial_velocity,
+ PHYSICS_PT_flow_texture,
PHYSICS_PT_viewport_display,
PHYSICS_PT_viewport_display_color,
PHYSICS_PT_viewport_display_debug,
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 6a89fb007cf..c5c75f95937 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -297,7 +297,7 @@ class RENDER_PT_eevee_volumetric_shadows(RenderButtonsPanel, Panel):
props = scene.eevee
layout.active = props.use_volumetric_shadows
- layout.prop(props, "volumetric_shadow_samples", text="Shadow Samples")
+ layout.prop(props, "volumetric_shadow_samples", text="Samples")
class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel):
@@ -478,39 +478,47 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
scene = context.scene
rd = scene.render
+ props = scene.eevee
col = layout.column()
col.prop(rd, "filter_size")
col.prop(rd, "film_transparent", text="Transparent")
+ col = layout.column(align=False, heading="Overscan")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(props, "use_overscan", text="")
+ sub = sub.row(align=True)
+ sub.active = props.use_overscan
+ sub.prop(props, "overscan_size", text="")
+ row.prop_decorator(props, "overscan_size")
+
-class RENDER_PT_eevee_film_overscan(RenderButtonsPanel, Panel):
- bl_label = "Overscan"
- bl_parent_id = "RENDER_PT_eevee_film"
+class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
+ bl_label = "Hair"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE'}
- def draw_header(self, context):
-
- scene = context.scene
- props = scene.eevee
-
- self.layout.prop(props, "use_overscan", text="")
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- layout.use_property_split = True
scene = context.scene
- props = scene.eevee
+ rd = scene.render
- layout.active = props.use_overscan
- layout.prop(props, "overscan_size", text="Size")
+ layout.use_property_split = True
+ layout.prop(rd, "hair_type", expand=True)
+ layout.prop(rd, "hair_subdiv")
-class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
- bl_label = "Hair"
+
+class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel):
+ bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -523,8 +531,28 @@ class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
layout.use_property_split = True
- layout.prop(rd, "hair_type", expand=True)
- layout.prop(rd, "hair_subdiv")
+ layout.prop(rd, "use_high_quality_normals")
+
+
+class RENDER_PT_gpencil(RenderButtonsPanel, Panel):
+ bl_label = "Grease Pencil"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ scene = context.scene
+ props = scene.grease_pencil_settings
+
+ col = layout.column()
+ col.prop(props, "antialias_threshold")
+
class RENDER_PT_opengl_sampling(RenderButtonsPanel, Panel):
@@ -545,7 +573,7 @@ class RENDER_PT_opengl_sampling(RenderButtonsPanel, Panel):
col = layout.column()
col.prop(props, "render_aa", text="Render")
- col.prop(props, "viewport_aa", text="Viewport Render")
+ col.prop(props, "viewport_aa", text="Viewport")
class RENDER_PT_opengl_film(RenderButtonsPanel, Panel):
@@ -632,9 +660,6 @@ class RENDER_PT_simplify_viewport(RenderButtonsPanel, Panel):
col = flow.column()
col.prop(rd, "simplify_child_particles", text="Max Child Particles")
- col = flow.column()
- col.prop(rd, "use_simplify_smoke_highres", text="High-resolution Smoke")
-
class RENDER_PT_simplify_render(RenderButtonsPanel, Panel):
bl_label = "Render"
@@ -979,12 +1004,14 @@ classes = (
RENDER_PT_eevee_volumetric,
RENDER_PT_eevee_volumetric_lighting,
RENDER_PT_eevee_volumetric_shadows,
+ RENDER_PT_eevee_performance,
RENDER_PT_eevee_hair,
RENDER_PT_eevee_shadows,
RENDER_PT_eevee_indirect_lighting,
RENDER_PT_eevee_indirect_lighting_display,
RENDER_PT_eevee_film,
- RENDER_PT_eevee_film_overscan,
+
+ RENDER_PT_gpencil,
RENDER_PT_opengl_sampling,
RENDER_PT_opengl_lighting,
RENDER_PT_opengl_color,
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 40a630ff834..5af8bc2aaa7 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -163,6 +163,8 @@ class TEXTURE_PT_node(TextureButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
node = context.texture_node
ntree = node.id_data
layout.template_node_view(ntree, node, None)
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 121b8f2f401..3645f0dc2f2 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -40,17 +40,12 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- layout.use_property_split = True
-
scene = context.scene
rd = scene.render
layer = context.view_layer
- col = flow.column()
+ col = layout.column()
col.prop(layer, "use", text="Use for Rendering")
- col = flow.column()
col.prop(rd, "use_single_layer", text="Render Single Layer")
@@ -59,33 +54,94 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel):
COMPAT_ENGINES = {'BLENDER_EEVEE'}
def draw(self, context):
- layout = self.layout
+ pass
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel):
+ bl_label = "Data"
+ bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes"
+
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ scene = context.scene
+ rd = scene.render
view_layer = context.view_layer
- col = flow.column()
+ col = layout.column()
col.prop(view_layer, "use_pass_combined")
- col = flow.column()
col.prop(view_layer, "use_pass_z")
- col = flow.column()
col.prop(view_layer, "use_pass_mist")
- col = flow.column()
col.prop(view_layer, "use_pass_normal")
- col = flow.column()
- col.prop(view_layer, "use_pass_ambient_occlusion")
- col = flow.column()
- col.prop(view_layer, "use_pass_subsurface_direct", text="Subsurface Direct")
- col = flow.column()
- col.prop(view_layer, "use_pass_subsurface_color", text="Subsurface Color")
+class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel):
+ bl_label = "Light"
+ bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ view_layer = context.view_layer
+ view_layer_eevee = view_layer.eevee
+ scene = context.scene
+ scene_eevee = scene.eevee
+
+ col = layout.column(heading="Diffuse", align=True)
+ col.prop(view_layer, "use_pass_diffuse_direct", text="Light")
+ col.prop(view_layer, "use_pass_diffuse_color", text="Color")
+
+ col = layout.column(heading="Specular", align=True)
+ col.prop(view_layer, "use_pass_glossy_direct", text="Light")
+ col.prop(view_layer, "use_pass_glossy_color", text="Color")
+
+ col = layout.column(heading="Volume", align=True)
+ col.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance")
+ col.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter")
+
+ col = layout.column(heading="Other", align=True)
+ col.prop(view_layer, "use_pass_emit", text="Emission")
+ col.prop(view_layer, "use_pass_environment")
+ col.prop(view_layer, "use_pass_shadow")
+ row = col.row()
+ row.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion")
+ row.active = scene_eevee.use_gtao
+
+
+class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel):
+ bl_label = "Effects"
+ bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ view_layer = context.view_layer
+ view_layer_eevee = view_layer.eevee
+ scene = context.scene
+ scene_eevee = scene.eevee
+
+ col = layout.column()
+ col.prop(view_layer_eevee, "use_pass_bloom", text="Bloom")
+ col.active = scene_eevee.use_bloom
+
classes = (
VIEWLAYER_PT_layer,
VIEWLAYER_PT_eevee_layer_passes,
+ VIEWLAYER_PT_eevee_layer_passes_data,
+ VIEWLAYER_PT_eevee_layer_passes_light,
+ VIEWLAYER_PT_eevee_layer_passes_effects,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_workspace.py b/release/scripts/startup/bl_ui/properties_workspace.py
index 322cdee0922..8af30b5c002 100644
--- a/release/scripts/startup/bl_ui/properties_workspace.py
+++ b/release/scripts/startup/bl_ui/properties_workspace.py
@@ -77,8 +77,6 @@ class WORKSPACE_PT_addons(WorkSpaceButtonsPanel, Panel):
if module is None:
continue
info = addon_utils.module_bl_info(module)
- if not info["use_owner"]:
- continue
is_enabled = module_name in owner_ids
row = col.row()
row.alignment = 'LEFT'
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index a6a58ec4e2b..4a9f35ee59a 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -105,6 +105,8 @@ class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel):
layout.prop(world, "use_nodes", icon='NODETREE')
layout.separator()
+ layout.use_property_split = True
+
if world.use_nodes:
ntree = world.node_tree
node = ntree.get_output_node('EEVEE')
@@ -139,6 +141,8 @@ class EEVEE_WORLD_PT_volume(WorldButtonsPanel, Panel):
ntree = world.node_tree
node = ntree.get_output_node('EEVEE')
+ layout.use_property_split = True
+
if node:
input = find_node_input(node, 'Volume')
if input:
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index f93629a4f03..5b6cc6609e0 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -918,6 +918,10 @@ class CLIP_PT_tracking_lens(Panel):
col = layout.column(align=True)
col.prop(camera, "division_k1")
col.prop(camera, "division_k2")
+ elif camera.distortion_model == 'NUKE':
+ col = layout.column(align=True)
+ col.prop(camera, "nuke_k1")
+ col.prop(camera, "nuke_k2")
class CLIP_PT_marker(CLIP_PT_tracking_panel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index a09e263fd87..3f8c41e4f21 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -26,6 +26,7 @@ from bpy.types import (
)
from bl_ui.properties_grease_pencil_common import (
+ GreasePencilLayerMasksPanel,
GreasePencilLayerAdjustmentsPanel,
GreasePencilLayerRelationsPanel,
GreasePencilLayerDisplayPanel,
@@ -125,6 +126,12 @@ class DopesheetFilterPopoverBase:
flow.prop(dopesheet, "show_lattices", text="Lattices")
if bpy.data.metaballs:
flow.prop(dopesheet, "show_metaballs", text="Metaballs")
+ if hasattr(bpy.data, "hairs") and bpy.data.hairs:
+ flow.prop(dopesheet, "show_hairs", text="Hairs")
+ if hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds:
+ flow.prop(dopesheet, "show_pointclouds", text="Point Clouds")
+ if bpy.data.volumes:
+ flow.prop(dopesheet, "show_volumes", text="Volumes")
# data types
flow.prop(dopesheet, "show_worlds", text="Worlds")
@@ -251,15 +258,25 @@ class DOPESHEET_HT_editor_buttons(Header):
# Layer management
if st.mode == 'GPENCIL':
- row = layout.row(align=True)
- row.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
- row.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+ ob = context.active_object
+ selected = st.dopesheet.show_only_selected
+ enable_but = selected and ob is not None and ob.type == 'GPENCIL'
row = layout.row(align=True)
+ row.enabled = enable_but
row.operator("gpencil.layer_add", icon='ADD', text="")
row.operator("gpencil.layer_remove", icon='REMOVE', text="")
+ row.menu("GPENCIL_MT_layer_context_menu", icon='DOWNARROW_HLT', text="")
- layout.separator_spacer()
+ row = layout.row(align=True)
+ row.enabled = enable_but
+ row.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
+ row.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+
+ row = layout.row(align=True)
+ row.enabled = enable_but
+ row.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
+ row.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
layout.separator_spacer()
@@ -269,15 +286,8 @@ class DOPESHEET_HT_editor_buttons(Header):
dopesheet_filter(layout, context)
elif st.mode == 'GPENCIL':
row = layout.row(align=True)
- row.prop(st.dopesheet, "show_gpencil_3d_only", text="Active Only")
-
- if st.dopesheet.show_gpencil_3d_only:
- row = layout.row(align=True)
- row.prop(st.dopesheet, "show_only_selected", text="")
- row.prop(st.dopesheet, "show_hidden", text="")
-
- row = layout.row(align=True)
- row.prop(st.dopesheet, "filter_text", text="")
+ row.prop(st.dopesheet, "show_only_selected", text="")
+ row.prop(st.dopesheet, "show_hidden", text="")
layout.popover(
panel="DOPESHEET_PT_filters",
@@ -497,6 +507,7 @@ class DOPESHEET_MT_key(Menu):
layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type")
layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
+ layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode")
layout.separator()
layout.operator("action.clean").channels = False
@@ -599,6 +610,7 @@ class DOPESHEET_MT_context_menu(Menu):
layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type")
layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
+ layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode")
layout.separator()
@@ -616,7 +628,7 @@ class DOPESHEET_MT_context_menu(Menu):
class DOPESHEET_MT_channel_context_menu(Menu):
bl_label = "Dope Sheet Channel Context Menu"
- def draw(self, _context):
+ def draw(self, context):
layout = self.layout
layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE'
@@ -631,7 +643,12 @@ class DOPESHEET_MT_channel_context_menu(Menu):
layout.separator()
layout.operator("anim.channels_editable_toggle")
- layout.operator_menu_enum("action.extrapolation_type", "type", text="Extrapolation Mode")
+
+ if bpy.ops.graph.extrapolation_type.poll(context.copy()):
+ operator = "graph.extrapolation_type"
+ else:
+ operator = "action.extrapolation_type"
+ layout.operator_menu_enum(operator, "type", text="Extrapolation Mode")
layout.separator()
layout.operator("anim.channels_expand")
@@ -699,6 +716,15 @@ class DOPESHEET_PT_gpencil_mode(LayersDopeSheetPanel, Panel):
row = layout.row(align=True)
row.prop(gpl, "opacity", text="Opacity", slider=True)
+ row = layout.row(align=True)
+ row.prop(gpl, "use_lights")
+
+
+class DOPESHEET_PT_gpencil_layer_masks(LayersDopeSheetPanel, GreasePencilLayerMasksPanel, Panel):
+ bl_label = "Masks"
+ bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
+ bl_options = {'DEFAULT_CLOSED'}
+
class DOPESHEET_PT_gpencil_layer_adjustments(LayersDopeSheetPanel, GreasePencilLayerAdjustmentsPanel, Panel):
bl_label = "Adjustments"
@@ -736,6 +762,7 @@ classes = (
DOPESHEET_MT_snap_pie,
DOPESHEET_PT_filters,
DOPESHEET_PT_gpencil_mode,
+ DOPESHEET_PT_gpencil_layer_masks,
DOPESHEET_PT_gpencil_layer_adjustments,
DOPESHEET_PT_gpencil_layer_relations,
DOPESHEET_PT_gpencil_layer_display,
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 8dd0eaf5445..9a39d840149 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -20,6 +20,7 @@
from bpy.types import Header, Panel, Menu, UIList
+
class FILEBROWSER_HT_header(Header):
bl_space_type = 'FILE_BROWSER'
@@ -31,8 +32,7 @@ class FILEBROWSER_HT_header(Header):
if st.active_operator is None:
layout.template_header()
- layout.menu("FILEBROWSER_MT_view")
- layout.menu("FILEBROWSER_MT_select")
+ FILEBROWSER_MT_editor_menus.draw_collapsible(context, layout)
# can be None when save/reload with a file selector open
@@ -66,8 +66,9 @@ class FILEBROWSER_PT_display(Panel):
if params.display_type == 'THUMBNAIL':
layout.prop(params, "display_size", text="Size")
else:
- layout.prop(params, "show_details_size", text="Size")
- layout.prop(params, "show_details_datetime", text="Date")
+ col = layout.column(heading="Columns", align=True)
+ col.prop(params, "show_details_size", text="Size")
+ col.prop(params, "show_details_datetime", text="Date")
layout.prop(params, "recursion_level", text="Recursions")
@@ -137,6 +138,9 @@ class FILEBROWSER_PT_filter(Panel):
row = col.row()
row.label(icon='FILE_TEXT')
row.prop(params, "use_filter_text", text="Text Files", toggle=0)
+ row = col.row()
+ row.label(icon='FILE_VOLUME')
+ row.prop(params, "use_filter_volume", text="Volume Files", toggle=0)
col.separator()
@@ -148,7 +152,12 @@ class FILEBROWSER_PT_filter(Panel):
if params.use_filter_blendid:
row = col.row()
row.label(icon='BLANK1') # Indentation
- row.prop(params, "filter_id_category", text="")
+
+ sub = row.column(align=True)
+ filter_id = params.filter_id
+ for identifier in dir(filter_id):
+ if identifier.startswith("category_"):
+ sub.prop(filter_id, identifier, toggle=True)
col.separator()
@@ -275,7 +284,7 @@ class FILEBROWSER_PT_bookmarks_recents(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'TOOLS'
bl_category = "Bookmarks"
- bl_label = "Recents"
+ bl_label = "Recent"
@classmethod
def poll(cls, context):
@@ -314,8 +323,11 @@ class FILEBROWSER_PT_advanced_filter(Panel):
layout.prop(params, "use_filter_blendid")
if params.use_filter_blendid:
layout.separator()
- col = layout.column()
- col.prop(params, "filter_id")
+ col = layout.column(align=True)
+ filter_id = params.filter_id
+ for identifier in dir(filter_id):
+ if identifier.startswith("filter_"):
+ col.prop(filter_id, identifier, toggle=True)
class FILEBROWSER_PT_directory_path(Panel):
@@ -399,6 +411,17 @@ class FILEBROWSER_PT_directory_path(Panel):
).region_type = 'TOOL_PROPS'
+class FILEBROWSER_MT_editor_menus(Menu):
+ bl_idname = "FILEBROWSER_MT_editor_menus"
+ bl_label = ""
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.menu("FILEBROWSER_MT_view")
+ layout.menu("FILEBROWSER_MT_select")
+
+
class FILEBROWSER_MT_view(Menu):
bl_label = "View"
@@ -490,6 +513,7 @@ classes = (
FILEBROWSER_PT_bookmarks_recents,
FILEBROWSER_PT_advanced_filter,
FILEBROWSER_PT_directory_path,
+ FILEBROWSER_MT_editor_menus,
FILEBROWSER_MT_view,
FILEBROWSER_MT_select,
FILEBROWSER_MT_context_menu,
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 2e853a287ea..c251d55714f 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -171,14 +171,10 @@ class GRAPH_MT_select(Menu):
layout.separator()
- props = layout.operator("graph.select_box")
- props.axis_range = False
- props.include_handles = False
+ layout.operator("graph.select_box")
props = layout.operator("graph.select_box", text="Box Select (Axis Range)")
props.axis_range = True
- props.include_handles = False
props = layout.operator("graph.select_box", text="Box Select (Include Handles)")
- props.axis_range = False
props.include_handles = True
layout.operator("graph.select_circle")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index c6f490f9d26..bc4665209aa 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -116,7 +116,7 @@ class IMAGE_MT_view(Menu):
if show_uvedit:
layout.operator("image.view_selected", text="Frame Selected")
- layout.operator("image.view_all", text="Frame All")
+ layout.operator("image.view_all")
layout.operator("image.view_all", text="Frame All Fit").fit_view = True
layout.operator("image.view_center_cursor", text="Center View to Cursor")
@@ -238,6 +238,11 @@ class IMAGE_MT_image(Menu):
layout.separator()
layout.operator("image.pack", text="Pack")
+ if ima:
+ layout.separator()
+ layout.operator("palette.extract_from_image", text="Extract Palette")
+ layout.operator("gpencil.image_to_grease_pencil", text="Generate Grease Pencil")
+
class IMAGE_MT_image_invert(Menu):
bl_label = "Invert"
@@ -379,6 +384,10 @@ class IMAGE_MT_uvs(Menu):
layout.separator()
+ layout.operator("uv.reset")
+
+ layout.separator()
+
class IMAGE_MT_uvs_select_mode(Menu):
bl_label = "UV Select Mode"
@@ -698,7 +707,7 @@ class IMAGE_HT_header(Header):
layout.prop(tool_settings, "uv_select_mode", text="", expand=True)
layout.prop(uvedit, "sticky_select_mode", icon_only=True)
- MASK_MT_editor_menus.draw_collapsible(context, layout)
+ IMAGE_MT_editor_menus.draw_collapsible(context, layout)
layout.separator_spacer()
@@ -744,8 +753,8 @@ class IMAGE_HT_header(Header):
row.operator("image.play_composite", icon='PLAY')
-class MASK_MT_editor_menus(Menu):
- bl_idname = "MASK_MT_editor_menus"
+class IMAGE_MT_editor_menus(Menu):
+ bl_idname = "IMAGE_MT_editor_menus"
bl_label = ""
def draw(self, context):
@@ -950,6 +959,7 @@ class IMAGE_PT_view_display_uv_edit_overlays(Panel):
col = layout.column()
col.prop(uvedit, "show_smooth_edges", text="Smooth")
col.prop(uvedit, "show_modified_edges", text="Modified")
+ col.prop(uvedit, "uv_opacity")
class IMAGE_PT_view_display_uv_edit_overlays_stretch(Panel):
@@ -1460,7 +1470,7 @@ classes = (
IMAGE_MT_uvs_snap_pie,
IMAGE_HT_tool_header,
IMAGE_HT_header,
- MASK_MT_editor_menus,
+ IMAGE_MT_editor_menus,
IMAGE_PT_active_tool,
IMAGE_PT_mask,
IMAGE_PT_mask_layers,
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 2ce81ba8359..b5926692324 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -76,7 +76,8 @@ class NODE_HT_header(Header):
layout.separator_spacer()
- types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'GPENCIL'}
+ types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META',
+ 'GPENCIL', 'VOLUME', 'HAIR', 'POINTCLOUD'}
# disable material slot buttons when pinned, cannot find correct slot within id_from (#36589)
# disable also when the selected object does not support materials
has_material_slots = not snode.pin and ob_type in types_that_support_material
@@ -150,6 +151,14 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
+ elif snode.tree_type == 'SimulationNodeTree':
+ row = layout.row(align=True)
+ row.prop(snode, "simulation", text="")
+ row.operator("simulation.new", text="", icon='ADD')
+ simulation = snode.simulation
+ if simulation:
+ row.prop(snode.simulation, "use_fake_user", text="")
+
else:
# Custom node tree is edited as independent ID block
NODE_MT_editor_menus.draw_collapsible(context, layout)
@@ -530,7 +539,12 @@ class NODE_PT_active_node_properties(Panel):
layout.label(text="Inputs:")
for socket in value_inputs:
row = layout.row()
- socket.draw(context, row, node, iface_(socket.name, socket.bl_rna.translation_context))
+ socket.draw(
+ context,
+ row,
+ node,
+ iface_(socket.label if socket.label else socket.name, socket.bl_rna.translation_context),
+ )
class NODE_PT_texture_mapping(Panel):
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 11fb20d8b38..ee8015df273 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -19,6 +19,10 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bpy.app.translations import (
+ contexts as i18n_contexts,
+ pgettext_iface as iface_,
+)
class OUTLINER_HT_header(Header):
@@ -100,20 +104,26 @@ class OUTLINER_MT_editor_menus(Menu):
layout.menu("OUTLINER_MT_edit_datablocks")
-class OUTLINER_MT_context(Menu):
- bl_label = "Outliner"
+class OUTLINER_MT_context_menu(Menu):
+ bl_label = "Outliner Context Menu"
+
+ def draw(self, context):
+ space = context.space_data
- def draw(self, _context):
layout = self.layout
- layout.menu("OUTLINER_MT_context_view")
+ if space.display_mode == 'VIEW_LAYER':
+ OUTLINER_MT_collection_new.draw_without_context_menu(context, layout)
+ layout.separator()
+
+ layout.menu("OUTLINER_MT_context_menu_view")
layout.separator()
layout.menu("INFO_MT_area")
-class OUTLINER_MT_context_view(Menu):
+class OUTLINER_MT_context_menu_view(Menu):
bl_label = "View"
def draw(self, _context):
@@ -202,8 +212,8 @@ class OUTLINER_MT_collection(Menu):
layout.separator()
- layout.operator("outliner.collection_delete", text="Delete", icon='X').hierarchy = False
- layout.operator("outliner.collection_delete", text="Delete Hierarchy").hierarchy = True
+ layout.operator("outliner.delete", text="Delete", icon='X')
+ layout.operator("outliner.collection_hierarchy_delete")
layout.separator()
@@ -232,21 +242,25 @@ class OUTLINER_MT_collection(Menu):
layout.separator()
- OUTLINER_MT_context.draw(self, context)
+ OUTLINER_MT_context_menu.draw(self, context)
class OUTLINER_MT_collection_new(Menu):
bl_label = "Collection"
+ @staticmethod
+ def draw_without_context_menu(context, layout):
+ layout.operator("outliner.collection_new", text="New Collection").nested = False
+ layout.operator("outliner.id_paste", text="Paste Data-Blocks", icon='PASTEDOWN')
+
def draw(self, context):
layout = self.layout
- layout.operator("outliner.collection_new", text="New").nested = False
- layout.operator("outliner.id_paste", text="Paste", icon='PASTEDOWN')
+ self.draw_without_context_menu(context, layout)
layout.separator()
- OUTLINER_MT_context.draw(self, context)
+ OUTLINER_MT_context_menu.draw(self, context)
class OUTLINER_MT_object(Menu):
@@ -264,7 +278,7 @@ class OUTLINER_MT_object(Menu):
layout.separator()
- layout.operator("outliner.object_operation", text="Delete", icon='X').type = 'DELETE'
+ layout.operator("outliner.delete", text="Delete", icon='X')
if space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection:
layout.operator("outliner.object_operation", text="Delete Hierarchy").type = 'DELETE_HIERARCHY'
@@ -279,8 +293,10 @@ class OUTLINER_MT_object(Menu):
if object_mode in {'EDIT', 'POSE'}:
name = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode].name
- layout.operator("outliner.object_operation", text=f"{name:s} Set").type = 'OBJECT_MODE_ENTER'
- layout.operator("outliner.object_operation", text=f"{name:s} Clear").type = 'OBJECT_MODE_EXIT'
+ layout.operator("outliner.object_operation",
+ text=iface_("%s Set", i18n_contexts.operator_default) % name).type = 'OBJECT_MODE_ENTER'
+ layout.operator("outliner.object_operation",
+ text=iface_("%s Clear", i18n_contexts.operator_default) % name).type = 'OBJECT_MODE_EXIT'
del name
layout.separator()
@@ -293,7 +309,7 @@ class OUTLINER_MT_object(Menu):
layout.separator()
- OUTLINER_MT_context.draw(self, context)
+ OUTLINER_MT_context_menu.draw(self, context)
class OUTLINER_PT_filter(Panel):
@@ -391,6 +407,9 @@ class OUTLINER_PT_filter(Panel):
if (
bpy.data.curves or
bpy.data.metaballs or
+ (hasattr(bpy.data, "hairs") and bpy.data.hairs) or
+ (hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds) or
+ bpy.data.volumes or
bpy.data.lightprobes or
bpy.data.lattices or
bpy.data.fonts or
@@ -410,8 +429,8 @@ classes = (
OUTLINER_MT_collection_visibility,
OUTLINER_MT_collection_view_layer,
OUTLINER_MT_object,
- OUTLINER_MT_context,
- OUTLINER_MT_context_view,
+ OUTLINER_MT_context_menu,
+ OUTLINER_MT_context_menu_view,
OUTLINER_PT_filter,
)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index af0c23e7892..ca25c29960c 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -29,6 +29,7 @@ from bpy.app.translations import (
)
from bl_ui.properties_grease_pencil_common import (
AnnotationDataPanel,
+ AnnotationOnionSkin,
)
from bl_ui.space_toolsystem_common import (
ToolActivePanelHelper,
@@ -275,7 +276,7 @@ class SEQUENCER_MT_view(Menu):
if is_sequencer_view:
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("sequencer.view_selected", text="Frame Selected")
- layout.operator("sequencer.view_all", text="Frame All")
+ layout.operator("sequencer.view_all")
layout.operator("view2d.zoom_border", text="Zoom")
if is_preview:
@@ -309,6 +310,7 @@ class SEQUENCER_MT_view(Menu):
layout.prop(st, "show_seconds")
layout.prop(st, "show_locked_time")
layout.prop(st, "show_strip_offset")
+ layout.prop(st, "show_fcurves")
layout.separator()
layout.prop(st, "show_markers")
@@ -404,6 +406,8 @@ 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
layout.separator()
@@ -716,8 +720,8 @@ class SEQUENCER_MT_strip(Menu):
layout.menu("SEQUENCER_MT_strip_transform")
layout.separator()
- layout.operator("sequencer.cut", text="Cut").type = 'SOFT'
- layout.operator("sequencer.cut", text="Hold Cut").type = 'HARD'
+ 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")
@@ -781,7 +785,7 @@ class SEQUENCER_MT_context_menu(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("sequencer.cut", text="Cut").type = 'SOFT'
+ layout.operator("sequencer.split", text="Split").type = 'SOFT'
layout.separator()
@@ -842,7 +846,7 @@ class SEQUENCER_MT_context_menu(Menu):
}:
layout.separator()
layout.menu("SEQUENCER_MT_strip_effect")
- elif strip_type in 'MOVIE':
+ elif strip_type == 'MOVIE':
layout.separator()
layout.menu("SEQUENCER_MT_strip_movie")
elif strip_type == 'IMAGE':
@@ -1113,11 +1117,11 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
if i == strip.multicam_source:
sub = row.row(align=True)
sub.enabled = False
- sub.operator("sequencer.cut_multicam", text=f"{i:d}").camera = i
+ sub.operator("sequencer.split_multicam", text="%d" % i).camera = i
else:
sub_1 = row.row(align=True)
sub_1.enabled = True
- sub_1.operator("sequencer.cut_multicam", text=f"{i:d}").camera = i
+ sub_1.operator("sequencer.split_multicam", text="%d" % i).camera = i
if strip.channel > BT_ROW and (strip_channel - 1) % BT_ROW:
for i in range(strip.channel, strip_channel + ((BT_ROW + 1 - strip_channel) % BT_ROW)):
@@ -1135,6 +1139,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
col = layout.column(align=True)
if strip_type == 'SPEED':
col.prop(strip, "multiply_speed")
+ col.prop(strip, "frame_interpolation_mode")
+
elif strip_type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}:
col.prop(strip, "use_default_fade", text="Default fade")
if not strip.use_default_fade:
@@ -1684,18 +1690,15 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel):
layout = self.layout
strip = act_strip(context)
- layout.active = not strip.mute
-
- split = layout.split()
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
+ layout.active = not strip.mute
- col = split.column()
- row = col.row(align=True)
- row.prop(strip, "use_flip_x", text="X", toggle=True)
- row.prop(strip, "use_flip_y", text="Y", toggle=True)
+ row = layout.row(heading="Mirror")
+ sub = row.row(align=True)
+ sub.prop(strip, "use_flip_x", text="X", toggle=True)
+ sub.prop(strip, "use_flip_y", text="Y", toggle=True)
class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel):
@@ -1799,12 +1802,12 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel):
ed = context.scene.sequence_editor
- col = layout.column()
+ col = layout.column(heading="Cache", align=True)
- col.prop(ed, "use_cache_raw")
- col.prop(ed, "use_cache_preprocessed")
- col.prop(ed, "use_cache_composite")
- col.prop(ed, "use_cache_final")
+ col.prop(ed, "use_cache_raw", text="Raw")
+ col.prop(ed, "use_cache_preprocessed", text="Pre-Processed")
+ col.prop(ed, "use_cache_composite", text="Composite")
+ col.prop(ed, "use_cache_final", text="Final")
col.separator()
col.prop(ed, "recycle_max_cost")
@@ -1868,21 +1871,19 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
flow = layout.column_flow()
if ed.proxy_storage == 'PER_STRIP':
- flow.prop(proxy, "use_proxy_custom_directory")
- flow.prop(proxy, "use_proxy_custom_file")
-
+ col = layout.column(heading="Custom Proxy")
+ col.prop(proxy, "use_proxy_custom_directory", text="Directory")
if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file:
- flow.prop(proxy, "directory")
+ col.prop(proxy, "directory")
+ col.prop(proxy, "use_proxy_custom_file", text="File")
if proxy.use_proxy_custom_file:
- flow.prop(proxy, "filepath")
+ col.prop(proxy, "filepath")
- box = layout.box()
- row = box.row(align=True)
- row.prop(strip.proxy, "build_25")
- row.prop(strip.proxy, "build_75")
- row = box.row(align=True)
- row.prop(strip.proxy, "build_50")
- row.prop(strip.proxy, "build_100")
+ row = layout.row(heading="Resolutions", align=True)
+ row.prop(strip.proxy, "build_25", toggle=True)
+ row.prop(strip.proxy, "build_50", toggle=True)
+ row.prop(strip.proxy, "build_75", toggle=True)
+ row.prop(strip.proxy, "build_100", toggle=True)
layout.use_property_split = True
layout.use_property_decorate = False
@@ -1923,10 +1924,10 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
strip = act_strip(context)
layout.active = strip.override_cache_settings
- col = layout.column()
- col.prop(strip, "use_cache_raw")
- col.prop(strip, "use_cache_preprocessed")
- col.prop(strip, "use_cache_composite")
+ col = layout.column(heading="Cache")
+ col.prop(strip, "use_cache_raw", text="Raw")
+ col.prop(strip, "use_cache_preprocessed", text="Pre-Processed")
+ col.prop(strip, "use_cache_composite", text="Composite")
class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
@@ -1972,7 +1973,9 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
col.prop(st, "show_separate_color")
col.prop(st, "proxy_render_size")
- col.prop(ed, "use_prefetch")
+
+ if ed:
+ col.prop(ed, "use_prefetch")
class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
@@ -1980,6 +1983,12 @@ class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
bl_category = "View"
bl_options = {'DEFAULT_CLOSED'}
+ @classmethod
+ def poll(cls, context):
+ if not context.scene.sequence_editor:
+ return False
+ return SequencerButtonsPanel_Output.poll(context)
+
def draw_header(self, context):
scene = context.scene
ed = scene.sequence_editor
@@ -2084,10 +2093,12 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
box = layout.box()
row = box.row()
+ row.use_property_decorate = False
row.prop(mod, "show_expanded", text="", emboss=False)
row.prop(mod, "name", text="")
row.prop(mod, "mute", text="")
+ row.use_property_decorate = True
sub = row.row(align=True)
props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_UP')
@@ -2159,6 +2170,33 @@ class SEQUENCER_PT_annotation(AnnotationDataPanel, SequencerButtonsPanel_Output,
# But, it should only show up when there are images in the preview region
+class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_Output, Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'UI'
+ bl_category = "View"
+
+ @staticmethod
+ def has_preview(context):
+ st = context.space_data
+ return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
+
+ @classmethod
+ def poll(cls, context):
+ if context.annotation_data_owner is None:
+ return False
+ elif type(context.annotation_data_owner) is bpy.types.Object:
+ return False
+ else:
+ gpl = context.active_annotation_layer
+ if gpl is None:
+ return False
+
+ return cls.has_preview(context)
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+ # But, it should only show up when there are images in the preview region
+
+
class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
_context_path = "scene.sequence_editor.active_strip"
@@ -2232,6 +2270,7 @@ classes = (
SEQUENCER_PT_view_safe_areas_center_cut,
SEQUENCER_PT_annotation,
+ SEQUENCER_PT_annotation_onion,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index b7c5dcd5437..f6f22ad464f 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -129,18 +129,21 @@ class TEXT_PT_properties(Panel):
layout.use_property_decorate = False
st = context.space_data
- flow = layout.column_flow()
if not st.text:
- flow.active = False
- row = flow.row(align=True)
+ layout.active = False
+
st = context.space_data
- row.prop(st, "show_margin", text="Margin")
- rowsub = row.row()
- rowsub.active = st.show_margin
- rowsub.prop(st, "margin_column", text="")
- flow.prop(st, "font_size")
- flow.prop(st, "tab_width")
+ col = layout.column(align=False, heading="Margin")
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(st, "show_margin", text="")
+ sub = sub.row(align=True)
+ sub.active = st.show_margin
+ sub.prop(st, "margin_column", text="")
+
+ layout.prop(st, "font_size")
+ layout.prop(st, "tab_width")
text = st.text
if text:
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 629958a783e..257e0c26a5d 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -142,6 +142,7 @@ class TIME_MT_view(Menu):
layout.separator()
layout.prop(scene, "show_keys_from_selected_only")
+ layout.prop(st.dopesheet, "show_only_errors")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 4dc724299f0..e0651dcac2b 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -68,8 +68,8 @@ ToolDef = namedtuple(
"idname",
# The name to display in the interface.
"label",
- # Description (for tooltip), when not set, use the description of 'operator',
- # may be a string or a 'function(context, item, keymap) -> string'.
+ # Description (for tool-tip), when not set, use the description of 'operator',
+ # may be a string or a 'function(context, item, key-map) -> string'.
"description",
# The name of the icon to use (found in ``release/datafiles/icons``) or None for no icon.
"icon",
@@ -77,13 +77,34 @@ ToolDef = namedtuple(
"cursor",
# An optional gizmo group to activate when the tool is set or None for no gizmo.
"widget",
- # Optional keymap for tool, either:
- # - A function that populates a keymaps passed in as an argument.
+ # Optional key-map for tool, possible values are:
+ #
+ # - ``None`` when the tool doesn't have a key-map.
+ # Also the default value when no key-map value is defined.
+ #
+ # - A string literal for the key-map name, the key-map items are located in the default key-map.
+ #
+ # - ``()`` an empty tuple for a default name.
+ # This is convenience functionality for generating a key-map name.
+ # So if a tool name is "Bone Size", in "Edit Armature" mode for the "3D View",
+ # All of these values are combined into an id, e.g:
+ # "3D View Tool: Edit Armature, Bone Envelope"
+ #
+ # Typically searching for a string ending with the tool name
+ # in the default key-map will lead you to the key-map for a tool.
+ #
+ # - A function that populates a key-maps passed in as an argument.
+ #
# - A tuple filled with triple's of:
# ``(operator_id, operator_properties, keymap_item_args)``.
#
+ # Use this to define the key-map in-line.
+ #
+ # Note that this isn't used for Blender's built in tools which use the built-in key-map.
+ # 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 keymap function for the keymap it's self.
+ # so internally we can swap the key-map function for the key-map it's self.
# This isn't very nice and may change, tool definitions shouldn't care about this.
"keymap",
# Optional data-block associated with this tool.
@@ -216,29 +237,52 @@ class ToolSelectPanelHelper:
else:
return 0
+ # tool flattening
+ #
+ # usually 'tools' is already expanded into ToolDef
+ # but when registering a tool, this can still be a function
+ # (_tools_flatten is usually called with cls.tools_from_context(context)
+ # [that already yields from the function])
+ # so if item is still a function (e.g._defs_XXX.generate_from_brushes)
+ # seems like we cannot expand here (have no context yet)
+ # if we yield None here, this will risk running into duplicate tool bl_idname [in register_tool()]
+ # but still better than erroring out
@staticmethod
def _tools_flatten(tools):
- for item in tools:
- if type(item) is tuple:
- yield from item
- else:
- # May be None.
- yield item
+ for item_parent in tools:
+ if item_parent is None:
+ yield None
+ for item in item_parent if (type(item_parent) is tuple) else (item_parent,):
+ if item is None or _item_is_fn(item):
+ yield None
+ else:
+ yield item
@staticmethod
def _tools_flatten_with_tool_index(tools):
- for item in tools:
- if type(item) is tuple:
- i = 0
- for sub_item in item:
- if sub_item is None:
- yield None, -1
- else:
- yield sub_item, i
- i += 1
- else:
- # May be None.
- yield item, -1
+ for item_parent in tools:
+ if item_parent is None:
+ yield None, -1
+ i = 0
+ for item in item_parent if (type(item_parent) is tuple) else (item_parent,):
+ if item is None or _item_is_fn(item):
+ yield None, -1
+ else:
+ yield item, i
+ i += 1
+
+ # Special internal function, gives use items that contain keymaps.
+ @staticmethod
+ def _tools_flatten_with_keymap(tools):
+ for item_parent in tools:
+ if item_parent is None:
+ continue
+ for item in item_parent if (type(item_parent) is tuple) else (item_parent,):
+ # skip None or generator function
+ if item is None or _item_is_fn(item):
+ continue
+ if item.keymap is not None:
+ yield item
@classmethod
def _tool_get_active(cls, context, space_type, mode, with_icon=False):
@@ -405,32 +449,24 @@ class ToolSelectPanelHelper:
return context.button_operator.name
@classmethod
- def _km_action_simple(cls, kc, context_descr, label, keymap_fn):
+ def _km_action_simple(cls, kc_default, kc, context_descr, label, keymap_fn):
km_idname = f"{cls.keymap_prefix:s} {context_descr:s}, {label:s}"
km = kc.keymaps.get(km_idname)
+ km_kwargs = dict(space_type=cls.bl_space_type, region_type='WINDOW', tool=True)
if km is None:
- km = kc.keymaps.new(km_idname, space_type=cls.bl_space_type, region_type='WINDOW', tool=True)
+ km = kc.keymaps.new(km_idname, **km_kwargs)
keymap_fn[0](km)
keymap_fn[0] = km.name
- # Special internal function, gives use items that contain keymaps.
- @staticmethod
- def _tools_flatten_with_keymap(tools):
- for item_parent in tools:
- if item_parent is None:
- continue
- for item in item_parent if (type(item_parent) is tuple) else (item_parent,):
- # skip None or generator function
- if item is None or _item_is_fn(item):
- continue
- if item.keymap is not None:
- yield item
+ # Ensure we have a default key map, so the add-ons keymap is properly overlayed.
+ if kc_default is not kc:
+ kc_default.keymaps.new(km_idname, **km_kwargs)
@classmethod
def register(cls):
wm = bpy.context.window_manager
# Write into defaults, users may modify in preferences.
- kc = wm.keyconfigs.default
+ kc_default = wm.keyconfigs.default
# Track which tool-group was last used for non-active groups.
# Blender stores the active tool-group index.
@@ -439,7 +475,7 @@ class ToolSelectPanelHelper:
cls._tool_group_active = {}
# ignore in background mode
- if kc is None:
+ if kc_default is None:
return
for context_mode, tools in cls.tools_all():
@@ -451,7 +487,7 @@ class ToolSelectPanelHelper:
for item in cls._tools_flatten_with_keymap(tools):
keymap_data = item.keymap
if callable(keymap_data[0]):
- cls._km_action_simple(kc, context_descr, item.label, keymap_data)
+ cls._km_action_simple(kc_default, kc_default, context_descr, item.label, keymap_data)
@classmethod
def keymap_ui_hierarchy(cls, context_mode):
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index c1ad196b555..e64a7c9731b 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -18,6 +18,9 @@
# <pep8 compliant>
+# For documentation on tool definitions: see "bl_ui.space_toolsystem_common.ToolDef"
+# where there are comments for each field and their use.
+
# For now group all tools together
# we may want to move these into per space-type files.
#
@@ -125,7 +128,7 @@ class _defs_view3d_generic:
"\u2022 Drag ruler segment to measure an angle.\n"
"\u2022 {} to remove the active ruler.\n"
"\u2022 Ctrl while dragging to snap.\n"
- "\u2022 Shift while dragging to measure surface thickness."
+ "\u2022 Shift while dragging to measure surface thickness"
).format(
kmi_to_string_or_none(kmi_add),
kmi_to_string_or_none(kmi_remove),
@@ -144,10 +147,8 @@ class _defs_view3d_generic:
class _defs_annotate:
def draw_settings_common(context, layout, tool):
- if type(context.gpencil_data_owner) is bpy.types.Object:
- gpd = context.scene.grease_pencil
- else:
- gpd = context.gpencil_data
+ gpd = context.annotation_data
+ region_type = context.region.type
if gpd is not None:
if gpd.layers.active_note is not None:
@@ -158,20 +159,27 @@ class _defs_annotate:
else:
text = ""
- gpl = context.active_gpencil_layer
+ gpl = context.active_annotation_layer
if gpl is not None:
layout.label(text="Annotation:")
- sub = layout.row(align=True)
- sub.ui_units_x = 8
-
- sub.prop(gpl, "color", text="")
- sub.popover(
- panel="TOPBAR_PT_annotation_layers",
- text=text,
- )
+ if context.space_data.type == 'VIEW_3D':
+ if region_type == 'TOOL_HEADER':
+ sub = layout.split(align=True, factor=0.5)
+ sub.ui_units_x = 6.5
+ sub.prop(gpl, "color", text="")
+ else:
+ sub = layout.row(align=True)
+ sub.prop(gpl, "color", text="")
+ sub.popover(
+ panel="TOPBAR_PT_annotation_layers",
+ text=text,
+ )
+ else:
+ layout.prop(gpl, "color", text="")
- tool_settings = context.tool_settings
space_type = tool.space_type
+ tool_settings = context.tool_settings
+
if space_type == 'VIEW_3D':
layout.separator()
@@ -182,6 +190,29 @@ class _defs_annotate:
elif tool_settings.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
row.prop(tool_settings, "use_gpencil_stroke_endpoints")
+ if tool.idname == "builtin.annotate_line":
+ layout.separator()
+
+ props = tool.operator_properties("gpencil.annotate")
+ if region_type == 'TOOL_HEADER':
+ row = layout.row()
+ row.ui_units_x = 15
+ row.prop(props, "arrowstyle_start", text="Start")
+ row.separator()
+ row.prop(props, "arrowstyle_end", text="End")
+ else:
+ col = layout.row().column(align=True)
+ col.prop(props, "arrowstyle_start", text="Style Start")
+ col.prop(props, "arrowstyle_end", text="End")
+ elif tool.idname == "builtin.annotate" and region_type != 'TOOL_HEADER':
+ layout.separator()
+ props = tool.operator_properties("gpencil.annotate")
+ layout.prop(props, "use_stabilizer", text="Stabilize Stroke")
+ col = layout.column(align=False)
+ col.active = props.use_stabilizer
+ col.prop(props, "stabilizer_radius", text="Radius", slider=True)
+ col.prop(props, "stabilizer_factor", text="Factor", slider=True)
+
@ToolDef.from_fn.with_args(draw_settings=draw_settings_common)
def scribble(*, draw_settings):
return dict(
@@ -460,6 +491,7 @@ class _defs_edit_armature:
return dict(
idname="builtin.extrude_to_cursor",
label="Extrude to Cursor",
+ cursor='CROSSHAIR',
icon="ops.armature.extrude_cursor",
widget=None,
keymap=(),
@@ -611,15 +643,6 @@ class _defs_edit_mesh:
region_type = context.region.type
if not extra:
- if props.offset_type == 'PERCENT':
- layout.prop(props, "offset_pct")
- else:
- offset_text = "Width"
- if props.offset_type == 'DEPTH':
- offset_text = "Depth"
- elif props.offset_type == 'OFFSET':
- offset_text = "Offset"
- layout.prop(props, "offset", text=offset_text)
if region_type == 'TOOL_HEADER':
layout.prop(props, "offset_type", text="")
else:
@@ -637,9 +660,10 @@ class _defs_edit_mesh:
layout.prop(props, "vertex_only")
layout.prop(props, "clamp_overlap")
layout.prop(props, "loop_slide")
- layout.prop(props, "mark_seam")
- layout.prop(props, "mark_sharp")
layout.prop(props, "harden_normals")
+ col = layout.column(heading="Mark")
+ col.prop(props, "mark_seam", text="Seam")
+ col.prop(props, "mark_sharp", text="Sharp")
layout.prop(props, "material")
@@ -680,6 +704,19 @@ class _defs_edit_mesh:
)
@ToolDef.from_fn
+ def extrude_dissolve_and_intersect():
+ return dict(
+ idname="builtin.extrude_dissolve_and_intersect",
+ label="Extrude Dissolve and Intersect",
+ description=(
+ "Extrude, dissolves edges whose faces form a flat surface and intersect new edges"
+ ),
+ icon="none",
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
+ keymap=(),
+ )
+
+ @ToolDef.from_fn
def extrude_normals():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("mesh.extrude_region_shrink_fatten")
@@ -714,6 +751,7 @@ class _defs_edit_mesh:
return dict(
idname="builtin.extrude_to_cursor",
label="Extrude to Cursor",
+ cursor='CROSSHAIR',
icon="ops.mesh.dupli_extrude_cursor",
widget=None,
keymap=(),
@@ -853,23 +891,61 @@ class _defs_edit_curve:
@ToolDef.from_fn
def draw():
- def draw_settings(context, layout, _tool):
+ def draw_settings(context, layout, tool, *, extra=False):
# Tool settings initialize operator options.
tool_settings = context.tool_settings
cps = tool_settings.curve_paint_settings
+ region_type = context.region.type
- col = layout.column()
+ if region_type == 'TOOL_HEADER':
+ if not extra:
+ layout.prop(cps, "curve_type", text="")
+ layout.prop(cps, "depth_mode", expand=True)
+ layout.popover("TOPBAR_PT_tool_settings_extra", text="...")
+ return
- col.prop(cps, "curve_type")
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ if region_type != 'TOOL_HEADER':
+ layout.prop(cps, "curve_type")
+ layout.separator()
if cps.curve_type == 'BEZIER':
- col.prop(cps, "error_threshold")
- col.prop(cps, "fit_method")
- col.prop(cps, "use_corners_detect")
+ layout.prop(cps, "fit_method")
+ layout.prop(cps, "error_threshold")
+ if region_type != 'TOOL_HEADER':
+ row = layout.row(heading="Detect Corners", align=True)
+ else:
+ row = layout.row(heading="Corners", align=True)
+ row.prop(cps, "use_corners_detect", text="")
+ sub = row.row(align=True)
+ sub.active = cps.use_corners_detect
+ sub.prop(cps, "corner_angle", text="")
+ layout.separator()
+
+
+ col = layout.column(align=True)
+ col.prop(cps, "radius_taper_start", text="Taper Start", slider=True)
+ col.prop(cps, "radius_taper_end", text="End", slider=True)
+ col = layout.column(align=True)
+ col.prop(cps, "radius_min", text="Radius Min")
+ col.prop(cps, "radius_max", text="Max")
+ col.prop(cps, "use_pressure_radius")
+
+ layout.separator()
+
+ if region_type != 'TOOL_HEADER':
+ row = layout.row()
+ row.prop(cps, "depth_mode", expand=True)
+ if cps.depth_mode == 'SURFACE':
+ col = layout.column()
+ col.prop(cps, "surface_offset")
+ col.prop(cps, "use_offset_absolute")
+ col.prop(cps, "use_stroke_endpoints")
+ if cps.use_stroke_endpoints:
+ colsub = layout.column(align=True)
+ colsub.prop(cps, "surface_plane")
- col = layout.row()
- col.active = cps.use_corners_detect
- col.prop(cps, "corner_angle")
return dict(
idname="builtin.draw",
@@ -896,7 +972,8 @@ class _defs_edit_curve:
def extrude_cursor():
return dict(
idname="builtin.extrude_cursor",
- label="Extrude Cursor",
+ label="Extrude to Cursor",
+ cursor='CROSSHAIR',
icon="ops.curve.extrude_cursor",
widget=None,
keymap=(),
@@ -1037,6 +1114,12 @@ class _defs_sculpt:
layout.prop(props, "type", expand=False)
layout.prop(props, "strength")
layout.prop(props, "deform_axis")
+ layout.prop(props, "use_face_sets")
+ if (props.type == "SURFACE_SMOOTH"):
+ layout.prop(props, "surface_smooth_shape_preservation", expand=False)
+ layout.prop(props, "surface_smooth_current_vertex", expand=False)
+ if (props.type == "SHARPEN"):
+ layout.prop(props, "sharpen_smooth_ratio", expand=False)
return dict(
idname="builtin.mesh_filter",
@@ -1137,8 +1220,25 @@ class _defs_weight_paint:
def draw_settings(context, layout, tool):
brush = context.tool_settings.weight_paint.brush
if brush is not None:
- layout.prop(brush, "weight", slider=True)
- layout.prop(brush, "strength", slider=True)
+ from bl_ui.properties_paint_common import UnifiedPaintPanel
+ UnifiedPaintPanel.prop_unified(
+ layout,
+ context,
+ brush,
+ "weight",
+ unified_name="use_unified_weight",
+ slider=True,
+ header=True
+ )
+ UnifiedPaintPanel.prop_unified(
+ layout,
+ context,
+ brush,
+ "strength",
+ unified_name="use_unified_strength",
+ header=True
+ )
+
props = tool.operator_properties("paint.weight_gradient")
layout.prop(props, "type", expand=True)
@@ -1444,6 +1544,11 @@ class _defs_gpencil_paint:
@ToolDef.from_fn
def eyedropper():
+ def draw_settings(context, layout, tool):
+ props = tool.operator_properties("ui.eyedropper_gpencil_color")
+ row = layout.row()
+ row.use_property_split = False
+ row.prop(props, "mode", expand=True)
return dict(
idname="builtin.eyedropper",
label="Eyedropper",
@@ -1451,10 +1556,22 @@ class _defs_gpencil_paint:
cursor='EYEDROPPER',
widget=None,
keymap=(),
+ draw_settings=draw_settings,
)
class _defs_gpencil_edit:
+ def is_segment(context):
+ ts = context.scene.tool_settings
+ if context.mode == 'EDIT_GPENCIL':
+ return ts.gpencil_selectmode_edit == 'SEGMENT'
+ elif context.mode == 'SCULPT_GPENCIL':
+ return ts.use_gpencil_select_mask_segment
+ elif context.mode == 'VERTEX_GPENCIL':
+ return ts.use_gpencil_vertex_select_mask_segment
+ else:
+ return False
+
@ToolDef.from_fn
def bend():
return dict(
@@ -1468,7 +1585,8 @@ class _defs_gpencil_edit:
@ToolDef.from_fn
def select():
def draw_settings(context, layout, _tool):
- layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
+ if _defs_gpencil_edit.is_segment(context):
+ layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
return dict(
idname="builtin.select",
label="Tweak",
@@ -1485,7 +1603,8 @@ class _defs_gpencil_edit:
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
- layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
+ if _defs_gpencil_edit.is_segment(context):
+ layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
return dict(
idname="builtin.select_box",
label="Select Box",
@@ -1502,7 +1621,8 @@ class _defs_gpencil_edit:
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
- layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
+ if _defs_gpencil_edit.is_segment(context):
+ layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
return dict(
idname="builtin.select_lasso",
label="Select Lasso",
@@ -1520,7 +1640,8 @@ class _defs_gpencil_edit:
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
layout.prop(props, "radius")
- layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
+ if _defs_gpencil_edit.is_segment(context):
+ layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
def draw_cursor(_context, tool, xy):
from gpu_extras.presets import draw_circle_2d
@@ -1583,6 +1704,23 @@ class _defs_gpencil_edit:
draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
)
+ @ToolDef.from_fn
+ def transform_fill():
+ def draw_settings(context, layout, tool):
+ props = tool.operator_properties("gpencil.transform_fill")
+ row = layout.row()
+ row.use_property_split = False
+ row.prop(props, "mode", expand=True)
+
+ return dict(
+ idname="builtin.transform_fill",
+ label="Transform Fill",
+ icon="ops.gpencil.transform_fill",
+ cursor='DEFAULT',
+ widget=None,
+ keymap=(),
+ draw_settings=draw_settings,
+ )
class _defs_gpencil_sculpt:
@@ -1602,11 +1740,10 @@ class _defs_gpencil_sculpt:
context,
idname_prefix="builtin_brush.",
icon_prefix="ops.gpencil.sculpt_",
- type=bpy.types.GPencilSculptSettings,
- attr="sculpt_tool",
+ type=bpy.types.Brush,
+ attr="gpencil_sculpt_tool",
tooldef_keywords=dict(
operator="gpencil.sculpt_paint",
- keymap="3D View Tool: Sculpt Gpencil, Paint",
),
)
@@ -1619,11 +1756,37 @@ class _defs_gpencil_weight:
context,
idname_prefix="builtin_brush.",
icon_prefix="ops.gpencil.sculpt_",
- type=bpy.types.GPencilSculptSettings,
- attr="weight_tool",
+ type=bpy.types.Brush,
+ attr="gpencil_weight_tool",
tooldef_keywords=dict(
- operator="gpencil.sculpt_paint",
- keymap="3D View Tool: Sculpt Gpencil, Paint",
+ operator="gpencil.weight_paint",
+ ),
+ )
+
+
+class _defs_gpencil_vertex:
+
+ @staticmethod
+ def poll_select_mask(context):
+ if context is None:
+ return True
+ ob = context.active_object
+ ts = context.scene.tool_settings
+ return ob and ob.type == 'GPENCIL' and (ts.use_gpencil_vertex_select_mask_point or
+ ts.use_gpencil_vertex_select_mask_stroke or
+ ts.use_gpencil_vertex_select_mask_segment)
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_enum_ex(
+ context,
+ idname_prefix="builtin_brush.",
+ icon_prefix="brush.paint_vertex.",
+ type=bpy.types.Brush,
+ attr="gpencil_vertex_tool",
+ cursor='DOT',
+ tooldef_keywords=dict(
+ operator="gpencil.vertex_paint",
),
)
@@ -1710,24 +1873,42 @@ class _defs_node_edit:
keymap="Node Tool: Links Cut",
)
+
class _defs_sequencer_generic:
@ToolDef.from_fn
- def cut():
+ def blade():
def draw_settings(_context, layout, tool):
- props = tool.operator_properties("sequencer.cut")
+ props = tool.operator_properties("sequencer.split")
row = layout.row()
row.use_property_split = False
row.prop(props, "type", expand=True)
return dict(
- idname="builtin.cut",
- label="Cut",
- icon="ops.mesh.knife_tool",
+ idname="builtin.blade",
+ label="Blade",
+ icon="ops.sequencer.blade",
+ cursor='CROSSHAIR',
widget=None,
- keymap="Sequencer Tool: Cut",
+ keymap="Sequencer Tool: Blade",
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def sample():
+ def draw_settings(_context, layout, tool):
+ props = tool.operator_properties("sequencer.sample")
+ return dict(
+ idname="builtin.sample",
+ label="Sample",
+ description=(
+ "Sample pixel values under the cursor"
+ ),
+ icon="ops.paint.weight_sample", # XXX, needs own icon.
+ keymap="Sequencer Tool: Sample",
draw_settings=draw_settings,
)
+
class _defs_sequencer_select:
@ToolDef.from_fn
def select():
@@ -1839,6 +2020,8 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
],
'PAINT': [
_defs_texture_paint.generate_from_brushes,
+ None,
+ *_tools_annotate,
],
}
@@ -2015,6 +2198,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
(
_defs_edit_mesh.extrude,
+ _defs_edit_mesh.extrude_dissolve_and_intersect,
_defs_edit_mesh.extrude_normals,
_defs_edit_mesh.extrude_individual,
_defs_edit_mesh.extrude_cursor,
@@ -2188,6 +2372,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_gpencil_edit.tosphere,
),
None,
+ _defs_gpencil_edit.transform_fill,
+ None,
*_tools_annotate,
],
'SCULPT_GPENCIL': [
@@ -2205,6 +2391,17 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
*_tools_annotate,
],
+ 'VERTEX_GPENCIL': [
+ _defs_gpencil_vertex.generate_from_brushes,
+ None,
+ *_tools_annotate,
+ None,
+ lambda context: (
+ VIEW3D_PT_tools_active._tools_gpencil_select
+ if _defs_gpencil_vertex.poll_select_mask(context)
+ else ()
+ ),
+ ],
}
class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
bl_space_type = 'SEQUENCE_EDITOR'
@@ -2253,19 +2450,22 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
None: [
],
'PREVIEW': [
+ _defs_sequencer_generic.sample,
*_tools_annotate,
],
'SEQUENCER': [
*_tools_select,
- _defs_sequencer_generic.cut,
+ _defs_sequencer_generic.blade,
],
'SEQUENCER_PREVIEW': [
+ _defs_sequencer_generic.sample,
*_tools_select,
*_tools_annotate,
- _defs_sequencer_generic.cut,
+ _defs_sequencer_generic.blade,
],
}
+
classes = (
IMAGE_PT_tools_active,
NODE_PT_tools_active,
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index fd46bd53cd2..9aedd7ef0b3 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -165,11 +165,11 @@ class TOPBAR_PT_gpencil_layers(Panel):
srow = col.row(align=True)
srow.prop(gpl, "opacity", text="Opacity", slider=True)
- srow.prop(gpl, "mask_layer", text="",
- icon='MOD_MASK' if gpl.mask_layer else 'LAYER_ACTIVE')
+ srow.prop(gpl, "use_mask_layer", text="",
+ icon='MOD_MASK' if gpl.use_mask_layer else 'LAYER_ACTIVE')
srow = col.row(align=True)
- srow.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
+ srow.prop(gpl, "use_lights")
col = row.column()
@@ -207,7 +207,8 @@ class TOPBAR_MT_editor_menus(Menu):
def draw(self, context):
layout = self.layout
- if context.area.show_menus:
+ # Allow calling this menu directly (this might not be a header area).
+ if getattr(context.area, "show_menus", False):
layout.menu("TOPBAR_MT_app", text="", icon='BLENDER')
else:
layout.menu("TOPBAR_MT_app", text="Blender")
@@ -228,19 +229,16 @@ class TOPBAR_MT_app(Menu):
layout = self.layout
layout.operator("wm.splash")
+ layout.operator("wm.splash_about")
layout.separator()
- layout.menu("TOPBAR_MT_app_support")
-
- layout.separator()
-
- layout.menu("TOPBAR_MT_app_about")
+ layout.operator("preferences.app_template_install",
+ text="Install Application Template...")
layout.separator()
- layout.operator("preferences.app_template_install",
- text="Install Application Template...")
+ layout.menu("TOPBAR_MT_app_system")
class TOPBAR_MT_file_cleanup(Menu):
@@ -402,43 +400,24 @@ class TOPBAR_MT_file_defaults(Menu):
props.app_template = app_template
-class TOPBAR_MT_app_about(Menu):
- bl_label = "About"
+# Include technical operators here which would otherwise have no way for users to access.
+class TOPBAR_MT_app_system(Menu):
+ bl_label = "System"
def draw(self, _context):
layout = self.layout
- layout.operator("wm.url_open_preset", text="Release Notes",
- icon='URL').type = 'RELEASE_NOTES'
+ layout.operator("script.reload")
layout.separator()
- layout.operator("wm.url_open_preset",
- text="Blender Website", icon='URL').type = 'BLENDER'
- layout.operator("wm.url_open_preset", text="Credits",
- icon='URL').type = 'CREDITS'
+ layout.operator("wm.memory_statistics")
+ layout.operator("wm.debug_menu")
+ layout.operator_menu_enum("wm.redraw_timer", "type")
layout.separator()
- layout.operator(
- "wm.url_open", text="License", icon='URL',
- ).url = "https://www.blender.org/about/license/"
-
-
-class TOPBAR_MT_app_support(Menu):
- bl_label = "Support Blender"
-
- def draw(self, _context):
- layout = self.layout
-
- layout.operator("wm.url_open_preset",
- text="Development Fund", icon='FUND').type = 'FUND'
-
- layout.separator()
-
- layout.operator(
- "wm.url_open", text="Blender Store", icon='URL',
- ).url = "https://store.blender.org"
+ layout.operator("screen.spacedata_cleanup")
class TOPBAR_MT_templates_more(Menu):
@@ -452,6 +431,7 @@ class TOPBAR_MT_templates_more(Menu):
class TOPBAR_MT_file_import(Menu):
bl_idname = "TOPBAR_MT_file_import"
bl_label = "Import"
+ bl_owner_use_filter = False
def draw(self, _context):
if bpy.app.build_options.collada:
@@ -464,6 +444,7 @@ class TOPBAR_MT_file_import(Menu):
class TOPBAR_MT_file_export(Menu):
bl_idname = "TOPBAR_MT_file_export"
bl_label = "Export"
+ bl_owner_use_filter = False
def draw(self, context):
if bpy.app.build_options.collada:
@@ -553,6 +534,8 @@ class TOPBAR_MT_edit(Menu):
def draw(self, context):
layout = self.layout
+ show_developer = context.preferences.view.show_developer_ui
+
layout.operator("ed.undo")
layout.operator("ed.redo")
@@ -571,8 +554,9 @@ class TOPBAR_MT_edit(Menu):
layout.separator()
- layout.operator("wm.search_menu",
- text="Operator Search...", icon='VIEWZOOM')
+ layout.operator("wm.search_menu", text="Menu Search...", icon='VIEWZOOM')
+ if show_developer:
+ layout.operator("wm.search_operator", text="Operator Search...", icon='VIEWZOOM')
layout.separator()
@@ -824,8 +808,7 @@ classes = (
TOPBAR_MT_workspace_menu,
TOPBAR_MT_editor_menus,
TOPBAR_MT_app,
- TOPBAR_MT_app_about,
- TOPBAR_MT_app_support,
+ TOPBAR_MT_app_system,
TOPBAR_MT_file,
TOPBAR_MT_file_new,
TOPBAR_MT_file_recover,
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index ad5e7b5442c..153533dbde6 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -37,18 +37,13 @@ class USERPREF_HT_header(Header):
def draw_buttons(layout, context):
prefs = context.preferences
- layout.scale_x = 1.0
- layout.scale_y = 1.0
layout.operator_context = 'EXEC_AREA'
- row = layout.row()
- row.menu("USERPREF_MT_save_load", text="", icon='COLLAPSEMENU')
-
if prefs.use_preferences_save and (not bpy.app.use_userpref_skip_save_on_exit):
pass
else:
# Show '*' to let users know the preferences have been modified.
- row.operator(
+ layout.operator(
"wm.save_userpref",
text="Save Preferences{:s}".format(" *" if prefs.is_dirty else ""),
)
@@ -59,7 +54,10 @@ class USERPREF_HT_header(Header):
layout.template_header()
+ USERPREF_MT_editor_menus.draw_collapsible(context, layout)
+
layout.separator_spacer()
+
self.draw_buttons(layout, context)
@@ -84,6 +82,25 @@ class USERPREF_PT_navigation_bar(Panel):
col.prop(prefs, "active_section", expand=True)
+class USERPREF_MT_editor_menus(Menu):
+ bl_idname = "USERPREF_MT_editor_menus"
+ bl_label = ""
+
+ def draw(self, _context):
+ layout = self.layout
+ layout.menu("USERPREF_MT_view")
+ layout.menu("USERPREF_MT_save_load", text="Preferences")
+
+
+class USERPREF_MT_view(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.menu("INFO_MT_area")
+
+
class USERPREF_MT_save_load(Menu):
bl_label = "Save & Load"
@@ -125,11 +142,10 @@ class USERPREF_PT_save_preferences(Panel):
return False
def draw(self, context):
- layout = self.layout
+ layout = self.layout.row()
layout.operator_context = 'EXEC_AREA'
- layout.scale_x = 1.3
- layout.scale_y = 1.3
+ layout.menu("USERPREF_MT_save_load", text="", icon='COLLAPSEMENU')
USERPREF_HT_header.draw_buttons(layout, context)
@@ -184,20 +200,16 @@ class USERPREF_PT_interface_display(InterfacePanel, CenterAlignMixIn, Panel):
prefs = context.preferences
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "ui_scale", text="Resolution Scale")
- flow.prop(view, "ui_line_width", text="Line Width")
-
- layout.separator()
+ col = layout.column()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col.prop(view, "ui_scale", text="Resolution Scale")
+ col.prop(view, "ui_line_width", text="Line Width")
+ col.prop(view, "show_splash", text="Splash Screen")
+ col.prop(view, "show_developer_ui")
- flow.prop(view, "show_splash", text="Splash Screen")
- flow.prop(view, "show_tooltips")
- flow.prop(view, "show_tooltips_python")
- flow.prop(view, "show_developer_ui")
- flow.prop(view, "show_large_cursors")
+ col = layout.column(heading="Tooltips")
+ col.prop(view, "show_tooltips")
+ col.prop(view, "show_tooltips_python")
class USERPREF_PT_interface_text(InterfacePanel, CenterAlignMixIn, Panel):
@@ -227,25 +239,17 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel)
def poll(cls, context):
return bpy.app.build_options.international
- def draw_header(self, context):
- prefs = context.preferences
- view = prefs.view
-
- self.layout.prop(view, "use_international_fonts", text="")
-
def draw_centered(self, context, layout):
prefs = context.preferences
view = prefs.view
- layout.active = view.use_international_fonts
-
layout.prop(view, "language")
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "use_translate_tooltips", text="Tooltips")
- flow.prop(view, "use_translate_interface", text="Interface")
- flow.prop(view, "use_translate_new_dataname", text="New Data")
+ col = layout.column(heading="Affect")
+ col.active = (bpy.app.translations.locale != 'en_US')
+ col.prop(view, "use_translate_tooltips", text="Tooltips")
+ col.prop(view, "use_translate_interface", text="Interface")
+ col.prop(view, "use_translate_new_dataname", text="New Data")
class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel):
@@ -256,14 +260,13 @@ class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel):
view = prefs.view
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(system, "use_region_overlap")
- flow.prop(view, "show_layout_ui", text="Corner Splitting")
- flow.prop(view, "show_navigate_ui")
- flow.prop(view, "color_picker_type")
- flow.row().prop(view, "header_align")
- flow.prop(view, "factor_display_type")
+ col = layout.column()
+ col.prop(system, "use_region_overlap")
+ col.prop(view, "show_layout_ui", text="Corner Splitting")
+ col.prop(view, "show_navigate_ui")
+ col.prop(view, "color_picker_type")
+ col.row().prop(view, "header_align")
+ col.prop(view, "factor_display_type")
class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn, Panel):
@@ -275,10 +278,9 @@ class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn,
prefs = context.preferences
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "render_display_type", text="Render in")
- flow.prop(view, "filebrowser_display_type", text="File Browser")
+ col = layout.column()
+ col.prop(view, "render_display_type", text="Render in")
+ col.prop(view, "filebrowser_display_type", text="File Browser")
class USERPREF_PT_interface_menus(InterfacePanel, Panel):
@@ -358,6 +360,7 @@ class USERPREF_PT_edit_objects_new(EditingPanel, CenterAlignMixIn, Panel):
flow.prop(edit, "material_link", text="Link Materials to")
flow.prop(edit, "object_align", text="Align to")
flow.prop(edit, "use_enter_edit_mode", text="Enter Edit Mode")
+ flow.prop(edit, "collection_instance_empty_size", text="Instance Empty Size")
class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Panel):
@@ -368,6 +371,8 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
prefs = context.preferences
edit = prefs.edit
+ layout.use_property_split = False
+
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
col = flow.column()
@@ -375,18 +380,23 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
col.prop(edit, "use_duplicate_armature", text="Armature")
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.prop(edit, "use_duplicate_lightprobe", text="Light Probe")
col = flow.column()
+ 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()
+ if hasattr(edit, "use_duplicate_pointcloud"):
+ col.prop(edit, "use_duplicate_pointcloud", text="Point Cloud")
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.
- col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
+ col.prop(edit, "use_duplicate_volume", text="Volume")
class USERPREF_PT_edit_cursor(EditingPanel, CenterAlignMixIn, Panel):
@@ -396,10 +406,9 @@ class USERPREF_PT_edit_cursor(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "use_mouse_depth_cursor")
- flow.prop(edit, "use_cursor_lock_adjust")
+ col = layout.column()
+ col.prop(edit, "use_mouse_depth_cursor")
+ col.prop(edit, "use_cursor_lock_adjust")
class USERPREF_PT_edit_gpencil(EditingPanel, CenterAlignMixIn, Panel):
@@ -410,10 +419,9 @@ class USERPREF_PT_edit_gpencil(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance")
- flow.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance")
+ col = layout.column(heading="Distance")
+ col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan")
+ col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean")
class USERPREF_PT_edit_annotations(EditingPanel, CenterAlignMixIn, Panel):
@@ -423,10 +431,9 @@ class USERPREF_PT_edit_annotations(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "grease_pencil_default_color", text="Default Color")
- flow.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
+ col = layout.column()
+ col.prop(edit, "grease_pencil_default_color", text="Default Color")
+ col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
@@ -437,6 +444,8 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
view = prefs.view
+ layout.use_property_split = False
+
layout.prop(view, "use_weight_color_range", text="Use Custom Colors")
col = layout.column()
@@ -452,10 +461,9 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color")
- flow.prop(edit, "node_margin", text="Node Auto-offset Margin")
+ col = layout.column()
+ col.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color")
+ col.prop(edit, "node_margin", text="Node Auto-offset Margin")
# -----------------------------------------------------------------------------
@@ -475,20 +483,16 @@ class USERPREF_PT_animation_timeline(AnimationPanel, CenterAlignMixIn, Panel):
view = prefs.view
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
- flow.prop(edit, "use_negative_frames")
-
- layout.separator()
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(edit, "use_negative_frames")
- flow.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
- flow.prop(view, "timecode_style")
- flow.prop(view, "view_frame_type")
+ col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
+ col.prop(view, "timecode_style")
+ col.prop(view, "view_frame_type")
if view.view_frame_type == 'SECONDS':
- flow.prop(view, "view_frame_seconds")
+ col.prop(view, "view_frame_seconds")
elif view.view_frame_type == 'KEYFRAMES':
- flow.prop(view, "view_frame_keyframes")
+ col.prop(view, "view_frame_keyframes")
class USERPREF_PT_animation_keyframes(AnimationPanel, CenterAlignMixIn, Panel):
@@ -498,25 +502,14 @@ class USERPREF_PT_animation_keyframes(AnimationPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "use_visual_keying")
- flow.prop(edit, "use_keyframe_insert_needed", text="Only Insert Needed")
-
-
-class USERPREF_PT_animation_autokey(AnimationPanel, CenterAlignMixIn, Panel):
- bl_label = "Auto-Keyframing"
- bl_parent_id = "USERPREF_PT_animation_keyframes"
-
- def draw_centered(self, context, layout):
- prefs = context.preferences
- edit = prefs.edit
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(edit, "use_visual_keying")
+ col.prop(edit, "use_keyframe_insert_needed", text="Only Insert Needed")
- flow.prop(edit, "use_auto_keying_warning", text="Show Warning")
- flow.prop(edit, "use_keyframe_insert_available", text="Only Insert Available")
- flow.prop(edit, "use_auto_keying", text="Enable in New Scenes")
+ col = layout.column(heading="Auto-Keyframing")
+ col.prop(edit, "use_auto_keying_warning", text="Show Warning")
+ col.prop(edit, "use_keyframe_insert_available", text="Only Insert Available")
+ col.prop(edit, "use_auto_keying", text="Enable in New Scenes")
class USERPREF_PT_animation_fcurves(AnimationPanel, CenterAlignMixIn, Panel):
@@ -546,6 +539,7 @@ class SystemPanel:
class USERPREF_PT_system_sound(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "Sound"
+ bl_options = {'DEFAULT_CLOSED'}
def draw_centered(self, context, layout):
prefs = context.preferences
@@ -591,32 +585,47 @@ class USERPREF_PT_system_memory(SystemPanel, CenterAlignMixIn, Panel):
system = prefs.system
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "undo_steps", text="Undo Steps")
- flow.prop(edit, "undo_memory_limit", text="Undo Memory Limit")
- flow.prop(edit, "use_global_undo")
+ col = layout.column()
+ col.prop(edit, "undo_steps", text="Undo Steps")
+ col.prop(edit, "undo_memory_limit", text="Undo Memory Limit")
+ col.prop(edit, "use_global_undo")
layout.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(system, "scrollback", text="Console Scrollback Lines")
- flow.prop(system, "memory_cache_limit", text="Sequencer Cache Limit")
- flow.prop(system, "scrollback", text="Console Scrollback Lines")
+ layout.separator()
+
+ col = layout.column()
+ col.prop(system, "texture_time_out", text="Texture Time Out")
+ col.prop(system, "texture_collection_rate", text="Garbage Collection Rate")
layout.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(system, "vbo_time_out", text="Vbo Time Out")
+ col.prop(system, "vbo_collection_rate", text="Garbage Collection Rate")
- flow.prop(system, "texture_time_out", text="Texture Time Out")
- flow.prop(system, "texture_collection_rate", text="Garbage Collection Rate")
- layout.separator()
+class USERPREF_PT_system_video_sequencer(SystemPanel, CenterAlignMixIn, Panel):
+ bl_label = "Video Sequencer"
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ def draw_centered(self, context, layout):
+ prefs = context.preferences
+ system = prefs.system
+ edit = prefs.edit
+
+ layout.prop(system, "memory_cache_limit")
+
+ layout.separator()
- flow.prop(system, "vbo_time_out", text="Vbo Time Out")
- flow.prop(system, "vbo_collection_rate", text="Garbage Collection Rate")
+ layout.prop(system, "use_sequencer_disk_cache")
+ col = layout.column()
+ col.active = system.use_sequencer_disk_cache
+ col.prop(system, "sequencer_disk_cache_dir", text="Directory")
+ col.prop(system, "sequencer_disk_cache_size_limit", text="Cache Limit")
+ col.prop(system, "sequencer_disk_cache_compression", text="Compression")
# -----------------------------------------------------------------------------
@@ -635,23 +644,19 @@ class USERPREF_PT_viewport_display(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "show_object_info", text="Object Info")
- flow.prop(view, "show_view_name", text="View Name")
- flow.prop(view, "show_playback_fps", text="Playback FPS")
+ col = layout.column(heading="Show")
+ col.prop(view, "show_object_info", text="Object Info")
+ col.prop(view, "show_view_name", text="View Name")
+ col.prop(view, "show_playback_fps", text="Playback FPS")
layout.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column()
col.prop(view, "gizmo_size")
col.prop(view, "lookdev_sphere_size")
- flow.separator()
+ col.separator()
- col = flow.column()
col.prop(view, "mini_axis_type", text="3D Viewport Axis")
if view.mini_axis_type == 'MINIMAL':
@@ -666,12 +671,12 @@ class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(system, "viewport_aa")
- flow.prop(system, "viewport_aa")
- flow.prop(system, "gpencil_multi_sample", text="Grease Pencil Multisampling")
- flow.prop(system, "use_overlay_smooth_wire")
- flow.prop(system, "use_edit_mode_smooth_wire")
+ col = layout.column(heading="Smooth Wires")
+ col.prop(system, "use_overlay_smooth_wire", text="Overlay")
+ col.prop(system, "use_edit_mode_smooth_wire", text="Edit Mode")
class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel):
@@ -681,12 +686,11 @@ class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(system, "gl_texture_limit", text="Limit Size")
- flow.prop(system, "anisotropic_filter")
- flow.prop(system, "gl_clip_alpha", slider=True)
- flow.prop(system, "image_draw_method", text="Image Display Method")
+ col = layout.column()
+ col.prop(system, "gl_texture_limit", text="Limit Size")
+ col.prop(system, "anisotropic_filter")
+ col.prop(system, "gl_clip_alpha", slider=True)
+ col.prop(system, "image_draw_method", text="Image Display Method")
class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel):
@@ -697,9 +701,7 @@ class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(system, "use_select_pick_depth")
+ layout.prop(system, "use_select_pick_depth")
# -----------------------------------------------------------------------------
@@ -861,14 +863,31 @@ class USERPREF_PT_theme_interface_styles(ThemePanel, CenterAlignMixIn, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(ui, "menu_shadow_fac")
+ flow.prop(ui, "menu_shadow_width")
flow.prop(ui, "icon_alpha")
flow.prop(ui, "icon_saturation")
flow.prop(ui, "editor_outline")
flow.prop(ui, "widget_text_cursor")
- flow.prop(ui, "menu_shadow_width")
flow.prop(ui, "widget_emboss")
+class USERPREF_PT_theme_interface_transparent_checker(ThemePanel, CenterAlignMixIn, Panel):
+ bl_label = "Transparent Checkerboard"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = "USERPREF_PT_theme_user_interface"
+
+ def draw_centered(self, context, layout):
+ theme = context.preferences.themes[0]
+ ui = theme.user_interface
+
+ flow = layout.grid_flow(
+ row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+
+ flow.prop(ui, "transparent_checker_primary")
+ flow.prop(ui, "transparent_checker_secondary")
+ flow.prop(ui, "transparent_checker_size")
+
+
class USERPREF_PT_theme_interface_gizmos(ThemePanel, CenterAlignMixIn, Panel):
bl_label = "Axis & Gizmo Colors"
bl_options = {'DEFAULT_CLOSED'}
@@ -888,6 +907,7 @@ class USERPREF_PT_theme_interface_gizmos(ThemePanel, CenterAlignMixIn, Panel):
col = flow.column()
col.prop(ui, "gizmo_primary")
col.prop(ui, "gizmo_secondary")
+ col.prop(ui, "gizmo_view_align")
col = flow.column()
col.prop(ui, "gizmo_a")
@@ -1289,37 +1309,40 @@ class USERPREF_PT_saveload_blend(SaveLoadPanel, CenterAlignMixIn, Panel):
paths = prefs.filepaths
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column(heading="Save")
+ col.prop(view, "use_save_prompt")
+ col.prop(paths, "use_save_preview_images")
- flow.prop(paths, "use_relative_paths")
- flow.prop(paths, "use_file_compression")
- flow.prop(paths, "use_load_ui")
- flow.prop(paths, "use_save_preview_images")
- flow.prop(paths, "use_tabs_as_spaces")
- flow.prop(view, "use_save_prompt")
+ col = layout.column(heading="Default to")
+ col.prop(paths, "use_relative_paths")
+ col.prop(paths, "use_file_compression")
+ col.prop(paths, "use_load_ui")
- layout.separator()
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column(heading="Text Files")
+ col.prop(paths, "use_tabs_as_spaces")
- flow.prop(paths, "save_version")
- flow.prop(paths, "recent_files")
+ col = layout.column()
+ col.prop(paths, "save_version")
+ col.prop(paths, "recent_files")
class USERPREF_PT_saveload_blend_autosave(SaveLoadPanel, CenterAlignMixIn, Panel):
bl_label = "Auto Save"
bl_parent_id = "USERPREF_PT_saveload_blend"
- def draw_centered(self, context, layout):
+ def draw_header(self, context):
prefs = context.preferences
paths = prefs.filepaths
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ self.layout.prop(paths, "use_auto_save_temporary_files", text="")
- flow.prop(paths, "use_auto_save_temporary_files")
- sub = flow.column()
- sub.active = paths.use_auto_save_temporary_files
- sub.prop(paths, "auto_save_time", text="Timer (mins)")
+ def draw_centered(self, context, layout):
+ prefs = context.preferences
+ paths = prefs.filepaths
+
+ col = layout.column()
+ col.active = paths.use_auto_save_temporary_files
+ col.prop(paths, "auto_save_time", text="Timer (mins)")
class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel):
@@ -1329,12 +1352,13 @@ class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
paths = prefs.filepaths
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(paths, "use_filter_files")
- flow.prop(paths, "use_filter_files")
- flow.prop(paths, "show_hidden_files_datablocks")
- flow.prop(paths, "hide_recent_locations")
- flow.prop(paths, "hide_system_bookmarks")
+ col = layout.column(heading="Hide")
+ col.prop(paths, "show_hidden_files_datablocks", text="Dot File & Datablocks")
+ col.prop(paths, "hide_recent_locations", text="Recent Locations")
+ col.prop(paths, "hide_system_bookmarks", text="System Bookmarks")
# -----------------------------------------------------------------------------
@@ -1393,10 +1417,9 @@ class USERPREF_PT_input_tablet(InputPanel, CenterAlignMixIn, Panel):
layout.prop(inputs, "tablet_api")
layout.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(inputs, "pressure_threshold_max")
- flow.prop(inputs, "pressure_softness")
+ col = layout.column()
+ col.prop(inputs, "pressure_threshold_max")
+ col.prop(inputs, "pressure_softness")
class USERPREF_PT_input_ndof(InputPanel, CenterAlignMixIn, Panel):
@@ -1443,24 +1466,27 @@ class USERPREF_PT_navigation_orbit(NavigationPanel, CenterAlignMixIn, Panel):
inputs = prefs.inputs
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
- flow.row().prop(inputs, "view_rotate_method", expand=True)
+ col.row().prop(inputs, "view_rotate_method", expand=True)
if inputs.view_rotate_method == 'TURNTABLE':
- flow.prop(inputs, "view_rotate_sensitivity_turntable")
+ col.prop(inputs, "view_rotate_sensitivity_turntable")
else:
- flow.prop(inputs, "view_rotate_sensitivity_trackball")
+ col.prop(inputs, "view_rotate_sensitivity_trackball")
+ col.prop(inputs, "use_rotate_around_active")
+
+ col.separator()
- flow.prop(inputs, "use_rotate_around_active")
- flow.prop(inputs, "use_auto_perspective")
- flow.prop(inputs, "use_mouse_depth_navigate")
if sys.platform == "darwin":
- flow.prop(inputs, "use_trackpad_natural", text="Natural Trackpad Direction")
+ col.prop(inputs, "use_trackpad_natural", text="Natural Trackpad Direction")
- flow.separator()
+ col = layout.column(heading="Auto")
+ col.prop(inputs, "use_auto_perspective", text="Perspective")
+ col.prop(inputs, "use_mouse_depth_navigate", text="Depth")
- flow.prop(view, "smooth_view")
- flow.prop(view, "rotation_angle")
+ col = layout.column()
+ col.prop(view, "smooth_view")
+ col.prop(view, "rotation_angle")
class USERPREF_PT_navigation_zoom(NavigationPanel, CenterAlignMixIn, Panel):
@@ -1470,16 +1496,20 @@ class USERPREF_PT_navigation_zoom(NavigationPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
inputs = prefs.inputs
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
- flow.row().prop(inputs, "view_zoom_method", text="Zoom Method", expand=True)
+ col.row().prop(inputs, "view_zoom_method", text="Zoom Method")
if inputs.view_zoom_method in {'DOLLY', 'CONTINUE'}:
- flow.row().prop(inputs, "view_zoom_axis", expand=True)
- flow.prop(inputs, "invert_mouse_zoom", text="Invert Mouse Zoom Direction")
+ col.row().prop(inputs, "view_zoom_axis")
+ col.prop(inputs, "use_zoom_to_mouse")
+ col = layout.column(heading="Invert Zoom Direction", align=True)
+ col.prop(inputs, "invert_mouse_zoom", text="Mouse")
+ col.prop(inputs, "invert_zoom_wheel", text="Wheel")
+ else:
+ col.prop(inputs, "use_zoom_to_mouse")
+ col.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction")
- flow.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction")
# sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
- flow.prop(inputs, "use_zoom_to_mouse")
class USERPREF_PT_navigation_fly_walk(NavigationPanel, CenterAlignMixIn, Panel):
@@ -1510,15 +1540,14 @@ class USERPREF_PT_navigation_fly_walk_navigation(NavigationPanel, CenterAlignMix
inputs = prefs.inputs
walk = inputs.walk_navigation
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(walk, "use_mouse_reverse")
- flow.prop(walk, "mouse_speed")
- flow.prop(walk, "teleport_time")
+ col = layout.column()
+ col.prop(walk, "use_mouse_reverse")
+ col.prop(walk, "mouse_speed")
+ col.prop(walk, "teleport_time")
- sub = flow.column(align=True)
- sub.prop(walk, "walk_speed")
- sub.prop(walk, "walk_speed_factor")
+ col = layout.column(align=True)
+ col.prop(walk, "walk_speed")
+ col.prop(walk, "walk_speed_factor")
class USERPREF_PT_navigation_fly_walk_gravity(NavigationPanel, CenterAlignMixIn, Panel):
@@ -1545,10 +1574,9 @@ class USERPREF_PT_navigation_fly_walk_gravity(NavigationPanel, CenterAlignMixIn,
layout.active = walk.use_gravity
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(walk, "view_height")
- flow.prop(walk, "jump_height")
+ col = layout.column()
+ col.prop(walk, "view_height")
+ col.prop(walk, "jump_height")
# Special case, this is only exposed as a popover.
@@ -1837,7 +1865,7 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
# 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(text="Upgrade to 2.8x required")
sub.label(icon='ERROR')
# Remove code above after 2.8x migration is complete.
elif info["warning"]:
@@ -1874,16 +1902,16 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
split.label(text=" " + info["warning"], icon='ERROR')
user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
- tot_row = bool(info["wiki_url"]) + bool(user_addon)
+ tot_row = bool(info["doc_url"]) + bool(user_addon)
if tot_row:
split = colsub.row().split(factor=0.15)
split.label(text="Internet:")
sub = split.row()
- if info["wiki_url"]:
+ if info["doc_url"]:
sub.operator(
"wm.url_open", text="Documentation", icon='HELP',
- ).url = info["wiki_url"]
+ ).url = info["doc_url"]
# Only add "Report a Bug" button if tracker_url is set
# or the add-on is bundled (use official tracker then).
if info.get("tracker_url"):
@@ -2088,6 +2116,21 @@ class ExperimentalPanel:
url_prefix = "https://developer.blender.org/"
+ def _draw_items(self, context, items):
+ prefs = context.preferences
+ experimental = prefs.experimental
+
+ layout = self.layout
+ layout.use_property_split = False
+ layout.use_property_decorate = False
+
+ for prop_keywords, task in items:
+ split = layout.split(factor=0.66)
+ col = split.split()
+ col.prop(experimental, **prop_keywords)
+ col = split.split()
+ col.operator("wm.url_open", text=task, icon='URL').url = self.url_prefix + task
+
"""
# Example panel, leave it here so we always have a template to follow even
# after the features are gone from the experimental panel.
@@ -2096,27 +2139,24 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel):
bl_label = "Virtual Reality"
def draw(self, context):
- prefs = context.preferences
- experimental = prefs.experimental
+ self._draw_items(
+ context, (
+ ({"property": "use_virtual_reality_scene_inspection"}, "T71347"),
+ ({"property": "use_virtual_reality_immersive_drawing"}, "T71348"),
+ )
+ )
+"""
- layout = self.layout
- layout.use_property_split = True
- layout.use_property_decorate = False
- task = "T71347"
- split = layout.split(factor=0.66)
- col = split.split()
- col.prop(experimental, "use_virtual_reality_scene_inspection", text="Scene Inspection")
- col = split.split()
- col.operator("wm.url_open", text=task, icon='URL').url = self.url_prefix + task
-
- task = "T71348"
- split = layout.split(factor=0.66)
- col = split.column()
- col.prop(experimental, "use_virtual_reality_immersive_drawing", text="Continuous Immersive Drawing")
- col = split.column()
- col.operator("wm.url_open", text=task, icon='URL').url = self.url_prefix + task
-"""
+class USERPREF_PT_experimental_system(ExperimentalPanel, Panel):
+ bl_label = "System"
+
+ def draw(self, context):
+ self._draw_items(
+ context, (
+ ({"property": "use_undo_legacy"}, "T60695"),
+ ),
+ )
# -----------------------------------------------------------------------------
@@ -2130,6 +2170,8 @@ classes = (
USERPREF_HT_header,
USERPREF_PT_navigation_bar,
USERPREF_PT_save_preferences,
+ USERPREF_MT_editor_menus,
+ USERPREF_MT_view,
USERPREF_MT_save_load,
USERPREF_PT_interface_display,
@@ -2157,11 +2199,11 @@ classes = (
USERPREF_PT_animation_timeline,
USERPREF_PT_animation_keyframes,
- USERPREF_PT_animation_autokey,
USERPREF_PT_animation_fcurves,
USERPREF_PT_system_cycles_devices,
USERPREF_PT_system_memory,
+ USERPREF_PT_system_video_sequencer,
USERPREF_PT_system_sound,
USERPREF_MT_interface_theme_presets,
@@ -2169,6 +2211,7 @@ classes = (
USERPREF_PT_theme_interface_state,
USERPREF_PT_theme_interface_styles,
USERPREF_PT_theme_interface_gizmos,
+ USERPREF_PT_theme_interface_transparent_checker,
USERPREF_PT_theme_interface_icons,
USERPREF_PT_theme_text_style,
USERPREF_PT_theme_bone_color_sets,
@@ -2206,6 +2249,8 @@ classes = (
# Popovers.
USERPREF_PT_ndof_settings,
+ USERPREF_PT_experimental_system,
+
# Add dynamically generated editor theme panels last,
# so they show up last in the theme section.
*ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(),
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index aa8f343e1a0..61d5d79473f 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -31,6 +31,7 @@ from bl_ui.properties_grease_pencil_common import (
AnnotationDataPanel,
AnnotationOnionSkin,
GreasePencilMaterialsPanel,
+ GreasePencilVertexcolorPanel,
)
from bl_ui.space_toolsystem_common import (
ToolActivePanelHelper,
@@ -119,21 +120,26 @@ class VIEW3D_HT_tool_header(Header):
if is_valid_context:
brush = context.tool_settings.gpencil_paint.brush
if brush.gpencil_tool != 'ERASE':
- layout.popover("VIEW3D_PT_tools_grease_pencil_brush_advanced")
+ if brush.gpencil_tool != 'TINT':
+ layout.popover("VIEW3D_PT_tools_grease_pencil_brush_advanced")
- if brush.gpencil_tool != 'FILL':
+ if brush.gpencil_tool not in {'FILL', 'TINT'}:
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_stroke")
- layout.popover("VIEW3D_PT_tools_grease_pencil_brushcurves")
layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance")
elif tool_mode == 'SCULPT_GPENCIL':
- settings = context.tool_settings.gpencil_sculpt
- tool = settings.sculpt_tool
- if tool in {'SMOOTH', 'RANDOMIZE', 'SMOOTH'}:
- layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_options")
- layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
+ if is_valid_context:
+ brush = context.tool_settings.gpencil_sculpt_paint.brush
+ tool = brush.gpencil_tool
+ if tool in ('SMOOTH', 'RANDOMIZE'):
+ layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_options")
+ layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
elif tool_mode == 'WEIGHT_GPENCIL':
- layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
+ if is_valid_context:
+ layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
+ elif tool_mode == 'VERTEX_GPENCIL':
+ if is_valid_context:
+ layout.popover("VIEW3D_PT_tools_grease_pencil_vertex_appearance")
def draw_mode_settings(self, context):
layout = self.layout
@@ -386,7 +392,7 @@ class _draw_tool_settings_context_mode:
}:
# is_paint = False
pass
- elif tool.idname == "Cutter":
+ elif tool.idname == "builtin.cutter":
row = layout.row(align=True)
row.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
return False
@@ -425,6 +431,15 @@ class _draw_tool_settings_context_mode:
row.prop(gp_settings, "use_material_pin", text="")
+ if brush.gpencil_tool in {'DRAW', 'FILL'} and ma:
+ row.separator(factor=1.0)
+ subrow = row.row(align=True)
+ row.prop_enum(settings, "color_mode", 'MATERIAL', text="", icon='MATERIAL')
+ row.prop_enum(settings, "color_mode", 'VERTEXCOLOR', text="", icon='VPAINT_HLT')
+ sub_row = row.row(align=True)
+ sub_row.enabled = settings.color_mode == 'VERTEXCOLOR'
+ sub_row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
+
row = layout.row(align=True)
tool_settings = context.scene.tool_settings
settings = tool_settings.gpencil_paint
@@ -433,6 +448,10 @@ class _draw_tool_settings_context_mode:
if context.object and brush.gpencil_tool in {'FILL', 'DRAW'}:
draw_color_selector()
+ if context.object and brush.gpencil_tool == 'TINT':
+ row.separator(factor=0.4)
+ row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
+
from bl_ui.properties_paint_common import (
brush_basic_gpencil_paint_settings,
)
@@ -444,9 +463,8 @@ class _draw_tool_settings_context_mode:
def SCULPT_GPENCIL(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return False
- tool_settings = context.tool_settings
- settings = tool_settings.gpencil_sculpt
- brush = settings.brush
+ paint = context.tool_settings.gpencil_sculpt_paint
+ brush = paint.brush
from bl_ui.properties_paint_common import (
brush_basic_gpencil_sculpt_settings,
@@ -459,9 +477,8 @@ class _draw_tool_settings_context_mode:
def WEIGHT_GPENCIL(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return False
- tool_settings = context.tool_settings
- settings = tool_settings.gpencil_sculpt
- brush = settings.brush
+ paint = context.tool_settings.gpencil_weight_paint
+ brush = paint.brush
from bl_ui.properties_paint_common import (
brush_basic_gpencil_weight_settings,
@@ -471,6 +488,31 @@ class _draw_tool_settings_context_mode:
return True
@staticmethod
+ def VERTEX_GPENCIL(context, layout, tool):
+ if (tool is None) or (not tool.has_datablock):
+ return False
+
+ paint = context.tool_settings.gpencil_vertex_paint
+ brush = paint.brush
+
+ row = layout.row(align=True)
+ tool_settings = context.scene.tool_settings
+ settings = tool_settings.gpencil_vertex_paint
+ row.template_ID_preview(settings, "brush", rows=3, cols=8, hide_buttons=True)
+
+ if brush.gpencil_vertex_tool not in {'BLUR', 'AVERAGE', 'SMEAR'}:
+ row.separator(factor=0.4)
+ row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
+
+ from bl_ui.properties_paint_common import (
+ brush_basic_gpencil_vertex_settings,
+ )
+
+ brush_basic_gpencil_vertex_settings(layout, context, brush, compact=True)
+
+ return True
+
+ @staticmethod
def PARTICLE(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return False
@@ -550,7 +592,7 @@ class VIEW3D_HT_header(Header):
else:
if (object_mode not in {
'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
- 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'
+ 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'
}) or has_pose_mode:
show_snap = True
else:
@@ -687,7 +729,14 @@ class VIEW3D_HT_header(Header):
row.prop(tool_settings, "use_gpencil_select_mask_stroke", text="")
row.prop(tool_settings, "use_gpencil_select_mask_segment", text="")
- if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode:
+ # Select mode for Vertex Paint
+ if gpd.is_stroke_vertex_mode:
+ row = layout.row(align=True)
+ row.prop(tool_settings, "use_gpencil_vertex_select_mask_point", text="")
+ row.prop(tool_settings, "use_gpencil_vertex_select_mask_stroke", text="")
+ row.prop(tool_settings, "use_gpencil_vertex_select_mask_segment", text="")
+
+ if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode or gpd.is_stroke_vertex_mode:
row = layout.row(align=True)
row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING')
@@ -780,18 +829,17 @@ class VIEW3D_HT_header(Header):
# While exposing 'shading.show_xray(_wireframe)' is correct.
# this hides the key shortcut from users: T70433.
+ if has_pose_mode:
+ draw_depressed = overlay.show_xray_bone
+ elif shading.type == 'WIREFRAME':
+ draw_depressed = shading.show_xray_wireframe
+ else:
+ draw_depressed = shading.show_xray
row.operator(
"view3d.toggle_xray",
text="",
icon='XRAY',
- depress=(
- overlay.show_xray_bone if has_pose_mode else
- getattr(
- shading,
- "show_xray_wireframe" if shading.type == 'WIREFRAME' else
- "show_xray"
- )
- ),
+ depress=draw_depressed,
)
row = layout.row(align=True)
@@ -812,7 +860,8 @@ class VIEW3D_MT_editor_menus(Menu):
obj = context.active_object
mode_string = context.mode
edit_object = context.edit_object
- gp_edit = obj and obj.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}
+ gp_edit = obj and obj.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL',
+ 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}
ts = context.scene.tool_settings
layout.menu("VIEW3D_MT_view")
@@ -827,6 +876,8 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("VIEW3D_MT_select_gpencil")
elif mode_string == 'EDIT_GPENCIL':
layout.menu("VIEW3D_MT_select_gpencil")
+ elif mode_string == 'VERTEX_GPENCIL':
+ layout.menu("VIEW3D_MT_select_gpencil")
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
mesh = obj.data
if mesh.use_paint_mask:
@@ -878,6 +929,7 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("VIEW3D_MT_%s" % mode_string.lower())
if mode_string == 'SCULPT':
layout.menu("VIEW3D_MT_mask")
+ layout.menu("VIEW3D_MT_face_sets")
else:
layout.menu("VIEW3D_MT_object")
@@ -939,6 +991,7 @@ class VIEW3D_MT_transform(VIEW3D_MT_transform_base):
layout = self.layout
if context.mode == 'EDIT_MESH':
layout.operator("transform.shrink_fatten", text="Shrink Fatten")
+ layout.operator("transform.skin_resize")
elif context.mode == 'EDIT_CURVE':
layout.operator("transform.transform", text="Radius").mode = 'CURVE_SHRINKFATTEN'
@@ -1110,7 +1163,7 @@ class VIEW3D_MT_view(Menu):
if view.region_quadviews:
layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True
- layout.operator("view3d.view_all", text="Frame All").center = False
+ layout.operator("view3d.view_all").center = False
layout.operator("view3d.view_persportho", text="Perspective/Orthographic")
layout.menu("VIEW3D_MT_view_local")
@@ -1241,7 +1294,7 @@ class VIEW3D_MT_view_align(Menu):
layout.separator()
- layout.operator("view3d.view_all", text="Center Cursor and View All").center = True
+ layout.operator("view3d.view_all", text="Center Cursor and Frame All").center = True
layout.operator("view3d.view_center_cursor")
layout.separator()
@@ -1443,7 +1496,7 @@ class VIEW3D_MT_select_particle(Menu):
layout.separator()
- layout.operator("particle.select_linked")
+ layout.operator("particle.select_linked", text="Select Linked")
layout.separator()
@@ -1652,60 +1705,33 @@ class VIEW3D_MT_select_edit_surface(Menu):
layout.operator("curve.select_less")
-class VIEW3D_MT_edit_text_context_menu(Menu):
- bl_label = "Text Context Menu"
-
- def draw(self, _context):
- layout = self.layout
-
- layout.operator_context = 'INVOKE_DEFAULT'
-
- layout.operator("font.text_cut", text="Cut")
- layout.operator("font.text_copy", text="Copy", icon='COPYDOWN')
- layout.operator("font.text_paste", text="Paste", icon='PASTEDOWN')
-
- layout.separator()
-
- layout.operator("font.select_all")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_font")
-
-
class VIEW3D_MT_select_edit_text(Menu):
- # intentional name mismatch
- # select menu for 3d-text doesn't make sense
- bl_label = "Edit"
+ bl_label = "Select"
def draw(self, _context):
layout = self.layout
- layout.operator("ed.undo")
- layout.operator("ed.redo")
-
- layout.separator()
-
- layout.operator("font.text_cut", text="Cut")
- layout.operator("font.text_copy", text="Copy", icon='COPYDOWN')
- layout.operator("font.text_paste", text="Paste", icon='PASTEDOWN')
+ layout.operator("font.select_all", text="All")
layout.separator()
- layout.operator("font.text_paste_from_file")
+ layout.operator("font.move_select", text="Previous Block").type = 'PREVIOUS_PAGE'
+ layout.operator("font.move_select", text="Next Block").type = 'NEXT_PAGE'
layout.separator()
- layout.operator("font.select_all")
+ layout.operator("font.move_select", text="Line Begin").type = 'LINE_BEGIN'
+ layout.operator("font.move_select", text="Line End").type = 'LINE_END'
layout.separator()
- layout.operator("font.case_set", text="To Uppercase").case = 'UPPER'
- layout.operator("font.case_set", text="To Lowercase").case = 'LOWER'
+ layout.operator("font.move_select", text="Previous Line").type = 'PREVIOUS_LINE'
+ layout.operator("font.move_select", text="Next Line").type = 'NEXT_LINE'
layout.separator()
- layout.menu("VIEW3D_MT_edit_text_chars")
+ layout.operator("font.move_select", text="Previous Word").type = 'PREVIOUS_WORD'
+ layout.operator("font.move_select", text="Next Word").type = 'NEXT_WORD'
class VIEW3D_MT_select_edit_metaball(Menu):
@@ -1805,6 +1831,10 @@ class VIEW3D_MT_select_edit_armature(Menu):
layout.separator()
+ layout.operator("armature.select_linked", text="Linked")
+
+ layout.separator()
+
props = layout.operator("armature.select_hierarchy", text="Parent")
props.extend = False
props.direction = 'PARENT'
@@ -1848,6 +1878,9 @@ class VIEW3D_MT_select_gpencil(Menu):
layout.operator("gpencil.select_alternate")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
+ if _context.mode == 'VERTEX_GPENCIL':
+ layout.operator("gpencil.select_vertex_color", text="Vertex Color")
+
layout.separator()
layout.operator("gpencil.select_first")
@@ -2100,6 +2133,16 @@ class VIEW3D_MT_camera_add(Menu):
layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
+class VIEW3D_MT_volume_add(Menu):
+ bl_idname = "VIEW3D_MT_volume_add"
+ bl_label = "Volume"
+
+ def draw(self, _context):
+ layout = self.layout
+ layout.operator("object.volume_import", text="Import OpenVDB...", icon='OUTLINER_DATA_VOLUME')
+ layout.operator("object.volume_add", text="Empty", icon='OUTLINER_DATA_VOLUME')
+
+
class VIEW3D_MT_add(Menu):
bl_label = "Add"
bl_translation_context = i18n_contexts.operator_default
@@ -2122,6 +2165,11 @@ class VIEW3D_MT_add(Menu):
layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE')
layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
+ if hasattr(bpy.data, "hairs"):
+ layout.operator("object.hair_add", text="Hair", icon='OUTLINER_OB_HAIR')
+ if hasattr(bpy.data, "pointclouds"):
+ layout.operator("object.pointcloud_add", text="Point Cloud", icon='OUTLINER_OB_POINTCLOUD')
+ layout.menu("VIEW3D_MT_volume_add", text="Volume", icon='OUTLINER_OB_VOLUME')
layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
layout.separator()
@@ -2713,6 +2761,7 @@ class VIEW3D_MT_make_single_user(Menu):
def draw(self, _context):
layout = self.layout
+ layout.operator_context = 'EXEC_DEFAULT'
props = layout.operator("object.make_single_user", text="Object")
props.object = True
@@ -2866,6 +2915,32 @@ class VIEW3D_MT_gpencil_vertex_group(Menu):
layout.operator("gpencil.vertex_group_deselect", text="Deselect")
+class VIEW3D_MT_paint_weight_lock(Menu):
+ bl_label = "Vertex Group Locks"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ op = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
+ op.action, op.mask = 'LOCK', 'ALL'
+ op = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
+ op.action, op.mask = 'UNLOCK', 'ALL'
+ op = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Selected")
+ op.action, op.mask = 'LOCK', 'SELECTED'
+ op = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock Selected")
+ op.action, op.mask = 'UNLOCK', 'SELECTED'
+ op = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Unselected")
+ op.action, op.mask = 'LOCK', 'UNSELECTED'
+ op = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock Unselected")
+ op.action, op.mask = 'UNLOCK', 'UNSELECTED'
+ op = layout.operator("object.vertex_group_lock", text="Lock Only Selected")
+ op.action, op.mask = 'LOCK', 'INVERT_UNSELECTED'
+ op = layout.operator("object.vertex_group_lock", text="Lock Only Unselected")
+ op.action, op.mask = 'UNLOCK', 'INVERT_UNSELECTED'
+ op = layout.operator("object.vertex_group_lock", text="Invert Locks")
+ op.action, op.mask = 'INVERT', 'ALL'
+
+
class VIEW3D_MT_paint_weight(Menu):
bl_label = "Weights"
@@ -2907,6 +2982,8 @@ class VIEW3D_MT_paint_weight(Menu):
layout.operator("paint.weight_set")
+ layout.menu("VIEW3D_MT_paint_weight_lock", text="Locks")
+
def draw(self, _context):
self.draw_generic(self.layout, is_editmode=False)
@@ -2937,6 +3014,10 @@ class VIEW3D_MT_sculpt(Menu):
layout.menu("VIEW3D_MT_sculpt_set_pivot", text="Set Pivot")
+ layout.separator()
+
+ layout.operator("sculpt.optimize")
+
class VIEW3D_MT_mask(Menu):
bl_label = "Mask"
@@ -2991,12 +3072,14 @@ class VIEW3D_MT_mask(Menu):
props.keep_previous_mask = False
props.invert = True
props.smooth_iterations = 2
+ props.create_face_set = False
props = layout.operator("sculpt.mask_expand", text="Expand Mask By Curvature")
props.use_normals = True
props.keep_previous_mask = True
props.invert = False
props.smooth_iterations = 0
+ props.create_face_set = False
layout.separator()
@@ -3015,6 +3098,38 @@ class VIEW3D_MT_mask(Menu):
props = layout.operator("sculpt.dirty_mask", text='Dirty Mask')
+class VIEW3D_MT_face_sets(Menu):
+ bl_label = "Face Sets"
+
+ def draw(self, _context):
+ layout = self.layout
+
+
+ op = layout.operator("sculpt.face_sets_create", text='Face Set From Masked')
+ op.mode = 'MASKED'
+
+ op = layout.operator("sculpt.face_sets_create", text='Face Set From Visible')
+ op.mode = 'VISIBLE'
+
+ op = layout.operator("sculpt.face_sets_create", text='Face Set From Edit Mode Selection')
+ op.mode = 'SELECTION'
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_face_sets_init", text="Init Face Sets")
+
+ layout.separator()
+
+ op = layout.operator("sculpt.face_set_change_visibility", text='Invert Visible Face Sets')
+ op.mode = 'INVERT'
+
+ op = layout.operator("sculpt.face_set_change_visibility", text='Show All Face Sets')
+ op.mode = 'SHOW_ALL'
+
+ layout.separator()
+
+ op = layout.operator("sculpt.face_sets_randomize_colors", text='Randomize Colors')
+
class VIEW3D_MT_sculpt_set_pivot(Menu):
bl_label = "Sculpt Set Pivot"
@@ -3037,6 +3152,37 @@ class VIEW3D_MT_sculpt_set_pivot(Menu):
props = layout.operator("sculpt.set_pivot_position", text="Pivot to Surface Under Cursor")
props.mode = 'SURFACE'
+class VIEW3D_MT_face_sets_init(Menu):
+ bl_label = "Face Sets Init"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ op = layout.operator("sculpt.face_sets_init", text='By Loose Parts')
+ op.mode = 'LOOSE_PARTS'
+
+ op = layout.operator("sculpt.face_sets_init", text='By Materials')
+ op.mode = 'MATERIALS'
+
+ op = layout.operator("sculpt.face_sets_init", text='By Normals')
+ op.mode = 'NORMALS'
+
+ op = layout.operator("sculpt.face_sets_init", text='By UV Seams')
+ op.mode = 'UV_SEAMS'
+
+ op = layout.operator("sculpt.face_sets_init", text='By Edge Creases')
+ op.mode = 'CREASES'
+
+ op = layout.operator("sculpt.face_sets_init", text='By Edge Bevel Weight')
+ op.mode = 'BEVEL_WEIGHT'
+
+ op = layout.operator("sculpt.face_sets_init", text='By Sharp Edges')
+ op.mode = 'SHARP_EDGES'
+
+ op = layout.operator("sculpt.face_sets_init", text='By Face Maps')
+ op.mode = 'FACE_MAPS'
+
+
class VIEW3D_MT_particle(Menu):
bl_label = "Particle"
@@ -3121,8 +3267,7 @@ class VIEW3D_MT_particle_context_menu(Menu):
layout.separator()
- layout.operator("particle.select_linked")
-
+ layout.operator("particle.select_linked", text="Select Linked")
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
_operator_name = "particle"
@@ -3170,13 +3315,7 @@ class VIEW3D_MT_pose(Menu):
layout.separator()
- layout.operator_context = 'EXEC_AREA'
- layout.operator("pose.autoside_names", text="AutoName Left/Right").axis = 'XAXIS'
- layout.operator("pose.autoside_names", text="AutoName Front/Back").axis = 'YAXIS'
- layout.operator("pose.autoside_names", text="AutoName Top/Bottom").axis = 'ZAXIS'
-
- layout.operator("pose.flip_names")
-
+ layout.menu("VIEW3D_MT_pose_names")
layout.operator("pose.quaternions_flip")
layout.separator()
@@ -3313,6 +3452,19 @@ class VIEW3D_MT_pose_constraints(Menu):
layout.operator("pose.constraints_clear")
+class VIEW3D_MT_pose_names(Menu):
+ bl_label = "Names"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator_context = 'EXEC_REGION_WIN'
+ layout.operator("pose.autoside_names", text="AutoName Left/Right").axis = 'XAXIS'
+ layout.operator("pose.autoside_names", text="AutoName Front/Back").axis = 'YAXIS'
+ layout.operator("pose.autoside_names", text="AutoName Top/Bottom").axis = 'ZAXIS'
+ layout.operator("pose.flip_names")
+
+
class VIEW3D_MT_pose_showhide(ShowHideMenu, Menu):
_operator_name = "pose"
@@ -3385,7 +3537,6 @@ class BoneOptions:
"use_deform",
"use_envelope_multiply",
"use_inherit_rotation",
- "inherit_scale",
]
if context.mode == 'EDIT_ARMATURE':
@@ -3440,7 +3591,15 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.operator("mesh.duplicate_move", text="Duplicate")
layout.menu("VIEW3D_MT_edit_mesh_extrude")
- layout.operator("mesh.split")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_mesh_merge", text="Merge")
+ layout.menu("VIEW3D_MT_edit_mesh_split", text="Split")
+ layout.operator_menu_enum("mesh.separate", "type")
+
+ layout.separator()
+
layout.operator("mesh.bisect")
layout.operator("mesh.knife_project")
@@ -3462,7 +3621,6 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.separator()
layout.menu("VIEW3D_MT_edit_mesh_showhide")
- layout.operator_menu_enum("mesh.separate", "type")
layout.menu("VIEW3D_MT_edit_mesh_clean")
layout.separator()
@@ -3580,7 +3738,8 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.separator()
- col.operator("mesh.loopcut_slide")
+ props = col.operator("mesh.loopcut_slide")
+ props.TRANSFORM_OT_edge_slide.release_confirm = False
col.operator("mesh.offset_edge_loops_slide")
col.separator()
@@ -3603,11 +3762,6 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.separator()
- col.operator("mesh.mark_seam").clear = False
- col.operator("mesh.mark_seam", text="Clear Seam").clear = True
-
- col.separator()
-
col.operator("mesh.mark_sharp")
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
@@ -3719,12 +3873,19 @@ class VIEW3D_MT_edit_mesh_extrude(Menu):
return menu
def draw(self, context):
+ from math import pi
+
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
for menu_id in self.extrude_options(context):
self._extrude_funcs[menu_id](layout)
+ layout.separator()
+
+ layout.operator("mesh.extrude_repeat")
+ layout.operator("mesh.spin").angle = pi * 2
+
class VIEW3D_MT_edit_mesh_vertices(Menu):
bl_label = "Vertex"
@@ -3755,6 +3916,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.operator("transform.vert_slide", text="Slide Vertices")
layout.operator_context = 'EXEC_DEFAULT'
layout.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5
+ layout.operator("mesh.vertices_smooth_laplacian", text="Smooth Vertices (Laplacian)")
layout.operator_context = 'INVOKE_REGION_WIN'
layout.separator()
@@ -3764,10 +3926,6 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.separator()
- layout.menu("VIEW3D_MT_edit_mesh_merge", text="Merge Vertices")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_vertex_group")
layout.menu("VIEW3D_MT_hook")
@@ -3823,6 +3981,7 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.operator("mesh.extrude_edges_move", text="Extrude Edges")
layout.operator("mesh.bevel", text="Bevel Edges").vertex_only = False
layout.operator("mesh.bridge_edge_loops")
+ layout.operator("mesh.screw")
layout.separator()
@@ -3838,7 +3997,7 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
layout.operator("transform.edge_slide")
- layout.operator("mesh.edge_split")
+ layout.operator("mesh.offset_edge_loops_slide")
layout.separator()
@@ -3847,11 +4006,6 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
- layout.operator("mesh.mark_seam").clear = False
- layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
-
- layout.separator()
-
layout.operator("mesh.mark_sharp")
layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
@@ -4017,7 +4171,7 @@ class VIEW3D_MT_edit_mesh_normals(Menu):
layout.operator("mesh.normals_tools", text="Copy Vectors").mode = 'COPY'
layout.operator("mesh.normals_tools", text="Paste Vectors").mode = 'PASTE'
- layout.operator("mesh.smoothen_normals", text="Smoothen Vectors")
+ layout.operator("mesh.smooth_normals", text="Smooth Vectors")
layout.operator("mesh.normals_tools", text="Reset Vectors").mode = 'RESET'
layout.separator()
@@ -4116,6 +4270,19 @@ class VIEW3D_MT_edit_mesh_merge(Menu):
layout.operator("mesh.remove_doubles", text="By Distance")
+class VIEW3D_MT_edit_mesh_split(Menu):
+ bl_label = "Split"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("mesh.split", text="Selection")
+
+ layout.separator()
+
+ layout.operator_enum("mesh.edge_split", "type")
+
+
class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
_operator_name = "mesh"
@@ -4157,6 +4324,9 @@ def draw_curve(self, _context):
layout.operator("curve.split")
layout.operator("curve.separate")
+
+ layout.separator()
+
layout.operator("curve.cyclic_toggle")
layout.operator_menu_enum("curve.spline_type_set", "type")
@@ -4285,6 +4455,7 @@ class VIEW3D_MT_edit_curve_context_menu(Menu):
# Remove
layout.operator("curve.split")
layout.operator("curve.decimate")
+ layout.operator("curve.separate")
layout.operator("curve.dissolve_verts")
layout.operator("curve.delete", text="Delete Segment").type = 'SEGMENT'
layout.operator("curve.delete", text="Delete Point").type = 'VERT'
@@ -4313,19 +4484,7 @@ class VIEW3D_MT_edit_surface(Menu):
draw = draw_curve
-class VIEW3D_MT_edit_font(Menu):
- bl_label = "Font"
-
- def draw(self, _context):
- layout = self.layout
-
- layout.operator("font.style_toggle", text="Toggle Bold", icon='BOLD').style = 'BOLD'
- layout.operator("font.style_toggle", text="Toggle Italic", icon='ITALIC').style = 'ITALIC'
- layout.operator("font.style_toggle", text="Toggle Underline", icon='UNDERLINE').style = 'UNDERLINE'
- layout.operator("font.style_toggle", text="Toggle Small Caps", icon='SMALL_CAPS').style = 'SMALL_CAPS'
-
-
-class VIEW3D_MT_edit_text_chars(Menu):
+class VIEW3D_MT_edit_font_chars(Menu):
bl_label = "Special Characters"
def draw(self, _context):
@@ -4365,6 +4524,91 @@ class VIEW3D_MT_edit_text_chars(Menu):
layout.operator("font.text_insert", text="Spanish Exclamation Mark").text = "\u00A1"
+class VIEW3D_MT_edit_font_kerning(Menu):
+ bl_label = "Kerning"
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.active_object
+ text = ob.data
+ kerning = text.edit_format.kerning
+
+ layout.operator("font.change_spacing", text="Decrease Kerning").delta = -1
+ layout.operator("font.change_spacing", text="Increase Kerning").delta = 1
+ layout.operator("font.change_spacing", text="Reset Kerning").delta = -kerning
+
+
+class VIEW3D_MT_edit_font_delete(Menu):
+ bl_label = "Delete"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("font.delete", text="Previous Character").type = 'PREVIOUS_CHARACTER'
+ layout.operator("font.delete", text="Next Character").type = 'NEXT_CHARACTER'
+ layout.operator("font.delete", text="Previous Word").type = 'PREVIOUS_WORD'
+ layout.operator("font.delete", text="Next Word").type = 'NEXT_WORD'
+
+
+class VIEW3D_MT_edit_font(Menu):
+ bl_label = "Text"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("font.text_cut", text="Cut")
+ layout.operator("font.text_copy", text="Copy", icon='COPYDOWN')
+ layout.operator("font.text_paste", text="Paste", icon='PASTEDOWN')
+
+ layout.separator()
+
+ layout.operator("font.text_paste_from_file")
+
+ layout.separator()
+
+ layout.operator("font.case_set", text="To Uppercase").case = 'UPPER'
+ layout.operator("font.case_set", text="To Lowercase").case = 'LOWER'
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_font_chars")
+
+ layout.separator()
+
+ layout.operator("font.style_toggle", text="Toggle Bold", icon='BOLD').style = 'BOLD'
+ layout.operator("font.style_toggle", text="Toggle Italic", icon='ITALIC').style = 'ITALIC'
+ layout.operator("font.style_toggle", text="Toggle Underline", icon='UNDERLINE').style = 'UNDERLINE'
+ layout.operator("font.style_toggle", text="Toggle Small Caps", icon='SMALL_CAPS').style = 'SMALL_CAPS'
+
+ layout.menu("VIEW3D_MT_edit_font_kerning")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_font_delete")
+
+
+class VIEW3D_MT_edit_font_context_menu(Menu):
+ bl_label = "Text Context Menu"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_DEFAULT'
+
+ layout.operator("font.text_cut", text="Cut")
+ layout.operator("font.text_copy", text="Copy", icon='COPYDOWN')
+ layout.operator("font.text_paste", text="Paste", icon='PASTEDOWN')
+
+ layout.separator()
+
+ layout.operator("font.select_all")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_font")
+
+
class VIEW3D_MT_edit_meta(Menu):
bl_label = "Metaball"
@@ -4442,8 +4686,10 @@ class VIEW3D_MT_edit_armature(Menu):
layout.operator("armature.extrude_forked")
layout.operator("armature.duplicate_move")
- layout.operator("armature.merge")
layout.operator("armature.fill")
+
+ layout.separator()
+
layout.operator("armature.split")
layout.operator("armature.separate")
@@ -4515,7 +4761,7 @@ class VIEW3D_MT_armature_context_menu(Menu):
# Remove
layout.operator("armature.split")
- layout.operator("armature.merge")
+ layout.operator("armature.separate")
layout.operator("armature.dissolve")
layout.operator("armature.delete")
@@ -4598,6 +4844,10 @@ class VIEW3D_MT_paint_gpencil(Menu):
layout = self.layout
+ layout.menu("GPENCIL_MT_layer_active", text="Active Layer")
+
+ layout.separator()
+
layout.menu("VIEW3D_MT_gpencil_animation")
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
@@ -4656,6 +4906,10 @@ class VIEW3D_MT_edit_gpencil(Menu):
layout.separator()
+ layout.menu("GPENCIL_MT_layer_active", text="Active Layer")
+
+ layout.separator()
+
layout.menu("VIEW3D_MT_gpencil_animation")
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
@@ -4690,6 +4944,7 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
def draw(self, _context):
layout = self.layout
+ settings = _context.tool_settings.gpencil_sculpt
layout.operator("gpencil.stroke_subdivide", text="Subdivide").only_selected = False
layout.menu("VIEW3D_MT_gpencil_simplify")
@@ -4715,6 +4970,10 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
layout.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
layout.operator_menu_enum("gpencil.stroke_caps_set", text="Toggle Caps", property="type")
layout.operator("gpencil.stroke_flip", text="Switch Direction")
+ layout.prop(settings, "use_scale_thickness")
+
+ layout.separator()
+ layout.operator("gpencil.reset_transform_fill", text="Reset Fill Transform")
class VIEW3D_MT_edit_gpencil_point(Menu):
@@ -4759,6 +5018,22 @@ class VIEW3D_MT_weight_gpencil(Menu):
layout.menu("VIEW3D_MT_gpencil_autoweights")
+class VIEW3D_MT_vertex_gpencil(Menu):
+ bl_label = "Paint"
+
+ def draw(self, _context):
+ layout = self.layout
+ layout.operator("gpencil.vertex_color_set", text="Set Vertex Colors")
+ layout.separator()
+ layout.operator("gpencil.vertex_color_invert", text="Invert")
+ layout.operator("gpencil.vertex_color_levels", text="Levels")
+ layout.operator("gpencil.vertex_color_hsv", text="Hue Saturation Value")
+ layout.operator("gpencil.vertex_color_brightness_contrast", text="Bright/Contrast")
+
+ layout.separator()
+ layout.menu("VIEW3D_MT_join_palette")
+
+
class VIEW3D_MT_gpencil_animation(Menu):
bl_label = "Animation"
@@ -5013,6 +5288,58 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
op.filter_type = 'CONTRAST_DECREASE'
op.auto_iteration_count = False
+class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
+
+ bl_label = "Face Sets Edit"
+
+ def draw(self, _context):
+ layout = self.layout
+ pie = layout.menu_pie()
+
+ op = pie.operator("sculpt.face_sets_create", text='Face Set From Masked')
+ op.mode = 'MASKED'
+
+ op = pie.operator("sculpt.face_sets_create", text='Face Set From Visible')
+ op.mode = 'VISIBLE'
+
+ op = pie.operator("sculpt.face_set_change_visibility", text='Invert Visible')
+ op.mode = 'INVERT'
+
+ op = pie.operator("sculpt.face_set_change_visibility", text='Show All')
+ op.mode = 'SHOW_ALL'
+
+class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
+ bl_label = "Vertex Group Locks"
+
+ def draw(self, _context):
+ layout = self.layout
+ pie = layout.menu_pie()
+
+ # 1: Left
+ op = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
+ op.action, op.mask = 'LOCK', 'ALL'
+ # 2: Right
+ op = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
+ op.action, op.mask = 'UNLOCK', 'ALL'
+ # 3: Down
+ op = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock Selected")
+ op.action, op.mask = 'UNLOCK', 'SELECTED'
+ # 4: Up
+ op = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Selected")
+ op.action, op.mask = 'LOCK', 'SELECTED'
+ # 5: Up/Left
+ op = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Unselected")
+ op.action, op.mask = 'LOCK', 'UNSELECTED'
+ # 6: Up/Right
+ op = pie.operator("object.vertex_group_lock", text="Lock Only Selected")
+ op.action, op.mask = 'LOCK', 'INVERT_UNSELECTED'
+ # 7: Down/Left
+ op = pie.operator("object.vertex_group_lock", text="Lock Only Unselected")
+ op.action, op.mask = 'UNLOCK', 'INVERT_UNSELECTED'
+ # 8: Down/Right
+ op = pie.operator("object.vertex_group_lock", text="Invert Locks")
+ op.action, op.mask = 'INVERT', 'ALL'
+
# ********** Panel **********
@@ -5058,8 +5385,8 @@ class VIEW3D_PT_view3d_properties(Panel):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
- col = flow.column()
+
+ col = layout.column()
subcol = col.column()
subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
@@ -5069,20 +5396,22 @@ class VIEW3D_PT_view3d_properties(Panel):
subcol.prop(view, "clip_start", text="Clip Start")
subcol.prop(view, "clip_end", text="End")
- subcol.separator()
-
- col = flow.column()
+ layout.separator()
- subcol = col.column()
- subcol.prop(view, "use_local_camera")
+ col = layout.column(align=False, heading="Local Camera")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(view, "use_local_camera", text="")
+ sub = sub.row(align=True)
+ sub.enabled = view.use_local_camera
+ sub.prop(view, "camera", text="")
- subcol = col.column()
- subcol.enabled = view.use_local_camera
- subcol.prop(view, "camera", text="Local Camera")
+ layout.separator()
- subcol = col.column(align=True)
- subcol.prop(view, "use_render_border")
- subcol.active = view.region_3d.view_perspective != 'CAMERA'
+ col = layout.column(align=True)
+ col.prop(view, "use_render_border")
+ col.active = view.region_3d.view_perspective != 'CAMERA'
class VIEW3D_PT_view3d_lock(Panel):
@@ -5101,23 +5430,24 @@ class VIEW3D_PT_view3d_lock(Panel):
view = context.space_data
col = layout.column(align=True)
- subcol = col.column()
- subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
+ sub = col.column()
+ sub.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
- subcol.prop(view, "lock_object")
+ sub.prop(view, "lock_object")
lock_object = view.lock_object
if lock_object:
if lock_object.type == 'ARMATURE':
- subcol.prop_search(
+ sub.prop_search(
view, "lock_bone", lock_object.data,
"edit_bones" if lock_object.mode == 'EDIT'
else "bones",
text="",
)
else:
- subcol.prop(view, "lock_cursor", text="Lock to 3D Cursor")
+ subcol = sub.column(heading="Lock")
+ subcol.prop(view, "lock_cursor", text="To 3D Cursor")
- col.prop(view, "lock_camera")
+ col.prop(view, "lock_camera", text="Camera to View")
class VIEW3D_PT_view3d_cursor(Panel):
@@ -5240,6 +5570,9 @@ class VIEW3D_PT_object_type_visibility(Panel):
("surf", "Surface"),
("meta", "Meta"),
("font", "Text"),
+ ("hair", "Hair"),
+ ("pointcloud", "Point Cloud"),
+ ("volume", "Volume"),
("grease_pencil", "Grease Pencil"),
(None, None),
# Other
@@ -5257,6 +5590,11 @@ class VIEW3D_PT_object_type_visibility(Panel):
col.separator()
continue
+ if attr == "hair" and not hasattr(bpy.data, "hairs"):
+ continue
+ elif attr == "pointcloud" and not hasattr(bpy.data, "pointclouds"):
+ continue
+
attr_v = "show_object_viewport_" f"{attr:s}"
attr_s = "show_object_select_" f"{attr:s}"
@@ -5377,6 +5715,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.prop(shading, "studiolight_rotate_z", text="Rotation")
col.prop(shading, "studiolight_intensity")
col.prop(shading, "studiolight_background_alpha")
+ col.prop(shading, "studiolight_background_blur")
col = split.column() # to align properly with above
elif shading.type == 'RENDERED':
@@ -5400,6 +5739,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.prop(shading, "studiolight_rotate_z", text="Rotation")
col.prop(shading, "studiolight_intensity")
col.prop(shading, "studiolight_background_alpha")
+ col.prop(shading, "studiolight_background_blur")
col = split.column() # to align properly with above
@@ -5697,13 +6037,16 @@ class VIEW3D_PT_overlay_guides(Panel):
split = col.split()
sub = split.column()
sub.prop(overlay, "show_text", text="Text Info")
+ sub.prop(overlay, "show_stats", text="Statistics")
+
sub = split.column()
sub.prop(overlay, "show_cursor", text="3D Cursor")
+ sub.prop(overlay, "show_annotation", text="Annotations")
if shading.type == 'MATERIAL':
- col.prop(overlay, "show_look_dev")
-
- col.prop(overlay, "show_annotation", text="Annotations")
+ row = col.row()
+ row.active = shading.render_pass == 'COMBINED'
+ row.prop(overlay, "show_look_dev")
class VIEW3D_PT_overlay_object(Panel):
@@ -6062,6 +6405,12 @@ class VIEW3D_PT_overlay_sculpt(Panel):
sub.active = sculpt.show_mask
sub.prop(overlay, "sculpt_mode_mask_opacity", text="Mask")
+ row = layout.row(align=True)
+ row.prop(sculpt, "show_face_sets", text="")
+ sub = row.row()
+ sub.active = sculpt.show_face_sets
+ row.prop(overlay, "sculpt_mode_face_sets_opacity", text="Face Sets")
+
class VIEW3D_PT_overlay_pose(Panel):
bl_space_type = 'VIEW_3D'
@@ -6362,6 +6711,7 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
'EDIT_GPENCIL': "Edit Grease Pencil",
'SCULPT_GPENCIL': "Sculpt Grease Pencil",
'WEIGHT_GPENCIL': "Weight Grease Pencil",
+ 'VERTEX_GPENCIL': "Vertex Grease Pencil",
'OBJECT': "Grease Pencil",
}[context.mode])
@@ -6375,9 +6725,10 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
col = layout.column()
row = col.row()
row.prop(overlay, "use_gpencil_grid", text="")
- sub = row.row()
+ sub = row.row(align=True)
sub.active = overlay.use_gpencil_grid
sub.prop(overlay, "gpencil_grid_opacity", text="Canvas", slider=True)
+ sub.prop(overlay, "use_gpencil_canvas_xray", text="", icon='XRAY')
row = col.row()
row.prop(overlay, "use_gpencil_fade_layers", text="")
@@ -6386,17 +6737,32 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
sub.prop(overlay, "gpencil_fade_layer", text="Fade Layers", slider=True)
row = col.row()
- row.prop(overlay, "use_gpencil_paper", text="")
+ row.prop(overlay, "use_gpencil_fade_objects", text="")
sub = row.row(align=True)
- sub.active = overlay.use_gpencil_paper
- sub.prop(overlay, "gpencil_paper_opacity", text="Fade Objects", slider=True)
- sub.prop(overlay, "use_gpencil_fade_objects", text="", icon='OUTLINER_OB_GREASEPENCIL')
+ sub.active = overlay.use_gpencil_fade_objects
+ sub.prop(overlay, "gpencil_fade_objects", text="Fade Objects", slider=True)
+ sub.prop(overlay, "use_gpencil_fade_gp_objects", text="", icon='OUTLINER_OB_GREASEPENCIL')
+
+ if context.object.mode in {'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}:
+ split = layout.split()
+ col = split.column()
+ col.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
+ col = split.column()
+ col.prop(overlay, "use_gpencil_multiedit_line_only", text="Only in Multiframe")
+
+ if context.object.mode == 'EDIT_GPENCIL':
+ split = layout.split()
+ col = split.column()
+ col.prop(overlay, "use_gpencil_show_directions")
+ col = split.column()
+ col.prop(overlay, "use_gpencil_show_material_name", text="Material Name")
- if context.object.mode in {'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
- layout.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
- layout.prop(overlay, "use_gpencil_multiedit_line_only", text="Show Edit Lines only in multiframe")
layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
+ if context.object.mode in {'PAINT_GPENCIL', 'VERTEX_GPENCIL'}:
+ layout.label(text="Vertex Paint")
+ layout.prop(overlay, "gpencil_vertex_paint_opacity", text="Opacity", slider=True)
+
class VIEW3D_PT_quad_view(Panel):
bl_space_type = 'VIEW_3D'
@@ -6672,77 +7038,143 @@ class VIEW3D_MT_gpencil_edit_context_menu(Menu):
col.operator("gpencil.reproject", text="Reproject Strokes")
+def draw_gpencil_layer_active(context, layout):
+ gpl = context.active_gpencil_layer
+ if gpl:
+ layout.label(text="Active Layer")
+ row = layout.row(align=True)
+ row.operator_context = 'EXEC_REGION_WIN'
+ row.operator_menu_enum("gpencil.layer_change", "layer", text="", icon='GREASEPENCIL')
+ row.prop(gpl, "info", text="")
+ row.operator("gpencil.layer_remove", text="", icon='X')
+
+
+def draw_gpencil_material_active(context, layout):
+ ob = context.active_object
+ if ob and len(ob.material_slots) > 0 and ob.active_material_index >= 0:
+ ma = ob.material_slots[ob.active_material_index].material
+ if ma:
+ layout.label(text="Active Material")
+ row = layout.row(align=True)
+ row.operator_context = 'EXEC_REGION_WIN'
+ row.operator_menu_enum("gpencil.material_set", "slot", text="", icon='MATERIAL')
+ row.prop(ma, "name", text="")
+
+
class VIEW3D_PT_gpencil_sculpt_context_menu(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_label = "Sculpt Context Menu"
+ bl_ui_units_x = 12
def draw(self, context):
- brush = context.tool_settings.gpencil_sculpt.brush
+ ts = context.tool_settings
+ settings = ts.gpencil_sculpt_paint
+ brush = settings.brush
layout = self.layout
- if context.mode == 'WEIGHT_GPENCIL':
- layout.prop(brush, "weight")
layout.prop(brush, "size", slider=True)
layout.prop(brush, "strength")
- layout.separator()
-
- # Frames
- layout.label(text="Frames:")
+ # Layers
+ draw_gpencil_layer_active(context, layout)
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("gpencil.blank_frame_add", text="Insert Blank in Active Layer", icon='ADD')
- layout.operator("gpencil.blank_frame_add", text="Insert Blank in All Layers", icon='ADD').all_layers = True
+class VIEW3D_PT_gpencil_weight_context_menu(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'WINDOW'
+ bl_label = "Weight Paint Context Menu"
+ bl_ui_units_x = 12
- layout.separator()
+ def draw(self, context):
+ ts = context.tool_settings
+ settings = ts.gpencil_weight_paint
+ brush = settings.brush
- layout.operator("gpencil.frame_duplicate", text="Duplicate Active Layer", icon='DUPLICATE')
- layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers", icon='DUPLICATE').mode = 'ALL'
+ layout = self.layout
- layout.separator()
+ layout.prop(brush, "size", slider=True)
+ layout.prop(brush, "strength")
+ layout.prop(brush, "weight")
- layout.operator("gpencil.delete", text="Delete Active Layer", icon='REMOVE').type = 'FRAME'
- layout.operator("gpencil.active_frames_delete_all", text="Delete All Layers", icon='REMOVE')
+ # Layers
+ draw_gpencil_layer_active(context, layout)
class VIEW3D_PT_gpencil_draw_context_menu(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_label = "Draw Context Menu"
+ bl_ui_units_x = 12
def draw(self, context):
- brush = context.tool_settings.gpencil_paint.brush
+ ts = context.tool_settings
+ settings = ts.gpencil_paint
+ brush = settings.brush
gp_settings = brush.gpencil_settings
layout = self.layout
+ is_vertex = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
+
+ if brush.gpencil_tool not in {'ERASE', 'CUTTER', 'EYEDROPPER'} and is_vertex:
+ split = layout.split(factor=0.1)
+ split.prop(brush, "color", text="")
+ split.template_color_picker(brush, "color", value_slider=True)
+
+ col = layout.column()
+ col.separator()
+ col.prop_menu_enum(gp_settings, "vertex_mode", text="Mode")
+ col.separator()
if brush.gpencil_tool not in {'FILL', 'CUTTER'}:
layout.prop(brush, "size", slider=True)
if brush.gpencil_tool not in {'ERASE', 'FILL', 'CUTTER'}:
layout.prop(gp_settings, "pen_strength")
- layout.separator()
+ # Layers
+ draw_gpencil_layer_active(context, layout)
+ # Material
+ if not is_vertex:
+ draw_gpencil_material_active(context, layout)
- # Frames
- layout.label(text="Frames:")
- layout.operator_context = 'INVOKE_REGION_WIN'
+class VIEW3D_PT_gpencil_vertex_context_menu(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'WINDOW'
+ bl_label = "Vertex Paint Context Menu"
+ bl_ui_units_x = 12
- layout.operator("gpencil.blank_frame_add", text="Insert Blank in Active Layer", icon='ADD')
- layout.operator("gpencil.blank_frame_add", text="Insert Blank in All Layers", icon='ADD').all_layers = True
+ def draw(self, context):
+ layout = self.layout
+ ts = context.tool_settings
+ settings = ts.gpencil_vertex_paint
+ brush = settings.brush
+ gp_settings = brush.gpencil_settings
- layout.separator()
+ col = layout.column()
- layout.operator("gpencil.frame_duplicate", text="Duplicate Active Layer", icon='DUPLICATE')
- layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers", icon='DUPLICATE').mode = 'ALL'
+ if brush.gpencil_vertex_tool in {'DRAW', 'REPLACE'}:
+ split = layout.split(factor=0.1)
+ split.prop(brush, "color", text="")
+ split.template_color_picker(brush, "color", value_slider=True)
- layout.separator()
+ col = layout.column()
+ col.separator()
+ col.prop_menu_enum(gp_settings, "vertex_mode", text="Mode")
+ col.separator()
- layout.operator("gpencil.delete", text="Delete Active Layer", icon='REMOVE').type = 'FRAME'
- layout.operator("gpencil.active_frames_delete_all", text="Delete All Layers", icon='REMOVE')
+ row = col.row(align=True)
+ row.prop(brush, "size", text="Radius")
+ row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+
+ if brush.gpencil_vertex_tool in {'DRAW', 'BLUR', 'SMEAR'}:
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_strength", slider=True)
+ row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+
+ # Layers
+ draw_gpencil_layer_active(context, layout)
class VIEW3D_PT_paint_vertex_context_menu(Panel):
@@ -6898,7 +7330,10 @@ class VIEW3D_PT_sculpt_context_menu(Panel):
layout.prop(brush, "normal_weight", slider=True)
if capabilities.has_pinch_factor:
- layout.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
+ text = "Pinch"
+ if brush.sculpt_tool in {'BLOB', 'SNAKE_HOOK'}:
+ text = "Magnify"
+ layout.prop(brush, "crease_pinch_factor", slider=True, text=text)
if capabilities.has_rake_factor:
layout.prop(brush, "rake_factor", slider=True)
@@ -6923,6 +7358,17 @@ class TOPBAR_PT_gpencil_materials(GreasePencilMaterialsPanel, Panel):
return ob and ob.type == 'GPENCIL'
+class TOPBAR_PT_gpencil_vertexcolor(GreasePencilVertexcolorPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Vertex Color"
+ bl_ui_units_x = 10
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
classes = (
VIEW3D_HT_header,
VIEW3D_HT_tool_header,
@@ -6954,7 +7400,6 @@ classes = (
VIEW3D_MT_select_edit_mesh,
VIEW3D_MT_select_edit_curve,
VIEW3D_MT_select_edit_surface,
- VIEW3D_MT_edit_text_context_menu,
VIEW3D_MT_select_edit_text,
VIEW3D_MT_select_edit_metaball,
VIEW3D_MT_edit_lattice_context_menu,
@@ -6975,6 +7420,7 @@ classes = (
VIEW3D_MT_light_add,
VIEW3D_MT_lightprobe_add,
VIEW3D_MT_camera_add,
+ VIEW3D_MT_volume_add,
VIEW3D_MT_add,
VIEW3D_MT_image_add,
VIEW3D_MT_object,
@@ -6999,9 +7445,12 @@ classes = (
VIEW3D_MT_vertex_group,
VIEW3D_MT_gpencil_vertex_group,
VIEW3D_MT_paint_weight,
+ VIEW3D_MT_paint_weight_lock,
VIEW3D_MT_sculpt,
VIEW3D_MT_sculpt_set_pivot,
VIEW3D_MT_mask,
+ VIEW3D_MT_face_sets,
+ VIEW3D_MT_face_sets_init,
VIEW3D_MT_particle,
VIEW3D_MT_particle_context_menu,
VIEW3D_MT_particle_showhide,
@@ -7014,6 +7463,7 @@ classes = (
VIEW3D_MT_pose_group,
VIEW3D_MT_pose_ik,
VIEW3D_MT_pose_constraints,
+ VIEW3D_MT_pose_names,
VIEW3D_MT_pose_showhide,
VIEW3D_MT_pose_apply,
VIEW3D_MT_pose_context_menu,
@@ -7039,6 +7489,7 @@ classes = (
VIEW3D_MT_edit_mesh_clean,
VIEW3D_MT_edit_mesh_delete,
VIEW3D_MT_edit_mesh_merge,
+ VIEW3D_MT_edit_mesh_split,
VIEW3D_MT_edit_mesh_showhide,
VIEW3D_MT_paint_gpencil,
VIEW3D_MT_assign_material,
@@ -7048,6 +7499,7 @@ classes = (
VIEW3D_MT_edit_gpencil_delete,
VIEW3D_MT_edit_gpencil_showhide,
VIEW3D_MT_weight_gpencil,
+ VIEW3D_MT_vertex_gpencil,
VIEW3D_MT_gpencil_animation,
VIEW3D_MT_gpencil_simplify,
VIEW3D_MT_gpencil_copy_layer,
@@ -7062,7 +7514,10 @@ classes = (
VIEW3D_MT_edit_curve_showhide,
VIEW3D_MT_edit_surface,
VIEW3D_MT_edit_font,
- VIEW3D_MT_edit_text_chars,
+ VIEW3D_MT_edit_font_chars,
+ VIEW3D_MT_edit_font_kerning,
+ VIEW3D_MT_edit_font_delete,
+ VIEW3D_MT_edit_font_context_menu,
VIEW3D_MT_edit_meta,
VIEW3D_MT_edit_meta_showhide,
VIEW3D_MT_edit_lattice,
@@ -7084,6 +7539,8 @@ classes = (
VIEW3D_MT_orientations_pie,
VIEW3D_MT_proportional_editing_falloff_pie,
VIEW3D_MT_sculpt_mask_edit_pie,
+ VIEW3D_MT_wpaint_vgroup_lock_pie,
+ VIEW3D_MT_sculpt_face_sets_edit_pie,
VIEW3D_PT_active_tool,
VIEW3D_PT_active_tool_duplicate,
VIEW3D_PT_view3d_properties,
@@ -7131,10 +7588,13 @@ classes = (
VIEW3D_PT_paint_vertex_context_menu,
VIEW3D_PT_paint_texture_context_menu,
VIEW3D_PT_paint_weight_context_menu,
+ VIEW3D_PT_gpencil_vertex_context_menu,
VIEW3D_PT_gpencil_sculpt_context_menu,
+ VIEW3D_PT_gpencil_weight_context_menu,
VIEW3D_PT_gpencil_draw_context_menu,
VIEW3D_PT_sculpt_context_menu,
TOPBAR_PT_gpencil_materials,
+ TOPBAR_PT_gpencil_vertexcolor,
TOPBAR_PT_annotation_layers,
)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 19d5e3da309..83144b33c67 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -21,6 +21,7 @@ from bpy.types import Menu, Panel, UIList
from bl_ui.properties_grease_pencil_common import (
GreasePencilSculptOptionsPanel,
GreasePencilDisplayPanel,
+ GreasePencilBrushFalloff,
)
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
@@ -71,6 +72,33 @@ class VIEW3D_MT_brush_context_menu(Menu):
layout.operator("brush.reset")
+class VIEW3D_MT_brush_gpencil_context_menu(Menu):
+ bl_label = "Brush Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ ts = context.tool_settings
+
+ settings = None
+ if context.mode == 'PAINT_GPENCIL':
+ settings = ts.gpencil_paint
+ if context.mode == 'SCULPT_GPENCIL':
+ settings = ts.gpencil_sculpt_paint
+ elif context.mode == 'WEIGHT_GPENCIL':
+ settings = ts.gpencil_weight_paint
+ elif context.mode == 'VERTEX_GPENCIL':
+ settings = ts.gpencil_vertex_paint
+
+ brush = getattr(settings, "brush", None)
+ # skip if no active brush
+ if not brush:
+ layout.label(text="No Brushes currently available", icon='INFO')
+ return
+
+ layout.operator("gpencil.brush_reset")
+ layout.operator("gpencil.brush_reset_all")
+
+
class VIEW3D_MT_brush_context_menu_paint_modes(Menu):
bl_label = "Enabled Modes"
@@ -97,21 +125,15 @@ class View3DPanel:
# Used by vertex & weight paint
def draw_vpaint_symmetry(layout, vpaint):
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
+ col = layout.column()
+ col.use_property_split = True
+ col.use_property_decorate = False
- col = split.column()
- row = col.row(align=True)
+ row = col.row(heading="Mirror", align=True)
row.prop(vpaint, "use_symmetry_x", text="X", toggle=True)
row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True)
row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True)
- col = layout.column()
- col.use_property_split = True
- col.use_property_decorate = False
col.prop(vpaint, "radial_symmetry", text="Radial")
@@ -151,10 +173,10 @@ class VIEW3D_PT_tools_object_options_transform(View3DPanel, Panel):
tool_settings = context.tool_settings
- layout.label(text="Affect Only")
- layout.prop(tool_settings, "use_transform_data_origin", text="Origins")
- layout.prop(tool_settings, "use_transform_pivot_point_align", text="Locations")
- layout.prop(tool_settings, "use_transform_skip_children", text="Parents")
+ col = layout.column(heading="Affect Only", align=True)
+ col.prop(tool_settings, "use_transform_data_origin", text="Origins")
+ col.prop(tool_settings, "use_transform_pivot_point_align", text="Locations")
+ col.prop(tool_settings, "use_transform_skip_children", text="Parents")
# ********** default tools for editmode_mesh ****************
@@ -181,16 +203,11 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
split = layout.split()
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
-
- col = split.column()
-
- row = col.row(align=True)
- row.prop(mesh, "use_mirror_x", text="X", toggle=True)
- row.prop(mesh, "use_mirror_y", text="Y", toggle=True)
- row.prop(mesh, "use_mirror_z", text="Z", toggle=True)
+ row = layout.row(heading="Mirror")
+ sub = row.row(align=True)
+ sub.prop(mesh, "use_mirror_x", text="X", toggle=True)
+ sub.prop(mesh, "use_mirror_y", text="Y", toggle=True)
+ sub.prop(mesh, "use_mirror_z", text="Z", toggle=True)
row = layout.row(align=True)
row.active = ob.data.use_mirror_x or ob.data.use_mirror_y or ob.data.use_mirror_z
@@ -226,62 +243,6 @@ class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel):
col.prop(tool_settings, "use_mesh_automerge_and_split", toggle=False)
col.prop(tool_settings, "double_threshold", text="Threshold")
-# ********** default tools for editmode_curve ****************
-
-
-class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel):
- bl_category = "Tool"
- bl_context = ".curve_edit" # dot on purpose (access from topbar)
- bl_label = "Curve Stroke"
-
- def draw(self, context):
- layout = self.layout
-
- tool_settings = context.tool_settings
- cps = tool_settings.curve_paint_settings
-
- col = layout.column()
-
- col.prop(cps, "curve_type")
-
- if cps.curve_type == 'BEZIER':
- col.label(text="Bezier Options:")
- col.prop(cps, "error_threshold")
- col.prop(cps, "fit_method")
- col.prop(cps, "use_corners_detect")
-
- col = layout.column()
- col.active = cps.use_corners_detect
- col.prop(cps, "corner_angle")
-
- col.label(text="Pressure Radius:")
- row = layout.row(align=True)
- rowsub = row.row(align=True)
- rowsub.prop(cps, "radius_min", text="Min")
- rowsub.prop(cps, "radius_max", text="Max")
-
- row.prop(cps, "use_pressure_radius", text="", icon_only=True)
-
- col = layout.column()
- col.label(text="Taper Radius:")
- row = layout.row(align=True)
- row.prop(cps, "radius_taper_start", text="Start")
- row.prop(cps, "radius_taper_end", text="End")
-
- col = layout.column()
- col.label(text="Projection Depth:")
- row = layout.row(align=True)
- row.prop(cps, "depth_mode", expand=True)
-
- col = layout.column()
- if cps.depth_mode == 'SURFACE':
- col.prop(cps, "surface_offset")
- col.prop(cps, "use_offset_absolute")
- col.prop(cps, "use_stroke_endpoints")
- if cps.use_stroke_endpoints:
- colsub = layout.column(align=True)
- colsub.prop(cps, "surface_plane", expand=True)
-
# ********** default tools for editmode_armature ****************
@@ -706,7 +667,7 @@ class VIEW3D_PT_tools_brush_falloff(Panel, View3DPaintPanel, FalloffPanel):
class VIEW3D_PT_tools_brush_falloff_frontface(View3DPaintPanel, Panel):
bl_context = ".imagepaint" # dot on purpose (access from topbar)
- bl_label = "Frontface Falloff"
+ bl_label = "Front-face Falloff"
bl_parent_id = "VIEW3D_PT_tools_brush_falloff"
bl_options = {'DEFAULT_CLOSED'}
@@ -810,38 +771,14 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
sub.prop(sculpt, "detail_refine_method", text="Refine Method")
sub.prop(sculpt, "detail_type_method", text="Detailing")
- col.prop(sculpt, "use_smooth_shading")
-
-
-class VIEW3D_PT_sculpt_dyntopo_remesh(Panel, View3DPaintPanel):
- bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
- bl_label = "Remesh"
- bl_parent_id = "VIEW3D_PT_sculpt_dyntopo"
- bl_options = {'DEFAULT_CLOSED'}
- bl_ui_units_x = 12
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- layout.use_property_decorate = False
+ if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
+ col.operator("sculpt.detail_flood_fill")
- tool_settings = context.tool_settings
- sculpt = tool_settings.sculpt
+ col.prop(sculpt, "use_smooth_shading")
- col = layout.column()
- col.active = context.sculpt_object.use_dynamic_topology_sculpting
- col.prop(sculpt, "symmetrize_direction")
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
- col.operator("sculpt.symmetrize")
- col = flow.column()
- col.operator("sculpt.optimize")
- if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
- col = flow.column()
- col.operator("sculpt.detail_flood_fill")
class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
@@ -868,9 +805,13 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
col.prop(mesh, "remesh_voxel_adaptivity")
col.prop(mesh, "use_remesh_fix_poles")
col.prop(mesh, "use_remesh_smooth_normals")
- col.prop(mesh, "use_remesh_preserve_volume")
- col.prop(mesh, "use_remesh_preserve_paint_mask")
- col.operator("object.voxel_remesh", text="Remesh")
+
+ col = layout.column(heading="Preserve", align=True)
+ col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
+ col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
+ col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
+
+ layout.operator("object.voxel_remesh", text="Remesh")
# TODO, move to space_view3d.py
@@ -891,15 +832,20 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column(heading="Display", align=True)
col.prop(sculpt, "use_threaded", text="Threaded Sculpt")
- col = flow.column()
col.prop(sculpt, "show_low_resolution")
- col = flow.column()
+ col.prop(sculpt, "use_sculpt_delay_updates")
col.prop(sculpt, "use_deform_only")
+ col.separator()
+
+ col = layout.column(heading="Auto-Masking", align=True)
+ col.prop(sculpt, "use_automasking_topology", text="Topology")
+ col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
+ col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
+ col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
+
class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
@@ -941,54 +887,34 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
sculpt = context.tool_settings.sculpt
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
-
- col = split.column()
-
- row = col.row(align=True)
+ row = layout.row(align=True, heading="Mirror")
row.prop(sculpt, "use_symmetry_x", text="X", toggle=True)
row.prop(sculpt, "use_symmetry_y", text="Y", toggle=True)
row.prop(sculpt, "use_symmetry_z", text="Z", toggle=True)
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Lock")
-
- col = split.column()
-
- row = col.row(align=True)
+ row = layout.row(align=True, heading="Lock")
row.prop(sculpt, "lock_x", text="X", toggle=True)
row.prop(sculpt, "lock_y", text="Y", toggle=True)
row.prop(sculpt, "lock_z", text="Z", toggle=True)
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Tiling")
-
- col = split.column()
-
- row = col.row(align=True)
+ row = layout.row(align=True, heading="Tiling")
row.prop(sculpt, "tile_x", text="X", toggle=True)
row.prop(sculpt, "tile_y", text="Y", toggle=True)
row.prop(sculpt, "tile_z", text="Z", toggle=True)
- layout.use_property_split = True
- layout.use_property_decorate = False
-
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
- layout.column().prop(sculpt, "radial_symmetry", text="Radial")
- layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
+ layout.prop(sculpt, "radial_symmetry", text="Radial")
+ layout.prop(sculpt, "tile_offset", text="Tile Offset")
+
+ layout.separator()
+
+ layout.prop(sculpt, "symmetrize_direction")
+ layout.operator("sculpt.symmetrize")
class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
@@ -1046,6 +972,7 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
col = layout.column()
col.prop(tool_settings, "use_auto_normalize", text="Auto Normalize")
+ col.prop(tool_settings, "use_lock_relative", text="Lock-Relative")
col.prop(tool_settings, "use_multipaint", text="Multi-Paint")
col.prop(wpaint, "use_group_restrict")
@@ -1190,19 +1117,14 @@ class VIEW3D_PT_tools_imagepaint_options(View3DPaintPanel, Panel):
layout.prop(ipaint, "seam_bleed")
layout.prop(ipaint, "dither", slider=True)
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column()
col.prop(ipaint, "use_occlude")
-
- col = flow.column()
col.prop(ipaint, "use_backface_culling", text="Backface Culling")
class VIEW3D_PT_tools_imagepaint_options_cavity(View3DPaintPanel, Panel):
bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Cavity Mask"
- bl_parent_id = "VIEW3D_PT_tools_imagepaint_options"
bl_parent_id = "VIEW3D_PT_mask"
bl_options = {'DEFAULT_CLOSED'}
@@ -1356,7 +1278,7 @@ class VIEW3D_PT_tools_particlemode_options_display(View3DPanel, Panel):
# Grease Pencil drawing brushes
-class GreasePencilPanel:
+class GreasePencilPaintPanel:
bl_context = ".greasepencil_paint"
bl_category = "Tool"
@@ -1372,7 +1294,7 @@ class GreasePencilPanel:
return True
-class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPanel):
+class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPaintPanel):
bl_label = "Brushes"
def draw(self, context):
@@ -1387,7 +1309,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePenci
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
col = row.column()
- col.operator("gpencil.brush_presets_create", icon='PRESET_NEW', text="")
+ col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
if context.mode == 'PAINT_GPENCIL':
brush = tool_settings.gpencil_paint.brush
@@ -1400,8 +1322,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePenci
layout.row().prop(brush, "icon_filepath", text="")
-class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePencilPanel):
+class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePencilPaintPanel):
bl_label = "Brush Settings"
+ bl_options = {'DEFAULT_CLOSED'}
# What is the point of brush presets? Seems to serve the exact same purpose as brushes themselves??
def draw_header_preset(self, _context):
@@ -1448,7 +1371,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.tool_settings.gpencil_paint.brush
- return brush is not None and brush.gpencil_tool != 'ERASE'
+ return brush is not None and brush.gpencil_tool not in {'ERASE', 'TINT'}
def draw(self, context):
layout = self.layout
@@ -1480,11 +1403,11 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
ma = brush.gpencil_settings.material
col.separator()
+ col.prop(gp_settings, "hardness", slider=True)
subcol = col.column(align=True)
if ma and ma.grease_pencil.mode == 'LINE':
subcol.enabled = False
- subcol.prop(gp_settings, "gradient_factor", slider=True)
- subcol.prop(gp_settings, "gradient_shape")
+ subcol.prop(gp_settings, "aspect")
elif brush.gpencil_tool == 'FILL':
row = col.row(align=True)
@@ -1496,6 +1419,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
col.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
col.prop(gp_settings, "fill_threshold", text="Threshold")
+
class VIEW3D_PT_tools_grease_pencil_brush_stroke(Panel, View3DPanel):
bl_context = ".greasepencil_paint"
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
@@ -1562,7 +1486,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.tool_settings.gpencil_paint.brush
- return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
+ return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
def draw_header(self, context):
if self.is_popover:
@@ -1593,12 +1517,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
col1.prop(gp_settings, "pen_smooth_steps")
col1 = col.column(align=True)
- col1.prop(gp_settings, "pen_thick_smooth_factor")
- col1.prop(gp_settings, "pen_thick_smooth_steps", text="Iterations")
-
- col1 = col.column(align=True)
col1.prop(gp_settings, "pen_subdivision_steps")
- col1.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
col1 = col.column(align=True)
col1.prop(gp_settings, "simplify_factor")
@@ -1617,7 +1536,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.tool_settings.gpencil_paint.brush
- return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
+ return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
def draw_header(self, context):
if self.is_popover:
@@ -1632,7 +1551,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
- brush = context.tool_settings.gpencil_paint.brush
+ tool_settings = context.tool_settings
+ brush = tool_settings.gpencil_paint.brush
+ mode = tool_settings.gpencil_paint.color_mode
gp_settings = brush.gpencil_settings
if self.is_popover:
@@ -1641,83 +1562,86 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
row.label(text=self.bl_label)
col = layout.column()
- col.active = gp_settings.use_settings_random
-
- col.prop(gp_settings, "random_pressure", text="Pressure", slider=True)
- col.prop(gp_settings, "random_strength", text="Strength", slider=True)
- col.prop(gp_settings, "uv_random", text="UV", slider=True)
+ col.enabled = gp_settings.use_settings_random
row = col.row(align=True)
- row.prop(gp_settings, "pen_jitter", slider=True)
- row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
-
-
-# Grease Pencil drawingcurves
-class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
- bl_context = ".greasepencil_paint"
- bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
- bl_label = "Curves"
- bl_category = "Tool"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- brush = context.tool_settings.gpencil_paint.brush
- return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
-
- def draw(self, context):
- pass
-
-
-class VIEW3D_PT_tools_grease_pencil_brushcurves_sensitivity(View3DPanel, Panel):
- bl_context = ".greasepencil_paint"
- bl_label = "Sensitivity"
- bl_category = "Tool"
- bl_parent_id = "VIEW3D_PT_tools_grease_pencil_brushcurves"
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
+ row.prop(gp_settings, "random_pressure", text="Radius", slider=True)
+ row.prop(gp_settings, "use_stroke_random_radius", text="", icon='GP_SELECT_STROKES')
+ row.prop(gp_settings, "use_random_press_radius", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_random_press_radius and self.is_popover is False:
+ col.template_curve_mapping(gp_settings, "curve_random_pressure", brush=True,
+ use_negative_slope=True)
- brush = context.tool_settings.gpencil_paint.brush
- gp_settings = brush.gpencil_settings
-
- layout.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True,
- use_negative_slope=True)
+ row = col.row(align=True)
+ row.prop(gp_settings, "random_strength", text="Strength", slider=True)
+ row.prop(gp_settings, "use_stroke_random_strength", text="", icon='GP_SELECT_STROKES')
+ row.prop(gp_settings, "use_random_press_strength", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_random_press_strength and self.is_popover is False:
+ col.template_curve_mapping(gp_settings, "curve_random_strength", brush=True,
+ use_negative_slope=True)
+ row = col.row(align=True)
+ row.prop(gp_settings, "uv_random", text="UV", slider=True)
+ row.prop(gp_settings, "use_stroke_random_uv", text="", icon='GP_SELECT_STROKES')
+ row.prop(gp_settings, "use_random_press_uv", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_random_press_uv and self.is_popover is False:
+ col.template_curve_mapping(gp_settings, "curve_random_uv", brush=True,
+ use_negative_slope=True)
-class VIEW3D_PT_tools_grease_pencil_brushcurves_strength(View3DPanel, Panel):
- bl_context = ".greasepencil_paint"
- bl_label = "Strength"
- bl_category = "Tool"
- bl_parent_id = "VIEW3D_PT_tools_grease_pencil_brushcurves"
+ col.separator()
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
+ col1 = col.column(align=True)
+ col1.enabled = mode == 'VERTEXCOLOR' and gp_settings.use_settings_random
+ row = col1.row(align=True)
+ row.prop(gp_settings, "random_hue_factor", slider=True)
+ row.prop(gp_settings, "use_stroke_random_hue", text="", icon='GP_SELECT_STROKES')
+ row.prop(gp_settings, "use_random_press_hue", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_random_press_hue and self.is_popover is False:
+ col1.template_curve_mapping(gp_settings, "curve_random_hue", brush=True,
+ use_negative_slope=True)
+
+ row = col1.row(align=True)
+ row.prop(gp_settings, "random_saturation_factor", slider=True)
+ row.prop(gp_settings, "use_stroke_random_sat", text="", icon='GP_SELECT_STROKES')
+ row.prop(gp_settings, "use_random_press_sat", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_random_press_sat and self.is_popover is False:
+ col1.template_curve_mapping(gp_settings, "curve_random_saturation", brush=True,
+ use_negative_slope=True)
+
+ row = col1.row(align=True)
+ row.prop(gp_settings, "random_value_factor", slider=True)
+ row.prop(gp_settings, "use_stroke_random_val", text="", icon='GP_SELECT_STROKES')
+ row.prop(gp_settings, "use_random_press_val", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_random_press_val and self.is_popover is False:
+ col1.template_curve_mapping(gp_settings, "curve_random_value", brush=True,
+ use_negative_slope=True)
- brush = context.tool_settings.gpencil_paint.brush
- gp_settings = brush.gpencil_settings
+ col.separator()
- layout.template_curve_mapping(gp_settings, "curve_strength", brush=True,
- use_negative_slope=True)
+ row = col.row(align=True)
+ row.prop(gp_settings, "pen_jitter", slider=True)
+ row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
+ if gp_settings.use_jitter_pressure and self.is_popover is False:
+ col.template_curve_mapping(gp_settings, "curve_jitter", brush=True,
+ use_negative_slope=True)
-class VIEW3D_PT_tools_grease_pencil_brushcurves_jitter(View3DPanel, Panel):
+class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
bl_context = ".greasepencil_paint"
- bl_label = "Jitter"
- bl_category = "Tool"
- bl_parent_id = "VIEW3D_PT_tools_grease_pencil_brushcurves"
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
+ @classmethod
+ def poll(cls, context):
+ ts = context.tool_settings
+ settings = ts.gpencil_paint
+ brush = settings.brush
+ if brush is None:
+ return False
- brush = context.tool_settings.gpencil_paint.brush
- gp_settings = brush.gpencil_settings
+ tool = brush.gpencil_tool
- layout.template_curve_mapping(gp_settings, "curve_jitter", brush=True,
- use_negative_slope=True)
+ return (settings and settings.brush and settings.brush.curve and tool == 'TINT')
# Grease Pencil stroke interpolation tools
@@ -1768,25 +1692,49 @@ class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
# Grease Pencil stroke sculpting tools
-
-class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel):
+class GreasePencilSculptPanel:
bl_context = ".greasepencil_sculpt"
- bl_label = "Brushes"
bl_category = "Tool"
+ @classmethod
+ def poll(cls, context):
+ if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(gpd.is_stroke_sculpt_mode)
+ else:
+ return True
+
+
+class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel, GreasePencilSculptPanel):
+ bl_label = "Brushes"
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
- settings = context.tool_settings.gpencil_sculpt
+ tool_settings = context.scene.tool_settings
+ gpencil_paint = tool_settings.gpencil_sculpt_paint
- layout.template_icon_view(settings, "sculpt_tool", show_labels=True)
+ row = layout.row()
+ row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
+ col = row.column()
+ col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
-class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
- bl_context = ".greasepencil_sculpt"
- bl_category = "Tool"
+ if context.mode == 'SCULPT_GPENCIL':
+ brush = tool_settings.gpencil_sculpt_paint.brush
+ if brush is not None:
+ col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
+
+ if(brush.use_custom_icon):
+ layout.row().prop(brush, "icon_filepath", text="")
+
+
+class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel, GreasePencilSculptPanel):
bl_label = "Brush Settings"
def draw(self, context):
@@ -1794,7 +1742,8 @@ class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
layout.use_property_split = True
layout.use_property_decorate = False
- settings = context.tool_settings.gpencil_sculpt
+ tool_settings = context.scene.tool_settings
+ settings = tool_settings.gpencil_sculpt_paint
brush = settings.brush
if not self.is_popover:
@@ -1803,27 +1752,63 @@ class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
)
brush_basic_gpencil_sculpt_settings(layout, context, brush)
-# Grease Pencil weight painting tools
+class VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
+ bl_context = ".greasepencil_sculpt"
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ ts = context.tool_settings
+ settings = ts.gpencil_sculpt_paint
+ return (settings and settings.brush and settings.brush.curve)
-class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel):
+
+# Grease Pencil weight painting tools
+class GreasePencilWeightPanel:
bl_context = ".greasepencil_weight"
- bl_label = "Brushes"
bl_category = "Tool"
+ @classmethod
+ def poll(cls, context):
+ if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(gpd.is_stroke_weight_mode)
+ else:
+ return True
+
+
+class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel, GreasePencilWeightPanel):
+ bl_label = "Brushes"
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
- settings = context.tool_settings.gpencil_sculpt
+ tool_settings = context.scene.tool_settings
+ gpencil_paint = tool_settings.gpencil_weight_paint
- layout.template_icon_view(settings, "weight_tool", show_labels=True)
+ row = layout.row()
+ row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
+ col = row.column()
+ col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
-class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
- bl_context = ".greasepencil_weight"
- bl_category = "Tool"
+ if context.mode == 'WEIGHT_GPENCIL':
+ brush = tool_settings.gpencil_weight_paint.brush
+ if brush is not None:
+ col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
+
+ if(brush.use_custom_icon):
+ layout.row().prop(brush, "icon_filepath", text="")
+
+
+class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel, GreasePencilWeightPanel):
bl_label = "Brush Settings"
def draw(self, context):
@@ -1831,7 +1816,8 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
layout.use_property_split = True
layout.use_property_decorate = False
- settings = context.tool_settings.gpencil_sculpt
+ tool_settings = context.scene.tool_settings
+ settings = tool_settings.gpencil_weight_paint
brush = settings.brush
if not self.is_popover:
@@ -1841,6 +1827,268 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
brush_basic_gpencil_weight_settings(layout, context, brush)
+class VIEW3D_PT_tools_grease_pencil_brush_weight_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
+ bl_context = ".greasepencil_weight"
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ ts = context.tool_settings
+ settings = ts.gpencil_weight_paint
+ brush = settings.brush
+ return (settings and settings.brush and settings.brush.curve)
+
+
+# Grease Pencil vertex painting tools
+class GreasePencilVertexPanel:
+ bl_context = ".greasepencil_vertex"
+ bl_category = "Tool"
+
+ @classmethod
+ def poll(cls, context):
+ if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(gpd.is_stroke_vertex_mode)
+ else:
+ return True
+
+
+class VIEW3D_PT_tools_grease_pencil_vertex_paint_select(View3DPanel, Panel, GreasePencilVertexPanel):
+ bl_label = "Brushes"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ tool_settings = context.scene.tool_settings
+ gpencil_paint = tool_settings.gpencil_vertex_paint
+
+ row = layout.row()
+ row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
+
+ col = row.column()
+ col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
+
+ if context.mode == 'VERTEX_GPENCIL':
+ brush = tool_settings.gpencil_vertex_paint.brush
+ if brush is not None:
+ col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
+
+ if(brush.use_custom_icon):
+ layout.row().prop(brush, "icon_filepath", text="")
+
+
+class VIEW3D_PT_tools_grease_pencil_vertex_paint_settings(Panel, View3DPanel, GreasePencilVertexPanel):
+ bl_label = "Brush Settings"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ tool_settings = context.scene.tool_settings
+ settings = tool_settings.gpencil_vertex_paint
+ brush = settings.brush
+
+ if not self.is_popover:
+ from bl_ui.properties_paint_common import (
+ brush_basic_gpencil_vertex_settings,
+ )
+ brush_basic_gpencil_vertex_settings(layout, context, brush)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_vertex_color(View3DPanel, Panel):
+ bl_context = ".greasepencil_vertex"
+ bl_label = "Color"
+ bl_category = "Tool"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ ts = context.tool_settings
+ settings = ts.gpencil_vertex_paint
+ brush = settings.brush
+
+ if ob is None or brush is None:
+ return False
+
+ if context.region.type == 'TOOL_HEADER' or brush.gpencil_vertex_tool in {'BLUR', 'AVERAGE', 'SMEAR'}:
+ return False
+
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ ts = context.tool_settings
+ settings = ts.gpencil_vertex_paint
+ brush = settings.brush
+ gp_settings = brush.gpencil_settings
+
+ col = layout.column()
+
+ col.template_color_picker(brush, "color", value_slider=True)
+
+ sub_row = col.row(align=True)
+ sub_row.prop(brush, "color", text="")
+ sub_row.prop(brush, "secondary_color", text="")
+
+ sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="")
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
+ bl_context = ".greasepencil_vertex"
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ ts = context.tool_settings
+ settings = ts.gpencil_vertex_paint
+ return (settings and settings.brush and settings.brush.curve)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_vertex_palette(View3DPanel, Panel):
+ bl_context = ".greasepencil_vertex"
+ bl_label = "Palette"
+ bl_category = "Tool"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_vertex_color'
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ ts = context.tool_settings
+ settings = ts.gpencil_vertex_paint
+ brush = settings.brush
+
+ if ob is None or brush is None:
+ return False
+
+ if brush.gpencil_vertex_tool in {'BLUR', 'AVERAGE', 'SMEAR'}:
+ return False
+
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ ts = context.tool_settings
+ settings = ts.gpencil_vertex_paint
+
+ col = layout.column()
+
+ row = col.row(align=True)
+ row.template_ID(settings, "palette", new="palette.new")
+ if settings.palette:
+ col.template_palette(settings, "palette", color=True)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Color"
+ bl_category = "Tool"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ ts = context.tool_settings
+ settings = ts.gpencil_paint
+ brush = settings.brush
+
+ if ob is None or brush is None:
+ return False
+
+ if context.region.type == 'TOOL_HEADER':
+ return False
+
+ if brush.gpencil_tool == 'TINT':
+ return True
+
+ if brush.gpencil_tool not in {'DRAW', 'FILL'}:
+ return False
+
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ ts = context.tool_settings
+ settings = ts.gpencil_paint
+ brush = settings.brush
+ gp_settings = brush.gpencil_settings
+
+ if brush.gpencil_tool != 'TINT':
+ row = layout.row()
+ row.prop(settings, "color_mode", expand=True)
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ col = layout.column()
+ col.enabled = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
+
+ col.template_color_picker(brush, "color", value_slider=True)
+
+ sub_row = col.row(align=True)
+ sub_row.prop(brush, "color", text="")
+ sub_row.prop(brush, "secondary_color", text="")
+
+ sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="")
+
+ if brush.gpencil_tool in {'DRAW', 'FILL'}:
+ col.prop(gp_settings, "vertex_mode", text="Mode")
+ col.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor")
+
+ if brush.gpencil_tool == 'TINT':
+ col.prop(gp_settings, "vertex_mode", text="Mode")
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Palette"
+ bl_category = "Tool"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_mixcolor'
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ ts = context.tool_settings
+ settings = ts.gpencil_paint
+ brush = settings.brush
+
+ if ob is None or brush is None:
+ return False
+
+ if brush.gpencil_tool == 'TINT':
+ return True
+
+ if brush.gpencil_tool not in {'DRAW', 'FILL'}:
+ return False
+
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ ts = context.tool_settings
+ settings = ts.gpencil_paint
+ brush = settings.brush
+
+ col = layout.column()
+ col.enabled = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
+
+ row = col.row(align=True)
+ row.template_ID(settings, "palette", new="palette.new")
+ if settings.palette:
+ col.template_palette(settings, "palette", color=True)
+
+
class VIEW3D_PT_tools_grease_pencil_sculpt_options(GreasePencilSculptOptionsPanel, Panel, View3DPanel):
bl_context = ".greasepencil_sculpt"
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings'
@@ -1870,6 +2118,13 @@ class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilDisplayPanel,
bl_label = "Cursor"
+class VIEW3D_PT_tools_grease_pencil_vertex_appearance(GreasePencilDisplayPanel, Panel, View3DPanel):
+ bl_context = ".greasepencil_vertex"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_vertex_paint_settings'
+ bl_category = "Tool"
+ bl_label = "Cursor"
+
+
class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
"""Brush settings"""
bl_label = "Brush Presets"
@@ -1880,15 +2135,15 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
classes = (
VIEW3D_MT_brush_context_menu,
+ VIEW3D_MT_brush_gpencil_context_menu,
VIEW3D_MT_brush_context_menu_paint_modes,
VIEW3D_PT_tools_object_options,
VIEW3D_PT_tools_object_options_transform,
VIEW3D_PT_tools_meshedit_options,
VIEW3D_PT_tools_meshedit_options_automerge,
- VIEW3D_PT_tools_curveedit_options_stroke,
VIEW3D_PT_tools_armatureedit_options,
VIEW3D_PT_tools_posemode_options,
-
+
VIEW3D_PT_slots_projectpaint,
VIEW3D_PT_tools_brush_select,
VIEW3D_PT_tools_brush_settings,
@@ -1908,7 +2163,6 @@ classes = (
VIEW3D_PT_tools_brush_display,
VIEW3D_PT_sculpt_dyntopo,
- VIEW3D_PT_sculpt_dyntopo_remesh,
VIEW3D_PT_sculpt_voxel_remesh,
VIEW3D_PT_sculpt_symmetry,
VIEW3D_PT_sculpt_symmetry_for_topbar,
@@ -1929,7 +2183,7 @@ classes = (
VIEW3D_PT_tools_imagepaint_symmetry,
VIEW3D_PT_tools_imagepaint_options,
-
+
VIEW3D_PT_tools_imagepaint_options_external,
VIEW3D_MT_tools_projectpaint_stencil,
@@ -1946,10 +2200,6 @@ classes = (
VIEW3D_PT_tools_grease_pencil_brush_post_processing,
VIEW3D_PT_tools_grease_pencil_brush_random,
VIEW3D_PT_tools_grease_pencil_brush_stabilizer,
- VIEW3D_PT_tools_grease_pencil_brushcurves,
- VIEW3D_PT_tools_grease_pencil_brushcurves_sensitivity,
- VIEW3D_PT_tools_grease_pencil_brushcurves_strength,
- VIEW3D_PT_tools_grease_pencil_brushcurves_jitter,
VIEW3D_PT_tools_grease_pencil_paint_appearance,
VIEW3D_PT_tools_grease_pencil_sculpt_select,
VIEW3D_PT_tools_grease_pencil_sculpt_settings,
@@ -1958,7 +2208,19 @@ classes = (
VIEW3D_PT_tools_grease_pencil_weight_paint_select,
VIEW3D_PT_tools_grease_pencil_weight_paint_settings,
VIEW3D_PT_tools_grease_pencil_weight_appearance,
+ VIEW3D_PT_tools_grease_pencil_vertex_paint_select,
+ VIEW3D_PT_tools_grease_pencil_vertex_paint_settings,
+ VIEW3D_PT_tools_grease_pencil_vertex_appearance,
VIEW3D_PT_tools_grease_pencil_interpolate,
+ VIEW3D_PT_tools_grease_pencil_brush_mixcolor,
+ VIEW3D_PT_tools_grease_pencil_brush_mix_palette,
+
+ VIEW3D_PT_tools_grease_pencil_brush_paint_falloff,
+ VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff,
+ VIEW3D_PT_tools_grease_pencil_brush_weight_falloff,
+ VIEW3D_PT_tools_grease_pencil_brush_vertex_color,
+ VIEW3D_PT_tools_grease_pencil_brush_vertex_palette,
+ VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
)
if __name__ == "__main__": # only for live edit.