2023-08-16 00:20:26 +10:00
|
|
|
# SPDX-FileCopyrightText: 2009-2023 Blender Authors
|
2023-06-15 13:09:04 +10:00
|
|
|
#
|
2022-02-11 09:07:11 +11:00
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
2023-06-15 13:09:04 +10:00
|
|
|
|
2009-07-11 13:32:20 +00:00
|
|
|
import bpy
|
2018-12-02 13:26:10 +11:00
|
|
|
from bpy.types import (
|
|
|
|
|
Header,
|
|
|
|
|
Menu,
|
|
|
|
|
Panel,
|
2025-04-09 14:41:01 +02:00
|
|
|
SurfaceCurve
|
2018-12-02 13:26:10 +11:00
|
|
|
)
|
2019-06-11 16:08:32 +10:00
|
|
|
from bl_ui.properties_paint_common import (
|
2018-12-02 13:26:10 +11:00
|
|
|
UnifiedPaintPanel,
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
brush_basic_texpaint_settings,
|
GPv3: Weight Paint tools (Draw, Blur, Average, Smear, Sample weight)
This PR implements the Weight Paint tools for GPv3.
Tools:
- Draw, for assigning weight to stroke points
- Blur, smooths out weight using adjacent stroke point weights
- Average, smooths weight using the average weight under the brush
- Smear, like finger painting, drags weights in the direction of the brush
- Sample weight, sets the brush weight to the weight under the cursor
The weights are assigned to the active vertex group. When there is no
active vertex group, a group is automatically created.
When the Auto Normalize option is enabled, it is ensured that all
bone-deforming vertex groups add up to the weight of 1.0.
When a vertex group is locked, it's weights will not be altered by
Auto Normalize.
The PR already supports multi frame editing, including the use of a
falloff (defined by a curve).
The implementation is in accordance with the Weight Paint tools in GPv2.
Pull Request: https://projects.blender.org/blender/blender/pulls/118347
2024-04-25 15:21:14 +02:00
|
|
|
brush_basic_grease_pencil_weight_settings,
|
2024-09-10 18:56:31 +02:00
|
|
|
brush_basic_grease_pencil_vertex_settings,
|
2024-05-02 20:53:22 -04:00
|
|
|
BrushAssetShelf,
|
2018-12-02 13:26:10 +11:00
|
|
|
)
|
2019-06-11 16:08:32 +10:00
|
|
|
from bl_ui.properties_grease_pencil_common import (
|
2018-12-02 13:26:10 +11:00
|
|
|
AnnotationDataPanel,
|
|
|
|
|
AnnotationOnionSkin,
|
|
|
|
|
GreasePencilMaterialsPanel,
|
|
|
|
|
)
|
2019-06-11 16:08:32 +10:00
|
|
|
from bl_ui.space_toolsystem_common import (
|
2019-05-15 12:20:13 +10:00
|
|
|
ToolActivePanelHelper,
|
|
|
|
|
)
|
2022-11-16 12:06:14 +01:00
|
|
|
from bpy.app.translations import (
|
2022-11-16 12:27:20 +01:00
|
|
|
pgettext_iface as iface_,
|
2024-01-11 19:49:03 +01:00
|
|
|
pgettext_rpt as rpt_,
|
2022-11-16 12:06:14 +01:00
|
|
|
contexts as i18n_contexts,
|
|
|
|
|
)
|
2009-10-12 21:06:03 +00:00
|
|
|
|
2019-05-13 17:27:40 +02:00
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
class VIEW3D_HT_tool_header(Header):
|
2009-10-31 19:31:45 +00:00
|
|
|
bl_space_type = 'VIEW_3D'
|
2019-05-22 00:27:01 +10:00
|
|
|
bl_region_type = 'TOOL_HEADER'
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
self.draw_tool_settings(context)
|
2018-05-14 14:00:29 +02:00
|
|
|
|
2018-06-11 16:57:35 +02:00
|
|
|
layout.separator_spacer()
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
self.draw_mode_settings(context)
|
|
|
|
|
|
|
|
|
|
def draw_tool_settings(self, context):
|
|
|
|
|
layout = self.layout
|
2019-04-29 22:50:14 +10:00
|
|
|
tool_mode = context.mode
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
# Active Tool
|
|
|
|
|
# -----------
|
2019-06-11 16:08:32 +10:00
|
|
|
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
2019-04-29 22:50:14 +10:00
|
|
|
tool = ToolSelectPanelHelper.draw_active_tool_header(
|
|
|
|
|
context, layout,
|
|
|
|
|
tool_key=('VIEW_3D', tool_mode),
|
|
|
|
|
)
|
2019-04-18 21:13:22 +02:00
|
|
|
# Object Mode Options
|
|
|
|
|
# -------------------
|
|
|
|
|
|
|
|
|
|
# Example of how tool_settings can be accessed as pop-overs.
|
|
|
|
|
|
|
|
|
|
# TODO(campbell): editing options should be after active tool options
|
|
|
|
|
# (obviously separated for from the users POV)
|
|
|
|
|
draw_fn = getattr(_draw_tool_settings_context_mode, tool_mode, None)
|
|
|
|
|
if draw_fn is not None:
|
2019-12-19 20:05:13 +11:00
|
|
|
is_valid_context = draw_fn(context, layout, tool)
|
2019-04-18 21:13:22 +02:00
|
|
|
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
def draw_3d_brush_settings(layout, tool_mode):
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_settings_advanced", text="Brush")
|
|
|
|
|
if tool_mode != 'PAINT_WEIGHT':
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_texture")
|
|
|
|
|
if tool_mode == 'PAINT_TEXTURE':
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_mask_texture")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_stroke")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_display")
|
2019-05-23 12:29:28 +10:00
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
# NOTE: general mode options should be added to `draw_mode_settings`.
|
2019-04-18 21:13:22 +02:00
|
|
|
if tool_mode == 'SCULPT':
|
2019-12-19 20:05:13 +11:00
|
|
|
if is_valid_context:
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
draw_3d_brush_settings(layout, tool_mode)
|
2019-04-18 21:13:22 +02:00
|
|
|
elif tool_mode == 'PAINT_VERTEX':
|
2019-12-19 20:05:13 +11:00
|
|
|
if is_valid_context:
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
draw_3d_brush_settings(layout, tool_mode)
|
2019-04-18 21:13:22 +02:00
|
|
|
elif tool_mode == 'PAINT_WEIGHT':
|
2019-12-19 20:05:13 +11:00
|
|
|
if is_valid_context:
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
draw_3d_brush_settings(layout, tool_mode)
|
2019-04-18 21:13:22 +02:00
|
|
|
elif tool_mode == 'PAINT_TEXTURE':
|
2019-12-19 20:05:13 +11:00
|
|
|
if is_valid_context:
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
draw_3d_brush_settings(layout, tool_mode)
|
2019-04-18 21:13:22 +02:00
|
|
|
elif tool_mode == 'EDIT_ARMATURE':
|
|
|
|
|
pass
|
|
|
|
|
elif tool_mode == 'EDIT_CURVE':
|
|
|
|
|
pass
|
|
|
|
|
elif tool_mode == 'EDIT_MESH':
|
|
|
|
|
pass
|
|
|
|
|
elif tool_mode == 'POSE':
|
|
|
|
|
pass
|
|
|
|
|
elif tool_mode == 'PARTICLE':
|
|
|
|
|
# Disable, only shows "Brush" panel, which is already in the top-bar.
|
2024-09-16 12:20:25 +02:00
|
|
|
# if tool.use_brushes:
|
2019-05-23 12:29:28 +10:00
|
|
|
# layout.popover_group(context=".paint_common", **popover_kw)
|
2019-04-18 21:13:22 +02:00
|
|
|
pass
|
2024-05-14 15:20:31 +02:00
|
|
|
elif tool_mode == 'PAINT_GREASE_PENCIL':
|
|
|
|
|
if is_valid_context:
|
|
|
|
|
brush = context.tool_settings.gpencil_paint.brush
|
|
|
|
|
if brush:
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type not in {'FILL', 'TINT', 'ERASE'}:
|
2025-05-31 12:23:39 +02:00
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_v3_brush_advanced")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_v3_brush_stroke")
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type == 'FILL':
|
2025-05-31 12:23:39 +02:00
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_v3_brush_fill_advanced")
|
2024-06-25 12:12:25 +02:00
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance")
|
2024-04-11 09:39:48 +02:00
|
|
|
elif tool_mode == 'SCULPT_GREASE_PENCIL':
|
|
|
|
|
if is_valid_context:
|
|
|
|
|
brush = context.tool_settings.gpencil_sculpt_paint.brush
|
|
|
|
|
if brush:
|
2025-06-06 23:40:13 +02:00
|
|
|
tool = brush.gpencil_sculpt_brush_type
|
2024-04-11 09:39:48 +02:00
|
|
|
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
2025-03-21 11:08:24 +00:00
|
|
|
elif tool_mode in {'WEIGHT_GPENCIL', 'WEIGHT_GREASE_PENCIL'}:
|
2020-03-09 16:27:24 +01:00
|
|
|
if is_valid_context:
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
|
2025-03-21 11:08:24 +00:00
|
|
|
elif tool_mode in {'VERTEX_GPENCIL', 'VERTEX_GREASE_PENCIL'}:
|
2020-03-09 16:27:24 +01:00
|
|
|
if is_valid_context:
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_vertex_appearance")
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
def draw_mode_settings(self, context):
|
|
|
|
|
layout = self.layout
|
2019-05-21 15:04:21 +10:00
|
|
|
mode_string = context.mode
|
2024-10-01 18:36:29 +02:00
|
|
|
tool_settings = context.tool_settings
|
2019-05-21 15:04:21 +10:00
|
|
|
|
|
|
|
|
def row_for_mirror():
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.label(icon='MOD_MIRROR')
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.scale_x = 0.6
|
2019-05-21 15:49:36 +10:00
|
|
|
return row, sub
|
2019-05-21 15:04:21 +10:00
|
|
|
|
2020-09-18 19:58:48 +02:00
|
|
|
if mode_string == 'EDIT_ARMATURE':
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
2019-05-21 15:49:36 +10:00
|
|
|
_row, sub = row_for_mirror()
|
2024-03-29 10:08:59 +11:00
|
|
|
sub.prop(ob.data, "use_mirror_x", text="X", toggle=True)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'POSE':
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
2019-05-21 15:49:36 +10:00
|
|
|
_row, sub = row_for_mirror()
|
2024-03-29 10:08:59 +11:00
|
|
|
sub.prop(ob.pose, "use_mirror_x", text="X", toggle=True)
|
2021-01-26 19:41:17 +01:00
|
|
|
elif mode_string in {'EDIT_MESH', 'PAINT_WEIGHT', 'SCULPT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
2020-09-18 19:58:48 +02:00
|
|
|
# Mesh Modes, Use Mesh Symmetry
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
2019-05-21 15:49:36 +10:00
|
|
|
row, sub = row_for_mirror()
|
2024-03-29 10:08:59 +11:00
|
|
|
sub.prop(ob, "use_mesh_mirror_x", text="X", toggle=True)
|
|
|
|
|
sub.prop(ob, "use_mesh_mirror_y", text="Y", toggle=True)
|
|
|
|
|
sub.prop(ob, "use_mesh_mirror_z", text="Z", toggle=True)
|
2020-09-18 19:58:48 +02:00
|
|
|
if mode_string == 'EDIT_MESH':
|
|
|
|
|
layout.prop(tool_settings, "use_mesh_automerge", text="")
|
|
|
|
|
elif mode_string == 'PAINT_WEIGHT':
|
|
|
|
|
row.popover(panel="VIEW3D_PT_tools_weightpaint_symmetry_for_topbar", text="")
|
|
|
|
|
elif mode_string == 'SCULPT':
|
|
|
|
|
row.popover(panel="VIEW3D_PT_sculpt_symmetry_for_topbar", text="")
|
|
|
|
|
elif mode_string == 'PAINT_VERTEX':
|
|
|
|
|
row.popover(panel="VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar", text="")
|
2022-05-04 09:51:32 +02:00
|
|
|
elif mode_string == 'SCULPT_CURVES':
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
2022-05-04 09:51:32 +02:00
|
|
|
_row, sub = row_for_mirror()
|
2024-03-29 10:08:59 +11:00
|
|
|
sub.prop(ob.data, "use_mirror_x", text="X", toggle=True)
|
|
|
|
|
sub.prop(ob.data, "use_mirror_y", text="Y", toggle=True)
|
|
|
|
|
sub.prop(ob.data, "use_mirror_z", text="Z", toggle=True)
|
2019-05-21 15:04:21 +10:00
|
|
|
|
2025-01-15 15:54:43 +01:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(ob.data, "use_sculpt_collision", icon='MOD_PHYSICS', icon_only=True, toggle=True)
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = ob.data.use_sculpt_collision
|
|
|
|
|
sub.prop(ob.data, "surface_collision_distance")
|
2023-02-11 13:46:37 +01:00
|
|
|
|
2019-05-21 15:04:21 +10:00
|
|
|
# Expand panels from the side-bar as popovers.
|
2019-05-23 12:29:28 +10:00
|
|
|
popover_kw = {"space_type": 'VIEW_3D', "region_type": 'UI', "category": "Tool"}
|
|
|
|
|
|
2019-05-21 15:04:21 +10:00
|
|
|
if mode_string == 'SCULPT':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".sculpt_mode", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'PAINT_VERTEX':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".vertexpaint", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'PAINT_WEIGHT':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".weightpaint", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'PAINT_TEXTURE':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".imagepaint", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'EDIT_TEXT':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".text_edit", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'EDIT_ARMATURE':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".armature_edit", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'EDIT_METABALL':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".mball_edit", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'EDIT_LATTICE':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".lattice_edit", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'EDIT_CURVE':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".curve_edit", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'EDIT_MESH':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".mesh_edit", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'POSE':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".posemode", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'PARTICLE':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".particlemode", **popover_kw)
|
2019-05-21 15:04:21 +10:00
|
|
|
elif mode_string == 'OBJECT':
|
2019-05-23 12:29:28 +10:00
|
|
|
layout.popover_group(context=".objectmode", **popover_kw)
|
2024-10-01 18:36:29 +02:00
|
|
|
|
2024-10-01 12:17:43 -07:00
|
|
|
if mode_string in {
|
|
|
|
|
'EDIT_GREASE_PENCIL',
|
|
|
|
|
'PAINT_GREASE_PENCIL',
|
|
|
|
|
'SCULPT_GREASE_PENCIL',
|
|
|
|
|
'WEIGHT_GREASE_PENCIL',
|
2024-10-02 15:42:46 +10:00
|
|
|
'VERTEX_GREASE_PENCIL',
|
|
|
|
|
}:
|
2024-10-01 18:36:29 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "use_grease_pencil_multi_frame_editing", text="")
|
|
|
|
|
|
2024-10-01 12:17:43 -07:00
|
|
|
if mode_string in {
|
|
|
|
|
'EDIT_GREASE_PENCIL',
|
|
|
|
|
'SCULPT_GREASE_PENCIL',
|
|
|
|
|
'WEIGHT_GREASE_PENCIL',
|
2024-10-02 15:42:46 +10:00
|
|
|
'VERTEX_GREASE_PENCIL',
|
|
|
|
|
}:
|
2024-10-01 18:36:29 +02:00
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = tool_settings.use_grease_pencil_multi_frame_editing
|
|
|
|
|
sub.popover(
|
|
|
|
|
panel="VIEW3D_PT_grease_pencil_multi_frame",
|
|
|
|
|
text="Multiframe",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if mode_string == 'PAINT_GREASE_PENCIL':
|
|
|
|
|
layout.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
|
|
|
|
|
layout.prop(tool_settings, "use_gpencil_automerge_strokes", text="")
|
|
|
|
|
layout.prop(tool_settings, "use_gpencil_weight_data_add", text="", icon='WPAINT_HLT')
|
|
|
|
|
layout.prop(tool_settings, "use_gpencil_draw_onback", text="", icon='MOD_OPACITY')
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class _draw_tool_settings_context_mode:
|
|
|
|
|
@staticmethod
|
|
|
|
|
def SCULPT(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
paint = context.tool_settings.sculpt
|
|
|
|
|
brush = paint.brush
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
if brush is None:
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
capabilities = brush.sculpt_capabilities
|
|
|
|
|
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
ups = paint.unified_paint_settings
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
2022-04-05 11:42:55 -07:00
|
|
|
if capabilities.has_color:
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.ui_units_x = 4
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
|
|
|
|
|
row.separator()
|
|
|
|
|
layout.prop(brush, "blend", text="", expand=False)
|
|
|
|
|
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
size = "size"
|
|
|
|
|
size_owner = ups if ups.use_unified_size else brush
|
|
|
|
|
if size_owner.use_locked_size == 'SCENE':
|
2025-08-30 00:18:41 +02:00
|
|
|
size = "unprojected_size"
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
size,
|
|
|
|
|
pressure_name="use_pressure_size",
|
2019-12-23 17:28:21 +01:00
|
|
|
unified_name="use_unified_size",
|
2025-08-30 00:18:41 +02:00
|
|
|
text="Size",
|
2019-12-16 14:29:03 +11:00
|
|
|
slider=True,
|
2022-05-12 14:07:15 +10:00
|
|
|
header=True,
|
2019-12-16 14:29:03 +11:00
|
|
|
)
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
|
|
|
|
# strength, use_strength_pressure
|
|
|
|
|
pressure_name = "use_pressure_strength" if capabilities.has_strength_pressure else None
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
pressure_name=pressure_name,
|
2019-12-23 17:28:21 +01:00
|
|
|
unified_name="use_unified_strength",
|
2019-12-16 14:29:03 +11:00
|
|
|
text="Strength",
|
2022-05-12 14:07:15 +10:00
|
|
|
header=True,
|
2019-12-16 14:29:03 +11:00
|
|
|
)
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
|
|
|
|
# direction
|
2025-04-10 22:05:23 +02:00
|
|
|
if capabilities.has_direction:
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
layout.row().prop(brush, "direction", expand=True, text="")
|
2019-04-18 21:13:22 +02:00
|
|
|
|
2019-12-19 20:05:13 +11:00
|
|
|
return True
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def PAINT_TEXTURE(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
paint = context.tool_settings.image_paint
|
|
|
|
|
brush = paint.brush
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
if brush is None:
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
brush_basic_texpaint_settings(layout, context, brush, compact=True)
|
|
|
|
|
|
2019-12-19 20:05:13 +11:00
|
|
|
return True
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def PAINT_VERTEX(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
paint = context.tool_settings.vertex_paint
|
|
|
|
|
brush = paint.brush
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
if brush is None:
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
brush_basic_texpaint_settings(layout, context, brush, compact=True)
|
2019-04-18 21:13:22 +02:00
|
|
|
|
2019-12-19 20:05:13 +11:00
|
|
|
return True
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def PAINT_WEIGHT(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
paint = context.tool_settings.weight_paint
|
|
|
|
|
brush = paint.brush
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
if brush is None:
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
capabilities = brush.weight_paint_capabilities
|
|
|
|
|
if capabilities.has_weight:
|
2019-12-23 17:28:21 +01:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"weight",
|
|
|
|
|
unified_name="use_unified_weight",
|
|
|
|
|
slider=True,
|
2022-05-12 14:07:15 +10:00
|
|
|
header=True,
|
2019-12-23 17:28:21 +01:00
|
|
|
)
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"size",
|
|
|
|
|
pressure_name="use_pressure_size",
|
2019-12-23 17:28:21 +01:00
|
|
|
unified_name="use_unified_size",
|
2019-12-16 14:29:03 +11:00
|
|
|
slider=True,
|
2025-08-30 00:18:41 +02:00
|
|
|
text="Size",
|
2022-05-12 14:07:15 +10:00
|
|
|
header=True,
|
2019-12-16 14:29:03 +11:00
|
|
|
)
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
pressure_name="use_pressure_strength",
|
2019-12-23 17:28:21 +01:00
|
|
|
unified_name="use_unified_strength",
|
2022-05-12 14:07:15 +10:00
|
|
|
header=True,
|
2019-12-16 14:29:03 +11:00
|
|
|
)
|
2019-04-18 21:13:22 +02:00
|
|
|
|
2019-12-19 20:05:13 +11:00
|
|
|
return True
|
|
|
|
|
|
2024-04-11 09:39:48 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def SCULPT_GREASE_PENCIL(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2024-04-11 09:39:48 +02:00
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
paint = context.tool_settings.gpencil_sculpt_paint
|
|
|
|
|
brush = paint.brush
|
|
|
|
|
if brush is None:
|
|
|
|
|
return False
|
|
|
|
|
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2024-04-11 09:39:48 +02:00
|
|
|
capabilities = brush.sculpt_capabilities
|
|
|
|
|
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
ups = paint.unified_paint_settings
|
2024-04-11 09:39:48 +02:00
|
|
|
|
|
|
|
|
size = "size"
|
|
|
|
|
size_owner = ups if ups.use_unified_size else brush
|
|
|
|
|
if size_owner.use_locked_size == 'SCENE':
|
2025-08-30 00:18:41 +02:00
|
|
|
size = "unprojected_size"
|
2024-04-11 09:39:48 +02:00
|
|
|
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
size,
|
|
|
|
|
pressure_name="use_pressure_size",
|
|
|
|
|
unified_name="use_unified_size",
|
2025-08-30 00:18:41 +02:00
|
|
|
text="Size",
|
2024-04-11 09:39:48 +02:00
|
|
|
slider=True,
|
|
|
|
|
header=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# strength, use_strength_pressure
|
|
|
|
|
pressure_name = "use_pressure_strength" if capabilities.has_strength_pressure else None
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
pressure_name=pressure_name,
|
|
|
|
|
unified_name="use_unified_strength",
|
|
|
|
|
text="Strength",
|
|
|
|
|
header=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# direction
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_sculpt_brush_type in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
|
2024-04-11 09:39:48 +02:00
|
|
|
layout.row().prop(brush, "direction", expand=True, text="")
|
|
|
|
|
|
2024-04-25 20:20:27 +02:00
|
|
|
# Brush falloff
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
|
|
|
|
|
2024-04-11 09:39:48 +02:00
|
|
|
return True
|
|
|
|
|
|
GPv3: Weight Paint tools (Draw, Blur, Average, Smear, Sample weight)
This PR implements the Weight Paint tools for GPv3.
Tools:
- Draw, for assigning weight to stroke points
- Blur, smooths out weight using adjacent stroke point weights
- Average, smooths weight using the average weight under the brush
- Smear, like finger painting, drags weights in the direction of the brush
- Sample weight, sets the brush weight to the weight under the cursor
The weights are assigned to the active vertex group. When there is no
active vertex group, a group is automatically created.
When the Auto Normalize option is enabled, it is ensured that all
bone-deforming vertex groups add up to the weight of 1.0.
When a vertex group is locked, it's weights will not be altered by
Auto Normalize.
The PR already supports multi frame editing, including the use of a
falloff (defined by a curve).
The implementation is in accordance with the Weight Paint tools in GPv2.
Pull Request: https://projects.blender.org/blender/blender/pulls/118347
2024-04-25 15:21:14 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def WEIGHT_GREASE_PENCIL(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
GPv3: Weight Paint tools (Draw, Blur, Average, Smear, Sample weight)
This PR implements the Weight Paint tools for GPv3.
Tools:
- Draw, for assigning weight to stroke points
- Blur, smooths out weight using adjacent stroke point weights
- Average, smooths weight using the average weight under the brush
- Smear, like finger painting, drags weights in the direction of the brush
- Sample weight, sets the brush weight to the weight under the cursor
The weights are assigned to the active vertex group. When there is no
active vertex group, a group is automatically created.
When the Auto Normalize option is enabled, it is ensured that all
bone-deforming vertex groups add up to the weight of 1.0.
When a vertex group is locked, it's weights will not be altered by
Auto Normalize.
The PR already supports multi frame editing, including the use of a
falloff (defined by a curve).
The implementation is in accordance with the Weight Paint tools in GPv2.
Pull Request: https://projects.blender.org/blender/blender/pulls/118347
2024-04-25 15:21:14 +02:00
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
paint = context.tool_settings.gpencil_weight_paint
|
|
|
|
|
brush = paint.brush
|
|
|
|
|
if brush is None:
|
|
|
|
|
return False
|
|
|
|
|
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
GPv3: Weight Paint tools (Draw, Blur, Average, Smear, Sample weight)
This PR implements the Weight Paint tools for GPv3.
Tools:
- Draw, for assigning weight to stroke points
- Blur, smooths out weight using adjacent stroke point weights
- Average, smooths weight using the average weight under the brush
- Smear, like finger painting, drags weights in the direction of the brush
- Sample weight, sets the brush weight to the weight under the cursor
The weights are assigned to the active vertex group. When there is no
active vertex group, a group is automatically created.
When the Auto Normalize option is enabled, it is ensured that all
bone-deforming vertex groups add up to the weight of 1.0.
When a vertex group is locked, it's weights will not be altered by
Auto Normalize.
The PR already supports multi frame editing, including the use of a
falloff (defined by a curve).
The implementation is in accordance with the Weight Paint tools in GPv2.
Pull Request: https://projects.blender.org/blender/blender/pulls/118347
2024-04-25 15:21:14 +02:00
|
|
|
brush_basic_grease_pencil_weight_settings(layout, context, brush, compact=True)
|
|
|
|
|
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_options", text="Options")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_weight_falloff", text="Falloff")
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2024-09-10 18:56:31 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def VERTEX_GREASE_PENCIL(context, layout, tool):
|
2024-09-16 13:08:52 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2024-09-10 18:56:31 +02:00
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
paint = tool_settings.gpencil_vertex_paint
|
|
|
|
|
brush = paint.brush
|
|
|
|
|
|
|
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_vertex_brush_type not in {'BLUR', 'AVERAGE', 'SMEAR'}:
|
2024-09-10 18:56:31 +02:00
|
|
|
layout.separator(factor=0.4)
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
ups = paint.unified_paint_settings
|
2024-09-10 18:56:31 +02:00
|
|
|
prop_owner = ups if ups.use_unified_color else brush
|
|
|
|
|
layout.prop_with_popover(prop_owner, "color", text="", panel="TOPBAR_PT_grease_pencil_vertex_color")
|
|
|
|
|
|
|
|
|
|
brush_basic_grease_pencil_vertex_settings(layout, context, brush, compact=True)
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def PARTICLE(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2019-12-19 20:05:13 +11:00
|
|
|
return False
|
2019-04-18 21:13:22 +02:00
|
|
|
|
2024-03-14 10:38:16 +11:00
|
|
|
# See: `VIEW3D_PT_tools_brush`, basically a duplicate
|
2023-09-15 10:44:42 +10:00
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
settings = tool_settings.particle_edit
|
2019-04-18 21:13:22 +02:00
|
|
|
brush = settings.brush
|
|
|
|
|
tool = settings.tool
|
2019-12-19 20:05:13 +11:00
|
|
|
if tool == 'NONE':
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
layout.prop(brush, "size", slider=True)
|
|
|
|
|
if tool == 'ADD':
|
|
|
|
|
layout.prop(brush, "count")
|
|
|
|
|
|
|
|
|
|
layout.prop(settings, "use_default_interpolate")
|
|
|
|
|
layout.prop(brush, "steps", slider=True)
|
|
|
|
|
layout.prop(settings, "default_key_count", slider=True)
|
|
|
|
|
else:
|
|
|
|
|
layout.prop(brush, "strength", slider=True)
|
|
|
|
|
|
|
|
|
|
if tool == 'LENGTH':
|
|
|
|
|
layout.row().prop(brush, "length_mode", expand=True)
|
|
|
|
|
elif tool == 'PUFF':
|
|
|
|
|
layout.row().prop(brush, "puff_mode", expand=True)
|
|
|
|
|
layout.prop(brush, "use_puff_volume")
|
|
|
|
|
elif tool == 'COMB':
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.active = settings.is_editable
|
|
|
|
|
row.prop(settings, "use_emitter_deflect", text="Deflect Emitter")
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = settings.use_emitter_deflect
|
|
|
|
|
sub.prop(settings, "emitter_distance", text="Distance")
|
|
|
|
|
|
|
|
|
|
return True
|
2019-04-18 21:13:22 +02:00
|
|
|
|
2022-02-21 12:49:36 +01:00
|
|
|
@staticmethod
|
|
|
|
|
def SCULPT_CURVES(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2022-02-21 12:49:36 +01:00
|
|
|
return False
|
|
|
|
|
|
2022-03-02 17:15:44 +01:00
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
paint = tool_settings.curves_sculpt
|
2022-02-21 12:49:36 +01:00
|
|
|
brush = paint.brush
|
2024-10-28 18:22:21 +01:00
|
|
|
|
|
|
|
|
BrushAssetShelf.draw_popup_selector(layout, context, brush)
|
|
|
|
|
|
2022-02-21 12:49:36 +01:00
|
|
|
if brush is None:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
2022-05-12 14:07:15 +10:00
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"size",
|
|
|
|
|
unified_name="use_unified_size",
|
|
|
|
|
pressure_name="use_pressure_size",
|
2025-08-30 00:18:41 +02:00
|
|
|
text="Size",
|
2022-05-12 14:07:15 +10:00
|
|
|
slider=True,
|
|
|
|
|
header=True,
|
|
|
|
|
)
|
2022-02-21 12:49:36 +01:00
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.curves_sculpt_brush_type not in {'ADD', 'DELETE'}:
|
|
|
|
|
use_strength_pressure = brush.curves_sculpt_brush_type not in {'SLIDE'}
|
2022-03-21 18:54:31 +01:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
unified_name="use_unified_strength",
|
2024-12-11 16:43:15 +01:00
|
|
|
pressure_name="use_pressure_strength" if use_strength_pressure else None,
|
2022-05-12 14:07:15 +10:00
|
|
|
header=True,
|
2022-03-21 18:54:31 +01:00
|
|
|
)
|
|
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
curves_tool = brush.curves_sculpt_brush_type
|
2022-06-02 22:17:50 +02:00
|
|
|
|
|
|
|
|
if curves_tool == 'COMB':
|
2022-03-23 18:19:38 +01:00
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
2023-02-15 10:42:30 +01:00
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff", text="Brush Falloff")
|
|
|
|
|
layout.popover("VIEW3D_PT_curves_sculpt_parameter_falloff", text="Curve Falloff")
|
2022-06-02 22:17:50 +02:00
|
|
|
elif curves_tool == 'ADD':
|
2022-03-21 18:54:31 +01:00
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
|
|
|
|
layout.prop(brush.curves_sculpt_settings, "add_amount")
|
2022-05-11 15:47:49 +02:00
|
|
|
layout.popover("VIEW3D_PT_curves_sculpt_add_shape", text="Curve Shape")
|
|
|
|
|
layout.prop(brush, "use_frontface", text="Front Faces Only")
|
2022-06-02 22:17:50 +02:00
|
|
|
elif curves_tool == 'GROW_SHRINK':
|
2022-04-05 15:24:12 +02:00
|
|
|
layout.prop(brush, "direction", expand=True, text="")
|
|
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
2022-05-11 15:47:49 +02:00
|
|
|
layout.popover("VIEW3D_PT_curves_sculpt_grow_shrink_scaling", text="Scaling")
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
2022-06-02 22:17:50 +02:00
|
|
|
elif curves_tool == 'SNAKE_HOOK':
|
2022-03-29 14:46:14 +02:00
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
2022-05-11 15:47:49 +02:00
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
2022-06-02 22:17:50 +02:00
|
|
|
elif curves_tool == 'DELETE':
|
2022-05-02 09:18:57 +02:00
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
2022-06-02 22:17:50 +02:00
|
|
|
elif curves_tool == 'SELECTION_PAINT':
|
2022-05-31 19:00:24 +02:00
|
|
|
layout.prop(brush, "direction", expand=True, text="")
|
|
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
2022-06-30 15:09:13 +02:00
|
|
|
elif curves_tool == 'PINCH':
|
|
|
|
|
layout.prop(brush, "direction", expand=True, text="")
|
|
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
|
|
|
|
elif curves_tool == 'SMOOTH':
|
|
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
|
|
|
|
elif curves_tool == 'PUFF':
|
|
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
|
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
|
|
|
|
elif curves_tool == 'DENSITY':
|
|
|
|
|
layout.prop(brush, "falloff_shape", expand=True)
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(brush.curves_sculpt_settings, "density_mode", text="", expand=True)
|
|
|
|
|
row = layout.row(align=True)
|
2022-07-01 10:20:07 +02:00
|
|
|
row.prop(brush.curves_sculpt_settings, "minimum_distance", text="Distance Min")
|
2022-06-30 15:09:13 +02:00
|
|
|
row.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
row.operator("sculpt_curves.min_distance_edit", text="", icon='DRIVER_DISTANCE')
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.enabled = brush.curves_sculpt_settings.density_mode != 'REMOVE'
|
2022-07-01 10:20:07 +02:00
|
|
|
row.prop(brush.curves_sculpt_settings, "density_add_attempts", text="Count Max")
|
2022-06-30 15:09:13 +02:00
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
|
|
|
|
layout.popover("VIEW3D_PT_curves_sculpt_add_shape", text="Curve Shape")
|
2023-05-15 20:53:17 +10:00
|
|
|
elif curves_tool == 'SLIDE':
|
2022-06-30 15:09:13 +02:00
|
|
|
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
2022-05-31 19:00:24 +02:00
|
|
|
|
2023-04-13 13:14:06 +10:00
|
|
|
return True
|
|
|
|
|
|
2023-10-06 10:49:54 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def PAINT_GREASE_PENCIL(context, layout, tool):
|
2024-09-16 12:20:25 +02:00
|
|
|
if (tool is None) or (not tool.use_brushes):
|
2023-10-06 10:49:54 +02:00
|
|
|
return False
|
2023-10-07 18:29:50 +11:00
|
|
|
|
2024-09-16 13:04:08 +02:00
|
|
|
# These draw their own properties.
|
|
|
|
|
if tool.idname in {
|
|
|
|
|
"builtin.arc",
|
|
|
|
|
"builtin.curve",
|
|
|
|
|
"builtin.line",
|
|
|
|
|
"builtin.box",
|
|
|
|
|
"builtin.circle",
|
|
|
|
|
"builtin.polyline",
|
|
|
|
|
}:
|
|
|
|
|
return False
|
|
|
|
|
|
2023-10-06 10:49:54 +02:00
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
paint = tool_settings.gpencil_paint
|
|
|
|
|
|
|
|
|
|
brush = paint.brush
|
|
|
|
|
if brush is None:
|
|
|
|
|
return False
|
2023-10-07 18:29:50 +11:00
|
|
|
|
2023-10-06 10:49:54 +02:00
|
|
|
row = layout.row(align=True)
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
2024-09-16 15:42:41 +02:00
|
|
|
BrushAssetShelf.draw_popup_selector(row, context, brush)
|
2023-10-06 10:49:54 +02:00
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
grease_pencil_tool = brush.gpencil_brush_type
|
2023-10-06 10:49:54 +02:00
|
|
|
|
2024-05-15 13:36:06 +02:00
|
|
|
if grease_pencil_tool in {'DRAW', 'FILL'}:
|
2023-10-06 10:49:54 +02:00
|
|
|
from bl_ui.properties_paint_common import (
|
|
|
|
|
brush_basic__draw_color_selector,
|
|
|
|
|
)
|
2024-10-03 00:28:50 +02:00
|
|
|
brush_basic__draw_color_selector(context, layout, brush, brush.gpencil_settings)
|
2023-10-07 18:29:50 +11:00
|
|
|
|
2024-03-29 12:43:15 +01:00
|
|
|
if grease_pencil_tool == 'TINT':
|
2024-04-22 11:44:10 +02:00
|
|
|
row.separator(factor=0.4)
|
2024-12-06 10:38:57 +01:00
|
|
|
row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_grease_pencil_vertex_color")
|
2024-03-29 12:43:15 +01:00
|
|
|
|
2024-02-29 10:44:19 +01:00
|
|
|
from bl_ui.properties_paint_common import (
|
|
|
|
|
brush_basic_grease_pencil_paint_settings,
|
2023-10-06 10:49:54 +02:00
|
|
|
)
|
|
|
|
|
|
2024-10-03 00:28:50 +02:00
|
|
|
brush_basic_grease_pencil_paint_settings(layout, context, brush, None, compact=True)
|
2023-10-06 10:49:54 +02:00
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2022-03-02 17:15:44 +01:00
|
|
|
|
2024-10-08 18:27:28 +02:00
|
|
|
def draw_topbar_grease_pencil_layer_panel(context, layout):
|
|
|
|
|
grease_pencil = context.object.data
|
|
|
|
|
layer = grease_pencil.layers.active
|
|
|
|
|
group = grease_pencil.layer_groups.active
|
|
|
|
|
|
|
|
|
|
icon = 'OUTLINER_DATA_GP_LAYER'
|
|
|
|
|
node_name = None
|
|
|
|
|
if layer or group:
|
|
|
|
|
icon = 'OUTLINER_DATA_GP_LAYER' if layer else 'GREASEPENCIL_LAYER_GROUP'
|
|
|
|
|
node_name = layer.name if layer else group.name
|
|
|
|
|
|
|
|
|
|
# Clamp long names otherwise the selector can get too wide.
|
|
|
|
|
max_width = 25
|
|
|
|
|
if len(node_name) > max_width:
|
|
|
|
|
node_name = node_name[:max_width - 5] + '..' + node_name[-3:]
|
|
|
|
|
|
|
|
|
|
sub = layout.row()
|
|
|
|
|
sub.popover(
|
|
|
|
|
panel="TOPBAR_PT_grease_pencil_layers",
|
|
|
|
|
text=node_name,
|
|
|
|
|
icon=icon,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
class VIEW3D_HT_header(Header):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
|
2019-04-29 22:50:14 +10:00
|
|
|
@staticmethod
|
|
|
|
|
def draw_xform_template(layout, context):
|
|
|
|
|
obj = context.active_object
|
|
|
|
|
object_mode = 'OBJECT' if obj is None else obj.mode
|
|
|
|
|
has_pose_mode = (
|
|
|
|
|
(object_mode == 'POSE') or
|
|
|
|
|
(object_mode == 'WEIGHT_PAINT' and context.pose_object is not None)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
|
|
|
|
|
# Mode & Transform Settings
|
|
|
|
|
scene = context.scene
|
|
|
|
|
|
|
|
|
|
# Orientation
|
2024-10-02 15:42:46 +10:00
|
|
|
if has_pose_mode or object_mode in {'OBJECT', 'EDIT', 'EDIT_GPENCIL'}:
|
2019-04-29 22:50:14 +10:00
|
|
|
orient_slot = scene.transform_orientation_slots[0]
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.prop_with_popover(
|
|
|
|
|
orient_slot,
|
|
|
|
|
"type",
|
|
|
|
|
text="",
|
|
|
|
|
panel="VIEW3D_PT_transform_orientations",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Pivot
|
2024-10-04 19:20:00 +02:00
|
|
|
if has_pose_mode or object_mode in {'OBJECT', 'EDIT', 'EDIT_GPENCIL', 'SCULPT_GREASE_PENCIL'}:
|
2019-11-05 17:47:35 +11:00
|
|
|
layout.prop(tool_settings, "transform_pivot_point", text="", icon_only=True)
|
2019-04-29 22:50:14 +10:00
|
|
|
|
|
|
|
|
# Snap
|
|
|
|
|
show_snap = False
|
|
|
|
|
if obj is None:
|
|
|
|
|
show_snap = True
|
|
|
|
|
else:
|
2024-10-02 15:42:46 +10:00
|
|
|
if has_pose_mode or (object_mode not in {
|
|
|
|
|
'SCULPT', 'SCULPT_CURVES',
|
|
|
|
|
'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
|
2024-10-04 19:20:00 +02:00
|
|
|
'PAINT_GREASE_PENCIL', 'SCULPT_GREASE_PENCIL', 'WEIGHT_GREASE_PENCIL', 'VERTEX_GREASE_PENCIL',
|
2024-10-02 15:42:46 +10:00
|
|
|
}):
|
2019-04-29 22:50:14 +10:00
|
|
|
show_snap = True
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
paint_settings = UnifiedPaintPanel.paint_settings(context)
|
|
|
|
|
|
|
|
|
|
if paint_settings:
|
|
|
|
|
brush = paint_settings.brush
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
if brush and hasattr(brush, "stroke_method") and brush.stroke_method == 'CURVE':
|
2019-04-29 22:50:14 +10:00
|
|
|
show_snap = True
|
|
|
|
|
|
|
|
|
|
if show_snap:
|
|
|
|
|
snap_items = bpy.types.ToolSettings.bl_rna.properties["snap_elements"].enum_items
|
|
|
|
|
snap_elements = tool_settings.snap_elements
|
|
|
|
|
if len(snap_elements) == 1:
|
|
|
|
|
text = ""
|
|
|
|
|
for elem in snap_elements:
|
|
|
|
|
icon = snap_items[elem].icon
|
|
|
|
|
break
|
|
|
|
|
else:
|
2023-12-19 18:41:09 +01:00
|
|
|
text = iface_("Mix", i18n_contexts.editor_view3d)
|
2019-04-29 22:50:14 +10:00
|
|
|
icon = 'NONE'
|
|
|
|
|
del snap_items, snap_elements
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "use_snap", text="")
|
|
|
|
|
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.popover(
|
|
|
|
|
panel="VIEW3D_PT_snapping",
|
|
|
|
|
icon=icon,
|
|
|
|
|
text=text,
|
2023-12-19 18:41:09 +01:00
|
|
|
translate=False,
|
2019-04-29 22:50:14 +10:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Proportional editing
|
2024-05-02 09:23:10 +02:00
|
|
|
if object_mode in {
|
|
|
|
|
'EDIT',
|
|
|
|
|
'PARTICLE_EDIT',
|
2024-10-04 19:20:00 +02:00
|
|
|
'SCULPT_GREASE_PENCIL',
|
2024-05-02 09:23:10 +02:00
|
|
|
'EDIT_GPENCIL',
|
2024-05-03 11:25:06 +10:00
|
|
|
'OBJECT',
|
|
|
|
|
} and context.mode != 'EDIT_ARMATURE':
|
2019-04-29 22:50:14 +10:00
|
|
|
row = layout.row(align=True)
|
2019-04-30 13:42:18 +10:00
|
|
|
kw = {}
|
|
|
|
|
if object_mode == 'OBJECT':
|
|
|
|
|
attr = "use_proportional_edit_objects"
|
|
|
|
|
else:
|
|
|
|
|
attr = "use_proportional_edit"
|
2019-04-29 22:50:14 +10:00
|
|
|
|
2019-05-07 10:01:25 +10:00
|
|
|
if tool_settings.use_proportional_edit:
|
2019-05-06 11:54:46 +02:00
|
|
|
if tool_settings.use_proportional_connected:
|
|
|
|
|
kw["icon"] = 'PROP_CON'
|
|
|
|
|
elif tool_settings.use_proportional_projected:
|
|
|
|
|
kw["icon"] = 'PROP_PROJECTED'
|
2019-05-07 10:01:25 +10:00
|
|
|
else:
|
|
|
|
|
kw["icon"] = 'PROP_ON'
|
|
|
|
|
else:
|
|
|
|
|
kw["icon"] = 'PROP_OFF'
|
2019-04-29 22:50:14 +10:00
|
|
|
|
2019-04-30 13:42:18 +10:00
|
|
|
row.prop(tool_settings, attr, icon_only=True, **kw)
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = getattr(tool_settings, attr)
|
|
|
|
|
sub.prop_with_popover(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"proportional_edit_falloff",
|
|
|
|
|
text="",
|
|
|
|
|
icon_only=True,
|
|
|
|
|
panel="VIEW3D_PT_proportional_edit",
|
|
|
|
|
)
|
2019-04-29 22:50:14 +10:00
|
|
|
|
2024-10-08 18:27:28 +02:00
|
|
|
if object_mode == 'EDIT' and obj.type == 'GREASEPENCIL':
|
|
|
|
|
draw_topbar_grease_pencil_layer_panel(context, layout)
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
view = context.space_data
|
|
|
|
|
shading = view.shading
|
|
|
|
|
|
2021-09-28 14:44:36 +10:00
|
|
|
layout.row(align=True).template_header()
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
2020-01-29 16:56:21 +11:00
|
|
|
obj = context.active_object
|
2023-09-15 10:44:45 +10:00
|
|
|
mode_string = context.mode
|
2019-04-18 21:13:22 +02:00
|
|
|
object_mode = 'OBJECT' if obj is None else obj.mode
|
2020-01-29 16:56:21 +11:00
|
|
|
has_pose_mode = (
|
|
|
|
|
(object_mode == 'POSE') or
|
|
|
|
|
(object_mode == 'WEIGHT_PAINT' and context.pose_object is not None)
|
|
|
|
|
)
|
2019-04-18 21:13:22 +02:00
|
|
|
|
|
|
|
|
# Note: This is actually deadly in case enum_items have to be dynamically generated
|
|
|
|
|
# (because internal RNA array iterator will free everything immediately...).
|
|
|
|
|
# XXX This is an RNA internal issue, not sure how to fix it.
|
|
|
|
|
# Note: Tried to add an accessor to get translated UI strings instead of manual call
|
2023-09-05 10:49:20 +10:00
|
|
|
# to pgettext_iface below, but this fails because translated enum-items
|
2019-04-18 21:13:22 +02:00
|
|
|
# are always dynamically allocated.
|
|
|
|
|
act_mode_item = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode]
|
|
|
|
|
act_mode_i18n_context = bpy.types.Object.bl_rna.properties["mode"].translation_context
|
|
|
|
|
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.operator_menu_enum(
|
|
|
|
|
"object.mode_set", "mode",
|
2022-11-16 12:27:20 +01:00
|
|
|
text=iface_(act_mode_item.name, act_mode_i18n_context),
|
2019-04-18 21:13:22 +02:00
|
|
|
icon=act_mode_item.icon,
|
|
|
|
|
)
|
|
|
|
|
del act_mode_item
|
|
|
|
|
|
|
|
|
|
layout.template_header_3D_mode()
|
|
|
|
|
|
|
|
|
|
# Contains buttons like Mode, Pivot, Layer, Mesh Select Mode...
|
|
|
|
|
if obj:
|
|
|
|
|
# Particle edit
|
|
|
|
|
if object_mode == 'PARTICLE_EDIT':
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.prop(tool_settings.particle_edit, "select_mode", text="", expand=True)
|
2023-01-20 16:40:51 +01:00
|
|
|
elif object_mode in {'EDIT', 'SCULPT_CURVES'} and obj.type == 'CURVES':
|
2022-05-31 19:00:24 +02:00
|
|
|
curves = obj.data
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
2022-07-08 14:41:21 +02:00
|
|
|
domain = curves.selection_domain
|
2023-01-03 11:03:50 +11:00
|
|
|
row.operator(
|
|
|
|
|
"curves.set_selection_domain",
|
|
|
|
|
text="",
|
|
|
|
|
icon='CURVE_BEZCIRCLE',
|
|
|
|
|
depress=(domain == 'POINT'),
|
|
|
|
|
).domain = 'POINT'
|
|
|
|
|
row.operator(
|
|
|
|
|
"curves.set_selection_domain",
|
|
|
|
|
text="",
|
|
|
|
|
icon='CURVE_PATH',
|
|
|
|
|
depress=(domain == 'CURVE'),
|
|
|
|
|
).domain = 'CURVE'
|
2019-04-18 21:13:22 +02:00
|
|
|
|
2025-04-07 11:39:16 +02:00
|
|
|
# Grease Pencil
|
2023-06-19 16:12:11 +02:00
|
|
|
if obj and obj.type == 'GREASEPENCIL':
|
|
|
|
|
# Select mode for Editing
|
|
|
|
|
if object_mode == 'EDIT':
|
|
|
|
|
row = layout.row(align=True)
|
2023-07-12 10:22:46 +02:00
|
|
|
row.operator(
|
|
|
|
|
"grease_pencil.set_selection_mode",
|
|
|
|
|
text="",
|
2023-08-29 14:55:10 +10:00
|
|
|
icon='GP_SELECT_POINTS',
|
2023-07-12 10:22:46 +02:00
|
|
|
depress=(tool_settings.gpencil_selectmode_edit == 'POINT'),
|
|
|
|
|
).mode = 'POINT'
|
|
|
|
|
row.operator(
|
|
|
|
|
"grease_pencil.set_selection_mode",
|
|
|
|
|
text="",
|
2023-08-29 14:55:10 +10:00
|
|
|
icon='GP_SELECT_STROKES',
|
2023-07-12 10:22:46 +02:00
|
|
|
depress=(tool_settings.gpencil_selectmode_edit == 'STROKE'),
|
|
|
|
|
).mode = 'STROKE'
|
2024-08-21 13:35:26 +02:00
|
|
|
row.operator(
|
|
|
|
|
"grease_pencil.set_selection_mode",
|
|
|
|
|
text="",
|
|
|
|
|
icon='GP_SELECT_BETWEEN_STROKES',
|
|
|
|
|
depress=(tool_settings.gpencil_selectmode_edit == 'SEGMENT'),
|
|
|
|
|
).mode = 'SEGMENT'
|
2024-05-14 12:51:33 +02:00
|
|
|
|
2024-10-04 19:20:00 +02:00
|
|
|
if object_mode == 'SCULPT_GREASE_PENCIL':
|
2024-05-14 12:51:33 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "use_gpencil_select_mask_point", text="")
|
|
|
|
|
row.prop(tool_settings, "use_gpencil_select_mask_stroke", text="")
|
|
|
|
|
row.prop(tool_settings, "use_gpencil_select_mask_segment", text="")
|
|
|
|
|
|
2024-10-04 19:20:00 +02:00
|
|
|
if object_mode == 'VERTEX_GREASE_PENCIL':
|
2024-09-10 18:56:31 +02:00
|
|
|
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="")
|
|
|
|
|
|
2019-04-18 21:13:22 +02:00
|
|
|
overlay = view.overlay
|
|
|
|
|
|
|
|
|
|
VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
|
|
|
|
|
|
|
|
|
|
layout.separator_spacer()
|
|
|
|
|
|
2024-10-04 19:20:00 +02:00
|
|
|
if object_mode in {'PAINT_GREASE_PENCIL', 'SCULPT_GREASE_PENCIL'}:
|
2019-05-20 15:29:19 +02:00
|
|
|
# Grease pencil
|
2024-10-04 19:20:00 +02:00
|
|
|
if object_mode == 'PAINT_GREASE_PENCIL':
|
2023-12-05 11:01:42 +01:00
|
|
|
sub = layout.row(align=True)
|
|
|
|
|
sub.prop_with_popover(
|
2019-05-20 15:29:19 +02:00
|
|
|
tool_settings,
|
|
|
|
|
"gpencil_stroke_placement_view3d",
|
|
|
|
|
text="",
|
2024-10-04 13:05:09 +02:00
|
|
|
panel="VIEW3D_PT_grease_pencil_origin",
|
2019-05-20 15:29:19 +02:00
|
|
|
)
|
|
|
|
|
|
2024-11-10 07:48:23 +01:00
|
|
|
sub = layout.row(align=True)
|
|
|
|
|
sub.active = tool_settings.gpencil_stroke_placement_view3d != 'SURFACE'
|
|
|
|
|
sub.prop_with_popover(
|
|
|
|
|
tool_settings.gpencil_sculpt,
|
|
|
|
|
"lock_axis",
|
|
|
|
|
text="",
|
|
|
|
|
panel="VIEW3D_PT_grease_pencil_lock",
|
|
|
|
|
)
|
2019-05-20 15:29:19 +02:00
|
|
|
|
2024-10-08 18:27:28 +02:00
|
|
|
draw_topbar_grease_pencil_layer_panel(context, layout)
|
2024-10-01 18:36:29 +02:00
|
|
|
|
2024-10-04 19:20:00 +02:00
|
|
|
if object_mode == 'PAINT_GREASE_PENCIL':
|
2019-05-20 15:29:19 +02:00
|
|
|
# FIXME: this is bad practice!
|
2023-09-05 10:49:20 +10:00
|
|
|
# Tool options are to be displayed in the top-bar.
|
2024-04-25 14:23:46 +02:00
|
|
|
tool = context.workspace.tools.from_space_view3d_mode(object_mode)
|
|
|
|
|
if tool and tool.idname == "builtin_brush.Draw":
|
2019-05-20 15:29:19 +02:00
|
|
|
settings = tool_settings.gpencil_sculpt.guide
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(settings, "use_guide", text="", icon='GRID')
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = settings.use_guide
|
|
|
|
|
sub.popover(
|
2024-10-04 13:05:09 +02:00
|
|
|
panel="VIEW3D_PT_grease_pencil_guide",
|
2019-05-20 15:29:19 +02:00
|
|
|
text="Guides",
|
|
|
|
|
)
|
2025-01-24 10:20:03 +01:00
|
|
|
if object_mode == 'SCULPT_GREASE_PENCIL':
|
|
|
|
|
layout.popover(
|
|
|
|
|
panel="VIEW3D_PT_grease_pencil_sculpt_automasking",
|
|
|
|
|
text="",
|
|
|
|
|
icon=VIEW3D_HT_header._grease_pencil_sculpt_automasking_icon(tool_settings.gpencil_sculpt),
|
|
|
|
|
)
|
2023-09-06 16:21:11 +02:00
|
|
|
|
2022-10-17 11:17:42 +02:00
|
|
|
elif object_mode == 'SCULPT':
|
2023-09-06 16:21:11 +02:00
|
|
|
# If the active tool supports it, show the canvas selector popover.
|
|
|
|
|
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
|
|
|
|
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
2024-11-01 19:23:16 +01:00
|
|
|
|
|
|
|
|
is_paint_tool = False
|
|
|
|
|
if tool.use_brushes:
|
|
|
|
|
paint = tool_settings.sculpt
|
|
|
|
|
brush = paint.brush
|
|
|
|
|
if brush:
|
2025-06-06 23:40:13 +02:00
|
|
|
is_paint_tool = brush.sculpt_brush_type in {'PAINT', 'SMEAR'}
|
2024-11-01 19:23:16 +01:00
|
|
|
else:
|
|
|
|
|
is_paint_tool = tool and tool.use_paint_canvas
|
2023-09-06 16:21:11 +02:00
|
|
|
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
color_type = shading.color_type
|
|
|
|
|
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.active = is_paint_tool and color_type == 'VERTEX'
|
|
|
|
|
|
|
|
|
|
if context.preferences.experimental.use_sculpt_texture_paint:
|
|
|
|
|
canvas_source = tool_settings.paint_mode.canvas_source
|
|
|
|
|
icon = 'GROUP_VCOL' if canvas_source == 'COLOR_ATTRIBUTE' else canvas_source
|
|
|
|
|
row.popover(panel="VIEW3D_PT_slots_paint_canvas", icon=icon)
|
2025-02-03 19:50:33 +01:00
|
|
|
# TODO: Update this boolean condition so that the Canvas button is only active when
|
|
|
|
|
# the appropriate color types are selected in Solid mode, I.E. 'TEXTURE'
|
|
|
|
|
row.active = is_paint_tool
|
2023-09-06 16:21:11 +02:00
|
|
|
else:
|
2023-09-13 13:36:00 +10:00
|
|
|
row.popover(panel="VIEW3D_PT_slots_color_attributes", icon='GROUP_VCOL')
|
2023-09-06 16:21:11 +02:00
|
|
|
|
2024-05-14 19:00:58 +02:00
|
|
|
layout.popover(
|
|
|
|
|
panel="VIEW3D_PT_sculpt_snapping",
|
2024-10-16 14:45:08 +11:00
|
|
|
icon='SNAP_INCREMENT',
|
2024-05-14 19:00:58 +02:00
|
|
|
text="",
|
|
|
|
|
translate=False,
|
|
|
|
|
)
|
|
|
|
|
|
2022-10-17 11:17:42 +02:00
|
|
|
layout.popover(
|
|
|
|
|
panel="VIEW3D_PT_sculpt_automasking",
|
|
|
|
|
text="",
|
2024-06-06 11:26:28 +10:00
|
|
|
icon=VIEW3D_HT_header._sculpt_automasking_icon(tool_settings.sculpt),
|
2022-10-17 11:17:42 +02:00
|
|
|
)
|
2023-09-06 16:21:11 +02:00
|
|
|
|
|
|
|
|
elif object_mode == 'VERTEX_PAINT':
|
|
|
|
|
row = layout.row()
|
2023-09-13 13:36:00 +10:00
|
|
|
row.popover(panel="VIEW3D_PT_slots_color_attributes", icon='GROUP_VCOL')
|
2024-10-08 18:27:28 +02:00
|
|
|
elif object_mode == 'VERTEX_GREASE_PENCIL':
|
|
|
|
|
draw_topbar_grease_pencil_layer_panel(context, layout)
|
2024-10-16 01:10:33 +02:00
|
|
|
elif object_mode == 'WEIGHT_PAINT':
|
2023-09-06 16:21:11 +02:00
|
|
|
row = layout.row()
|
2023-09-13 13:36:00 +10:00
|
|
|
row.popover(panel="VIEW3D_PT_slots_vertex_groups", icon='GROUP_VERTEX')
|
2023-09-06 16:21:11 +02:00
|
|
|
|
2024-10-16 01:10:33 +02:00
|
|
|
layout.popover(
|
|
|
|
|
panel="VIEW3D_PT_sculpt_snapping",
|
2024-10-16 14:45:08 +11:00
|
|
|
icon='SNAP_INCREMENT',
|
2024-10-16 01:10:33 +02:00
|
|
|
text="",
|
|
|
|
|
translate=False,
|
|
|
|
|
)
|
|
|
|
|
elif object_mode == 'WEIGHT_GREASE_PENCIL':
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.popover(panel="VIEW3D_PT_slots_vertex_groups", icon='GROUP_VERTEX')
|
|
|
|
|
draw_topbar_grease_pencil_layer_panel(context, row)
|
2024-05-14 19:00:58 +02:00
|
|
|
|
2023-09-06 16:21:11 +02:00
|
|
|
elif object_mode == 'TEXTURE_PAINT':
|
|
|
|
|
tool_mode = tool_settings.image_paint.mode
|
|
|
|
|
icon = 'MATERIAL' if tool_mode == 'MATERIAL' else 'IMAGE_DATA'
|
|
|
|
|
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.popover(panel="VIEW3D_PT_slots_projectpaint", icon=icon)
|
2024-03-12 17:34:08 -04:00
|
|
|
row.popover(
|
|
|
|
|
panel="VIEW3D_PT_mask",
|
2024-03-15 10:04:03 +11:00
|
|
|
icon=VIEW3D_HT_header._texture_mask_icon(tool_settings.image_paint),
|
2025-01-14 12:46:40 +11:00
|
|
|
text="",
|
|
|
|
|
)
|
2021-09-28 14:44:36 +10:00
|
|
|
else:
|
2019-05-20 15:29:19 +02:00
|
|
|
# Transform settings depending on tool header visibility
|
2019-04-29 22:50:14 +10:00
|
|
|
VIEW3D_HT_header.draw_xform_template(layout, context)
|
|
|
|
|
|
2022-10-17 11:17:42 +02:00
|
|
|
layout.separator_spacer()
|
2019-04-29 22:50:14 +10:00
|
|
|
|
2018-07-11 13:06:01 +02:00
|
|
|
# Viewport Settings
|
2018-07-11 13:24:04 +02:00
|
|
|
layout.popover(
|
2018-07-13 19:13:44 +02:00
|
|
|
panel="VIEW3D_PT_object_type_visibility",
|
2018-07-12 09:38:19 +02:00
|
|
|
icon_value=view.icon_from_show_object_viewport,
|
2018-07-11 13:58:10 +02:00
|
|
|
text="",
|
|
|
|
|
)
|
2018-07-11 13:24:04 +02:00
|
|
|
|
2019-04-15 15:54:25 +02:00
|
|
|
# Gizmo toggle & popover.
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
# FIXME: place-holder icon.
|
2019-05-06 11:54:46 +02:00
|
|
|
row.prop(view, "show_gizmo", text="", toggle=True, icon='GIZMO')
|
2019-04-15 15:54:25 +02:00
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = view.show_gizmo
|
|
|
|
|
sub.popover(
|
|
|
|
|
panel="VIEW3D_PT_gizmo_display",
|
|
|
|
|
text="",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Overlay toggle & popover.
|
2018-07-11 13:06:01 +02:00
|
|
|
row = layout.row(align=True)
|
2018-08-24 12:54:48 +02:00
|
|
|
row.prop(overlay, "show_overlays", icon='OVERLAY', text="")
|
2018-07-11 13:06:01 +02:00
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = overlay.show_overlays
|
2019-04-13 12:14:12 +02:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay", text="")
|
2018-07-11 13:06:01 +02:00
|
|
|
|
2023-09-15 10:44:46 +10:00
|
|
|
if mode_string == 'EDIT_MESH':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_edit_mesh", text="", icon='EDITMODE_HLT')
|
2023-09-15 10:44:45 +10:00
|
|
|
if mode_string == 'EDIT_CURVE':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_edit_curve", text="", icon='EDITMODE_HLT')
|
2024-10-08 21:17:16 +02:00
|
|
|
elif mode_string == 'EDIT_CURVES':
|
|
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_edit_curves", text="", icon='EDITMODE_HLT')
|
2023-09-15 10:44:45 +10:00
|
|
|
elif mode_string == 'SCULPT':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_sculpt", text="", icon='SCULPTMODE_HLT')
|
2023-09-15 10:44:45 +10:00
|
|
|
elif mode_string == 'SCULPT_CURVES':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_sculpt_curves", text="", icon='SCULPTMODE_HLT')
|
2023-09-15 10:44:45 +10:00
|
|
|
elif mode_string == 'PAINT_WEIGHT':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_weight_paint", text="", icon='WPAINT_HLT')
|
2023-09-15 10:44:45 +10:00
|
|
|
elif mode_string == 'PAINT_TEXTURE':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_texture_paint", text="", icon='TPAINT_HLT')
|
2023-09-15 10:44:45 +10:00
|
|
|
elif mode_string == 'PAINT_VERTEX':
|
2023-09-15 10:44:40 +10:00
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_vertex_paint", text="", icon='VPAINT_HLT')
|
2023-12-07 11:42:06 +01:00
|
|
|
elif obj is not None and obj.type == 'GREASEPENCIL':
|
|
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_grease_pencil_options", text="", icon='OUTLINER_DATA_GREASEPENCIL')
|
2023-09-14 21:20:48 +02:00
|
|
|
|
2023-09-15 10:44:46 +10:00
|
|
|
# Separate from `elif` chain because it may coexist with weight-paint.
|
|
|
|
|
if (
|
|
|
|
|
has_pose_mode or
|
|
|
|
|
(object_mode in {'EDIT_ARMATURE', 'OBJECT'} and VIEW3D_PT_overlay_bones.is_using_wireframe(context))
|
|
|
|
|
):
|
|
|
|
|
sub.popover(panel="VIEW3D_PT_overlay_bones", text="", icon='POSE_HLT')
|
|
|
|
|
|
2018-09-26 20:31:14 +02:00
|
|
|
row = layout.row()
|
2019-06-22 11:08:12 +10:00
|
|
|
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
|
2018-09-26 20:31:14 +02:00
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
# While exposing `shading.show_xray(_wireframe)` is correct.
|
2023-02-12 14:37:16 +11:00
|
|
|
# this hides the key shortcut from users: #70433.
|
2020-05-11 13:02:11 +02:00
|
|
|
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
|
2019-10-15 20:27:04 +11:00
|
|
|
row.operator(
|
|
|
|
|
"view3d.toggle_xray",
|
|
|
|
|
text="",
|
|
|
|
|
icon='XRAY',
|
2020-05-11 13:02:11 +02:00
|
|
|
depress=draw_depressed,
|
2019-10-15 20:27:04 +11:00
|
|
|
)
|
2018-09-26 20:31:14 +02:00
|
|
|
|
2018-07-11 20:10:27 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(shading, "type", text="", expand=True)
|
|
|
|
|
sub = row.row(align=True)
|
2018-12-19 11:23:21 +11:00
|
|
|
# TODO, currently render shading type ignores mesh two-side, until it's supported
|
|
|
|
|
# show the shading popover which shows double-sided option.
|
|
|
|
|
|
|
|
|
|
# sub.enabled = shading.type != 'RENDERED'
|
2019-04-13 12:14:12 +02:00
|
|
|
sub.popover(panel="VIEW3D_PT_shading", text="")
|
2018-07-11 20:10:27 +02:00
|
|
|
|
2024-02-02 14:34:43 +01:00
|
|
|
@staticmethod
|
|
|
|
|
def _sculpt_automasking_icon(sculpt):
|
2024-04-30 12:46:05 +10:00
|
|
|
automask_enabled = (
|
|
|
|
|
sculpt.use_automasking_topology or
|
|
|
|
|
sculpt.use_automasking_face_sets or
|
|
|
|
|
sculpt.use_automasking_boundary_edges or
|
|
|
|
|
sculpt.use_automasking_boundary_face_sets or
|
|
|
|
|
sculpt.use_automasking_cavity or
|
|
|
|
|
sculpt.use_automasking_cavity_inverted or
|
|
|
|
|
sculpt.use_automasking_start_normal or
|
|
|
|
|
sculpt.use_automasking_view_normal
|
|
|
|
|
)
|
2024-02-02 14:34:43 +01:00
|
|
|
|
2024-05-03 11:25:06 +10:00
|
|
|
return 'CLIPUV_DEHLT' if automask_enabled else 'CLIPUV_HLT'
|
2024-02-02 14:34:43 +01:00
|
|
|
|
|
|
|
|
@staticmethod
|
2024-10-04 13:05:09 +02:00
|
|
|
def _grease_pencil_sculpt_automasking_icon(gpencil_sculpt):
|
2024-04-30 12:46:05 +10:00
|
|
|
automask_enabled = (
|
|
|
|
|
gpencil_sculpt.use_automasking_stroke or
|
|
|
|
|
gpencil_sculpt.use_automasking_layer_stroke or
|
|
|
|
|
gpencil_sculpt.use_automasking_material_stroke or
|
|
|
|
|
gpencil_sculpt.use_automasking_material_active or
|
|
|
|
|
gpencil_sculpt.use_automasking_layer_active
|
|
|
|
|
)
|
2024-02-02 14:34:43 +01:00
|
|
|
|
2024-05-03 11:25:06 +10:00
|
|
|
return 'CLIPUV_DEHLT' if automask_enabled else 'CLIPUV_HLT'
|
2024-02-02 14:34:43 +01:00
|
|
|
|
2024-03-12 21:34:43 +01:00
|
|
|
@staticmethod
|
|
|
|
|
def _texture_mask_icon(ipaint):
|
|
|
|
|
mask_enabled = ipaint.use_stencil_layer or ipaint.use_cavity
|
2024-05-03 11:25:06 +10:00
|
|
|
return 'CLIPUV_DEHLT' if mask_enabled else 'CLIPUV_HLT'
|
2024-03-12 21:34:43 +01:00
|
|
|
|
2009-11-28 22:35:56 +00:00
|
|
|
|
2014-01-27 18:38:53 +11:00
|
|
|
class VIEW3D_MT_editor_menus(Menu):
|
|
|
|
|
bl_label = ""
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
2018-12-20 12:02:21 +11:00
|
|
|
layout = self.layout
|
2014-01-27 18:38:53 +11:00
|
|
|
obj = context.active_object
|
|
|
|
|
mode_string = context.mode
|
|
|
|
|
edit_object = context.edit_object
|
2023-09-15 10:44:42 +10:00
|
|
|
tool_settings = context.tool_settings
|
2014-01-27 18:38:53 +11:00
|
|
|
|
2018-07-02 15:01:20 +02:00
|
|
|
layout.menu("VIEW3D_MT_view")
|
2014-01-27 18:38:53 +11:00
|
|
|
|
|
|
|
|
# Select Menu
|
2024-10-04 13:05:09 +02:00
|
|
|
if mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
2024-04-23 15:48:27 +02:00
|
|
|
mesh = obj.data
|
|
|
|
|
if mesh.use_paint_mask:
|
|
|
|
|
layout.menu("VIEW3D_MT_select_paint_mask")
|
|
|
|
|
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
|
|
|
|
|
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
|
2024-08-19 10:48:07 +10:00
|
|
|
elif mode_string not in {
|
|
|
|
|
'SCULPT', 'SCULPT_CURVES', 'PAINT_GREASE_PENCIL', 'SCULPT_GREASE_PENCIL', 'WEIGHT_GREASE_PENCIL',
|
2024-09-10 18:56:31 +02:00
|
|
|
'VERTEX_GREASE_PENCIL',
|
2024-08-19 10:48:07 +10:00
|
|
|
}:
|
2024-04-29 08:55:41 +10:00
|
|
|
layout.menu("VIEW3D_MT_select_" + mode_string.lower())
|
2014-01-27 18:38:53 +11:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
if mode_string == 'OBJECT':
|
2024-06-13 12:15:55 +02:00
|
|
|
layout.menu("VIEW3D_MT_add")
|
2014-01-27 18:38:53 +11:00
|
|
|
elif mode_string == 'EDIT_MESH':
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("VIEW3D_MT_mesh_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2014-01-27 18:38:53 +11:00
|
|
|
elif mode_string == 'EDIT_CURVE':
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("VIEW3D_MT_curve_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2024-05-03 11:25:06 +10:00
|
|
|
elif mode_string == 'EDIT_CURVES':
|
2024-04-11 15:11:02 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_curves_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2014-01-27 18:38:53 +11:00
|
|
|
elif mode_string == 'EDIT_SURFACE':
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("VIEW3D_MT_surface_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2014-01-27 18:38:53 +11:00
|
|
|
elif mode_string == 'EDIT_METABALL':
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("VIEW3D_MT_metaball_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2014-01-27 18:38:53 +11:00
|
|
|
elif mode_string == 'EDIT_ARMATURE':
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("TOPBAR_MT_edit_armature_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2014-01-27 18:38:53 +11:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
if edit_object:
|
2024-04-29 08:55:41 +10:00
|
|
|
layout.menu("VIEW3D_MT_edit_" + edit_object.type.lower())
|
2018-05-23 15:39:39 +02:00
|
|
|
|
|
|
|
|
if mode_string == 'EDIT_MESH':
|
2018-07-02 15:01:20 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_vertices")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_edges")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_faces")
|
2018-08-22 13:32:14 +02:00
|
|
|
layout.menu("VIEW3D_MT_uv_map", text="UV")
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2018-12-08 15:01:47 +11:00
|
|
|
elif mode_string in {'EDIT_CURVE', 'EDIT_SURFACE'}:
|
2018-11-30 09:45:13 +11:00
|
|
|
layout.menu("VIEW3D_MT_edit_curve_ctrlpoints")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_curve_segments")
|
2025-02-19 17:11:08 +01:00
|
|
|
elif mode_string == 'EDIT_POINTCLOUD':
|
2024-10-09 16:10:06 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
|
|
|
|
elif mode_string == 'EDIT_CURVES':
|
2024-04-10 13:08:50 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_curves_control_points")
|
2024-04-05 13:23:22 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_curves_segments")
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2023-07-18 11:54:34 +02:00
|
|
|
elif mode_string == 'EDIT_GREASE_PENCIL':
|
2023-10-26 16:52:31 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_point")
|
2024-04-30 14:03:31 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_stroke")
|
Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools.
Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`,
and `Draw Mode`.
While Grease Pencil has many editing tools, including editing
multiple frames at the same time, for now, node tools only
allow editing the current frame.
Currently, the idea is that node tools can do arbitrary changes
to the drawings, but cannot do changes to the existing layer tree, e.g.
changing the order of layers, removing a layer or groups, etc.
All the node tool specific nodes like `Selection` and `Set Selection`
are adapted to work with Grease Pencil. In `Draw Mode`, we currently
interpret everything as selected.
The `Active Element` node has a `Layer` mode that provides the
index of the active layer (if there is one).
When `Auto-Key` is used, a new keyframe is created on the
current frame.
Locked/invisible layers cannot be edited with node tools.
Pull Request: https://projects.blender.org/blender/blender/pulls/136624
2025-05-05 10:41:21 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2018-05-23 15:39:39 +02:00
|
|
|
|
2014-01-27 18:38:53 +11:00
|
|
|
elif obj:
|
2024-09-10 18:56:31 +02:00
|
|
|
if mode_string not in {'PAINT_TEXTURE', 'SCULPT_CURVES', 'SCULPT_GREASE_PENCIL', 'VERTEX_GREASE_PENCIL'}:
|
2024-04-29 08:55:41 +10:00
|
|
|
layout.menu("VIEW3D_MT_" + mode_string.lower())
|
2019-10-05 22:17:22 +02:00
|
|
|
if mode_string == 'SCULPT':
|
|
|
|
|
layout.menu("VIEW3D_MT_mask")
|
2020-03-05 14:53:23 +01:00
|
|
|
layout.menu("VIEW3D_MT_face_sets")
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2023-11-20 09:45:34 -05:00
|
|
|
elif mode_string == 'SCULPT_CURVES':
|
2022-05-31 19:00:24 +02:00
|
|
|
layout.menu("VIEW3D_MT_select_sculpt_curves")
|
2022-04-07 12:49:13 +02:00
|
|
|
layout.menu("VIEW3D_MT_sculpt_curves")
|
2023-06-29 13:57:54 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2024-09-10 18:56:31 +02:00
|
|
|
elif mode_string == 'VERTEX_GREASE_PENCIL':
|
|
|
|
|
layout.menu("VIEW3D_MT_select_edit_grease_pencil")
|
|
|
|
|
layout.menu("VIEW3D_MT_paint_vertex_grease_pencil")
|
|
|
|
|
layout.template_node_operator_asset_root_items()
|
2024-09-27 13:23:02 +02:00
|
|
|
elif mode_string == 'SCULPT_GREASE_PENCIL':
|
2025-03-21 11:08:26 +00:00
|
|
|
is_selection_mask = (
|
|
|
|
|
tool_settings.use_gpencil_select_mask_point or
|
|
|
|
|
tool_settings.use_gpencil_select_mask_stroke or
|
|
|
|
|
tool_settings.use_gpencil_select_mask_segment
|
|
|
|
|
)
|
2024-09-27 13:23:02 +02:00
|
|
|
if is_selection_mask:
|
|
|
|
|
layout.menu("VIEW3D_MT_select_edit_grease_pencil")
|
Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools.
Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`,
and `Draw Mode`.
While Grease Pencil has many editing tools, including editing
multiple frames at the same time, for now, node tools only
allow editing the current frame.
Currently, the idea is that node tools can do arbitrary changes
to the drawings, but cannot do changes to the existing layer tree, e.g.
changing the order of layers, removing a layer or groups, etc.
All the node tool specific nodes like `Selection` and `Set Selection`
are adapted to work with Grease Pencil. In `Draw Mode`, we currently
interpret everything as selected.
The `Active Element` node has a `Layer` mode that provides the
index of the active layer (if there is one).
When `Auto-Key` is used, a new keyframe is created on the
current frame.
Locked/invisible layers cannot be edited with node tools.
Pull Request: https://projects.blender.org/blender/blender/pulls/136624
2025-05-05 10:41:21 +02:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2023-11-15 17:01:18 +01:00
|
|
|
else:
|
|
|
|
|
layout.template_node_operator_asset_root_items()
|
2019-08-08 22:54:57 +02:00
|
|
|
|
2014-01-27 18:38:53 +11:00
|
|
|
else:
|
2018-07-02 15:01:20 +02:00
|
|
|
layout.menu("VIEW3D_MT_object")
|
2023-11-15 17:01:18 +01:00
|
|
|
layout.template_node_operator_asset_root_items()
|
2014-01-27 18:38:53 +11:00
|
|
|
|
|
|
|
|
|
2009-08-15 20:21:49 +00:00
|
|
|
# ********** Menu **********
|
2009-07-24 22:09:30 +00:00
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2009-08-23 22:13:56 +00:00
|
|
|
# ********** Utilities **********
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2015-01-29 15:35:06 +11:00
|
|
|
class ShowHideMenu:
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Show/Hide"
|
2009-10-31 19:31:45 +00:00
|
|
|
_operator_name = ""
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-04-27 16:02:37 +10:00
|
|
|
layout.operator("{:s}.reveal".format(self._operator_name))
|
|
|
|
|
layout.operator("{:s}.hide".format(self._operator_name), text="Hide Selected").unselected = False
|
|
|
|
|
layout.operator("{:s}.hide".format(self._operator_name), text="Hide Unselected").unselected = True
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2020-09-01 10:03:09 +10:00
|
|
|
# Standard transforms which apply to all cases (mix-in class, not used directly).
|
|
|
|
|
class VIEW3D_MT_transform_base:
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Transform"
|
2018-09-27 16:22:50 +10:00
|
|
|
bl_category = "View"
|
2009-11-22 06:19:30 +00:00
|
|
|
|
|
|
|
|
# TODO: get rid of the custom text strings?
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2023-05-19 23:45:27 +02:00
|
|
|
|
2023-11-09 21:32:16 -03:00
|
|
|
layout.operator("transform.translate")
|
|
|
|
|
layout.operator("transform.rotate")
|
|
|
|
|
layout.operator("transform.resize", text="Scale")
|
2019-03-11 16:18:34 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("transform.tosphere", text="To Sphere")
|
|
|
|
|
layout.operator("transform.shear", text="Shear")
|
2013-11-20 12:14:10 +11:00
|
|
|
layout.operator("transform.bend", text="Bend")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("transform.push_pull", text="Push/Pull")
|
2015-05-26 17:55:34 +10:00
|
|
|
|
2023-09-29 14:32:54 +10:00
|
|
|
if context.mode in {
|
2025-01-29 10:00:05 +01:00
|
|
|
'EDIT_MESH',
|
|
|
|
|
'EDIT_ARMATURE',
|
|
|
|
|
'EDIT_SURFACE',
|
|
|
|
|
'EDIT_CURVE',
|
|
|
|
|
'EDIT_CURVES',
|
|
|
|
|
'EDIT_LATTICE',
|
|
|
|
|
'EDIT_METABALL',
|
2025-02-19 17:11:08 +01:00
|
|
|
'EDIT_POINTCLOUD',
|
2023-09-29 14:32:54 +10:00
|
|
|
}:
|
2015-05-26 17:55:34 +10:00
|
|
|
layout.operator("transform.vertex_warp", text="Warp")
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2020-01-02 17:00:17 +11:00
|
|
|
layout.operator("transform.vertex_random", text="Randomize").offset = 0.1
|
2019-11-21 21:06:24 +11:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2010-09-16 07:14:48 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
|
|
|
|
|
# Generic transform menu - geometry types
|
2020-09-01 10:03:09 +10:00
|
|
|
class VIEW3D_MT_transform(VIEW3D_MT_transform_base, Menu):
|
2012-05-06 06:37:07 +00:00
|
|
|
def draw(self, context):
|
|
|
|
|
# base menu
|
|
|
|
|
VIEW3D_MT_transform_base.draw(self, context)
|
2012-05-15 18:50:51 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# generic...
|
|
|
|
|
layout = self.layout
|
2019-03-04 10:13:49 +01:00
|
|
|
if context.mode == 'EDIT_MESH':
|
2023-11-09 21:32:16 -03:00
|
|
|
layout.operator("transform.shrink_fatten", text="Shrink/Fatten")
|
2020-04-24 17:06:37 +10:00
|
|
|
layout.operator("transform.skin_resize")
|
2025-02-19 17:11:08 +01:00
|
|
|
elif context.mode in {'EDIT_CURVE', 'EDIT_GREASE_PENCIL', 'EDIT_CURVES', 'EDIT_POINTCLOUD'}:
|
2019-03-04 10:13:49 +01:00
|
|
|
layout.operator("transform.transform", text="Radius").mode = 'CURVE_SHRINKFATTEN'
|
2025-10-13 10:50:14 +02:00
|
|
|
if context.mode == 'EDIT_GREASE_PENCIL':
|
2025-10-12 02:10:14 +02:00
|
|
|
layout.operator("transform.transform", text="Opacity").mode = 'GPENCIL_OPACITY'
|
2012-11-09 06:06:50 +00:00
|
|
|
|
2023-10-21 15:12:47 +02:00
|
|
|
if context.mode != 'EDIT_CURVES' and context.mode != 'EDIT_GREASE_PENCIL':
|
2023-02-23 13:30:00 +01:00
|
|
|
layout.separator()
|
2023-06-05 16:36:34 -03:00
|
|
|
props = layout.operator("transform.translate", text="Move Texture Space")
|
|
|
|
|
props.texture_space = True
|
|
|
|
|
props = layout.operator("transform.resize", text="Scale Texture Space")
|
|
|
|
|
props.texture_space = True
|
2011-01-05 17:27:26 +00:00
|
|
|
|
|
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# Object-specific extensions to Transform menu
|
2020-09-01 10:03:09 +10:00
|
|
|
class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base, Menu):
|
2012-05-06 06:37:07 +00:00
|
|
|
def draw(self, context):
|
2012-07-29 10:03:46 +00:00
|
|
|
layout = self.layout
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# base menu
|
|
|
|
|
VIEW3D_MT_transform_base.draw(self, context)
|
2012-05-15 18:50:51 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# object-specific option follow...
|
|
|
|
|
layout.separator()
|
2010-09-16 07:14:48 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.operator("transform.translate", text="Move Texture Space").texture_space = True
|
|
|
|
|
layout.operator("transform.resize", text="Scale Texture Space").texture_space = True
|
2012-05-15 18:50:51 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.separator()
|
2012-05-15 18:50:51 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2024-09-21 16:22:52 +10:00
|
|
|
# XXX: see `alignmenu()` in `edit.c` of b2.4x to get this working.
|
2017-03-20 09:43:18 +11:00
|
|
|
layout.operator("transform.transform", text="Align to Transform Orientation").mode = 'ALIGN'
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2011-04-12 15:12:05 +00:00
|
|
|
layout.operator("object.randomize_transform")
|
|
|
|
|
layout.operator("object.align")
|
|
|
|
|
|
2017-08-06 19:47:25 +10:00
|
|
|
# TODO: there is a strange context bug here.
|
|
|
|
|
"""
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
layout.operator("object.transform_axis_target")
|
|
|
|
|
"""
|
|
|
|
|
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# Armature EditMode extensions to Transform menu
|
2020-09-01 10:03:09 +10:00
|
|
|
class VIEW3D_MT_transform_armature(VIEW3D_MT_transform_base, Menu):
|
2012-05-06 06:37:07 +00:00
|
|
|
def draw(self, context):
|
2012-07-29 10:03:46 +00:00
|
|
|
layout = self.layout
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# base menu
|
|
|
|
|
VIEW3D_MT_transform_base.draw(self, context)
|
2012-05-15 18:50:51 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
# armature specific extensions follow...
|
|
|
|
|
obj = context.object
|
2018-04-05 18:20:27 +02:00
|
|
|
if obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'}:
|
2018-09-03 18:58:41 +02:00
|
|
|
if obj.data.display_type == 'BBONE':
|
2017-10-19 15:10:41 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2014-01-10 00:44:03 +13:00
|
|
|
layout.operator("transform.transform", text="Scale BBone").mode = 'BONE_SIZE'
|
2018-09-03 18:58:41 +02:00
|
|
|
elif obj.data.display_type == 'ENVELOPE':
|
2017-10-19 15:10:41 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2014-01-10 00:44:03 +13:00
|
|
|
layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONE_SIZE'
|
|
|
|
|
layout.operator("transform.transform", text="Scale Radius").mode = 'BONE_ENVELOPE'
|
2012-05-06 06:37:07 +00:00
|
|
|
|
|
|
|
|
if context.edit_object and context.edit_object.type == 'ARMATURE':
|
2017-10-19 15:10:41 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.operator("armature.align")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_mirror(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Mirror"
|
2025-06-28 16:34:42 +02:00
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
2009-11-22 06:19:30 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-11-22 06:19:30 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("transform.mirror", text="Interactive Mirror")
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2019-03-20 16:41:00 +11:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2019-03-20 16:41:00 +11:00
|
|
|
for (space_name, space_id) in (("Global", 'GLOBAL'), ("Local", 'LOCAL')):
|
|
|
|
|
for axis_index, axis_name in enumerate("XYZ"):
|
2024-10-16 14:45:08 +11:00
|
|
|
props = layout.operator(
|
|
|
|
|
"transform.mirror",
|
|
|
|
|
text="{:s} {:s}".format(axis_name, iface_(space_name)),
|
|
|
|
|
translate=False,
|
|
|
|
|
)
|
2019-03-20 16:41:00 +11:00
|
|
|
props.constraint_axis[axis_index] = True
|
2020-07-16 18:06:51 +10:00
|
|
|
props.orient_type = space_id
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2019-03-20 16:41:00 +11:00
|
|
|
if space_id == 'GLOBAL':
|
|
|
|
|
layout.separator()
|
2010-01-15 17:28:00 +00:00
|
|
|
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_snap(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Snap"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid")
|
2013-08-23 20:41:21 +00:00
|
|
|
layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False
|
2018-07-23 13:15:20 +02:00
|
|
|
layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True
|
2016-07-15 17:07:18 +10:00
|
|
|
layout.operator("view3d.snap_selected_to_active", text="Selection to Active")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("view3d.snap_cursor_to_selected", text="Cursor to Selected")
|
2018-11-01 16:12:38 +01:00
|
|
|
layout.operator("view3d.snap_cursor_to_center", text="Cursor to World Origin")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
|
|
|
|
|
layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active")
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2009-11-14 13:35:44 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_uv_map(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "UV Mapping"
|
2009-11-03 18:20:03 +00:00
|
|
|
|
2021-03-06 18:21:17 +11:00
|
|
|
def draw(self, _context):
|
2009-11-03 18:20:03 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2025-01-08 11:31:44 +11:00
|
|
|
layout.menu_contents("IMAGE_MT_uvs_unwrap")
|
2011-03-29 14:13:11 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-04-19 15:50:17 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2012-01-14 06:30:27 +00:00
|
|
|
layout.operator("uv.project_from_view").scale_to_bounds = False
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("uv.project_from_view", text="Project from View (Bounds)").scale_to_bounds = True
|
2009-11-03 18:20:03 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2018-09-06 14:12:16 +02:00
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
layout.operator("mesh.mark_seam", icon='EDGE_SEAM').clear = False
|
2018-09-06 14:12:16 +02:00
|
|
|
layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
2009-11-03 18:20:03 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("uv.reset")
|
2011-03-30 07:21:41 +00:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="UV")
|
|
|
|
|
|
2009-11-03 18:20:03 +00:00
|
|
|
|
2009-08-15 20:21:49 +00:00
|
|
|
# ********** View menus **********
|
2009-07-11 13:32:20 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_view(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "View"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2017-10-19 12:35:58 +11:00
|
|
|
view = context.space_data
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-18 12:16:03 +02:00
|
|
|
layout.prop(view, "show_region_toolbar")
|
|
|
|
|
layout.prop(view, "show_region_ui")
|
2019-05-20 15:34:45 +02:00
|
|
|
layout.prop(view, "show_region_tool_header")
|
2023-08-23 12:09:15 +02:00
|
|
|
layout.prop(view, "show_region_asset_shelf")
|
2019-04-18 13:49:21 +02:00
|
|
|
layout.prop(view, "show_region_hud")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2025-01-03 14:47:57 +11:00
|
|
|
if context.mode in {'PAINT_TEXTURE', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'SCULPT'}:
|
2025-02-28 10:22:27 +01:00
|
|
|
layout.operator("view3d.view_selected", text="Frame Last Stroke")
|
2025-01-02 18:11:39 +01:00
|
|
|
else:
|
2025-02-28 10:22:27 +01:00
|
|
|
layout.operator("view3d.view_selected", text="Frame Selected")
|
2017-10-19 12:35:58 +11:00
|
|
|
if view.region_quadviews:
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2020-05-12 15:44:59 +02:00
|
|
|
layout.operator("view3d.view_all").center = False
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("view3d.view_persportho", text="Perspective/Orthographic")
|
2018-11-29 23:44:37 -02:00
|
|
|
layout.menu("VIEW3D_MT_view_local")
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
layout.prop(view, "show_viewer", text="Viewer Node")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2017-10-19 12:35:58 +11:00
|
|
|
layout.menu("VIEW3D_MT_view_cameras", text="Cameras")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2017-10-19 12:35:58 +11:00
|
|
|
layout.menu("VIEW3D_MT_view_viewpoint")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_view_navigation")
|
|
|
|
|
layout.menu("VIEW3D_MT_view_align")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-16 13:59:27 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2019-03-06 16:43:37 +01:00
|
|
|
layout.menu("VIEW3D_MT_view_regions", text="View Regions")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("screen.animation_play", text="Play Animation")
|
2009-12-04 17:54:48 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-12-04 17:54:48 +00:00
|
|
|
|
2025-09-25 12:24:35 +02:00
|
|
|
layout.operator(
|
|
|
|
|
"render.opengl",
|
|
|
|
|
text="Render Viewport Preview",
|
|
|
|
|
icon='RENDER_STILL',
|
|
|
|
|
)
|
|
|
|
|
layout.operator(
|
|
|
|
|
"render.opengl",
|
|
|
|
|
text="Render Playblast",
|
|
|
|
|
icon='RENDER_ANIMATION',
|
|
|
|
|
).animation = True
|
|
|
|
|
|
2018-05-12 14:59:51 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-24 18:35:19 +02:00
|
|
|
layout.menu("INFO_MT_area")
|
2009-12-03 16:28:50 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2018-11-29 23:44:37 -02:00
|
|
|
class VIEW3D_MT_view_local(Menu):
|
|
|
|
|
bl_label = "Local View"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-11-29 23:44:37 -02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("view3d.localview", text="Toggle Local View")
|
|
|
|
|
layout.operator("view3d.localview_remove_from")
|
|
|
|
|
|
|
|
|
|
|
2017-10-19 12:35:58 +11:00
|
|
|
class VIEW3D_MT_view_cameras(Menu):
|
|
|
|
|
bl_label = "Cameras"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-10-19 12:35:58 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("view3d.object_as_camera")
|
2018-07-05 16:54:30 +02:00
|
|
|
layout.operator("view3d.view_camera", text="Active Camera")
|
2020-06-01 11:34:07 -04:00
|
|
|
layout.operator("view3d.view_center_camera")
|
2017-10-19 12:35:58 +11:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_view_viewpoint(Menu):
|
|
|
|
|
bl_label = "Viewpoint"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-10-19 12:35:58 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
layout.operator("view3d.view_camera", text="Camera", text_ctxt=i18n_contexts.editor_view3d)
|
2017-10-19 12:35:58 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
layout.operator("view3d.view_axis", text="Top", text_ctxt=i18n_contexts.editor_view3d).type = 'TOP'
|
|
|
|
|
layout.operator("view3d.view_axis", text="Bottom", text_ctxt=i18n_contexts.editor_view3d).type = 'BOTTOM'
|
2017-10-19 12:35:58 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
layout.operator("view3d.view_axis", text="Front", text_ctxt=i18n_contexts.editor_view3d).type = 'FRONT'
|
|
|
|
|
layout.operator("view3d.view_axis", text="Back", text_ctxt=i18n_contexts.editor_view3d).type = 'BACK'
|
2017-10-19 12:35:58 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
layout.operator("view3d.view_axis", text="Right", text_ctxt=i18n_contexts.editor_view3d).type = 'RIGHT'
|
|
|
|
|
layout.operator("view3d.view_axis", text="Left", text_ctxt=i18n_contexts.editor_view3d).type = 'LEFT'
|
2017-10-19 12:35:58 +11:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_view_navigation(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Navigation"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-09-01 14:17:43 +00:00
|
|
|
from math import pi
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-02-18 06:07:41 +00:00
|
|
|
layout.operator_enum("view3d.view_orbit", "type")
|
2018-08-28 18:01:53 +02:00
|
|
|
props = layout.operator("view3d.view_orbit", text="Orbit Opposite")
|
2015-03-13 04:45:40 +11:00
|
|
|
props.type = 'ORBITRIGHT'
|
|
|
|
|
props.angle = pi
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2016-02-01 11:01:00 +11:00
|
|
|
layout.operator("view3d.view_roll", text="Roll Left").type = 'LEFT'
|
|
|
|
|
layout.operator("view3d.view_roll", text="Roll Right").type = 'RIGHT'
|
2013-09-01 14:17:43 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2011-02-18 06:07:41 +00:00
|
|
|
layout.operator_enum("view3d.view_pan", "type")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("view3d.zoom", text="Zoom In").delta = 1
|
|
|
|
|
layout.operator("view3d.zoom", text="Zoom Out").delta = -1
|
2019-06-23 03:31:49 +02:00
|
|
|
layout.operator("view3d.zoom_border", text="Zoom Region...")
|
2022-03-15 12:59:00 +11:00
|
|
|
layout.operator("view3d.dolly", text="Dolly View...")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("view3d.zoom_camera_1_to_1", text="Zoom Camera 1:1")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("view3d.fly")
|
2013-12-03 03:14:09 -02:00
|
|
|
layout.operator("view3d.walk")
|
2009-08-15 20:21:49 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_view_align(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Align View"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_view_align_selected")
|
2009-11-06 21:10:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-11-06 21:10:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("view3d.camera_to_view", text="Align Active Camera to View")
|
2011-11-14 03:54:23 +00:00
|
|
|
layout.operator("view3d.camera_to_view_selected", text="Align Active Camera to Selected")
|
2018-07-17 11:59:24 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-05-12 15:44:59 +02:00
|
|
|
layout.operator("view3d.view_all", text="Center Cursor and Frame All").center = True
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("view3d.view_center_cursor")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2012-05-05 16:38:23 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("view3d.view_lock_to_active")
|
|
|
|
|
layout.operator("view3d.view_lock_clear")
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_view_align_selected(Menu):
|
2014-06-17 15:27:59 +10:00
|
|
|
bl_label = "Align View to Active"
|
2009-11-06 21:10:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-11-06 21:10:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
props = layout.operator("view3d.view_axis", text="Top", text_ctxt=i18n_contexts.editor_view3d)
|
2009-11-06 21:10:45 +00:00
|
|
|
props.align_active = True
|
|
|
|
|
props.type = 'TOP'
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
props = layout.operator("view3d.view_axis", text="Bottom", text_ctxt=i18n_contexts.editor_view3d)
|
2009-11-06 21:10:45 +00:00
|
|
|
props.align_active = True
|
|
|
|
|
props.type = 'BOTTOM'
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2018-07-17 11:59:24 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
props = layout.operator("view3d.view_axis", text="Front", text_ctxt=i18n_contexts.editor_view3d)
|
2009-11-06 21:10:45 +00:00
|
|
|
props.align_active = True
|
|
|
|
|
props.type = 'FRONT'
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
props = layout.operator("view3d.view_axis", text="Back", text_ctxt=i18n_contexts.editor_view3d)
|
2009-11-06 21:10:45 +00:00
|
|
|
props.align_active = True
|
|
|
|
|
props.type = 'BACK'
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2018-07-17 11:59:24 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
props = layout.operator("view3d.view_axis", text="Right", text_ctxt=i18n_contexts.editor_view3d)
|
2009-11-06 21:10:45 +00:00
|
|
|
props.align_active = True
|
|
|
|
|
props.type = 'RIGHT'
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2022-05-09 12:36:56 +02:00
|
|
|
props = layout.operator("view3d.view_axis", text="Left", text_ctxt=i18n_contexts.editor_view3d)
|
2009-11-06 21:10:45 +00:00
|
|
|
props.align_active = True
|
|
|
|
|
props.type = 'LEFT'
|
|
|
|
|
|
|
|
|
|
|
2019-03-06 16:43:37 +01:00
|
|
|
class VIEW3D_MT_view_regions(Menu):
|
|
|
|
|
bl_label = "View Regions"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2019-03-06 16:43:37 +01:00
|
|
|
layout.operator("view3d.clip_border", text="Clipping Region...")
|
|
|
|
|
layout.operator("view3d.render_border", text="Render Region...")
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2017-10-19 12:35:58 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("view3d.clear_render_border")
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2016-01-14 09:41:11 +11:00
|
|
|
|
2009-08-16 03:40:00 +00:00
|
|
|
# ********** Select menus, suffix from context.mode **********
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2016-01-14 09:41:11 +11:00
|
|
|
class VIEW3D_MT_select_object_more_less(Menu):
|
|
|
|
|
bl_label = "Select More/Less"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2016-01-14 09:41:11 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("object.select_more", text="More")
|
|
|
|
|
layout.operator("object.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-06-13 12:15:55 +02:00
|
|
|
props = layout.operator("object.select_hierarchy", text="Parent", text_ctxt=i18n_contexts.default)
|
2016-01-14 09:41:11 +11:00
|
|
|
props.extend = False
|
|
|
|
|
props.direction = 'PARENT'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("object.select_hierarchy", text="Child")
|
|
|
|
|
props.extend = False
|
|
|
|
|
props.direction = 'CHILD'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
props = layout.operator("object.select_hierarchy", text="Extend Parent")
|
|
|
|
|
props.extend = True
|
|
|
|
|
props.direction = 'PARENT'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("object.select_hierarchy", text="Extend Child")
|
|
|
|
|
props.extend = True
|
|
|
|
|
props.direction = 'CHILD'
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_object(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("object.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("object.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("object.select_all", text="Invert").action = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("object.select_camera", text="Select Active Camera")
|
2021-04-12 14:18:05 -04:00
|
|
|
layout.operator("object.select_mirror")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("object.select_random", text="Select Random")
|
2009-11-03 07:23:02 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-11-03 07:23:02 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.menu("VIEW3D_MT_select_object_more_less", text="More/Less")
|
2016-01-14 09:41:11 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator_menu_enum("object.select_grouped", "type", text="Select Grouped")
|
|
|
|
|
layout.operator_menu_enum("object.select_linked", "type", text="Select Linked")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("object.select_pattern", text="Select Pattern...")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2016-01-14 09:41:11 +11:00
|
|
|
class VIEW3D_MT_select_pose_more_less(Menu):
|
|
|
|
|
bl_label = "Select More/Less"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-06-13 12:15:55 +02:00
|
|
|
props = layout.operator("pose.select_hierarchy", text="Parent", text_ctxt=i18n_contexts.default)
|
2015-01-29 17:34:05 +01:00
|
|
|
props.extend = False
|
|
|
|
|
props.direction = 'PARENT'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("pose.select_hierarchy", text="Child")
|
|
|
|
|
props.extend = False
|
|
|
|
|
props.direction = 'CHILD'
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("pose.select_hierarchy", text="Extend Parent")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.extend = True
|
|
|
|
|
props.direction = 'PARENT'
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("pose.select_hierarchy", text="Extend Child")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.extend = True
|
|
|
|
|
props.direction = 'CHILD'
|
2009-12-04 17:54:48 +00:00
|
|
|
|
2016-01-14 09:41:11 +11:00
|
|
|
|
|
|
|
|
class VIEW3D_MT_select_pose(Menu):
|
|
|
|
|
bl_label = "Select"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2016-01-14 09:41:11 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("pose.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("pose.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("pose.select_all", text="Invert").action = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2016-01-14 09:41:11 +11:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2016-01-14 09:41:11 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2021-04-12 14:18:05 -04:00
|
|
|
layout.operator("pose.select_mirror")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.menu("VIEW3D_MT_select_pose_more_less", text="More/Less")
|
2016-01-14 09:41:11 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator_menu_enum("pose.select_grouped", "type", text="Select Grouped")
|
|
|
|
|
layout.operator("pose.select_linked", text="Select Linked")
|
|
|
|
|
layout.operator("object.select_pattern", text="Select Pattern...")
|
2016-01-14 09:41:11 +11:00
|
|
|
|
2010-01-25 10:16:36 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-16 14:45:08 +11:00
|
|
|
layout.menu("POSE_MT_selection_sets_select", text="Bone Selection Set")
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("pose.select_constraint_target", text="Constraint Target")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
class VIEW3D_MT_select_particle(Menu):
|
|
|
|
|
bl_label = "Select"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2016-12-28 17:30:58 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("particle.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("particle.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("particle.select_all", text="Invert").action = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2016-11-15 15:55:54 +01:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("particle.select_random")
|
2020-02-12 17:08:35 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("particle.select_more", text="More")
|
|
|
|
|
layout.operator("particle.select_less", text="Less")
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("particle.select_linked", text="Select Linked")
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.select_roots", text="Roots")
|
|
|
|
|
layout.operator("particle.select_tips", text="Tips")
|
|
|
|
|
|
|
|
|
|
|
2014-09-27 18:30:48 +10:00
|
|
|
class VIEW3D_MT_edit_mesh_select_similar(Menu):
|
|
|
|
|
bl_label = "Select Similar"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2014-09-27 18:30:48 +10:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_enum("mesh.select_similar", "type")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.select_similar_region", text="Face Regions")
|
|
|
|
|
|
|
|
|
|
|
2016-01-08 04:07:20 +11:00
|
|
|
class VIEW3D_MT_edit_mesh_select_by_trait(Menu):
|
|
|
|
|
bl_label = "Select All by Trait"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2024-10-04 15:52:09 +10:00
|
|
|
_is_vert_mode, _is_edge_mode, is_face_mode = context.tool_settings.mesh_select_mode
|
2023-04-13 13:14:03 +10:00
|
|
|
|
2024-10-04 15:06:18 +10:00
|
|
|
if is_face_mode is False:
|
2016-01-08 04:07:20 +11:00
|
|
|
layout.operator("mesh.select_non_manifold", text="Non Manifold")
|
|
|
|
|
layout.operator("mesh.select_loose", text="Loose Geometry")
|
|
|
|
|
layout.operator("mesh.select_interior_faces", text="Interior Faces")
|
2017-10-19 14:45:56 +11:00
|
|
|
layout.operator("mesh.select_face_by_sides", text="Faces by Sides")
|
2024-10-04 15:06:18 +10:00
|
|
|
layout.operator("mesh.select_by_pole_count", text="Poles by Count")
|
2016-01-08 04:07:20 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-08-06 14:48:47 +02:00
|
|
|
layout.operator("mesh.select_ungrouped", text="Ungrouped Vertices")
|
2016-01-08 04:07:20 +11:00
|
|
|
|
|
|
|
|
|
2016-01-08 04:42:17 +11:00
|
|
|
class VIEW3D_MT_edit_mesh_select_more_less(Menu):
|
|
|
|
|
bl_label = "Select More/Less"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2016-01-08 04:42:17 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.select_more", text="More")
|
|
|
|
|
layout.operator("mesh.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.select_next_item", text="Next Active")
|
|
|
|
|
layout.operator("mesh.select_prev_item", text="Previous Active")
|
|
|
|
|
|
|
|
|
|
|
2017-10-19 14:45:56 +11:00
|
|
|
class VIEW3D_MT_edit_mesh_select_linked(Menu):
|
|
|
|
|
bl_label = "Select Linked"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-10-19 14:45:56 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.select_linked", text="Linked")
|
|
|
|
|
layout.operator("mesh.shortest_path_select", text="Shortest Path")
|
|
|
|
|
layout.operator("mesh.faces_select_linked_flat", text="Linked Flat Faces")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_mesh_select_loops(Menu):
|
|
|
|
|
bl_label = "Select Loops"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-10-19 14:45:56 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.loop_multi_select", text="Edge Loops").ring = False
|
|
|
|
|
layout.operator("mesh.loop_multi_select", text="Edge Rings").ring = True
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.loop_to_region")
|
|
|
|
|
layout.operator("mesh.region_to_loop")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_edit_mesh(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
# primitive
|
|
|
|
|
layout.operator("mesh.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("mesh.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("mesh.select_all", text="Invert").action = 'INVERT'
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
# gesture
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2013-05-01 05:59:58 +00:00
|
|
|
# numeric
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("mesh.select_mirror")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.select_random", text="Select Random")
|
2012-11-01 05:07:15 +00:00
|
|
|
layout.operator("mesh.select_nth")
|
2013-05-01 05:59:58 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
# more/less
|
2013-05-01 05:59:58 +00:00
|
|
|
layout.separator()
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_select_more_less", text="More/Less")
|
2013-05-01 05:59:58 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
# grouped
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2016-01-08 04:07:20 +11:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_select_similar")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_select_by_trait")
|
2017-10-19 14:45:56 +11:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_select_linked")
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_select_loops")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
# geometric
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
|
2017-10-19 14:45:56 +11:00
|
|
|
layout.operator("mesh.select_axis", text="Side of Active")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
# attribute
|
2023-10-17 09:24:51 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("mesh.select_by_attribute", text="By Attribute")
|
|
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_edit_curve(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("curve.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("curve.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("curve.select_all", text="Invert").action = 'INVERT'
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("curve.select_random")
|
2013-02-26 16:39:41 +00:00
|
|
|
layout.operator("curve.select_nth")
|
2024-05-13 16:29:17 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curve.select_more", text="More")
|
|
|
|
|
layout.operator("curve.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2012-05-15 15:34:49 +00:00
|
|
|
layout.operator("curve.select_linked", text="Select Linked")
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator_menu_enum("curve.select_similar", "type")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("curve.de_select_first")
|
|
|
|
|
layout.operator("curve.de_select_last")
|
|
|
|
|
layout.operator("curve.select_next")
|
|
|
|
|
layout.operator("curve.select_previous")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_edit_surface(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("curve.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("curve.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("curve.select_all", text="Invert").action = 'INVERT'
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("curve.select_random")
|
2013-02-26 16:39:41 +00:00
|
|
|
layout.operator("curve.select_nth")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("curve.select_more", text="More")
|
|
|
|
|
layout.operator("curve.select_less", text="Less")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("curve.select_linked", text="Select Linked")
|
|
|
|
|
layout.operator_menu_enum("curve.select_similar", "type")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curve.select_row", text="Control Point Row")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2013-12-29 23:43:19 +11:00
|
|
|
class VIEW3D_MT_select_edit_text(Menu):
|
2020-04-04 12:41:58 -04:00
|
|
|
bl_label = "Select"
|
2013-12-29 23:43:19 +11:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-12-29 23:43:19 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.select_all", text="All")
|
2013-12-29 23:43:19 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-04-19 02:18:19 +02:00
|
|
|
layout.operator("font.move_select", text="Top").type = 'TEXT_BEGIN'
|
|
|
|
|
layout.operator("font.move_select", text="Bottom").type = 'TEXT_END'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.move_select", text="Previous Block").type = 'PREVIOUS_PAGE'
|
|
|
|
|
layout.operator("font.move_select", text="Next Block").type = 'NEXT_PAGE'
|
2014-01-06 00:36:09 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.move_select", text="Line Begin").type = 'LINE_BEGIN'
|
|
|
|
|
layout.operator("font.move_select", text="Line End").type = 'LINE_END'
|
2013-12-29 23:43:19 +11:00
|
|
|
|
2019-05-09 16:57:59 +10:00
|
|
|
layout.separator()
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.move_select", text="Previous Line").type = 'PREVIOUS_LINE'
|
|
|
|
|
layout.operator("font.move_select", text="Next Line").type = 'NEXT_LINE'
|
2019-06-19 08:21:25 +10:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.move_select", text="Previous Word").type = 'PREVIOUS_WORD'
|
|
|
|
|
layout.operator("font.move_select", text="Next Word").type = 'NEXT_WORD'
|
2019-03-20 10:51:37 +01:00
|
|
|
|
2013-12-29 23:43:19 +11:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_edit_metaball(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("mball.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("mball.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("mball.select_all", text="Invert").action = 'INVERT'
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("mball.select_random_metaelems")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2013-10-25 06:22:15 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator_menu_enum("mball.select_similar", "type")
|
2013-10-25 06:22:15 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2019-03-20 10:51:37 +01:00
|
|
|
class VIEW3D_MT_edit_lattice_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Lattice"
|
2019-03-20 10:51:37 +01:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2019-03-20 10:51:37 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.operator_menu_enum("lattice.flip", "axis")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("lattice.make_regular")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_edit_lattice(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("lattice.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("lattice.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("lattice.select_all", text="Invert").action = 'INVERT'
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2013-03-16 16:11:50 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2017-10-19 15:10:41 +11:00
|
|
|
layout.operator("lattice.select_mirror")
|
|
|
|
|
layout.operator("lattice.select_random")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("lattice.select_more", text="More")
|
|
|
|
|
layout.operator("lattice.select_less", text="Less")
|
2018-10-23 20:40:19 -03:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-08-06 14:48:47 +02:00
|
|
|
layout.operator("lattice.select_ungrouped", text="Ungrouped Vertices")
|
2013-03-16 16:11:50 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_select_edit_armature(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("armature.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("armature.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("armature.select_all", text="Invert").action = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2013-04-11 13:29:01 +00:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2009-11-03 07:23:02 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2021-04-12 14:18:05 -04:00
|
|
|
layout.operator("armature.select_mirror")
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2013-07-19 10:51:54 +00:00
|
|
|
layout.operator("armature.select_more", text="More")
|
|
|
|
|
layout.operator("armature.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("armature.select_linked", text="Select Linked")
|
|
|
|
|
layout.operator_menu_enum("armature.select_similar", "type")
|
|
|
|
|
layout.operator("object.select_pattern", text="Select Pattern...")
|
2020-03-31 14:39:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-06-13 12:15:55 +02:00
|
|
|
props = layout.operator("armature.select_hierarchy", text="Parent", text_ctxt=i18n_contexts.default)
|
2015-01-29 17:34:05 +01:00
|
|
|
props.extend = False
|
|
|
|
|
props.direction = 'PARENT'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("armature.select_hierarchy", text="Child")
|
|
|
|
|
props.extend = False
|
|
|
|
|
props.direction = 'CHILD'
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("armature.select_hierarchy", text="Extend Parent")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.extend = True
|
|
|
|
|
props.direction = 'PARENT'
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("armature.select_hierarchy", text="Extend Child")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.extend = True
|
|
|
|
|
props.direction = 'CHILD'
|
2009-12-04 17:54:48 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2023-06-21 17:28:39 +02:00
|
|
|
class VIEW3D_MT_select_edit_grease_pencil(Menu):
|
|
|
|
|
bl_label = "Select"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("grease_pencil.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("grease_pencil.select_all", text="Invert").action = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-01 17:04:50 +02:00
|
|
|
layout.operator("view3d.select_box", text="Box Select")
|
|
|
|
|
layout.operator("view3d.select_circle", text="Circle Select")
|
|
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("grease_pencil.select_random")
|
|
|
|
|
layout.operator("grease_pencil.select_alternate")
|
2024-05-13 16:54:52 +02:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.select_more", text="More")
|
|
|
|
|
layout.operator("grease_pencil.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-01 17:04:50 +02:00
|
|
|
layout.operator_menu_enum("grease_pencil.select_similar", "mode")
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("grease_pencil.select_linked")
|
2023-06-21 17:28:39 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-06-22 12:35:49 +10:00
|
|
|
props = layout.operator("grease_pencil.select_ends", text="First")
|
|
|
|
|
props.amount_start = 1
|
|
|
|
|
props.amount_end = 0
|
|
|
|
|
props = layout.operator("grease_pencil.select_ends", text="Last")
|
|
|
|
|
props.amount_start = 0
|
|
|
|
|
props.amount_end = 1
|
2023-06-21 17:28:39 +02:00
|
|
|
|
Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools.
Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`,
and `Draw Mode`.
While Grease Pencil has many editing tools, including editing
multiple frames at the same time, for now, node tools only
allow editing the current frame.
Currently, the idea is that node tools can do arbitrary changes
to the drawings, but cannot do changes to the existing layer tree, e.g.
changing the order of layers, removing a layer or groups, etc.
All the node tool specific nodes like `Selection` and `Set Selection`
are adapted to work with Grease Pencil. In `Draw Mode`, we currently
interpret everything as selected.
The `Active Element` node has a `Layer` mode that provides the
index of the active layer (if there is one).
When `Auto-Key` is used, a new keyframe is created on the
current frame.
Locked/invisible layers cannot be edited with node tools.
Pull Request: https://projects.blender.org/blender/blender/pulls/136624
2025-05-05 10:41:21 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2023-07-04 07:51:11 +02:00
|
|
|
|
2023-07-03 16:34:30 +02:00
|
|
|
class VIEW3D_MT_paint_grease_pencil(Menu):
|
2023-12-01 12:55:30 +01:00
|
|
|
bl_label = "Draw"
|
2023-07-03 16:34:30 +02:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
2023-11-30 16:10:06 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.menu("GREASE_PENCIL_MT_layer_active", text="Active Layer")
|
2023-07-03 16:34:30 +02:00
|
|
|
|
2023-12-01 12:55:30 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-01 17:04:50 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_animation", text="Animation")
|
|
|
|
|
layout.operator("grease_pencil.interpolate_sequence", text="Interpolate Sequence")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-12-01 12:55:30 +01:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_showhide")
|
2024-03-25 12:17:03 +01:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_cleanup")
|
2023-12-01 12:55:30 +01:00
|
|
|
|
2024-01-12 11:11:55 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-12-18 20:30:10 +01:00
|
|
|
layout.operator("paint.sample_color").merged = False
|
2024-01-12 11:11:55 +01:00
|
|
|
|
2023-06-21 17:28:39 +02:00
|
|
|
|
2024-09-10 18:56:31 +02:00
|
|
|
class VIEW3D_MT_paint_vertex_grease_pencil(Menu):
|
|
|
|
|
bl_label = "Paint"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
2024-09-13 15:42:21 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.vertex_color_set", text="Set Color Attribute")
|
|
|
|
|
layout.operator("grease_pencil.stroke_reset_vertex_color")
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("grease_pencil.vertex_color_invert", text="Invert")
|
|
|
|
|
layout.operator("grease_pencil.vertex_color_levels", text="Levels")
|
|
|
|
|
layout.operator("grease_pencil.vertex_color_hsv", text="Hue/Saturation/Value")
|
|
|
|
|
layout.operator("grease_pencil.vertex_color_brightness_contrast", text="Brightness/Contrast")
|
2024-09-10 18:56:31 +02:00
|
|
|
|
|
|
|
|
|
2013-02-26 15:42:33 +00:00
|
|
|
class VIEW3D_MT_select_paint_mask(Menu):
|
2009-10-31 19:31:45 +00:00
|
|
|
bl_label = "Select"
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-02-26 15:42:33 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("paint.face_select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("paint.face_select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("paint.face_select_all", text="Invert").action = 'INVERT'
|
2013-02-26 15:42:33 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2013-02-26 15:42:33 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("paint.face_select_more", text="More")
|
|
|
|
|
layout.operator("paint.face_select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("paint.face_select_linked")
|
2013-02-26 15:42:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_select_paint_mask_vertex(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-02-26 15:42:33 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("paint.vert_select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("paint.vert_select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("paint.vert_select_all", text="Invert").action = 'INVERT'
|
2013-02-26 15:42:33 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("view3d.select_box")
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("view3d.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("view3d.select_lasso", "mode")
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2013-03-16 16:11:50 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("paint.vert_select_more", text="More")
|
|
|
|
|
layout.operator("paint.vert_select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-02-02 16:16:14 +01:00
|
|
|
layout.operator("paint.vert_select_linked", text="Select Linked")
|
2013-03-16 16:11:50 +00:00
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("paint.vert_select_ungrouped", text="Ungrouped Vertices")
|
|
|
|
|
|
2015-02-24 11:56:26 +01:00
|
|
|
|
2025-02-19 17:11:08 +01:00
|
|
|
class VIEW3D_MT_select_edit_pointcloud(Menu):
|
2023-06-28 12:52:45 -04:00
|
|
|
bl_label = "Select"
|
|
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2025-02-15 12:36:39 +01:00
|
|
|
|
2025-02-19 17:11:08 +01:00
|
|
|
layout.operator("pointcloud.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("pointcloud.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("pointcloud.select_all", text="Invert").action = 'INVERT'
|
2025-02-15 12:36:39 +01:00
|
|
|
|
2025-02-19 17:23:37 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("pointcloud.select_random")
|
|
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
2023-06-28 12:52:45 -04:00
|
|
|
|
|
|
|
|
|
2023-02-20 11:51:16 +01:00
|
|
|
class VIEW3D_MT_edit_curves_select_more_less(Menu):
|
|
|
|
|
bl_label = "Select More/Less"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("curves.select_more", text="More")
|
|
|
|
|
layout.operator("curves.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
|
2022-02-18 11:16:02 +01:00
|
|
|
class VIEW3D_MT_select_edit_curves(Menu):
|
|
|
|
|
bl_label = "Select"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
2023-01-20 16:40:51 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("curves.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("curves.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
|
2023-02-20 11:51:16 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("curves.select_random")
|
2022-02-18 11:16:02 +01:00
|
|
|
|
2023-02-20 11:51:16 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_curves_select_more_less", text="More/Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curves.select_linked")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curves.select_ends", text="Endpoints")
|
2023-02-20 11:51:16 +01:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2022-02-18 11:16:02 +01:00
|
|
|
|
2022-05-31 19:00:24 +02:00
|
|
|
class VIEW3D_MT_select_sculpt_curves(Menu):
|
|
|
|
|
bl_label = "Select"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-01-13 10:47:24 -06:00
|
|
|
layout.operator("curves.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("curves.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
|
2024-05-13 16:29:17 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("sculpt_curves.select_random")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-06-09 16:12:27 +02:00
|
|
|
layout.operator("curves.select_ends", text="Endpoints")
|
2024-05-13 16:29:17 +02:00
|
|
|
layout.operator("sculpt_curves.select_grow", text="Grow Selection")
|
2022-05-31 19:00:24 +02:00
|
|
|
|
2023-06-29 13:57:54 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Select")
|
|
|
|
|
|
2022-05-31 19:00:24 +02:00
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_mesh_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_mesh_add"
|
2013-11-04 22:49:49 +00:00
|
|
|
bl_label = "Mesh"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-11-04 22:49:49 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2014-03-20 01:32:44 +11:00
|
|
|
|
2018-04-24 16:13:03 +02:00
|
|
|
layout.operator("mesh.primitive_plane_add", text="Plane", icon='MESH_PLANE')
|
|
|
|
|
layout.operator("mesh.primitive_cube_add", text="Cube", icon='MESH_CUBE')
|
|
|
|
|
layout.operator("mesh.primitive_circle_add", text="Circle", icon='MESH_CIRCLE')
|
|
|
|
|
layout.operator("mesh.primitive_uv_sphere_add", text="UV Sphere", icon='MESH_UVSPHERE')
|
|
|
|
|
layout.operator("mesh.primitive_ico_sphere_add", text="Ico Sphere", icon='MESH_ICOSPHERE')
|
|
|
|
|
layout.operator("mesh.primitive_cylinder_add", text="Cylinder", icon='MESH_CYLINDER')
|
|
|
|
|
layout.operator("mesh.primitive_cone_add", text="Cone", icon='MESH_CONE')
|
|
|
|
|
layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.primitive_grid_add", text="Grid", icon='MESH_GRID')
|
|
|
|
|
layout.operator("mesh.primitive_monkey_add", text="Monkey", icon='MESH_MONKEY')
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Add")
|
|
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_curve_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_curve_add"
|
2013-11-04 22:49:49 +00:00
|
|
|
bl_label = "Curve"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2022-05-06 12:06:57 +02:00
|
|
|
def draw(self, context):
|
2013-11-04 22:49:49 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2014-03-20 01:32:44 +11:00
|
|
|
|
2024-02-05 17:08:17 +01:00
|
|
|
layout.operator("curve.primitive_bezier_curve_add", text="Bézier", icon='CURVE_BEZCURVE')
|
2018-04-24 16:13:03 +02:00
|
|
|
layout.operator("curve.primitive_bezier_circle_add", text="Circle", icon='CURVE_BEZCIRCLE')
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curve.primitive_nurbs_curve_add", text="Nurbs Curve", icon='CURVE_NCURVE')
|
|
|
|
|
layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
|
|
|
|
|
layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
|
|
|
|
|
|
2022-07-08 14:41:21 +02:00
|
|
|
layout.separator()
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2022-07-08 14:41:21 +02:00
|
|
|
layout.operator("object.curves_empty_hair_add", text="Empty Hair", icon='CURVES_DATA')
|
2023-02-15 12:13:34 +01:00
|
|
|
layout.operator("object.quick_fur", text="Fur", icon='CURVES_DATA')
|
2022-04-07 13:02:03 +02:00
|
|
|
|
2022-07-08 14:41:21 +02:00
|
|
|
experimental = context.preferences.experimental
|
|
|
|
|
if experimental.use_new_curves_tools:
|
|
|
|
|
layout.operator("object.curves_random_add", text="Random", icon='CURVES_DATA')
|
2022-04-07 13:02:03 +02:00
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_surface_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_surface_add"
|
2013-11-04 22:49:49 +00:00
|
|
|
bl_label = "Surface"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-11-04 22:49:49 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2014-03-20 01:32:44 +11:00
|
|
|
|
2018-05-23 17:23:38 -03:00
|
|
|
layout.operator("surface.primitive_nurbs_surface_curve_add", text="Nurbs Curve", icon='SURFACE_NCURVE')
|
|
|
|
|
layout.operator("surface.primitive_nurbs_surface_circle_add", text="Nurbs Circle", icon='SURFACE_NCIRCLE')
|
|
|
|
|
layout.operator("surface.primitive_nurbs_surface_surface_add", text="Nurbs Surface", icon='SURFACE_NSURFACE')
|
2024-04-30 12:46:05 +10:00
|
|
|
layout.operator(
|
|
|
|
|
"surface.primitive_nurbs_surface_cylinder_add",
|
|
|
|
|
text="Nurbs Cylinder", icon='SURFACE_NCYLINDER',
|
|
|
|
|
)
|
2018-05-23 17:23:38 -03:00
|
|
|
layout.operator("surface.primitive_nurbs_surface_sphere_add", text="Nurbs Sphere", icon='SURFACE_NSPHERE')
|
|
|
|
|
layout.operator("surface.primitive_nurbs_surface_torus_add", text="Nurbs Torus", icon='SURFACE_NTORUS')
|
2013-11-04 22:49:49 +00:00
|
|
|
|
|
|
|
|
|
2019-03-20 10:51:37 +01:00
|
|
|
class VIEW3D_MT_edit_metaball_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Metaball"
|
2019-03-20 10:51:37 +01:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2019-03-20 10:51:37 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
|
|
|
|
# Add
|
|
|
|
|
layout.operator("mball.duplicate_move")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Modify
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Remove
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2019-03-20 10:51:37 +01:00
|
|
|
layout.operator("mball.delete_metaelems", text="Delete")
|
|
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_metaball_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_metaball_add"
|
2013-11-19 17:16:15 +11:00
|
|
|
bl_label = "Metaball"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-19 17:16:15 +11:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-11-19 17:16:15 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
layout.operator_enum("object.metaball_add", "type")
|
|
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class TOPBAR_MT_edit_curve_add(Menu):
|
|
|
|
|
bl_idname = "TOPBAR_MT_edit_curve_add"
|
2014-01-03 01:34:35 +06:00
|
|
|
bl_label = "Add"
|
2019-05-13 17:27:40 +02:00
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2014-01-03 01:34:35 +06:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
2023-04-13 13:14:03 +10:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2014-01-03 01:34:35 +06:00
|
|
|
is_surf = context.active_object.type == 'SURFACE'
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
|
|
|
|
|
|
|
|
|
if is_surf:
|
2018-08-29 15:02:21 +02:00
|
|
|
VIEW3D_MT_surface_add.draw(self, context)
|
2014-01-03 01:34:35 +06:00
|
|
|
else:
|
2018-08-29 15:02:21 +02:00
|
|
|
VIEW3D_MT_curve_add.draw(self, context)
|
2014-01-03 01:34:35 +06:00
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class TOPBAR_MT_edit_armature_add(Menu):
|
|
|
|
|
bl_idname = "TOPBAR_MT_edit_armature_add"
|
2013-12-14 13:47:18 +01:00
|
|
|
bl_label = "Armature"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-11-04 22:49:49 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2013-12-14 13:47:18 +01:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
|
|
|
|
layout.operator("armature.bone_primitive_add", text="Single Bone", icon='BONE_DATA')
|
2013-11-04 22:49:49 +00:00
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_armature_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_armature_add"
|
2013-11-04 22:49:49 +00:00
|
|
|
bl_label = "Armature"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-11-04 22:49:49 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
|
|
|
|
layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA')
|
|
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_light_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_light_add"
|
2022-08-22 14:30:32 +02:00
|
|
|
bl_context = i18n_contexts.id_light
|
2018-06-27 14:41:53 +02:00
|
|
|
bl_label = "Light"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2015-04-12 11:38:18 +01:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2015-04-12 11:38:18 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2018-06-27 14:41:53 +02:00
|
|
|
layout.operator_enum("object.light_add", "type")
|
2015-04-12 11:38:18 +01:00
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_lightprobe_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_lightprobe_add"
|
2017-06-12 20:59:54 +10:00
|
|
|
bl_label = "Light Probe"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2017-06-07 18:32:27 +02:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-06-07 18:32:27 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2017-06-12 20:59:54 +10:00
|
|
|
layout.operator_enum("object.lightprobe_add", "type")
|
2017-06-07 18:32:27 +02:00
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_camera_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_camera_add"
|
2017-03-23 20:42:44 +11:00
|
|
|
bl_label = "Camera"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2017-03-23 20:42:44 +11:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-03-23 20:42:44 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
|
|
|
|
layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
|
|
|
|
|
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
class VIEW3D_MT_volume_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_volume_add"
|
|
|
|
|
bl_label = "Volume"
|
2023-01-30 09:32:47 +01:00
|
|
|
bl_translation_context = i18n_contexts.id_id
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator("object.volume_import", text="Import OpenVDB...", icon='OUTLINER_DATA_VOLUME')
|
2024-04-30 12:46:05 +10:00
|
|
|
layout.operator(
|
|
|
|
|
"object.volume_add", text="Empty",
|
|
|
|
|
text_ctxt=i18n_contexts.id_volume,
|
|
|
|
|
icon='OUTLINER_DATA_VOLUME',
|
|
|
|
|
)
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
|
2023-05-31 18:00:26 +02:00
|
|
|
class VIEW3D_MT_grease_pencil_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_grease_pencil_add"
|
|
|
|
|
bl_label = "Grease Pencil"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2023-05-31 18:00:26 +02:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2025-02-06 13:38:36 +01:00
|
|
|
layout.operator("object.grease_pencil_add", text="Blank", icon='EMPTY_AXIS').type = 'EMPTY'
|
2023-05-31 18:00:26 +02:00
|
|
|
layout.operator("object.grease_pencil_add", text="Stroke", icon='STROKE').type = 'STROKE'
|
2024-08-30 15:43:40 +02:00
|
|
|
layout.operator("object.grease_pencil_add", text="Monkey", icon='MONKEY').type = 'MONKEY'
|
2024-02-28 16:20:48 +01:00
|
|
|
layout.separator()
|
2024-08-30 15:43:40 +02:00
|
|
|
layout.operator("object.grease_pencil_add", text="Scene Line Art", icon='SCENE_DATA').type = 'LINEART_SCENE'
|
2024-02-28 16:20:48 +01:00
|
|
|
layout.operator(
|
|
|
|
|
"object.grease_pencil_add",
|
|
|
|
|
text="Collection Line Art",
|
2025-01-14 12:46:40 +11:00
|
|
|
icon='OUTLINER_COLLECTION',
|
|
|
|
|
).type = 'LINEART_COLLECTION'
|
2024-08-30 15:43:40 +02:00
|
|
|
layout.operator("object.grease_pencil_add", text="Object Line Art", icon='OBJECT_DATA').type = 'LINEART_OBJECT'
|
2023-05-31 18:00:26 +02:00
|
|
|
|
|
|
|
|
|
2025-09-19 11:26:14 +10:00
|
|
|
class VIEW3D_MT_lattice_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_lattice_add"
|
|
|
|
|
bl_label = "Lattice"
|
|
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
|
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
|
|
|
|
layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
|
|
|
|
|
layout.operator("object.lattice_add_to_selected", text="Lattice Deform Selected", icon='OUTLINER_OB_LATTICE')
|
|
|
|
|
|
|
|
|
|
|
2024-12-23 22:31:33 +01:00
|
|
|
class VIEW3D_MT_empty_add(Menu):
|
|
|
|
|
bl_idname = "VIEW3D_MT_empty_add"
|
|
|
|
|
bl_label = "Empty"
|
|
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
|
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2025-06-06 10:49:29 +02:00
|
|
|
|
|
|
|
|
layout.operator("object.empty_add", text="Plain Axes", icon='EMPTY_AXIS').type = 'PLAIN_AXES'
|
|
|
|
|
layout.operator("object.empty_add", text="Arrows", icon='EMPTY_ARROWS').type = 'ARROWS'
|
|
|
|
|
layout.operator("object.empty_add", text="Single Arrow", icon='EMPTY_SINGLE_ARROW').type = 'SINGLE_ARROW'
|
|
|
|
|
layout.operator("object.empty_add", text="Circle", icon='MESH_CIRCLE').type = 'CIRCLE'
|
|
|
|
|
layout.operator("object.empty_add", text="Cube", icon='CUBE').type = 'CUBE'
|
|
|
|
|
layout.operator("object.empty_add", text="Sphere", icon='SPHERE').type = 'SPHERE'
|
|
|
|
|
layout.operator("object.empty_add", text="Cone", icon='CONE').type = 'CONE'
|
2024-12-23 22:31:33 +01:00
|
|
|
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
class VIEW3D_MT_add(Menu):
|
2013-11-04 22:49:49 +00:00
|
|
|
bl_label = "Add"
|
2019-05-13 17:27:40 +02:00
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2013-11-04 22:49:49 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-10-12 17:54:59 +02:00
|
|
|
if layout.operator_context == 'EXEC_REGION_WIN':
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
layout.operator("WM_OT_search_single_menu", text="Search...", icon='VIEWZOOM').menu_idname = "VIEW3D_MT_add"
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
# NOTE: don't use 'EXEC_SCREEN' or operators won't get the `v3d` context.
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
# NOTE: was `EXEC_AREA`, but this context does not have the `rv3d`, which prevents
|
2023-02-12 14:37:16 +11:00
|
|
|
# "align_view" to work on first call (see #32719).
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
|
|
|
|
|
2017-10-19 15:10:41 +11:00
|
|
|
# layout.operator_menu_enum("object.mesh_add", "type", text="Mesh", icon='OUTLINER_OB_MESH')
|
2018-08-29 15:02:21 +02:00
|
|
|
layout.menu("VIEW3D_MT_mesh_add", icon='OUTLINER_OB_MESH')
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2017-10-19 15:10:41 +11:00
|
|
|
# layout.operator_menu_enum("object.curve_add", "type", text="Curve", icon='OUTLINER_OB_CURVE')
|
2018-08-29 15:02:21 +02:00
|
|
|
layout.menu("VIEW3D_MT_curve_add", icon='OUTLINER_OB_CURVE')
|
2017-10-19 15:10:41 +11:00
|
|
|
# layout.operator_menu_enum("object.surface_add", "type", text="Surface", icon='OUTLINER_OB_SURFACE')
|
2018-08-29 15:02:21 +02:00
|
|
|
layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE')
|
|
|
|
|
layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
|
2025-05-10 02:24:18 +02:00
|
|
|
layout.operator("object.pointcloud_random_add", text="Point Cloud", icon='OUTLINER_OB_POINTCLOUD')
|
2023-02-23 22:00:57 +01:00
|
|
|
layout.menu("VIEW3D_MT_volume_add", text="Volume", text_ctxt=i18n_contexts.id_id, icon='OUTLINER_OB_VOLUME')
|
2024-06-17 13:50:41 +02:00
|
|
|
layout.menu("VIEW3D_MT_grease_pencil_add", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
|
2019-02-28 18:53:49 +01:00
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2019-02-28 18:53:49 +01:00
|
|
|
if VIEW3D_MT_armature_add.is_extended():
|
|
|
|
|
layout.menu("VIEW3D_MT_armature_add", icon='OUTLINER_OB_ARMATURE')
|
|
|
|
|
else:
|
|
|
|
|
layout.operator("object.armature_add", text="Armature", icon='OUTLINER_OB_ARMATURE')
|
|
|
|
|
|
2025-09-19 11:26:14 +10:00
|
|
|
layout.menu("VIEW3D_MT_lattice_add", icon='OUTLINER_OB_LATTICE')
|
2019-02-28 18:53:49 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-12-23 22:31:33 +01:00
|
|
|
layout.menu("VIEW3D_MT_empty_add", icon='OUTLINER_OB_EMPTY')
|
2018-11-20 12:44:42 +01:00
|
|
|
layout.menu("VIEW3D_MT_image_add", text="Image", icon='OUTLINER_OB_IMAGE')
|
2018-09-27 16:21:51 +02:00
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2019-02-28 18:53:49 +01:00
|
|
|
layout.menu("VIEW3D_MT_light_add", icon='OUTLINER_OB_LIGHT')
|
|
|
|
|
layout.menu("VIEW3D_MT_lightprobe_add", icon='OUTLINER_OB_LIGHTPROBE')
|
|
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2018-08-29 15:02:21 +02:00
|
|
|
if VIEW3D_MT_camera_add.is_extended():
|
|
|
|
|
layout.menu("VIEW3D_MT_camera_add", icon='OUTLINER_OB_CAMERA')
|
2017-03-23 20:42:44 +11:00
|
|
|
else:
|
2018-08-29 15:02:21 +02:00
|
|
|
VIEW3D_MT_camera_add.draw(self, context)
|
2017-03-23 20:42:44 +11:00
|
|
|
|
2017-06-22 17:20:39 +02:00
|
|
|
layout.separator()
|
2019-02-28 18:53:49 +01:00
|
|
|
|
|
|
|
|
layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
|
|
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2017-06-10 16:41:58 +02:00
|
|
|
layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_FORCE_FIELD')
|
2019-02-28 18:53:49 +01:00
|
|
|
|
2013-11-04 22:49:49 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2018-06-01 15:07:32 +02:00
|
|
|
has_collections = bool(bpy.data.collections)
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.enabled = has_collections
|
|
|
|
|
|
|
|
|
|
if not has_collections or len(bpy.data.collections) > 10:
|
|
|
|
|
col.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
col.operator(
|
2018-05-24 15:37:52 +02:00
|
|
|
"object.collection_instance_add",
|
2018-06-01 15:07:32 +02:00
|
|
|
text="Collection Instance..." if has_collections else "No Collections to Instance",
|
2018-05-24 15:37:52 +02:00
|
|
|
icon='OUTLINER_OB_GROUP_INSTANCE',
|
|
|
|
|
)
|
2013-11-04 22:49:49 +00:00
|
|
|
else:
|
2018-06-01 15:07:32 +02:00
|
|
|
col.operator_menu_enum(
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
"object.collection_instance_add",
|
|
|
|
|
"collection",
|
|
|
|
|
text="Collection Instance",
|
2017-10-19 11:24:01 +11:00
|
|
|
icon='OUTLINER_OB_GROUP_INSTANCE',
|
|
|
|
|
)
|
2013-11-04 22:49:49 +00:00
|
|
|
|
2009-08-15 19:40:09 +00:00
|
|
|
|
2018-11-20 12:44:42 +01:00
|
|
|
class VIEW3D_MT_image_add(Menu):
|
|
|
|
|
bl_label = "Add Image"
|
2023-10-12 17:54:59 +02:00
|
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
2018-11-20 12:44:42 +01:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-11-20 12:44:42 +01:00
|
|
|
layout = self.layout
|
2024-03-21 10:01:43 +11:00
|
|
|
# Explicitly set background mode on/off as operator will try to
|
2024-03-11 16:18:25 +01:00
|
|
|
# auto detect which mode to use otherwise.
|
|
|
|
|
layout.operator("object.empty_image_add", text="Reference", icon='IMAGE_REFERENCE').background = False
|
|
|
|
|
layout.operator("object.empty_image_add", text="Background", icon='IMAGE_BACKGROUND').background = True
|
2024-05-27 12:41:25 +10:00
|
|
|
layout.operator("image.import_as_mesh_planes", text="Mesh Plane", icon='MESH_PLANE')
|
2025-06-06 10:49:29 +02:00
|
|
|
layout.operator("object.empty_add", text="Empty Image", icon='FILE_IMAGE').type = 'IMAGE'
|
2018-11-20 12:44:42 +01:00
|
|
|
|
|
|
|
|
|
2017-10-19 16:09:21 +11:00
|
|
|
class VIEW3D_MT_object_relations(Menu):
|
|
|
|
|
bl_label = "Relations"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-10-19 16:09:21 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("object.make_dupli_face")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator_menu_enum("object.make_local", "type", text="Make Local...")
|
|
|
|
|
layout.menu("VIEW3D_MT_make_single_user")
|
|
|
|
|
|
|
|
|
|
|
2022-08-16 15:42:04 +02:00
|
|
|
class VIEW3D_MT_object_liboverride(Menu):
|
|
|
|
|
bl_label = "Library Override"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("object.make_override_library", text="Make")
|
|
|
|
|
layout.operator("object.reset_override_library", text="Reset")
|
|
|
|
|
layout.operator("object.clear_override_library", text="Clear")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object(Menu):
|
2009-10-31 19:31:45 +00:00
|
|
|
bl_context = "objectmode"
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Object"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2023-10-23 09:37:16 +02:00
|
|
|
def draw(self, context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
|
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform_object")
|
2019-03-11 23:33:13 +01:00
|
|
|
layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_object_clear")
|
|
|
|
|
layout.menu("VIEW3D_MT_object_apply")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("object.duplicate_move")
|
2010-01-14 04:36:27 +00:00
|
|
|
layout.operator("object.duplicate_move_linked")
|
2017-10-19 16:09:21 +11:00
|
|
|
layout.operator("object.join")
|
2018-05-24 15:37:52 +02:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2018-05-25 08:16:24 +02:00
|
|
|
|
2018-11-23 13:55:33 +11:00
|
|
|
layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN')
|
|
|
|
|
layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
|
2018-05-25 08:16:24 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-09-13 13:36:00 +10:00
|
|
|
layout.menu("VIEW3D_MT_object_asset", icon='ASSET_MANAGER')
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.menu("VIEW3D_MT_object_collection")
|
2023-09-26 12:19:27 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-09-29 14:32:54 +10:00
|
|
|
layout.menu("VIEW3D_MT_object_liboverride", icon='LIBRARY_DATA_OVERRIDE')
|
2023-09-26 12:19:27 +02:00
|
|
|
layout.menu("VIEW3D_MT_object_relations")
|
|
|
|
|
layout.menu("VIEW3D_MT_object_parent")
|
2024-05-02 18:13:41 +02:00
|
|
|
layout.menu("VIEW3D_MT_object_modifiers", icon='MODIFIER')
|
|
|
|
|
layout.menu("VIEW3D_MT_object_constraints", icon='CONSTRAINT')
|
2017-10-19 16:09:21 +11:00
|
|
|
layout.menu("VIEW3D_MT_object_track")
|
2021-01-20 20:48:14 +11:00
|
|
|
layout.menu("VIEW3D_MT_make_links")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-07-17 12:33:47 +02:00
|
|
|
layout.operator("object.shade_smooth")
|
2024-03-29 10:08:59 +11:00
|
|
|
if ob and ob.type == 'MESH':
|
2024-05-08 20:24:10 +02:00
|
|
|
layout.operator("object.shade_auto_smooth")
|
2018-07-17 12:33:47 +02:00
|
|
|
layout.operator("object.shade_flat")
|
2018-05-25 08:16:24 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2017-10-19 16:09:21 +11:00
|
|
|
layout.menu("VIEW3D_MT_object_animation")
|
2018-04-24 20:46:18 +02:00
|
|
|
layout.menu("VIEW3D_MT_object_rigid_body")
|
2010-06-03 06:41:24 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2011-10-06 05:45:06 +00:00
|
|
|
layout.menu("VIEW3D_MT_object_quick_effects")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2021-01-25 17:49:02 +11:00
|
|
|
layout.menu("VIEW3D_MT_object_convert")
|
2020-09-21 19:53:36 +02:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
Objects: restore H key per object hiding.
H hides selected objects, Shift+H hides unselected objects, and Alt+H
reveals hidden objects.
This hiding state is distinct from restrict viewport and render, and
meant for temporarily hiding objects without affecting more persistent
collection hiding.
Object hiding is per view-layer, same as selection. It affects the
viewport and any preview renders in there, but not final renders.
In the outliner, different icons are now used for temporary hiding, and
restrict viewport and render. Hidden objects are greyed out.
Remaining design issues:
* For lamps we probably still want to keep their effect on the scene,
currently they are fully disabled by hiding. Arguably mesh lights or
even objects being reflected or casting shadows are not that different
but perhaps the special lamp exception from local view should remain.
* We need a feature still to disabled this hiding for specific viewports,
for render or animation preview where you want to see the entire scene
while working in another view.
* We need a new icon for restrict viewport, for now it uses a grid similar
to the 2.4 icon.
* Hiding objects does not preserve selection state as it did in 2.7,
it's probably convenient to support this again?
2018-05-14 23:36:56 +02:00
|
|
|
layout.menu("VIEW3D_MT_object_showhide")
|
2020-08-30 13:34:27 +10:00
|
|
|
layout.menu("VIEW3D_MT_object_cleanup")
|
Objects: restore H key per object hiding.
H hides selected objects, Shift+H hides unselected objects, and Alt+H
reveals hidden objects.
This hiding state is distinct from restrict viewport and render, and
meant for temporarily hiding objects without affecting more persistent
collection hiding.
Object hiding is per view-layer, same as selection. It affects the
viewport and any preview renders in there, but not final renders.
In the outliner, different icons are now used for temporary hiding, and
restrict viewport and render. Hidden objects are greyed out.
Remaining design issues:
* For lamps we probably still want to keep their effect on the scene,
currently they are fully disabled by hiding. Arguably mesh lights or
even objects being reflected or casting shadows are not that different
but perhaps the special lamp exception from local view should remain.
* We need a feature still to disabled this hiding for specific viewports,
for render or animation preview where you want to see the entire scene
while working in another view.
* We need a new icon for restrict viewport, for now it uses a grid similar
to the 2.4 icon.
* Hiding objects does not preserve selection state as it did in 2.7,
it's probably convenient to support this again?
2018-05-14 23:36:56 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2018-09-08 06:56:48 +10:00
|
|
|
layout.operator("object.delete", text="Delete").use_global = False
|
|
|
|
|
layout.operator("object.delete", text="Delete Global").use_global = True
|
2018-05-24 15:37:52 +02:00
|
|
|
|
2023-11-15 17:01:18 +01:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Object")
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object_animation(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Animation"
|
2010-09-18 16:17:32 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2010-09-18 16:17:32 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-11-21 15:38:01 +01:00
|
|
|
layout.operator("anim.keyframe_insert", text="Insert Keyframe")
|
2024-01-25 16:18:05 +01:00
|
|
|
layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe with Keying Set").always_prompt = True
|
2012-10-04 10:58:03 +00:00
|
|
|
layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframes...")
|
|
|
|
|
layout.operator("anim.keyframe_clear_v3d", text="Clear Keyframes...")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("anim.keying_set_active_set", text="Change Keying Set...")
|
2010-09-18 16:17:32 +00:00
|
|
|
|
2012-02-08 14:01:47 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("nla.bake", text="Bake Action...")
|
2024-09-20 10:53:31 +02:00
|
|
|
layout.operator("grease_pencil.bake_grease_pencil_animation", text="Bake Object Transform to Grease Pencil...")
|
2012-02-08 14:01:47 +00:00
|
|
|
|
2010-09-18 16:17:32 +00:00
|
|
|
|
2018-04-24 20:46:18 +02:00
|
|
|
class VIEW3D_MT_object_rigid_body(Menu):
|
|
|
|
|
bl_label = "Rigid Body"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-04-24 20:46:18 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("rigidbody.objects_add", text="Add Active").type = 'ACTIVE'
|
|
|
|
|
layout.operator("rigidbody.objects_add", text="Add Passive").type = 'PASSIVE'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("rigidbody.objects_remove", text="Remove")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("rigidbody.shape_change", text="Change Shape")
|
|
|
|
|
layout.operator("rigidbody.mass_calculate", text="Calculate Mass")
|
|
|
|
|
layout.operator("rigidbody.object_settings_copy", text="Copy from Active")
|
|
|
|
|
layout.operator("object.visual_transform_apply", text="Apply Transformation")
|
2019-09-20 14:31:24 +02:00
|
|
|
layout.operator("rigidbody.bake_to_keyframes", text="Bake to Keyframes")
|
2018-04-24 20:46:18 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("rigidbody.connect", text="Connect")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object_clear(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Clear"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
I18n: extract and disambiguate a few messages
Extract
- Add to Quick Favorites tooltip.
- "Mask", the name of a newly created mask (DATA_).
- "New" in the context of the new mask ID button.
- A few strings using BLI_STR_UTF8_ defines were not extracted.
Take the special characters out of the translation macros.
- "External" menu items from the filebrowser's Files context
menu (right-click on a file). These items were already extracted,
but not translated.
Improve
- Separate formatted error message "%s is not compatible with
["the specified", "any"] 'refresh' options" into two messages.
Disambiguate
- Use Action context for new F-modifiers' names. This is already used
for the "type" operator prop.
- Translate ImportHelper's default confirmation text using the
Operator context, as it uses the operator name which is extracted
with this context.
- "Scale" can be a noun, the scale of something, or a verb, to scale
something. The latter mostly uses the Operator context, so apply
this context to verbs, and the default contexts to nouns.
- "Scale Influence" can mean "Influence on Scale" (tracking
stabilization) and "to Scale the Influence" (dynamic paint canvas).
- "Object Line Art" as type of Line Art to add, as opposed to the
active object's Line Art settings.
- Float to Integer node: use NodeTree context for the node label, as
this is already extracted and used for the enum.
Do not translate
- Sequencer labels containing only a string formatting field.
Some issues reported by Gabriel Gazzán and Ye Gui.
Pull Request: https://projects.blender.org/blender/blender/pulls/122283
2024-05-27 19:33:35 +02:00
|
|
|
layout.operator("object.location_clear", text="Location", text_ctxt=i18n_contexts.default).clear_delta = False
|
|
|
|
|
layout.operator("object.rotation_clear", text="Rotation", text_ctxt=i18n_contexts.default).clear_delta = False
|
|
|
|
|
layout.operator("object.scale_clear", text="Scale", text_ctxt=i18n_contexts.default).clear_delta = False
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2012-01-17 17:57:20 +00:00
|
|
|
layout.operator("object.origin_clear", text="Origin")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_MT_object_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Object"
|
2010-02-21 14:05:02 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2023-04-13 13:14:03 +10:00
|
|
|
|
2018-11-29 23:44:37 -02:00
|
|
|
view = context.space_data
|
2010-02-21 14:05:02 +00:00
|
|
|
|
|
|
|
|
obj = context.object
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
selected_objects_len = len(context.selected_objects)
|
2018-12-20 15:26:27 +11:00
|
|
|
|
|
|
|
|
# If nothing is selected
|
|
|
|
|
# (disabled for now until it can be made more useful).
|
|
|
|
|
'''
|
2018-12-18 07:54:32 +11:00
|
|
|
if selected_objects_len == 0:
|
|
|
|
|
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("VIEW3D_MT_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
|
|
|
|
|
|
|
|
|
|
return
|
2018-12-20 15:26:27 +11:00
|
|
|
'''
|
2018-12-18 07:54:32 +11:00
|
|
|
|
|
|
|
|
# If something is selected
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2021-01-25 21:26:19 +11:00
|
|
|
# Individual object types.
|
2019-01-02 19:03:32 +11:00
|
|
|
if obj is None:
|
|
|
|
|
pass
|
2019-03-26 14:48:35 +01:00
|
|
|
|
2018-12-20 15:26:27 +11:00
|
|
|
elif obj.type == 'CAMERA':
|
2010-02-21 14:05:02 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2021-01-25 21:26:19 +11:00
|
|
|
layout.operator("view3d.object_as_camera", text="Set Active Camera")
|
|
|
|
|
|
2011-06-24 03:41:07 +00:00
|
|
|
if obj.data.type == 'PERSP':
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Focal Length")
|
2011-06-24 03:41:07 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.lens"
|
|
|
|
|
props.input_scale = 0.1
|
2012-02-25 19:49:23 +00:00
|
|
|
if obj.data.lens_unit == 'MILLIMETERS':
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Camera Focal Length: %.1fmm")
|
2012-02-25 19:49:23 +00:00
|
|
|
else:
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Camera Focal Length: %.1f\u00B0")
|
2012-02-25 19:49:23 +00:00
|
|
|
|
2011-06-24 03:41:07 +00:00
|
|
|
else:
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Camera Lens Scale")
|
2011-06-24 03:41:07 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.ortho_scale"
|
|
|
|
|
props.input_scale = 0.01
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Camera Lens Scale: %.3f")
|
2010-06-26 19:00:44 +00:00
|
|
|
|
2019-05-20 16:14:02 +02:00
|
|
|
if not obj.data.dof.focus_object:
|
2015-01-14 08:01:40 +11:00
|
|
|
if view and view.camera == obj and view.region_3d.view_perspective == 'CAMERA':
|
|
|
|
|
props = layout.operator("ui.eyedropper_depth", text="DOF Distance (Pick)")
|
|
|
|
|
else:
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Focus Distance")
|
2015-01-14 08:01:40 +11:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
2019-05-20 16:14:02 +02:00
|
|
|
props.data_path_item = "data.dof.focus_distance"
|
2015-01-14 08:01:40 +11:00
|
|
|
props.input_scale = 0.02
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Focus Distance: %.3f")
|
2010-06-26 19:00:44 +00:00
|
|
|
|
2019-03-26 14:48:35 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2018-12-20 15:26:27 +11:00
|
|
|
elif obj.type in {'CURVE', 'FONT'}:
|
2010-06-26 19:00:44 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Extrusion")
|
2010-06-26 19:00:44 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.extrude"
|
2010-02-21 14:05:02 +00:00
|
|
|
props.input_scale = 0.01
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Extrude: %.3f")
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Offset")
|
2010-06-14 03:52:10 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
2010-08-20 06:09:58 +00:00
|
|
|
props.data_path_item = "data.offset"
|
2010-06-26 19:00:44 +00:00
|
|
|
props.input_scale = 0.01
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Offset: %.3f")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
2019-03-26 14:48:35 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2018-12-20 15:26:27 +11:00
|
|
|
elif obj.type == 'EMPTY':
|
2010-06-26 19:00:44 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Empty Display Size")
|
2010-06-14 03:52:10 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
2018-09-03 18:58:41 +02:00
|
|
|
props.data_path_item = "empty_display_size"
|
2010-06-26 19:00:44 +00:00
|
|
|
props.input_scale = 0.01
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Empty Display Size: %.3f")
|
2010-06-26 19:00:44 +00:00
|
|
|
|
2019-03-26 14:48:35 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2021-01-25 21:26:19 +11:00
|
|
|
if obj.empty_display_type == 'IMAGE':
|
2024-06-06 10:55:15 +10:00
|
|
|
layout.operator("image.convert_to_mesh_plane", text="Convert to Mesh Plane")
|
2024-07-25 18:44:07 +02:00
|
|
|
layout.operator("grease_pencil.trace_image")
|
2021-01-25 21:26:19 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-12-20 15:26:27 +11:00
|
|
|
elif obj.type == 'LIGHT':
|
2018-06-27 14:41:53 +02:00
|
|
|
light = obj.data
|
2013-06-10 19:01:40 +00:00
|
|
|
|
2010-06-26 19:00:44 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2013-06-10 19:01:40 +00:00
|
|
|
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Light Power")
|
2019-05-13 22:32:50 +02:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.energy"
|
2021-01-25 20:35:56 +11:00
|
|
|
props.input_scale = 1.0
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Light Power: %.3f")
|
2013-06-06 11:18:39 +00:00
|
|
|
|
2018-06-27 14:41:53 +02:00
|
|
|
if light.type == 'AREA':
|
|
|
|
|
if light.shape in {'RECTANGLE', 'ELLIPSE'}:
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light X Size")
|
|
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.size"
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Light Size X: %.3f")
|
2021-01-25 20:05:49 +11:00
|
|
|
|
|
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light Y Size")
|
2013-06-06 11:18:39 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
Remove Blender Internal and legacy viewport from Blender 2.8.
Brecht authored this commit, but he gave me the honours to actually
do it. Here it goes; Blender Internal. Bye bye, you did great!
* Point density, voxel data, ocean, environment map textures were removed,
as these only worked within BI rendering. Note that the ocean modifier
and the Cycles point density shader node continue to work.
* Dynamic paint using material shading was removed, as this only worked
with BI. If we ever wanted to support this again probably it should go
through the baking API.
* GPU shader export through the Python API was removed. This only worked
for the old BI GLSL shaders, which no longer exists. Doing something
similar for Eevee would be significantly more complicated because it
uses a lot of multiplass rendering and logic outside the shader, it's
probably impractical.
* Collada material import / export code is mostly gone, as it only worked
for BI materials. We need to add Cycles / Eevee material support at some
point.
* The mesh noise operator was removed since it only worked with BI
material texture slots. A displacement modifier can be used instead.
* The delete texture paint slot operator was removed since it only worked
for BI material texture slots. Could be added back with node support.
* Not all legacy viewport features are supported in the new viewport, but
their code was removed. If we need to bring anything back we can look at
older git revisions.
* There is some legacy viewport code that I could not remove yet, and some
that I probably missed.
* Shader node execution code was left mostly intact, even though it is not
used anywhere now. We may eventually use this to replace the texture
nodes with Cycles / Eevee shader nodes.
* The Cycles Bake panel now includes settings for baking multires normal
and displacement maps. The underlying code needs to be merged properly,
and we plan to add back support for multires AO baking and add support
to Cycles baking for features like vertex color, displacement, and other
missing baking features.
* This commit removes DNA and the Python API for BI material, lamp, world
and scene settings. This breaks a lot of addons.
* There is more DNA that can be removed or renamed, where Cycles or Eevee
are reusing some old BI properties but the names are not really correct
anymore.
* Texture slots for materials, lamps and world were removed. They remain
for brushes, particles and freestyle linestyles.
* 'BLENDER_RENDER' remains in the COMPAT_ENGINES of UI panels. Cycles and
other renderers use this to find all panels to show, minus a few panels
that they have their own replacement for.
2018-04-19 17:34:44 +02:00
|
|
|
props.data_path_item = "data.size_y"
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Light Size Y: %.3f")
|
2021-01-25 20:05:49 +11:00
|
|
|
else:
|
|
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light Size")
|
|
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.size"
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Light Size: %.3f")
|
Remove Blender Internal and legacy viewport from Blender 2.8.
Brecht authored this commit, but he gave me the honours to actually
do it. Here it goes; Blender Internal. Bye bye, you did great!
* Point density, voxel data, ocean, environment map textures were removed,
as these only worked within BI rendering. Note that the ocean modifier
and the Cycles point density shader node continue to work.
* Dynamic paint using material shading was removed, as this only worked
with BI. If we ever wanted to support this again probably it should go
through the baking API.
* GPU shader export through the Python API was removed. This only worked
for the old BI GLSL shaders, which no longer exists. Doing something
similar for Eevee would be significantly more complicated because it
uses a lot of multiplass rendering and logic outside the shader, it's
probably impractical.
* Collada material import / export code is mostly gone, as it only worked
for BI materials. We need to add Cycles / Eevee material support at some
point.
* The mesh noise operator was removed since it only worked with BI
material texture slots. A displacement modifier can be used instead.
* The delete texture paint slot operator was removed since it only worked
for BI material texture slots. Could be added back with node support.
* Not all legacy viewport features are supported in the new viewport, but
their code was removed. If we need to bring anything back we can look at
older git revisions.
* There is some legacy viewport code that I could not remove yet, and some
that I probably missed.
* Shader node execution code was left mostly intact, even though it is not
used anywhere now. We may eventually use this to replace the texture
nodes with Cycles / Eevee shader nodes.
* The Cycles Bake panel now includes settings for baking multires normal
and displacement maps. The underlying code needs to be merged properly,
and we plan to add back support for multires AO baking and add support
to Cycles baking for features like vertex color, displacement, and other
missing baking features.
* This commit removes DNA and the Python API for BI material, lamp, world
and scene settings. This breaks a lot of addons.
* There is more DNA that can be removed or renamed, where Cycles or Eevee
are reusing some old BI properties but the names are not really correct
anymore.
* Texture slots for materials, lamps and world were removed. They remain
for brushes, particles and freestyle linestyles.
* 'BLENDER_RENDER' remains in the COMPAT_ENGINES of UI panels. Cycles and
other renderers use this to find all panels to show, minus a few panels
that they have their own replacement for.
2018-04-19 17:34:44 +02:00
|
|
|
|
2019-05-15 14:45:33 +02:00
|
|
|
elif light.type in {'SPOT', 'POINT'}:
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Light Radius")
|
Remove Blender Internal and legacy viewport from Blender 2.8.
Brecht authored this commit, but he gave me the honours to actually
do it. Here it goes; Blender Internal. Bye bye, you did great!
* Point density, voxel data, ocean, environment map textures were removed,
as these only worked within BI rendering. Note that the ocean modifier
and the Cycles point density shader node continue to work.
* Dynamic paint using material shading was removed, as this only worked
with BI. If we ever wanted to support this again probably it should go
through the baking API.
* GPU shader export through the Python API was removed. This only worked
for the old BI GLSL shaders, which no longer exists. Doing something
similar for Eevee would be significantly more complicated because it
uses a lot of multiplass rendering and logic outside the shader, it's
probably impractical.
* Collada material import / export code is mostly gone, as it only worked
for BI materials. We need to add Cycles / Eevee material support at some
point.
* The mesh noise operator was removed since it only worked with BI
material texture slots. A displacement modifier can be used instead.
* The delete texture paint slot operator was removed since it only worked
for BI material texture slots. Could be added back with node support.
* Not all legacy viewport features are supported in the new viewport, but
their code was removed. If we need to bring anything back we can look at
older git revisions.
* There is some legacy viewport code that I could not remove yet, and some
that I probably missed.
* Shader node execution code was left mostly intact, even though it is not
used anywhere now. We may eventually use this to replace the texture
nodes with Cycles / Eevee shader nodes.
* The Cycles Bake panel now includes settings for baking multires normal
and displacement maps. The underlying code needs to be merged properly,
and we plan to add back support for multires AO baking and add support
to Cycles baking for features like vertex color, displacement, and other
missing baking features.
* This commit removes DNA and the Python API for BI material, lamp, world
and scene settings. This breaks a lot of addons.
* There is more DNA that can be removed or renamed, where Cycles or Eevee
are reusing some old BI properties but the names are not really correct
anymore.
* Texture slots for materials, lamps and world were removed. They remain
for brushes, particles and freestyle linestyles.
* 'BLENDER_RENDER' remains in the COMPAT_ENGINES of UI panels. Cycles and
other renderers use this to find all panels to show, minus a few panels
that they have their own replacement for.
2018-04-19 17:34:44 +02:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.shadow_soft_size"
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Light Radius: %.3f")
|
2010-06-26 19:00:44 +00:00
|
|
|
|
2019-05-15 14:45:33 +02:00
|
|
|
elif light.type == 'SUN':
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Sun Light Angle")
|
2019-05-15 14:45:33 +02:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.angle"
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Light Angle: %.3f")
|
2019-05-15 14:45:33 +02:00
|
|
|
|
2018-06-27 14:41:53 +02:00
|
|
|
if light.type == 'SPOT':
|
2010-06-26 19:00:44 +00:00
|
|
|
layout.separator()
|
2018-11-22 19:02:44 +01:00
|
|
|
|
2025-08-22 16:47:50 +02:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Spot Light Beam Angle")
|
2010-06-26 19:00:44 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.spot_size"
|
|
|
|
|
props.input_scale = 0.01
|
2025-08-22 16:47:50 +02:00
|
|
|
props.header_text = rpt_("Beam Angle: %.2f")
|
2010-06-26 19:00:44 +00:00
|
|
|
|
2021-01-25 20:05:49 +11:00
|
|
|
props = layout.operator("wm.context_modal_mouse", text="Adjust Spot Light Blend")
|
2010-06-26 19:00:44 +00:00
|
|
|
props.data_path_iter = "selected_editable_objects"
|
|
|
|
|
props.data_path_item = "data.spot_blend"
|
|
|
|
|
props.input_scale = -0.01
|
2024-01-11 19:49:03 +01:00
|
|
|
props.header_text = rpt_("Spot Blend: %.2f")
|
2010-06-26 19:00:44 +00:00
|
|
|
|
2019-03-26 14:48:35 +01:00
|
|
|
layout.separator()
|
2019-03-26 14:36:15 +01:00
|
|
|
|
2021-01-25 21:26:19 +11:00
|
|
|
# Shared among some object types.
|
|
|
|
|
if obj is not None:
|
|
|
|
|
if obj.type in {'MESH', 'CURVE', 'SURFACE'}:
|
2022-05-11 11:54:14 +02:00
|
|
|
layout.operator("object.shade_smooth")
|
Mesh: Replace auto smooth with node group
Design task: #93551
This PR replaces the auto smooth option with a geometry nodes modifier
that sets the sharp edge attribute. This solves a fair number of long-
standing problems related to auto smooth, simplifies the process of
normal computation, and allows Blender to automatically choose between
face, vertex, and face corner normals based on the sharp edge and face
attributes.
Versioning adds a geometry node group to objects with meshes that had
auto-smooth enabled. The modifier can be applied, which also improves
performance.
Auto smooth is now unnecessary to get a combination of sharp and smooth
edges. In general workflows are changed a bit. Separate procedural and
destructive workflows are available. Custom normals can be used
immediately without turning on the removed auto smooth option.
**Procedural**
The node group asset "Smooth by Angle" is the main way to set sharp
normals based on the edge angle. It can be accessed directly in the add
modifier menu. Of course the modifier can be reordered, muted, or
applied like any other, or changed internally like any geometry nodes
modifier.
**Destructive**
Often the sharp edges don't need to be dynamic. This can give better
performance since edge angles don't need to be recalculated. In edit
mode the two operators "Select Sharp Edges" and "Mark Sharp" can be
used. In other modes, the "Shade Smooth by Angle" controls the edge
sharpness directly.
### Breaking API Changes
- `use_auto_smooth` is removed. Face corner normals are now used
automatically if there are mixed smooth vs. not smooth tags. Meshes
now always use custom normals if they exist.
- In Cycles, the lack of the separate auto smooth state makes normals look
triangulated when all faces are shaded smooth.
- `auto_smooth_angle` is removed. Replaced by a modifier (or operator)
controlling the sharp edge attribute. This means the mesh itself
(without an object) doesn't know anything about automatically smoothing
by angle anymore.
- `create_normals_split`, `calc_normals_split`, and `free_normals_split`
are removed, and are replaced by the simpler `Mesh.corner_normals`
collection property. Since it gives access to the normals cache, it
is automatically updated when relevant data changes.
Addons are updated here: https://projects.blender.org/blender/blender-addons/pulls/104609
### Tests
- `geo_node_curves_test_deform_curves_on_surface` has slightly different
results because face corner normals are used instead of interpolated
vertex normals.
- `bf_wavefront_obj_tests` has different export results for one file
which mixed sharp and smooth faces without turning on auto smooth.
- `cycles_mesh_cpu` has one object which is completely flat shaded.
Previously every edge was split before rendering, now it looks triangulated.
Pull Request: https://projects.blender.org/blender/blender/pulls/108014
2023-10-20 16:54:08 +02:00
|
|
|
if obj.type == 'MESH':
|
2024-05-08 20:24:10 +02:00
|
|
|
layout.operator("object.shade_auto_smooth")
|
Mesh: Replace auto smooth with node group
Design task: #93551
This PR replaces the auto smooth option with a geometry nodes modifier
that sets the sharp edge attribute. This solves a fair number of long-
standing problems related to auto smooth, simplifies the process of
normal computation, and allows Blender to automatically choose between
face, vertex, and face corner normals based on the sharp edge and face
attributes.
Versioning adds a geometry node group to objects with meshes that had
auto-smooth enabled. The modifier can be applied, which also improves
performance.
Auto smooth is now unnecessary to get a combination of sharp and smooth
edges. In general workflows are changed a bit. Separate procedural and
destructive workflows are available. Custom normals can be used
immediately without turning on the removed auto smooth option.
**Procedural**
The node group asset "Smooth by Angle" is the main way to set sharp
normals based on the edge angle. It can be accessed directly in the add
modifier menu. Of course the modifier can be reordered, muted, or
applied like any other, or changed internally like any geometry nodes
modifier.
**Destructive**
Often the sharp edges don't need to be dynamic. This can give better
performance since edge angles don't need to be recalculated. In edit
mode the two operators "Select Sharp Edges" and "Mark Sharp" can be
used. In other modes, the "Shade Smooth by Angle" controls the edge
sharpness directly.
### Breaking API Changes
- `use_auto_smooth` is removed. Face corner normals are now used
automatically if there are mixed smooth vs. not smooth tags. Meshes
now always use custom normals if they exist.
- In Cycles, the lack of the separate auto smooth state makes normals look
triangulated when all faces are shaded smooth.
- `auto_smooth_angle` is removed. Replaced by a modifier (or operator)
controlling the sharp edge attribute. This means the mesh itself
(without an object) doesn't know anything about automatically smoothing
by angle anymore.
- `create_normals_split`, `calc_normals_split`, and `free_normals_split`
are removed, and are replaced by the simpler `Mesh.corner_normals`
collection property. Since it gives access to the normals cache, it
is automatically updated when relevant data changes.
Addons are updated here: https://projects.blender.org/blender/blender-addons/pulls/104609
### Tests
- `geo_node_curves_test_deform_curves_on_surface` has slightly different
results because face corner normals are used instead of interpolated
vertex normals.
- `bf_wavefront_obj_tests` has different export results for one file
which mixed sharp and smooth faces without turning on auto smooth.
- `cycles_mesh_cpu` has one object which is completely flat shaded.
Previously every edge was split before rendering, now it looks triangulated.
Pull Request: https://projects.blender.org/blender/blender/pulls/108014
2023-10-20 16:54:08 +02:00
|
|
|
layout.operator("object.shade_flat")
|
2021-01-25 21:26:19 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-12-14 11:19:24 +01:00
|
|
|
if obj.type in {'MESH', 'CURVE', 'SURFACE', 'ARMATURE', 'GREASEPENCIL'}:
|
2021-01-25 21:26:19 +11:00
|
|
|
if selected_objects_len > 1:
|
|
|
|
|
layout.operator("object.join")
|
|
|
|
|
|
2025-02-24 17:00:21 +01:00
|
|
|
if obj.type in {'MESH', 'CURVE', 'CURVES', 'SURFACE', 'POINTCLOUD',
|
|
|
|
|
'META', 'FONT', 'GREASEPENCIL'}:
|
2021-01-25 21:26:19 +11:00
|
|
|
layout.operator_menu_enum("object.convert", "target")
|
|
|
|
|
|
2024-12-14 11:19:24 +01:00
|
|
|
if (obj.type in {'MESH',
|
|
|
|
|
'CURVE',
|
|
|
|
|
'CURVES',
|
|
|
|
|
'SURFACE',
|
|
|
|
|
'GREASEPENCIL',
|
|
|
|
|
'LATTICE',
|
|
|
|
|
'ARMATURE',
|
|
|
|
|
'META',
|
|
|
|
|
'FONT',
|
|
|
|
|
'POINTCLOUD',
|
|
|
|
|
} or (obj.type == 'EMPTY' and obj.instance_collection is not None)):
|
2021-01-25 21:26:19 +11:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
|
|
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Shared among all object types
|
2018-11-22 19:02:44 +01:00
|
|
|
layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN')
|
|
|
|
|
layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-11-23 13:55:33 +11:00
|
|
|
layout.operator("object.duplicate_move", icon='DUPLICATE')
|
2018-11-22 19:02:44 +01:00
|
|
|
layout.operator("object.duplicate_move_linked")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-03-26 14:48:35 +01:00
|
|
|
props = layout.operator("wm.call_panel", text="Rename Active Object...")
|
|
|
|
|
props.name = "TOPBAR_PT_name"
|
|
|
|
|
props.keep_open = False
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-03-20 10:17:10 +01:00
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
2018-11-22 19:02:44 +01:00
|
|
|
layout.menu("VIEW3D_MT_snap")
|
|
|
|
|
layout.menu("VIEW3D_MT_object_parent")
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2018-11-29 23:44:37 -02:00
|
|
|
|
|
|
|
|
if view and view.local_view:
|
|
|
|
|
layout.operator("view3d.localview_remove_from")
|
|
|
|
|
else:
|
2025-07-02 16:21:36 +02:00
|
|
|
layout.menu("OBJECT_MT_move_to_collection")
|
2018-11-22 19:02:44 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-11-21 15:38:01 +01:00
|
|
|
layout.operator("anim.keyframe_insert", text="Insert Keyframe")
|
2024-01-25 16:18:05 +01:00
|
|
|
layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe with Keying Set").always_prompt = True
|
2018-11-22 19:02:44 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2018-11-23 03:47:02 +01:00
|
|
|
layout.operator("object.delete", text="Delete").use_global = False
|
2018-11-22 19:02:44 +01:00
|
|
|
|
2023-11-15 17:01:18 +01:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Object")
|
|
|
|
|
|
2010-09-07 15:17:42 +00:00
|
|
|
|
2018-04-25 07:25:08 +02:00
|
|
|
class VIEW3D_MT_object_shading(Menu):
|
|
|
|
|
# XXX, this menu is a place to store shading operator in object mode
|
|
|
|
|
bl_label = "Shading"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-04-25 07:25:08 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator("object.shade_smooth", text="Smooth")
|
|
|
|
|
layout.operator("object.shade_flat", text="Flat")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object_apply(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Apply"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2023-04-13 13:14:03 +10:00
|
|
|
|
2022-03-30 11:07:29 +02:00
|
|
|
# Need invoke for the popup confirming the multi-user data operation
|
|
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2013-03-28 15:41:43 +00:00
|
|
|
props = layout.operator("object.transform_apply", text="Location", text_ctxt=i18n_contexts.default)
|
2012-01-14 06:30:27 +00:00
|
|
|
props.location, props.rotation, props.scale = True, False, False
|
|
|
|
|
|
2013-03-28 15:41:43 +00:00
|
|
|
props = layout.operator("object.transform_apply", text="Rotation", text_ctxt=i18n_contexts.default)
|
2012-01-14 06:30:27 +00:00
|
|
|
props.location, props.rotation, props.scale = False, True, False
|
|
|
|
|
|
2013-03-28 15:41:43 +00:00
|
|
|
props = layout.operator("object.transform_apply", text="Scale", text_ctxt=i18n_contexts.default)
|
2012-01-14 06:30:27 +00:00
|
|
|
props.location, props.rotation, props.scale = False, False, True
|
2019-03-11 16:12:29 +01:00
|
|
|
|
|
|
|
|
props = layout.operator("object.transform_apply", text="All Transforms", text_ctxt=i18n_contexts.default)
|
|
|
|
|
props.location, props.rotation, props.scale = True, True, True
|
|
|
|
|
|
2013-03-28 15:41:43 +00:00
|
|
|
props = layout.operator("object.transform_apply", text="Rotation & Scale", text_ctxt=i18n_contexts.default)
|
2012-01-14 06:30:27 +00:00
|
|
|
props.location, props.rotation, props.scale = False, True, True
|
2011-05-03 07:09:02 +00:00
|
|
|
|
2016-07-04 12:52:51 +12:00
|
|
|
layout.separator()
|
2016-08-01 11:54:02 +10:00
|
|
|
|
2017-10-19 11:24:01 +11:00
|
|
|
layout.operator(
|
|
|
|
|
"object.transforms_to_deltas",
|
|
|
|
|
text="Location to Deltas",
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
).mode = 'LOC'
|
|
|
|
|
layout.operator(
|
|
|
|
|
"object.transforms_to_deltas",
|
|
|
|
|
text="Rotation to Deltas",
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
).mode = 'ROT'
|
|
|
|
|
layout.operator(
|
|
|
|
|
"object.transforms_to_deltas",
|
|
|
|
|
text="Scale to Deltas",
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
).mode = 'SCALE'
|
|
|
|
|
|
|
|
|
|
layout.operator(
|
|
|
|
|
"object.transforms_to_deltas",
|
|
|
|
|
text="All Transforms to Deltas",
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
).mode = 'ALL'
|
2016-07-04 12:52:51 +12:00
|
|
|
layout.operator("object.anim_transforms_to_deltas")
|
2016-08-01 11:54:02 +10:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2011-05-03 07:09:02 +00:00
|
|
|
|
2017-10-19 11:24:01 +11:00
|
|
|
layout.operator(
|
|
|
|
|
"object.visual_transform_apply",
|
|
|
|
|
text="Visual Transform",
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
)
|
|
|
|
|
layout.operator(
|
|
|
|
|
"object.convert",
|
|
|
|
|
text="Visual Geometry to Mesh",
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
).target = 'MESH'
|
2025-02-26 17:48:54 +01:00
|
|
|
layout.operator("object.visual_geometry_to_objects")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("object.duplicates_make_real")
|
2024-03-15 10:04:03 +11:00
|
|
|
layout.operator("object.parent_inverse_apply", text="Parent Inverse", text_ctxt=i18n_contexts.default)
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2023-11-15 17:01:18 +01:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Object/Apply")
|
|
|
|
|
|
2009-10-15 20:15:21 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object_parent(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Parent"
|
2024-06-13 12:15:55 +02:00
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2025-10-13 09:35:09 +00:00
|
|
|
from _bl_ui_utils.layout import operator_context
|
2023-04-13 13:13:59 +10:00
|
|
|
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2012-11-04 00:54:12 +00:00
|
|
|
layout.operator_enum("object.parent_set", "type")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2012-11-04 00:54:12 +00:00
|
|
|
layout.separator()
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2023-04-07 11:33:56 +02:00
|
|
|
with operator_context(layout, 'EXEC_REGION_WIN'):
|
|
|
|
|
layout.operator("object.parent_no_inverse_set").keep_transform = False
|
|
|
|
|
props = layout.operator("object.parent_no_inverse_set", text="Make Parent without Inverse (Keep Transform)")
|
|
|
|
|
props.keep_transform = True
|
2019-10-29 10:21:04 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2012-11-04 00:54:12 +00:00
|
|
|
layout.operator_enum("object.parent_clear", "type")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object_track(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Track"
|
2023-12-30 15:35:10 +01:00
|
|
|
bl_translation_context = i18n_contexts.constraint
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2012-11-04 00:54:12 +00:00
|
|
|
layout.operator_enum("object.track_set", "type")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2012-11-04 00:54:12 +00:00
|
|
|
layout.separator()
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2012-11-04 00:54:12 +00:00
|
|
|
layout.operator_enum("object.track_clear", "type")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
class VIEW3D_MT_object_collection(Menu):
|
|
|
|
|
bl_label = "Collection"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2025-07-02 16:21:36 +02:00
|
|
|
layout.menu("OBJECT_MT_move_to_collection")
|
|
|
|
|
layout.menu("OBJECT_MT_link_to_collection")
|
2019-02-05 22:36:09 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
layout.operator("collection.create")
|
|
|
|
|
# layout.operator_menu_enum("collection.objects_remove", "collection") # BUGGY
|
|
|
|
|
layout.operator("collection.objects_remove")
|
|
|
|
|
layout.operator("collection.objects_remove_all")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
layout.operator("collection.objects_add_active")
|
|
|
|
|
layout.operator("collection.objects_remove_active")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_object_constraints(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Constraints"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("object.constraint_add_with_targets")
|
2010-05-27 11:56:31 +00:00
|
|
|
layout.operator("object.constraints_copy")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("object.constraints_clear")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2024-05-01 14:15:53 +02:00
|
|
|
class VIEW3D_MT_object_modifiers(Menu):
|
|
|
|
|
bl_label = "Modifiers"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
2024-05-02 18:13:41 +02:00
|
|
|
active_object = bpy.context.active_object
|
2025-01-07 13:52:44 +01:00
|
|
|
supported_types = {
|
|
|
|
|
'MESH',
|
|
|
|
|
'CURVE',
|
|
|
|
|
'CURVES',
|
|
|
|
|
'SURFACE',
|
|
|
|
|
'FONT',
|
|
|
|
|
'VOLUME',
|
|
|
|
|
'GREASEPENCIL',
|
|
|
|
|
'LATTICE',
|
|
|
|
|
'POINTCLOUD'}
|
2024-05-02 18:13:41 +02:00
|
|
|
|
2024-05-01 14:15:53 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-05-02 21:34:43 +02:00
|
|
|
if active_object:
|
|
|
|
|
if active_object.type in supported_types:
|
|
|
|
|
layout.menu("OBJECT_MT_modifier_add", text="Add Modifier")
|
2024-05-02 18:13:41 +02:00
|
|
|
|
|
|
|
|
layout.operator("object.modifiers_copy_to_selected", text="Copy Modifiers to Selected Objects")
|
2024-05-01 14:15:53 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("object.modifiers_clear")
|
|
|
|
|
|
|
|
|
|
|
2011-10-06 05:45:06 +00:00
|
|
|
class VIEW3D_MT_object_quick_effects(Menu):
|
|
|
|
|
bl_label = "Quick Effects"
|
|
|
|
|
|
2021-03-06 18:21:17 +11:00
|
|
|
def draw(self, _context):
|
2011-10-06 05:45:06 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("object.quick_fur")
|
|
|
|
|
layout.operator("object.quick_explode")
|
|
|
|
|
layout.operator("object.quick_smoke")
|
2019-12-16 15:42:07 +01:00
|
|
|
layout.operator("object.quick_liquid")
|
2023-11-15 17:01:18 +01:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Object/Quick Effects")
|
2011-10-06 05:45:06 +00:00
|
|
|
|
|
|
|
|
|
Objects: restore H key per object hiding.
H hides selected objects, Shift+H hides unselected objects, and Alt+H
reveals hidden objects.
This hiding state is distinct from restrict viewport and render, and
meant for temporarily hiding objects without affecting more persistent
collection hiding.
Object hiding is per view-layer, same as selection. It affects the
viewport and any preview renders in there, but not final renders.
In the outliner, different icons are now used for temporary hiding, and
restrict viewport and render. Hidden objects are greyed out.
Remaining design issues:
* For lamps we probably still want to keep their effect on the scene,
currently they are fully disabled by hiding. Arguably mesh lights or
even objects being reflected or casting shadows are not that different
but perhaps the special lamp exception from local view should remain.
* We need a feature still to disabled this hiding for specific viewports,
for render or animation preview where you want to see the entire scene
while working in another view.
* We need a new icon for restrict viewport, for now it uses a grid similar
to the 2.4 icon.
* Hiding objects does not preserve selection state as it did in 2.7,
it's probably convenient to support this again?
2018-05-14 23:36:56 +02:00
|
|
|
class VIEW3D_MT_object_showhide(Menu):
|
|
|
|
|
bl_label = "Show/Hide"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
Objects: restore H key per object hiding.
H hides selected objects, Shift+H hides unselected objects, and Alt+H
reveals hidden objects.
This hiding state is distinct from restrict viewport and render, and
meant for temporarily hiding objects without affecting more persistent
collection hiding.
Object hiding is per view-layer, same as selection. It affects the
viewport and any preview renders in there, but not final renders.
In the outliner, different icons are now used for temporary hiding, and
restrict viewport and render. Hidden objects are greyed out.
Remaining design issues:
* For lamps we probably still want to keep their effect on the scene,
currently they are fully disabled by hiding. Arguably mesh lights or
even objects being reflected or casting shadows are not that different
but perhaps the special lamp exception from local view should remain.
* We need a feature still to disabled this hiding for specific viewports,
for render or animation preview where you want to see the entire scene
while working in another view.
* We need a new icon for restrict viewport, for now it uses a grid similar
to the 2.4 icon.
* Hiding objects does not preserve selection state as it did in 2.7,
it's probably convenient to support this again?
2018-05-14 23:36:56 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2019-03-19 22:25:25 +01:00
|
|
|
layout.operator("object.hide_view_clear")
|
Objects: restore H key per object hiding.
H hides selected objects, Shift+H hides unselected objects, and Alt+H
reveals hidden objects.
This hiding state is distinct from restrict viewport and render, and
meant for temporarily hiding objects without affecting more persistent
collection hiding.
Object hiding is per view-layer, same as selection. It affects the
viewport and any preview renders in there, but not final renders.
In the outliner, different icons are now used for temporary hiding, and
restrict viewport and render. Hidden objects are greyed out.
Remaining design issues:
* For lamps we probably still want to keep their effect on the scene,
currently they are fully disabled by hiding. Arguably mesh lights or
even objects being reflected or casting shadows are not that different
but perhaps the special lamp exception from local view should remain.
* We need a feature still to disabled this hiding for specific viewports,
for render or animation preview where you want to see the entire scene
while working in another view.
* We need a new icon for restrict viewport, for now it uses a grid similar
to the 2.4 icon.
* Hiding objects does not preserve selection state as it did in 2.7,
it's probably convenient to support this again?
2018-05-14 23:36:56 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("object.hide_view_set", text="Hide Selected").unselected = False
|
|
|
|
|
layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
|
|
|
|
|
|
|
|
|
|
|
2020-08-30 13:34:27 +10:00
|
|
|
class VIEW3D_MT_object_cleanup(Menu):
|
|
|
|
|
bl_label = "Clean Up"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("object.vertex_group_clean", text="Clean Vertex Group Weights").group_select_mode = 'ALL'
|
2020-08-30 18:49:38 +10:00
|
|
|
layout.operator("object.vertex_group_limit_total", text="Limit Total Vertex Groups").group_select_mode = 'ALL'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-08-30 13:34:27 +10:00
|
|
|
layout.operator("object.material_slot_remove_unused", text="Remove Unused Material Slots")
|
2025-05-07 08:06:52 +02:00
|
|
|
layout.operator("object.material_slot_remove_all", text="Remove All Materials")
|
2020-08-30 13:34:27 +10:00
|
|
|
|
2022-04-19 15:05:55 +10:00
|
|
|
|
2021-10-26 18:53:40 +02:00
|
|
|
class VIEW3D_MT_object_asset(Menu):
|
|
|
|
|
bl_label = "Asset"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("asset.mark")
|
|
|
|
|
layout.operator("asset.clear", text="Clear Asset").set_fake_user = False
|
|
|
|
|
layout.operator("asset.clear", text="Clear Asset (Set Fake User)").set_fake_user = True
|
|
|
|
|
|
2020-08-30 13:34:27 +10:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_make_single_user(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Make Single User"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("object.make_single_user", text="Object")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.object = True
|
2021-06-23 13:25:40 +02:00
|
|
|
props.obdata = props.material = props.animation = props.obdata_animation = False
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("object.make_single_user", text="Object & Data")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.object = props.obdata = True
|
2021-06-23 13:25:40 +02:00
|
|
|
props.material = props.animation = props.obdata_animation = False
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-04-29 09:07:35 +02:00
|
|
|
props = layout.operator("object.make_single_user", text="Object & Data & Materials")
|
|
|
|
|
props.object = props.obdata = props.material = True
|
2021-06-23 13:25:40 +02:00
|
|
|
props.animation = props.obdata_animation = False
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-04-29 09:07:35 +02:00
|
|
|
props = layout.operator("object.make_single_user", text="Materials")
|
|
|
|
|
props.material = True
|
2021-06-23 13:25:40 +02:00
|
|
|
props.object = props.obdata = props.animation = props.obdata_animation = False
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
props = layout.operator("object.make_single_user", text="Object Animation")
|
2009-10-31 19:31:45 +00:00
|
|
|
props.animation = True
|
2021-06-23 13:25:40 +02:00
|
|
|
props.object = props.obdata = props.material = props.obdata_animation = False
|
|
|
|
|
|
|
|
|
|
props = layout.operator("object.make_single_user", text="Object Data Animation")
|
|
|
|
|
props.obdata_animation = props.obdata = True
|
|
|
|
|
props.object = props.material = props.animation = False
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-04 10:25:57 +00:00
|
|
|
|
2021-01-25 17:49:02 +11:00
|
|
|
class VIEW3D_MT_object_convert(Menu):
|
|
|
|
|
bl_label = "Convert"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
ob = context.active_object
|
2023-06-21 16:47:18 +02:00
|
|
|
|
2025-02-19 11:06:31 +11:00
|
|
|
layout.operator_enum("object.convert", "target")
|
2021-01-25 17:49:02 +11:00
|
|
|
|
2025-02-19 11:06:31 +11:00
|
|
|
if ob and ob.type == 'EMPTY':
|
2024-06-06 10:55:15 +10:00
|
|
|
# Potrace lib dependency.
|
|
|
|
|
if bpy.app.build_options.potrace:
|
2025-02-19 11:06:31 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-06-06 10:55:15 +10:00
|
|
|
layout.operator("image.convert_to_mesh_plane", text="Convert to Mesh Plane", icon='MESH_PLANE')
|
2024-07-25 18:44:07 +02:00
|
|
|
layout.operator("grease_pencil.trace_image", icon='OUTLINER_OB_GREASEPENCIL')
|
2021-01-25 17:49:02 +11:00
|
|
|
|
2022-03-30 13:29:31 +02:00
|
|
|
if ob and ob.type == 'CURVES':
|
2025-02-19 11:06:31 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2022-03-30 13:29:31 +02:00
|
|
|
layout.operator("curves.convert_to_particle_system", text="Particle System")
|
2023-11-16 07:59:20 +01:00
|
|
|
|
2023-11-15 17:01:18 +01:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Object/Convert")
|
2022-03-30 13:29:31 +02:00
|
|
|
|
2021-01-25 17:49:02 +11:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_make_links(Menu):
|
2021-01-20 20:48:14 +11:00
|
|
|
bl_label = "Link/Transfer Data"
|
2009-11-04 10:25:57 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-11-04 10:25:57 +00:00
|
|
|
layout = self.layout
|
2013-01-22 04:54:31 +00:00
|
|
|
operator_context_default = layout.operator_context
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2013-04-04 17:01:51 +00:00
|
|
|
if len(bpy.data.scenes) > 10:
|
2013-01-22 04:54:31 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2021-01-20 20:48:14 +11:00
|
|
|
layout.operator("object.make_links_scene", text="Link Objects to Scene...", icon='OUTLINER_OB_EMPTY')
|
2010-12-02 22:58:23 +00:00
|
|
|
else:
|
2013-01-22 04:54:31 +00:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2021-01-20 20:48:14 +11:00
|
|
|
layout.operator_menu_enum("object.make_links_scene", "scene", text="Link Objects to Scene")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-01-22 04:54:31 +00:00
|
|
|
layout.operator_context = operator_context_default
|
2010-12-02 22:58:23 +00:00
|
|
|
|
2011-02-18 06:07:41 +00:00
|
|
|
layout.operator_enum("object.make_links_data", "type") # inline
|
2009-11-04 10:25:57 +00:00
|
|
|
|
2021-01-20 20:48:14 +11:00
|
|
|
layout.operator("object.join_uvs", text="Copy UV Maps")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
2025-01-18 19:58:35 +01:00
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
2021-01-20 20:48:14 +11:00
|
|
|
layout.operator("object.data_transfer")
|
|
|
|
|
layout.operator("object.datalayout_transfer")
|
2009-11-04 10:25:57 +00:00
|
|
|
|
2024-10-03 18:41:06 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator_menu_enum("object.light_linking_receivers_link", "link_state")
|
|
|
|
|
layout.operator_menu_enum("object.light_linking_blockers_link", "link_state")
|
|
|
|
|
|
2011-10-15 05:01:47 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_paint_vertex(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Paint"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-22 02:27:37 +00:00
|
|
|
|
2013-04-27 19:00:26 +00:00
|
|
|
layout.operator("paint.vertex_color_smooth")
|
2010-04-21 16:22:37 +00:00
|
|
|
layout.operator("paint.vertex_color_dirt")
|
2017-09-29 17:10:15 +10:00
|
|
|
layout.operator("paint.vertex_color_from_weight")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2016-06-17 01:45:40 +10:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("paint.vertex_color_invert", text="Invert")
|
|
|
|
|
layout.operator("paint.vertex_color_levels", text="Levels")
|
2023-04-11 23:48:05 +02:00
|
|
|
layout.operator("paint.vertex_color_hsv", text="Hue/Saturation/Value")
|
2023-04-11 21:32:29 +02:00
|
|
|
layout.operator("paint.vertex_color_brightness_contrast", text="Brightness/Contrast")
|
2016-06-17 01:45:40 +10:00
|
|
|
|
2023-07-28 16:27:24 +10:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("paint.vertex_color_set")
|
2024-12-18 20:30:10 +01:00
|
|
|
layout.operator("paint.sample_color").merged = False
|
2023-07-28 16:27:24 +10:00
|
|
|
|
2009-11-16 13:59:27 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_hook(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Hooks"
|
2009-11-16 13:59:27 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator_context = 'EXEC_AREA'
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("object.hook_add_newob")
|
2012-08-22 15:38:03 +00:00
|
|
|
layout.operator("object.hook_add_selob").use_bone = False
|
2012-08-13 08:54:33 +00:00
|
|
|
layout.operator("object.hook_add_selob", text="Hook to Selected Object Bone").use_bone = True
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2019-07-30 11:22:57 +02:00
|
|
|
if any([mod.type == 'HOOK' for mod in context.active_object.modifiers]):
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator_menu_enum("object.hook_assign", "modifier")
|
|
|
|
|
layout.operator_menu_enum("object.hook_remove", "modifier")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator_menu_enum("object.hook_select", "modifier")
|
|
|
|
|
layout.operator_menu_enum("object.hook_reset", "modifier")
|
|
|
|
|
layout.operator_menu_enum("object.hook_recenter", "modifier")
|
2009-11-22 06:20:56 +00:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_vertex_group(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Vertex Groups"
|
2009-11-22 06:20:56 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2012-07-29 12:07:06 +00:00
|
|
|
|
2009-11-22 06:20:56 +00:00
|
|
|
layout.operator_context = 'EXEC_AREA'
|
2013-07-01 13:02:53 +00:00
|
|
|
layout.operator("object.vertex_group_assign_new")
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2009-11-22 06:20:56 +00:00
|
|
|
ob = context.active_object
|
2018-04-05 18:20:27 +02:00
|
|
|
if ob.mode == 'EDIT' or (ob.mode == 'WEIGHT_PAINT' and ob.type == 'MESH' and ob.data.use_paint_mask_vertex):
|
2010-08-24 04:02:50 +00:00
|
|
|
if ob.vertex_groups.active:
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2013-07-01 13:02:53 +00:00
|
|
|
layout.operator("object.vertex_group_assign", text="Assign to Active Group")
|
2017-10-19 11:24:01 +11:00
|
|
|
layout.operator(
|
|
|
|
|
"object.vertex_group_remove_from",
|
|
|
|
|
text="Remove from Active Group",
|
|
|
|
|
).use_all_groups = False
|
2013-06-25 22:58:45 +00:00
|
|
|
layout.operator("object.vertex_group_remove_from", text="Remove from All").use_all_groups = True
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2010-08-24 04:02:50 +00:00
|
|
|
if ob.vertex_groups.active:
|
2017-10-19 15:10:41 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator_menu_enum("object.vertex_group_set_active", "group", text="Set Active Group")
|
2012-01-14 06:30:27 +00:00
|
|
|
layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
|
2009-11-16 13:59:27 +00:00
|
|
|
|
2017-02-09 16:18:33 -05:00
|
|
|
|
2024-04-30 14:03:31 +02:00
|
|
|
class VIEW3D_MT_greasepencil_vertex_group(Menu):
|
|
|
|
|
bl_label = "Vertex Groups"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'EXEC_AREA'
|
|
|
|
|
|
|
|
|
|
layout.operator("object.vertex_group_add", text="Add New Group")
|
|
|
|
|
|
2019-08-09 17:36:27 +02:00
|
|
|
|
2020-03-20 20:04:11 -04:00
|
|
|
class VIEW3D_MT_paint_weight_lock(Menu):
|
|
|
|
|
bl_label = "Vertex Group Locks"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'ALL'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", text="Lock Selected")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'SELECTED'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", text="Lock Unselected")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'UNSELECTED'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", text="Lock Only Selected")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'INVERT_UNSELECTED'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", text="Lock Only Unselected")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'INVERT_UNSELECTED'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'ALL'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", text="Unlock Selected")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'SELECTED'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", text="Unlock Unselected")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'UNSELECTED'
|
2022-11-06 02:27:52 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("object.vertex_group_lock", icon='ARROW_LEFTRIGHT', text="Invert Locks")
|
|
|
|
|
props.action, props.mask = 'INVERT', 'ALL'
|
2020-03-20 20:04:11 -04:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_paint_weight(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Weights"
|
2010-01-26 11:11:53 +00:00
|
|
|
|
2018-04-24 16:54:38 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def draw_generic(layout, is_editmode=False):
|
2010-01-26 11:11:53 +00:00
|
|
|
|
2018-04-24 16:54:38 +02:00
|
|
|
if not is_editmode:
|
2010-09-18 16:17:32 +00:00
|
|
|
|
2020-10-07 08:04:53 -05:00
|
|
|
layout.operator("paint.weight_from_bones", text="Assign Automatic from Bones").type = 'AUTOMATIC'
|
|
|
|
|
layout.operator("paint.weight_from_bones", text="Assign from Bone Envelopes").type = 'ENVELOPES'
|
2010-01-26 11:11:53 +00:00
|
|
|
|
2018-04-24 16:54:38 +02:00
|
|
|
layout.separator()
|
2010-01-26 11:11:53 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("object.vertex_group_normalize_all", text="Normalize All")
|
|
|
|
|
layout.operator("object.vertex_group_normalize", text="Normalize")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-06-30 11:21:04 +02:00
|
|
|
# Using default context for 'flipping along axis', to differentiate from 'symmetrizing' (i.e.
|
|
|
|
|
# 'mirrored copy').
|
|
|
|
|
# See https://projects.blender.org/blender/blender/issues/43295#issuecomment-1400465
|
2025-06-28 16:34:42 +02:00
|
|
|
layout.operator("object.vertex_group_mirror", text="Mirror", text_ctxt=i18n_contexts.default)
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("object.vertex_group_invert", text="Invert")
|
|
|
|
|
layout.operator("object.vertex_group_clean", text="Clean")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-11-17 14:54:42 +11:00
|
|
|
layout.operator("object.vertex_group_quantize", text="Quantize")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("object.vertex_group_levels", text="Levels")
|
2015-06-25 16:10:18 +10:00
|
|
|
layout.operator("object.vertex_group_smooth", text="Smooth")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2018-04-24 16:54:38 +02:00
|
|
|
if not is_editmode:
|
|
|
|
|
props = layout.operator("object.data_transfer", text="Transfer Weights")
|
|
|
|
|
props.use_reverse_transfer = True
|
|
|
|
|
props.data_type = 'VGROUP_WEIGHTS'
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2012-10-09 10:56:35 +00:00
|
|
|
layout.operator("object.vertex_group_limit_total", text="Limit Total")
|
2011-04-04 22:42:43 +00:00
|
|
|
|
2018-04-24 16:54:38 +02:00
|
|
|
if not is_editmode:
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-07-29 16:32:09 +10:00
|
|
|
# Primarily for shortcut discoverability.
|
2018-04-24 16:54:38 +02:00
|
|
|
layout.operator("paint.weight_set")
|
2023-07-28 16:27:24 +10:00
|
|
|
layout.operator("paint.weight_sample", text="Sample Weight")
|
|
|
|
|
layout.operator("paint.weight_sample_group", text="Sample Group")
|
|
|
|
|
|
2023-07-29 16:32:09 +10:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Primarily for shortcut discoverability.
|
|
|
|
|
layout.operator("paint.weight_gradient", text="Gradient (Linear)").type = 'LINEAR'
|
|
|
|
|
layout.operator("paint.weight_gradient", text="Gradient (Radial)").type = 'RADIAL'
|
|
|
|
|
|
2023-07-28 16:27:24 +10:00
|
|
|
layout.separator()
|
2018-04-24 16:54:38 +02:00
|
|
|
|
2020-03-20 20:04:11 -04:00
|
|
|
layout.menu("VIEW3D_MT_paint_weight_lock", text="Locks")
|
|
|
|
|
|
2024-04-23 15:48:27 +02:00
|
|
|
def draw(self, _context):
|
|
|
|
|
self.draw_generic(self.layout, is_editmode=False)
|
2009-11-16 13:59:27 +00:00
|
|
|
|
2017-02-09 16:18:33 -05:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_sculpt(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Sculpt"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2023-10-25 16:17:44 +11:00
|
|
|
def draw(self, context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-06-03 16:36:32 +02:00
|
|
|
layout.menu("VIEW3D_MT_sculpt_transform", text="Transform")
|
2024-04-29 14:04:16 +02:00
|
|
|
|
2023-03-08 01:18:21 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.face_set_change_visibility", text="Toggle Visibility")
|
|
|
|
|
props.mode = 'TOGGLE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.face_set_change_visibility", text="Hide Active Face Set")
|
|
|
|
|
props.mode = 'HIDE_ACTIVE'
|
|
|
|
|
|
2024-03-06 05:25:43 +01:00
|
|
|
props = layout.operator("paint.hide_show_all", text="Show All")
|
2023-03-08 01:18:21 +01:00
|
|
|
props.action = 'SHOW'
|
|
|
|
|
|
2023-12-06 11:19:25 -05:00
|
|
|
layout.operator("paint.visibility_invert", text="Invert Visible")
|
2019-10-05 22:17:22 +02:00
|
|
|
|
2024-03-06 05:25:43 +01:00
|
|
|
props = layout.operator("paint.hide_show_masked", text="Hide Masked")
|
2019-09-19 14:40:33 +02:00
|
|
|
props.action = 'HIDE'
|
2012-05-10 20:36:13 +00:00
|
|
|
|
2024-05-28 17:12:45 +02:00
|
|
|
props = layout.operator("paint.visibility_filter", text="Grow Visibility")
|
2025-01-21 23:50:17 +11:00
|
|
|
props.action = 'GROW'
|
2024-05-28 17:12:45 +02:00
|
|
|
|
|
|
|
|
props = layout.operator("paint.visibility_filter", text="Shrink Visibility")
|
2025-01-21 23:50:17 +11:00
|
|
|
props.action = 'SHRINK'
|
2024-05-28 17:12:45 +02:00
|
|
|
|
2024-06-03 16:36:32 +02:00
|
|
|
layout.menu("VIEW3D_MT_sculpt_showhide", text="Show/Hide")
|
2023-03-08 01:18:21 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Fair Positions
|
|
|
|
|
props = layout.operator("sculpt.face_set_edit", text="Fair Positions")
|
|
|
|
|
props.mode = 'FAIR_POSITIONS'
|
|
|
|
|
|
|
|
|
|
# Fair Tangency
|
|
|
|
|
props = layout.operator("sculpt.face_set_edit", text="Fair Tangency")
|
|
|
|
|
props.mode = 'FAIR_TANGENCY'
|
|
|
|
|
|
2024-06-03 16:36:32 +02:00
|
|
|
# Project
|
|
|
|
|
layout.operator("sculpt.project_line_gesture", text="Line Project")
|
|
|
|
|
|
|
|
|
|
# Trim/Add
|
|
|
|
|
layout.menu("VIEW3D_MT_sculpt_trim", text="Trim/Add")
|
|
|
|
|
|
2023-03-08 01:18:21 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
sculpt_filters_types = [
|
2025-01-05 13:10:17 +01:00
|
|
|
('SMOOTH', iface_("Smooth", i18n_contexts.operator_default)),
|
2023-10-04 02:53:31 +02:00
|
|
|
('SURFACE_SMOOTH', iface_("Surface Smooth")),
|
|
|
|
|
('INFLATE', iface_("Inflate")),
|
|
|
|
|
('RELAX', iface_("Relax Topology")),
|
|
|
|
|
('RELAX_FACE_SETS', iface_("Relax Face Sets")),
|
|
|
|
|
('SHARPEN', iface_("Sharpen")),
|
|
|
|
|
('ENHANCE_DETAILS', iface_("Enhance Details")),
|
2024-10-16 19:01:24 +02:00
|
|
|
('ERASE_DISPLACEMENT', iface_("Erase Multires Displacement")),
|
2024-06-06 11:26:28 +10:00
|
|
|
('RANDOM', iface_("Randomize")),
|
2023-03-08 01:18:21 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for filter_type, ui_name in sculpt_filters_types:
|
2023-10-04 02:53:31 +02:00
|
|
|
props = layout.operator("sculpt.mesh_filter", text=ui_name, translate=False)
|
2023-03-08 01:18:21 +01:00
|
|
|
props.type = filter_type
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-07-28 16:27:24 +10:00
|
|
|
layout.operator("sculpt.sample_color", text="Sample Color")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-10-05 22:17:22 +02:00
|
|
|
layout.menu("VIEW3D_MT_sculpt_set_pivot", text="Set Pivot")
|
|
|
|
|
|
2020-02-02 20:14:33 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-03-08 01:18:21 +01:00
|
|
|
# Rebuild BVH
|
2020-02-02 20:14:33 +01:00
|
|
|
layout.operator("sculpt.optimize")
|
|
|
|
|
|
2023-10-25 16:17:44 +11:00
|
|
|
layout.operator(
|
2024-06-03 16:36:32 +02:00
|
|
|
"sculpt.dynamic_topology_toggle", text="Dynamic Topology",
|
2023-10-25 16:17:44 +11:00
|
|
|
icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT',
|
|
|
|
|
)
|
|
|
|
|
|
2021-04-13 20:31:28 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2021-10-18 17:07:24 +11:00
|
|
|
layout.operator("object.transfer_mode", text="Transfer Sculpt Mode")
|
2021-04-13 20:31:28 +02:00
|
|
|
|
2019-10-05 22:17:22 +02:00
|
|
|
|
2024-06-03 16:36:32 +02:00
|
|
|
class VIEW3D_MT_sculpt_transform(Menu):
|
|
|
|
|
bl_label = "Transform"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("transform.translate")
|
|
|
|
|
layout.operator("transform.rotate")
|
|
|
|
|
layout.operator("transform.resize", text="Scale")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
props = layout.operator("sculpt.mesh_filter", text="To Sphere")
|
|
|
|
|
props.type = 'SPHERE'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_sculpt_showhide(Menu):
|
|
|
|
|
bl_label = "Show/Hide"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show", text="Box Hide")
|
|
|
|
|
props.action = 'HIDE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show_lasso_gesture", text="Lasso Hide")
|
|
|
|
|
props.action = 'HIDE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show_line_gesture", text="Line Hide")
|
|
|
|
|
props.action = 'HIDE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show_polyline_gesture", text="Polyline Hide")
|
|
|
|
|
props.action = 'HIDE'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show", text="Box Show")
|
|
|
|
|
props.action = 'SHOW'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show_lasso_gesture", text="Lasso Show")
|
|
|
|
|
props.action = 'SHOW'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show_line_gesture", text="Line Show")
|
|
|
|
|
props.action = 'SHOW'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("paint.hide_show_polyline_gesture", text="Polyline Show")
|
|
|
|
|
props.action = 'SHOW'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_sculpt_trim(Menu):
|
|
|
|
|
bl_label = "Trim/Add"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_box_gesture", text="Box Trim")
|
|
|
|
|
props.trim_mode = 'DIFFERENCE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_lasso_gesture", text="Lasso Trim")
|
|
|
|
|
props.trim_mode = 'DIFFERENCE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_line_gesture", text="Line Trim")
|
|
|
|
|
props.trim_mode = 'DIFFERENCE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_polyline_gesture", text="Polyline Trim")
|
|
|
|
|
props.trim_mode = 'DIFFERENCE'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_box_gesture", text="Box Add")
|
|
|
|
|
props.trim_mode = 'JOIN'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_lasso_gesture", text="Lasso Add")
|
|
|
|
|
props.trim_mode = 'JOIN'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.trim_polyline_gesture", text="Polyline Add")
|
|
|
|
|
props.trim_mode = 'JOIN'
|
|
|
|
|
|
|
|
|
|
|
2022-04-07 12:49:13 +02:00
|
|
|
class VIEW3D_MT_sculpt_curves(Menu):
|
|
|
|
|
bl_label = "Curves"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2022-05-06 12:15:31 +02:00
|
|
|
layout.operator("curves.snap_curves_to_surface", text="Snap to Deformed Surface").attach_mode = 'DEFORM'
|
|
|
|
|
layout.operator("curves.snap_curves_to_surface", text="Snap to Nearest Surface").attach_mode = 'NEAREST'
|
|
|
|
|
layout.separator()
|
2022-04-08 10:58:33 +02:00
|
|
|
layout.operator("curves.convert_to_particle_system", text="Convert to Particle System")
|
2022-04-07 12:49:13 +02:00
|
|
|
|
2023-06-29 13:57:54 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Curves")
|
|
|
|
|
|
2022-04-07 12:49:13 +02:00
|
|
|
|
2019-10-05 22:17:22 +02:00
|
|
|
class VIEW3D_MT_mask(Menu):
|
|
|
|
|
bl_label = "Mask"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2013-05-09 13:05:36 +00:00
|
|
|
props = layout.operator("paint.mask_flood_fill", text="Fill Mask")
|
|
|
|
|
props.mode = 'VALUE'
|
|
|
|
|
props.value = 1
|
2012-05-10 20:36:13 +00:00
|
|
|
|
2013-05-09 13:05:36 +00:00
|
|
|
props = layout.operator("paint.mask_flood_fill", text="Clear Mask")
|
|
|
|
|
props.mode = 'VALUE'
|
|
|
|
|
props.value = 0
|
2013-11-20 03:38:18 +11:00
|
|
|
|
2024-06-03 16:36:32 +02:00
|
|
|
props = layout.operator("paint.mask_flood_fill", text="Invert Mask")
|
|
|
|
|
props.mode = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-10-21 17:40:25 +02:00
|
|
|
props = layout.operator("paint.mask_box_gesture", text="Box Mask")
|
|
|
|
|
props.mode = 'VALUE'
|
|
|
|
|
props.value = 0
|
|
|
|
|
|
2013-10-30 00:54:41 +00:00
|
|
|
props = layout.operator("paint.mask_lasso_gesture", text="Lasso Mask")
|
2024-06-03 16:36:32 +02:00
|
|
|
props = layout.operator("paint.mask_line_gesture", text="Line Mask")
|
2024-05-28 18:33:45 +02:00
|
|
|
props = layout.operator("paint.mask_polyline_gesture", text="Polyline Mask")
|
2012-03-24 07:36:32 +00:00
|
|
|
|
2019-09-09 16:20:40 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
props = layout.operator("sculpt.mask_filter", text="Smooth Mask")
|
2019-09-09 16:20:40 +02:00
|
|
|
props.filter_type = 'SMOOTH'
|
|
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
props = layout.operator("sculpt.mask_filter", text="Sharpen Mask")
|
2019-09-09 16:20:40 +02:00
|
|
|
props.filter_type = 'SHARPEN'
|
|
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
props = layout.operator("sculpt.mask_filter", text="Grow Mask")
|
2019-09-09 16:20:40 +02:00
|
|
|
props.filter_type = 'GROW'
|
|
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
props = layout.operator("sculpt.mask_filter", text="Shrink Mask")
|
2019-09-09 16:20:40 +02:00
|
|
|
props.filter_type = 'SHRINK'
|
|
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
props = layout.operator("sculpt.mask_filter", text="Increase Contrast")
|
2019-09-09 16:20:40 +02:00
|
|
|
props.filter_type = 'CONTRAST_INCREASE'
|
2019-09-10 06:11:52 +10:00
|
|
|
props.auto_iteration_count = False
|
2019-09-09 16:20:40 +02:00
|
|
|
|
2023-01-06 13:52:57 +11:00
|
|
|
props = layout.operator("sculpt.mask_filter", text="Decrease Contrast")
|
2019-09-09 16:20:40 +02:00
|
|
|
props.filter_type = 'CONTRAST_DECREASE'
|
2019-09-10 06:11:52 +10:00
|
|
|
props.auto_iteration_count = False
|
2019-09-09 16:20:40 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2021-04-11 18:16:32 +02:00
|
|
|
props = layout.operator("sculpt.expand", text="Expand Mask by Topology")
|
|
|
|
|
props.target = 'MASK'
|
|
|
|
|
props.falloff_type = 'GEODESIC'
|
2023-04-16 15:04:58 -07:00
|
|
|
props.invert = False
|
|
|
|
|
props.use_auto_mask = False
|
|
|
|
|
props.use_mask_preserve = True
|
2019-09-10 15:11:33 +02:00
|
|
|
|
2021-04-11 18:16:32 +02:00
|
|
|
props = layout.operator("sculpt.expand", text="Expand Mask by Normals")
|
|
|
|
|
props.target = 'MASK'
|
|
|
|
|
props.falloff_type = 'NORMALS'
|
2019-09-10 15:11:33 +02:00
|
|
|
props.invert = False
|
2023-04-16 15:04:58 -07:00
|
|
|
props.use_mask_preserve = True
|
2019-09-10 15:11:33 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-05-07 10:30:58 +02:00
|
|
|
props = layout.operator("sculpt.paint_mask_extract", text="Mask Extract")
|
2019-09-10 15:18:51 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-05-07 10:30:58 +02:00
|
|
|
props = layout.operator("sculpt.paint_mask_slice", text="Mask Slice")
|
2019-11-21 18:26:16 +01:00
|
|
|
props.fill_holes = False
|
|
|
|
|
props.new_object = False
|
2025-05-07 10:30:58 +02:00
|
|
|
props = layout.operator("sculpt.paint_mask_slice", text="Mask Slice and Fill Holes")
|
2019-11-21 18:26:16 +01:00
|
|
|
props.new_object = False
|
2025-05-07 10:30:58 +02:00
|
|
|
props = layout.operator("sculpt.paint_mask_slice", text="Mask Slice to New Object")
|
2019-11-21 18:26:16 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-06-03 16:36:32 +02:00
|
|
|
props = layout.operator("sculpt.mask_from_cavity", text="Mask from Cavity")
|
2023-05-15 20:53:17 +10:00
|
|
|
props.settings_source = 'OPERATOR'
|
2019-09-09 16:20:40 +02:00
|
|
|
|
2024-09-24 18:02:30 +02:00
|
|
|
props = layout.operator("sculpt.mask_from_boundary", text="Mask from Mesh Boundary")
|
|
|
|
|
props.settings_source = 'OPERATOR'
|
|
|
|
|
props.boundary_mode = 'MESH'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.mask_from_boundary", text="Mask from Face Sets Boundary")
|
|
|
|
|
props.settings_source = 'OPERATOR'
|
|
|
|
|
props.boundary_mode = 'FACE_SETS'
|
|
|
|
|
|
2025-03-04 17:33:45 +01:00
|
|
|
props = layout.operator("sculpt.mask_by_color", text="Mask by Color")
|
|
|
|
|
|
2021-03-12 21:35:56 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_random_mask", text="Random Mask")
|
|
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
2021-03-12 21:35:56 +01:00
|
|
|
|
2023-08-05 02:57:52 +02:00
|
|
|
|
2020-03-05 14:53:23 +01:00
|
|
|
class VIEW3D_MT_face_sets(Menu):
|
|
|
|
|
bl_label = "Face Sets"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_create", text="Face Set from Masked")
|
|
|
|
|
props.mode = 'MASKED'
|
2020-03-05 14:53:23 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_create", text="Face Set from Visible")
|
|
|
|
|
props.mode = 'VISIBLE'
|
2020-03-29 17:34:40 -04:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_create", text="Face Set from Edit Mode Selection")
|
|
|
|
|
props.mode = 'SELECTION'
|
2020-03-05 14:53:23 +01:00
|
|
|
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
layout.separator()
|
2020-03-29 17:34:40 -04:00
|
|
|
|
2021-03-17 02:38:13 +01:00
|
|
|
layout.menu("VIEW3D_MT_face_sets_init", text="Initialize Face Sets")
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2020-03-05 14:53:23 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_set_edit", text="Grow Face Set")
|
|
|
|
|
props.mode = 'GROW'
|
2020-06-04 00:23:29 +02:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_set_edit", text="Shrink Face Set")
|
|
|
|
|
props.mode = 'SHRINK'
|
2020-06-04 00:23:29 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2021-04-11 18:16:32 +02:00
|
|
|
props = layout.operator("sculpt.expand", text="Expand Face Set by Topology")
|
|
|
|
|
props.target = 'FACE_SETS'
|
|
|
|
|
props.falloff_type = 'GEODESIC'
|
|
|
|
|
props.invert = False
|
2023-04-16 15:04:58 -07:00
|
|
|
props.use_mask_preserve = False
|
2021-04-11 18:16:32 +02:00
|
|
|
props.use_modify_active = False
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.expand", text="Expand Active Face Set")
|
|
|
|
|
props.target = 'FACE_SETS'
|
|
|
|
|
props.falloff_type = 'BOUNDARY_FACE_SET'
|
|
|
|
|
props.invert = False
|
2023-04-16 15:04:58 -07:00
|
|
|
props.use_mask_preserve = False
|
2021-04-11 18:16:32 +02:00
|
|
|
props.use_modify_active = True
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-05-07 10:30:58 +02:00
|
|
|
props = layout.operator("sculpt.face_set_extract", text="Extract Face Set")
|
2020-09-03 17:25:30 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_randomize_colors", text="Randomize Colors")
|
2020-03-05 14:53:23 +01:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2019-09-26 15:58:33 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_MT_sculpt_set_pivot(Menu):
|
|
|
|
|
bl_label = "Sculpt Set Pivot"
|
|
|
|
|
|
2019-10-23 02:34:30 +11:00
|
|
|
def draw(self, _context):
|
2019-09-26 15:58:33 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.set_pivot_position", text="Pivot to Origin")
|
|
|
|
|
props.mode = 'ORIGIN'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.set_pivot_position", text="Pivot to Unmasked")
|
|
|
|
|
props.mode = 'UNMASKED'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.set_pivot_position", text="Pivot to Mask Border")
|
|
|
|
|
props.mode = 'BORDER'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.set_pivot_position", text="Pivot to Active Vertex")
|
|
|
|
|
props.mode = 'ACTIVE'
|
|
|
|
|
|
|
|
|
|
props = layout.operator("sculpt.set_pivot_position", text="Pivot to Surface Under Cursor")
|
|
|
|
|
props.mode = 'SURFACE'
|
|
|
|
|
|
2020-10-02 10:15:51 +10:00
|
|
|
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
class VIEW3D_MT_face_sets_init(Menu):
|
|
|
|
|
bl_label = "Face Sets Init"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Loose Parts")
|
|
|
|
|
props.mode = 'LOOSE_PARTS'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Face Set Boundaries")
|
|
|
|
|
props.mode = 'FACE_SET_BOUNDARIES'
|
2021-03-03 20:01:54 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Materials")
|
|
|
|
|
props.mode = 'MATERIALS'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Normals")
|
|
|
|
|
props.mode = 'NORMALS'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By UV Seams")
|
|
|
|
|
props.mode = 'UV_SEAMS'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Edge Creases")
|
|
|
|
|
props.mode = 'CREASES'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Edge Bevel Weight")
|
|
|
|
|
props.mode = 'BEVEL_WEIGHT'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.face_sets_init", text="By Sharp Edges")
|
|
|
|
|
props.mode = 'SHARP_EDGES'
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
|
|
|
|
|
|
2021-03-12 21:35:56 +01:00
|
|
|
class VIEW3D_MT_random_mask(Menu):
|
|
|
|
|
bl_label = "Random Mask"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.mask_init", text="Per Vertex")
|
|
|
|
|
props.mode = 'RANDOM_PER_VERTEX'
|
2021-03-12 21:35:56 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.mask_init", text="Per Face Set")
|
|
|
|
|
props.mode = 'RANDOM_PER_FACE_SET'
|
2021-03-12 21:35:56 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("sculpt.mask_init", text="Per Loose Part")
|
|
|
|
|
props.mode = 'RANDOM_PER_LOOSE_PART'
|
2021-03-12 21:35:56 +01:00
|
|
|
|
2021-07-06 12:05:27 +10:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
class VIEW3D_MT_particle(Menu):
|
|
|
|
|
bl_label = "Particle"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-06-13 14:11:59 +02:00
|
|
|
tool_settings = context.tool_settings
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2018-06-13 14:11:59 +02:00
|
|
|
particle_edit = tool_settings.particle_edit
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2017-10-19 15:38:34 +11:00
|
|
|
layout.operator("particle.mirror")
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
layout.operator("particle.remove_doubles")
|
2017-10-19 15:38:34 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
if particle_edit.select_mode == 'POINT':
|
|
|
|
|
layout.operator("particle.subdivide")
|
|
|
|
|
|
2016-04-26 16:05:52 +02:00
|
|
|
layout.operator("particle.unify_length")
|
2016-12-28 17:30:58 +01:00
|
|
|
layout.operator("particle.rekey")
|
|
|
|
|
layout.operator("particle.weight_set")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_particle_showhide")
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.delete")
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_MT_particle_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Particle"
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-06-13 14:11:59 +02:00
|
|
|
tool_settings = context.tool_settings
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2018-06-13 14:11:59 +02:00
|
|
|
particle_edit = tool_settings.particle_edit
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
layout.operator("particle.rekey")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
layout.operator("particle.delete")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
layout.operator("particle.remove_doubles")
|
2016-04-26 16:05:52 +02:00
|
|
|
layout.operator("particle.unify_length")
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
if particle_edit.select_mode == 'POINT':
|
|
|
|
|
layout.operator("particle.subdivide")
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.weight_set")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.mirror")
|
|
|
|
|
|
|
|
|
|
if particle_edit.select_mode == 'POINT':
|
|
|
|
|
layout.separator()
|
2018-07-03 15:44:56 +02:00
|
|
|
|
|
|
|
|
layout.operator("particle.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("particle.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("particle.select_all", text="Invert").action = 'INVERT'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
layout.operator("particle.select_roots")
|
|
|
|
|
layout.operator("particle.select_tips")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.select_random")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.select_more")
|
|
|
|
|
layout.operator("particle.select_less")
|
|
|
|
|
|
2020-02-12 17:08:35 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("particle.select_linked", text="Select Linked")
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2020-10-02 10:10:01 +10:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
|
|
|
|
|
_operator_name = "particle"
|
|
|
|
|
|
2017-02-09 16:18:33 -05:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Pose"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform_armature")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_pose_transform")
|
2011-03-27 05:23:14 +00:00
|
|
|
layout.menu("VIEW3D_MT_pose_apply")
|
|
|
|
|
|
2011-03-24 03:02:34 +00:00
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-03-24 03:23:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_object_animation")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-03-24 03:02:34 +00:00
|
|
|
layout.menu("VIEW3D_MT_pose_slide")
|
|
|
|
|
layout.menu("VIEW3D_MT_pose_propagate")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-11-23 13:55:33 +11:00
|
|
|
layout.operator("pose.copy", icon='COPYDOWN')
|
|
|
|
|
layout.operator("pose.paste", icon='PASTEDOWN').flipped = False
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("pose.paste", icon='PASTEFLIPDOWN', text="Paste Pose Flipped").flipped = True
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_pose_motion")
|
Anim: replace Bone Groups & Armature Layers with Bone Collections
Armature layers (the 32 little dots) and bone groups are replaced with
Bone Collections:
- Bone collections are stored on the armature, and have a name that is
unique within that armature.
- An armature can have an arbitrary number of bone collections (instead
of the fixed 32 layers).
- Bones can be assigned to zero or more bone collections.
- Bone collections have a visibility setting, just like objects in scene
collections.
- When a bone is in at least one collection, and all its collections in
are hidden, the bone is hidden. In other cases (in any visible
collection, or in no collection at all), the bone visibility is
determined by its own 'hidden' flag.
- For now, bone collections cannot be nested; they are a flat list just
like bone groups were. Nestability of bone collections is intended to
be implemented in a later 4.x release.
- Since bone collections are defined on the armature, they can be used
from both pose mode and edit mode.
Versioning converts bone groups and armature layers to new bone
collections. Layers that do not contain any bones are skipped. The old
data structures remain in DNA and are unaltered, for limited forward
compatibility. That way at least a save with Blender 4.0 will not
immediately erase the bone group and armature layers and their bone
assignments.
Shortcuts:
- M/Shift+M in pose/edit mode: move to collection (M) and add to
collection (shift+M). This works similar to the M/Shift+M menus for
objects & scene collections.
- Ctrl+G in pose mode shows a port of the old 'bone groups' menu. This
is likely to be removed in the near future, as the functionality
overlaps with the M/Shift+M menus.
This is the first commit of a series; the bone collections feature will
be improved before the Blender 4.0 release. See #108941 for more info.
Pull request: https://projects.blender.org/blender/blender/pulls/109976
2023-08-22 12:15:54 +02:00
|
|
|
layout.menu("VIEW3D_MT_bone_collections")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2010-08-25 02:56:37 +00:00
|
|
|
layout.menu("VIEW3D_MT_object_parent")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_pose_ik")
|
|
|
|
|
layout.menu("VIEW3D_MT_pose_constraints")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2020-04-06 21:45:41 -04:00
|
|
|
layout.menu("VIEW3D_MT_pose_names")
|
2010-01-25 10:16:36 +00:00
|
|
|
layout.operator("pose.quaternions_flip")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_pose_showhide")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings")
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2025-02-04 11:29:05 +01:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("POSELIB.create_pose_asset")
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_transform(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Clear Transform"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("pose.transforms_clear", text="All")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-08-15 13:24:53 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
I18n: extract and disambiguate a few messages
Extract
- Add to Quick Favorites tooltip.
- "Mask", the name of a newly created mask (DATA_).
- "New" in the context of the new mask ID button.
- A few strings using BLI_STR_UTF8_ defines were not extracted.
Take the special characters out of the translation macros.
- "External" menu items from the filebrowser's Files context
menu (right-click on a file). These items were already extracted,
but not translated.
Improve
- Separate formatted error message "%s is not compatible with
["the specified", "any"] 'refresh' options" into two messages.
Disambiguate
- Use Action context for new F-modifiers' names. This is already used
for the "type" operator prop.
- Translate ImportHelper's default confirmation text using the
Operator context, as it uses the operator name which is extracted
with this context.
- "Scale" can be a noun, the scale of something, or a verb, to scale
something. The latter mostly uses the Operator context, so apply
this context to verbs, and the default contexts to nouns.
- "Scale Influence" can mean "Influence on Scale" (tracking
stabilization) and "to Scale the Influence" (dynamic paint canvas).
- "Object Line Art" as type of Line Art to add, as opposed to the
active object's Line Art settings.
- Float to Integer node: use NodeTree context for the node label, as
this is already extracted and used for the enum.
Do not translate
- Sequencer labels containing only a string formatting field.
Some issues reported by Gabriel Gazzán and Ye Gui.
Pull Request: https://projects.blender.org/blender/blender/pulls/122283
2024-05-27 19:33:35 +02:00
|
|
|
layout.operator("pose.loc_clear", text="Location", text_ctxt=i18n_contexts.default)
|
|
|
|
|
layout.operator("pose.rot_clear", text="Rotation", text_ctxt=i18n_contexts.default)
|
|
|
|
|
layout.operator("pose.scale_clear", text="Scale", text_ctxt=i18n_contexts.default)
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-08-15 13:24:53 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2017-09-02 15:42:29 +10:00
|
|
|
layout.operator("pose.user_transforms_clear", text="Reset Unkeyed")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_slide(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "In-Betweens"
|
2011-03-24 03:02:34 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2011-03-24 03:02:34 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-07-20 09:27:06 +02:00
|
|
|
layout.operator("pose.blend_with_rest")
|
2011-03-24 03:02:34 +00:00
|
|
|
layout.operator("pose.push")
|
|
|
|
|
layout.operator("pose.relax")
|
|
|
|
|
layout.operator("pose.breakdown")
|
2021-10-04 11:08:33 +02:00
|
|
|
layout.operator("pose.blend_to_neighbor")
|
2011-03-24 03:02:34 +00:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_propagate(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Propagate"
|
2011-03-24 03:02:34 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2011-03-24 03:02:34 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("pose.propagate", text="To Next Keyframe").mode = 'NEXT_KEY'
|
|
|
|
|
layout.operator("pose.propagate", text="To Last Keyframe (Make Cyclic)").mode = 'LAST_KEY'
|
2011-03-24 03:02:34 +00:00
|
|
|
|
2011-03-31 01:37:42 +00:00
|
|
|
layout.separator()
|
|
|
|
|
|
2015-04-02 23:30:30 +13:00
|
|
|
layout.operator("pose.propagate", text="On Selected Keyframes").mode = 'SELECTED_KEYS'
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS'
|
2011-03-31 01:37:42 +00:00
|
|
|
|
2011-03-24 03:02:34 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_motion(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Motion Paths"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("pose.paths_calculate", text="Calculate")
|
|
|
|
|
layout.operator("pose.paths_clear", text="Clear")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
Anim: replace Bone Groups & Armature Layers with Bone Collections
Armature layers (the 32 little dots) and bone groups are replaced with
Bone Collections:
- Bone collections are stored on the armature, and have a name that is
unique within that armature.
- An armature can have an arbitrary number of bone collections (instead
of the fixed 32 layers).
- Bones can be assigned to zero or more bone collections.
- Bone collections have a visibility setting, just like objects in scene
collections.
- When a bone is in at least one collection, and all its collections in
are hidden, the bone is hidden. In other cases (in any visible
collection, or in no collection at all), the bone visibility is
determined by its own 'hidden' flag.
- For now, bone collections cannot be nested; they are a flat list just
like bone groups were. Nestability of bone collections is intended to
be implemented in a later 4.x release.
- Since bone collections are defined on the armature, they can be used
from both pose mode and edit mode.
Versioning converts bone groups and armature layers to new bone
collections. Layers that do not contain any bones are skipped. The old
data structures remain in DNA and are unaltered, for limited forward
compatibility. That way at least a save with Blender 4.0 will not
immediately erase the bone group and armature layers and their bone
assignments.
Shortcuts:
- M/Shift+M in pose/edit mode: move to collection (M) and add to
collection (shift+M). This works similar to the M/Shift+M menus for
objects & scene collections.
- Ctrl+G in pose mode shows a port of the old 'bone groups' menu. This
is likely to be removed in the near future, as the functionality
overlaps with the M/Shift+M menus.
This is the first commit of a series; the bone collections feature will
be improved before the Blender 4.0 release. See #108941 for more info.
Pull request: https://projects.blender.org/blender/blender/pulls/109976
2023-08-22 12:15:54 +02:00
|
|
|
class VIEW3D_MT_bone_collections(Menu):
|
|
|
|
|
bl_label = "Bone Collections"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
|
|
|
|
if not (ob and ob.type == 'ARMATURE'):
|
2023-09-18 14:21:04 +02:00
|
|
|
return False
|
2024-05-16 14:53:09 +02:00
|
|
|
if not ob.data.is_editable:
|
2023-09-18 14:21:04 +02:00
|
|
|
return False
|
|
|
|
|
return True
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2013-01-15 23:15:32 +00:00
|
|
|
|
2023-12-28 16:10:02 +01:00
|
|
|
layout.operator("armature.move_to_collection")
|
|
|
|
|
layout.operator("armature.assign_to_collection")
|
Anim: replace Bone Groups & Armature Layers with Bone Collections
Armature layers (the 32 little dots) and bone groups are replaced with
Bone Collections:
- Bone collections are stored on the armature, and have a name that is
unique within that armature.
- An armature can have an arbitrary number of bone collections (instead
of the fixed 32 layers).
- Bones can be assigned to zero or more bone collections.
- Bone collections have a visibility setting, just like objects in scene
collections.
- When a bone is in at least one collection, and all its collections in
are hidden, the bone is hidden. In other cases (in any visible
collection, or in no collection at all), the bone visibility is
determined by its own 'hidden' flag.
- For now, bone collections cannot be nested; they are a flat list just
like bone groups were. Nestability of bone collections is intended to
be implemented in a later 4.x release.
- Since bone collections are defined on the armature, they can be used
from both pose mode and edit mode.
Versioning converts bone groups and armature layers to new bone
collections. Layers that do not contain any bones are skipped. The old
data structures remain in DNA and are unaltered, for limited forward
compatibility. That way at least a save with Blender 4.0 will not
immediately erase the bone group and armature layers and their bone
assignments.
Shortcuts:
- M/Shift+M in pose/edit mode: move to collection (M) and add to
collection (shift+M). This works similar to the M/Shift+M menus for
objects & scene collections.
- Ctrl+G in pose mode shows a port of the old 'bone groups' menu. This
is likely to be removed in the near future, as the functionality
overlaps with the M/Shift+M menus.
This is the first commit of a series; the bone collections feature will
be improved before the Blender 4.0 release. See #108941 for more info.
Pull request: https://projects.blender.org/blender/blender/pulls/109976
2023-08-22 12:15:54 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2023-12-28 16:10:02 +01:00
|
|
|
layout.operator("armature.collection_show_all")
|
2024-03-15 10:04:03 +11:00
|
|
|
props = layout.operator("armature.collection_create_and_assign", text="Assign to New Collection")
|
2023-09-18 14:21:04 +02:00
|
|
|
props.name = "New Collection"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_ik(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Inverse Kinematics"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("pose.ik_add")
|
|
|
|
|
layout.operator("pose.ik_clear")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_constraints(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Constraints"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2020-10-24 11:42:17 -07:00
|
|
|
layout.operator("pose.constraint_add_with_targets", text="Add (with Targets)...")
|
2010-05-27 11:56:31 +00:00
|
|
|
layout.operator("pose.constraints_copy")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("pose.constraints_clear")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2020-04-06 21:45:41 -04:00
|
|
|
class VIEW3D_MT_pose_names(Menu):
|
|
|
|
|
bl_label = "Names"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2020-10-24 11:42:17 -07:00
|
|
|
layout.operator("pose.autoside_names", text="Auto-Name Left/Right").axis = 'XAXIS'
|
|
|
|
|
layout.operator("pose.autoside_names", text="Auto-Name Front/Back").axis = 'YAXIS'
|
|
|
|
|
layout.operator("pose.autoside_names", text="Auto-Name Top/Bottom").axis = 'ZAXIS'
|
2020-04-06 21:45:41 -04:00
|
|
|
layout.operator("pose.flip_names")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_showhide(ShowHideMenu, Menu):
|
2009-10-31 19:31:45 +00:00
|
|
|
_operator_name = "pose"
|
2009-08-23 22:13:56 +00:00
|
|
|
|
2010-02-19 15:34:26 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_pose_apply(Menu):
|
2011-09-21 15:18:38 +00:00
|
|
|
bl_label = "Apply"
|
2010-02-19 15:34:26 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2010-02-19 15:34:26 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-08 17:10:15 +03:00
|
|
|
layout.operator("pose.armature_apply").selected = False
|
|
|
|
|
layout.operator("pose.armature_apply", text="Apply Selected as Rest Pose").selected = True
|
2010-02-19 15:34:26 +00:00
|
|
|
layout.operator("pose.visual_transform_apply")
|
|
|
|
|
|
2018-12-15 22:37:12 +03:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
props = layout.operator("object.assign_property_defaults")
|
|
|
|
|
props.process_bones = True
|
|
|
|
|
|
2010-02-19 15:34:26 +00:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_MT_pose_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Pose"
|
2012-05-06 12:13:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2012-05-06 12:13:45 +00:00
|
|
|
layout = self.layout
|
2013-04-07 01:38:03 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2023-11-21 15:38:01 +01:00
|
|
|
layout.operator("anim.keyframe_insert", text="Insert Keyframe")
|
2024-01-25 16:18:05 +01:00
|
|
|
layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe with Keying Set").always_prompt = True
|
2018-05-25 08:07:43 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-11-23 13:55:33 +11:00
|
|
|
layout.operator("pose.copy", icon='COPYDOWN')
|
|
|
|
|
layout.operator("pose.paste", icon='PASTEDOWN').flipped = False
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("pose.paste", icon='PASTEFLIPDOWN', text="Paste X-Flipped Pose").flipped = True
|
2013-04-07 01:38:03 +00:00
|
|
|
|
2013-04-06 10:52:52 +00:00
|
|
|
layout.separator()
|
2019-03-26 14:36:15 +01:00
|
|
|
|
|
|
|
|
props = layout.operator("wm.call_panel", text="Rename Active Bone...")
|
|
|
|
|
props.name = "TOPBAR_PT_name"
|
|
|
|
|
props.keep_open = False
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
2013-04-07 01:38:03 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("pose.push")
|
|
|
|
|
layout.operator("pose.relax")
|
|
|
|
|
layout.operator("pose.breakdown")
|
2021-10-04 11:08:33 +02:00
|
|
|
layout.operator("pose.blend_to_neighbor")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2022-03-14 11:15:09 +01:00
|
|
|
layout.operator("pose.paths_calculate", text="Calculate Motion Paths")
|
|
|
|
|
layout.operator("pose.paths_clear", text="Clear Motion Paths")
|
|
|
|
|
layout.operator("pose.paths_update", text="Update Armature Motion Paths")
|
|
|
|
|
layout.operator("object.paths_update_visible", text="Update All Motion Paths")
|
2012-05-06 12:13:45 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-25 08:07:43 +02:00
|
|
|
layout.operator("pose.hide").unselected = False
|
|
|
|
|
layout.operator("pose.reveal")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("pose.user_transforms_clear")
|
2012-05-06 12:13:45 +00:00
|
|
|
|
|
|
|
|
|
2011-06-27 07:51:52 +00:00
|
|
|
class BoneOptions:
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
options = [
|
|
|
|
|
"show_wire",
|
|
|
|
|
"use_deform",
|
|
|
|
|
"use_envelope_multiply",
|
|
|
|
|
"use_inherit_rotation",
|
|
|
|
|
]
|
|
|
|
|
|
2011-06-27 11:40:15 +00:00
|
|
|
if context.mode == 'EDIT_ARMATURE':
|
|
|
|
|
bone_props = bpy.types.EditBone.bl_rna.properties
|
2011-06-27 07:51:52 +00:00
|
|
|
data_path_iter = "selected_bones"
|
|
|
|
|
opt_suffix = ""
|
2011-06-27 11:40:15 +00:00
|
|
|
options.append("lock")
|
2011-10-17 06:58:07 +00:00
|
|
|
else: # pose-mode
|
2011-06-27 11:40:15 +00:00
|
|
|
bone_props = bpy.types.Bone.bl_rna.properties
|
|
|
|
|
data_path_iter = "selected_pose_bones"
|
|
|
|
|
opt_suffix = "bone."
|
2011-06-27 07:51:52 +00:00
|
|
|
|
|
|
|
|
for opt in options:
|
2025-01-14 12:46:40 +11:00
|
|
|
props = layout.operator(
|
|
|
|
|
"wm.context_collection_boolean_set",
|
|
|
|
|
text=bone_props[opt].name,
|
|
|
|
|
text_ctxt=i18n_contexts.default,
|
|
|
|
|
)
|
2011-06-27 07:51:52 +00:00
|
|
|
props.data_path_iter = data_path_iter
|
|
|
|
|
props.data_path_item = opt_suffix + opt
|
|
|
|
|
props.type = self.type
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_bone_options_toggle(Menu, BoneOptions):
|
2011-06-27 11:40:15 +00:00
|
|
|
bl_label = "Toggle Bone Options"
|
2011-06-27 07:51:52 +00:00
|
|
|
type = 'TOGGLE'
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_bone_options_enable(Menu, BoneOptions):
|
2011-06-27 11:40:15 +00:00
|
|
|
bl_label = "Enable Bone Options"
|
2011-06-27 07:51:52 +00:00
|
|
|
type = 'ENABLE'
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_bone_options_disable(Menu, BoneOptions):
|
2011-06-27 11:40:15 +00:00
|
|
|
bl_label = "Disable Bone Options"
|
2011-06-27 07:51:52 +00:00
|
|
|
type = 'DISABLE'
|
|
|
|
|
|
2017-02-09 16:18:33 -05:00
|
|
|
|
2009-08-23 22:13:56 +00:00
|
|
|
# ********** Edit Menus, suffix from ob.type **********
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Mesh"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
with_bullet = bpy.app.build_options.bullet
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform")
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.duplicate_move", text="Duplicate")
|
2013-06-01 05:26:37 +00:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_extrude")
|
2020-03-31 18:01:06 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_merge", text="Merge")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_split", text="Split")
|
2020-03-31 18:12:17 +11:00
|
|
|
layout.operator_menu_enum("mesh.separate", "type")
|
2020-03-31 18:01:06 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.bisect")
|
2018-12-06 16:52:49 +11:00
|
|
|
layout.operator("mesh.knife_project")
|
2025-08-01 18:55:36 +02:00
|
|
|
props = layout.operator("mesh.knife_tool")
|
|
|
|
|
props.use_occlude_geometry = True
|
|
|
|
|
props.only_selected = False
|
2017-10-19 15:10:41 +11:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
if with_bullet:
|
|
|
|
|
layout.operator("mesh.convex_hull")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2013-06-20 19:09:18 +00:00
|
|
|
layout.operator("mesh.symmetrize")
|
|
|
|
|
layout.operator("mesh.symmetry_snap")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_normals")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_shading")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_weights")
|
2023-02-15 04:34:53 +01:00
|
|
|
layout.operator("mesh.attribute_set")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_showhide")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_clean")
|
2018-07-17 11:59:24 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_delete")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_MT_edit_mesh_context_menu(Menu):
|
2018-12-18 07:54:32 +11:00
|
|
|
bl_label = ""
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
def count_selected_items_for_objects_in_mode():
|
|
|
|
|
selected_verts_len = 0
|
|
|
|
|
selected_edges_len = 0
|
|
|
|
|
selected_faces_len = 0
|
|
|
|
|
for ob in context.objects_in_mode_unique_data:
|
|
|
|
|
v, e, f = ob.data.count_selected_items()
|
|
|
|
|
selected_verts_len += v
|
|
|
|
|
selected_edges_len += e
|
|
|
|
|
selected_faces_len += f
|
|
|
|
|
return (selected_verts_len, selected_edges_len, selected_faces_len)
|
|
|
|
|
|
|
|
|
|
is_vert_mode, is_edge_mode, is_face_mode = context.tool_settings.mesh_select_mode
|
|
|
|
|
selected_verts_len, selected_edges_len, selected_faces_len = count_selected_items_for_objects_in_mode()
|
|
|
|
|
|
|
|
|
|
del count_selected_items_for_objects_in_mode
|
|
|
|
|
|
|
|
|
|
layout = self.layout
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2021-06-22 17:19:02 +10:00
|
|
|
with_freestyle = bpy.app.build_options.freestyle
|
|
|
|
|
|
2009-10-31 19:31:45 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2018-12-20 15:26:27 +11:00
|
|
|
# If nothing is selected
|
|
|
|
|
# (disabled for now until it can be made more useful).
|
|
|
|
|
'''
|
2018-12-18 07:54:32 +11:00
|
|
|
# If nothing is selected
|
|
|
|
|
if not (selected_verts_len or selected_edges_len or selected_faces_len):
|
2019-05-13 17:27:40 +02:00
|
|
|
layout.menu("VIEW3D_MT_mesh_add", text="Add", text_ctxt=i18n_contexts.operator_default)
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
return
|
2018-12-20 15:26:27 +11:00
|
|
|
'''
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Else something is selected
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
row = layout.row()
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
if is_vert_mode:
|
2020-08-06 11:51:54 +02:00
|
|
|
col = row.column(align=True)
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2023-09-25 16:25:55 +02:00
|
|
|
col.label(text="Vertex", icon='VERTEXSEL')
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Additive Operators
|
|
|
|
|
col.operator("mesh.subdivide", text="Subdivide")
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2019-04-19 08:07:46 +02:00
|
|
|
col.operator("mesh.extrude_vertices_move", text="Extrude Vertices")
|
2020-07-21 16:32:00 -04:00
|
|
|
col.operator("mesh.bevel", text="Bevel Vertices").affect = 'VERTICES'
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
if selected_verts_len > 1:
|
|
|
|
|
col.separator()
|
|
|
|
|
col.operator("mesh.edge_face_add", text="New Edge/Face from Vertices")
|
|
|
|
|
col.operator("mesh.vert_connect_path", text="Connect Vertex Path")
|
|
|
|
|
col.operator("mesh.vert_connect", text="Connect Vertex Pairs")
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Deform Operators
|
|
|
|
|
col.operator("transform.push_pull", text="Push/Pull")
|
|
|
|
|
col.operator("transform.shrink_fatten", text="Shrink/Fatten")
|
|
|
|
|
col.operator("transform.shear", text="Shear")
|
|
|
|
|
col.operator("transform.vert_slide", text="Slide Vertices")
|
2020-08-03 17:18:15 +02:00
|
|
|
col.operator_context = 'EXEC_REGION_WIN'
|
2020-01-02 17:00:17 +11:00
|
|
|
col.operator("transform.vertex_random", text="Randomize Vertices").offset = 0.1
|
|
|
|
|
col.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5
|
2019-11-21 21:06:24 +11:00
|
|
|
col.operator_context = 'INVOKE_REGION_WIN'
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.vertices_smooth_laplacian", text="Smooth Laplacian")
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2019-03-20 10:17:10 +01:00
|
|
|
col.menu("VIEW3D_MT_mirror", text="Mirror Vertices")
|
2019-03-11 23:33:13 +01:00
|
|
|
col.menu("VIEW3D_MT_snap", text="Snap Vertices")
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2023-09-20 08:58:17 +02:00
|
|
|
col.separator()
|
2023-09-21 07:55:23 +02:00
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
col.operator("transform.vert_crease", icon='VERTEX_CREASE')
|
2023-09-21 07:55:23 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Removal Operators
|
|
|
|
|
if selected_verts_len > 1:
|
2019-05-02 21:50:54 +10:00
|
|
|
col.menu("VIEW3D_MT_edit_mesh_merge", text="Merge Vertices")
|
2019-05-04 15:12:20 +02:00
|
|
|
col.operator("mesh.split")
|
|
|
|
|
col.operator_menu_enum("mesh.separate", "type")
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.dissolve_verts")
|
|
|
|
|
col.operator("mesh.delete", text="Delete Vertices").type = 'VERT'
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
if is_edge_mode:
|
2020-08-06 11:51:54 +02:00
|
|
|
col = row.column(align=True)
|
2023-09-25 16:25:55 +02:00
|
|
|
col.label(text="Edge", icon='EDGESEL')
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Additive Operators
|
|
|
|
|
col.operator("mesh.subdivide", text="Subdivide")
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2019-04-19 08:07:46 +02:00
|
|
|
col.operator("mesh.extrude_edges_move", text="Extrude Edges")
|
2020-07-21 16:32:00 -04:00
|
|
|
col.operator("mesh.bevel", text="Bevel Edges").affect = 'EDGES'
|
2018-12-18 07:54:32 +11:00
|
|
|
if selected_edges_len >= 2:
|
|
|
|
|
col.operator("mesh.bridge_edge_loops")
|
2019-03-12 08:22:38 +11:00
|
|
|
if selected_edges_len >= 1:
|
2019-03-11 16:48:39 +01:00
|
|
|
col.operator("mesh.edge_face_add", text="New Face from Edges")
|
2019-03-12 08:22:38 +11:00
|
|
|
if selected_edges_len >= 2:
|
2019-03-11 16:48:39 +01:00
|
|
|
col.operator("mesh.fill")
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2020-02-14 11:43:14 -03:00
|
|
|
props = col.operator("mesh.loopcut_slide")
|
|
|
|
|
props.TRANSFORM_OT_edge_slide.release_confirm = False
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.offset_edge_loops_slide")
|
2019-09-16 22:36:09 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.knife_tool")
|
|
|
|
|
col.operator("mesh.bisect")
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Deform Operators
|
|
|
|
|
col.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
|
|
|
|
|
col.operator("transform.edge_slide")
|
|
|
|
|
col.operator("mesh.edge_split")
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
2013-01-21 10:48:18 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
# Edge Flags
|
2025-08-07 11:09:56 +02:00
|
|
|
col.operator("transform.edge_bevelweight", icon='EDGE_BEVEL')
|
|
|
|
|
col.operator("transform.edge_crease", icon='EDGE_CREASE')
|
2009-10-12 21:06:03 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
|
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
col.operator("mesh.mark_seam", icon='EDGE_SEAM').clear = False
|
2020-05-22 13:41:48 +02:00
|
|
|
col.operator("mesh.mark_seam", text="Clear Seam").clear = True
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
col.operator("mesh.mark_sharp", icon='EDGE_SHARP').clear = False
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
|
2024-02-07 14:17:16 +01:00
|
|
|
col.operator("mesh.set_sharpness_by_angle")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
2021-06-22 17:19:02 +10:00
|
|
|
if with_freestyle:
|
|
|
|
|
col.separator()
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2021-06-22 17:19:02 +10:00
|
|
|
col.operator("mesh.mark_freestyle_edge").clear = False
|
|
|
|
|
col.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
|
2018-12-18 07:54:32 +11:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
# Removal Operators
|
|
|
|
|
col.operator("mesh.unsubdivide")
|
2019-05-04 15:12:20 +02:00
|
|
|
col.operator("mesh.split")
|
|
|
|
|
col.operator_menu_enum("mesh.separate", "type")
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.dissolve_edges")
|
|
|
|
|
col.operator("mesh.delete", text="Delete Edges").type = 'EDGE'
|
|
|
|
|
|
|
|
|
|
if is_face_mode:
|
2020-08-06 11:51:54 +02:00
|
|
|
col = row.column(align=True)
|
2018-12-18 07:54:32 +11:00
|
|
|
|
2023-09-25 16:25:55 +02:00
|
|
|
col.label(text="Face", icon='FACESEL')
|
2018-12-18 07:54:32 +11:00
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
# Additive Operators
|
|
|
|
|
col.operator("mesh.subdivide", text="Subdivide")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2024-03-15 10:04:03 +11:00
|
|
|
col.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces")
|
|
|
|
|
col.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals")
|
|
|
|
|
col.operator("mesh.extrude_faces_move", text="Extrude Individual Faces")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
2019-04-19 08:07:46 +02:00
|
|
|
col.operator("mesh.inset")
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.poke")
|
|
|
|
|
|
|
|
|
|
if selected_faces_len >= 2:
|
|
|
|
|
col.operator("mesh.bridge_edge_loops", text="Bridge Faces")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
# Modify Operators
|
2019-03-11 23:33:13 +01:00
|
|
|
col.menu("VIEW3D_MT_uv_map", text="UV Unwrap Faces")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
props = col.operator("mesh.quads_convert_to_tris")
|
|
|
|
|
props.quad_method = props.ngon_method = 'BEAUTY'
|
|
|
|
|
col.operator("mesh.tris_convert_to_quads")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col.operator("mesh.faces_shade_smooth")
|
|
|
|
|
col.operator("mesh.faces_shade_flat")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
# Removal Operators
|
|
|
|
|
col.operator("mesh.unsubdivide")
|
2019-05-04 15:12:20 +02:00
|
|
|
col.operator("mesh.split")
|
|
|
|
|
col.operator_menu_enum("mesh.separate", "type")
|
2018-12-18 07:54:32 +11:00
|
|
|
col.operator("mesh.dissolve_faces")
|
|
|
|
|
col.operator("mesh.delete", text="Delete Faces").type = 'FACE'
|
2018-05-25 08:07:43 +02:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_select_mode(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Mesh Select Mode"
|
2009-12-22 16:11:11 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-12-22 16:11:11 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2012-11-13 05:44:49 +00:00
|
|
|
layout.operator("mesh.select_mode", text="Vertex", icon='VERTEXSEL').type = 'VERT'
|
|
|
|
|
layout.operator("mesh.select_mode", text="Edge", icon='EDGESEL').type = 'EDGE'
|
|
|
|
|
layout.operator("mesh.select_mode", text="Face", icon='FACESEL').type = 'FACE'
|
2009-12-22 16:11:11 +00:00
|
|
|
|
2010-02-12 22:13:47 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_extrude(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Extrude"
|
2010-02-01 18:30:00 +00:00
|
|
|
|
2023-06-05 16:16:43 -03:00
|
|
|
def draw(self, context):
|
|
|
|
|
from math import pi
|
|
|
|
|
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2010-10-11 02:05:44 +00:00
|
|
|
|
2018-06-13 14:11:59 +02:00
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
select_mode = tool_settings.mesh_select_mode
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
|
|
|
|
mesh = ob.data
|
2010-02-12 22:13:47 +00:00
|
|
|
|
2010-10-11 02:05:44 +00:00
|
|
|
if mesh.total_face_sel:
|
2024-03-15 10:04:03 +11:00
|
|
|
layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces")
|
|
|
|
|
layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals")
|
|
|
|
|
layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces")
|
|
|
|
|
layout.operator("view3d.edit_mesh_extrude_manifold_normal", text="Extrude Manifold")
|
2023-06-05 16:36:34 -03:00
|
|
|
|
2010-10-11 02:05:44 +00:00
|
|
|
if mesh.total_edge_sel and (select_mode[0] or select_mode[1]):
|
2024-03-15 10:04:03 +11:00
|
|
|
layout.operator("mesh.extrude_edges_move", text="Extrude Edges")
|
2023-06-05 16:36:34 -03:00
|
|
|
|
2010-10-11 02:05:44 +00:00
|
|
|
if mesh.total_vert_sel and select_mode[0]:
|
2024-03-15 10:04:03 +11:00
|
|
|
layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices")
|
2010-02-12 22:13:47 +00:00
|
|
|
|
2020-03-30 10:27:42 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2020-03-30 11:41:44 +11:00
|
|
|
layout.operator("mesh.extrude_repeat")
|
2020-04-14 18:34:07 +10:00
|
|
|
layout.operator("mesh.spin").angle = pi * 2
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Extrude")
|
2020-03-30 10:27:42 +11:00
|
|
|
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_vertices(Menu):
|
2018-05-23 15:39:39 +02:00
|
|
|
bl_label = "Vertex"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2019-04-19 08:07:46 +02:00
|
|
|
layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator("mesh.dupli_extrude_cursor").rotate_source = True
|
2020-07-21 16:32:00 -04:00
|
|
|
layout.operator("mesh.bevel", text="Bevel Vertices").affect = 'VERTICES'
|
2016-09-05 00:10:13 +02:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.edge_face_add", text="New Edge/Face from Vertices")
|
2015-02-06 15:46:38 +11:00
|
|
|
layout.operator("mesh.vert_connect_path", text="Connect Vertex Path")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.vert_connect", text="Connect Vertex Pairs")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
props = layout.operator("mesh.rip_move", text="Rip Vertices")
|
|
|
|
|
props.MESH_OT_rip.use_fill = False
|
2018-05-24 16:09:20 +02:00
|
|
|
props = layout.operator("mesh.rip_move", text="Rip Vertices and Fill")
|
2018-05-24 15:37:52 +02:00
|
|
|
props.MESH_OT_rip.use_fill = True
|
2018-05-24 16:09:20 +02:00
|
|
|
layout.operator("mesh.rip_edge_move", text="Rip Vertices and Extend")
|
2015-06-13 00:30:39 +10:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("transform.vert_slide", text="Slide Vertices")
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2020-01-02 17:00:17 +11:00
|
|
|
layout.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5
|
2020-03-29 14:09:02 -04:00
|
|
|
layout.operator("mesh.vertices_smooth_laplacian", text="Smooth Vertices (Laplacian)")
|
2019-11-21 21:06:24 +11:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2018-05-24 15:37:52 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
layout.operator("transform.vert_crease", icon='VERTEX_CREASE')
|
Subdivision: add support for vertex creasing
This adds vertex creasing support for OpenSubDiv for modeling, rendering,
Alembic and USD I/O.
For modeling, vertex creasing follows the edge creasing implementation with an
operator accessible through the Vertex menu in Edit Mode, and some parameter in
the properties panel. The option in the Subsurf and Multires to use edge
creasing also affects vertex creasing.
The vertex crease data is stored as a CustomData layer, unlike edge creases
which for now are stored in `MEdge`, but will in the future also be moved to
a `CustomData` layer. See comments for details on the difference in behavior
for the `CD_CREASE` layer between egdes and vertices.
For Cycles this adds sockets on the Mesh node to hold data about which vertices
are creased (one socket for the indices, one for the weigths).
Viewport rendering of vertex creasing reuses the same color scheme as for edges
and creased vertices are drawn bigger than uncreased vertices.
For Alembic and USD, vertex crease support follows the edge crease
implementation, they are always read, but only exported if a `Subsurf` modifier
is present on the Mesh.
Reviewed By: brecht, fclem, sergey, sybren, campbellbarton
Differential Revision: https://developer.blender.org/D10145
2022-01-20 12:20:30 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("mesh.blend_from_shape")
|
2018-05-24 16:09:20 +02:00
|
|
|
layout.operator("mesh.shape_propagate_to_all", text="Propagate to Shapes")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_vertex_group")
|
|
|
|
|
layout.menu("VIEW3D_MT_hook")
|
2009-11-16 13:59:27 +00:00
|
|
|
|
2016-11-12 18:57:40 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("object.vertex_parent_set")
|
|
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2018-04-01 10:16:28 +02:00
|
|
|
class VIEW3D_MT_edit_mesh_edges(Menu):
|
2018-05-23 15:39:39 +02:00
|
|
|
bl_label = "Edge"
|
2018-04-01 10:16:28 +02:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-04-01 10:16:28 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-11-09 17:22:05 +01:00
|
|
|
with_freestyle = bpy.app.build_options.freestyle
|
|
|
|
|
|
2018-04-01 10:16:28 +02:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2019-04-19 08:07:46 +02:00
|
|
|
layout.operator("mesh.extrude_edges_move", text="Extrude Edges")
|
2020-07-21 16:32:00 -04:00
|
|
|
layout.operator("mesh.bevel", text="Bevel Edges").affect = 'EDGES'
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.bridge_edge_loops")
|
2020-03-29 14:09:02 -04:00
|
|
|
layout.operator("mesh.screw")
|
2018-04-01 10:16:28 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.subdivide")
|
|
|
|
|
layout.operator("mesh.subdivide_edgering")
|
|
|
|
|
layout.operator("mesh.unsubdivide")
|
2018-04-01 10:16:28 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2012-11-20 05:50:19 +00:00
|
|
|
layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
|
|
|
|
|
layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").use_ccw = True
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("transform.edge_slide")
|
2020-07-02 20:27:27 -04:00
|
|
|
props = layout.operator("mesh.loopcut_slide")
|
|
|
|
|
props.TRANSFORM_OT_edge_slide.release_confirm = False
|
2020-05-12 13:53:46 +10:00
|
|
|
layout.operator("mesh.offset_edge_loops_slide")
|
2017-01-03 10:34:05 -05:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
layout.operator("transform.edge_bevelweight", icon='EDGE_BEVEL')
|
|
|
|
|
layout.operator("transform.edge_crease", icon='EDGE_CREASE')
|
2018-11-09 17:22:05 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
layout.operator("mesh.mark_seam", icon='EDGE_SEAM').clear = False
|
2020-05-22 13:41:48 +02:00
|
|
|
layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-08-08 06:32:03 +00:00
|
|
|
layout.operator("mesh.mark_sharp", icon='EDGE_SHARP')
|
2018-11-09 17:22:05 +01:00
|
|
|
layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.mark_sharp", text="Mark Sharp from Vertices").use_verts = True
|
|
|
|
|
props = layout.operator("mesh.mark_sharp", text="Clear Sharp from Vertices")
|
|
|
|
|
props.use_verts = True
|
|
|
|
|
props.clear = True
|
|
|
|
|
|
2024-02-18 11:36:00 -05:00
|
|
|
layout.operator("mesh.set_sharpness_by_angle")
|
|
|
|
|
|
2018-11-09 17:22:05 +01:00
|
|
|
if with_freestyle:
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.mark_freestyle_edge").clear = False
|
|
|
|
|
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
|
2018-05-24 15:37:52 +02:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_mesh_faces_data(Menu):
|
|
|
|
|
bl_label = "Face Data"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-05-24 15:37:52 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-05-24 16:09:20 +02:00
|
|
|
with_freestyle = bpy.app.build_options.freestyle
|
|
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.colors_rotate")
|
|
|
|
|
layout.operator("mesh.colors_reverse")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.uvs_rotate")
|
|
|
|
|
layout.operator("mesh.uvs_reverse")
|
2009-10-12 21:06:03 +00:00
|
|
|
|
2018-05-24 16:09:20 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-01-27 11:00:36 -08:00
|
|
|
layout.operator("mesh.flip_quad_tessellation")
|
|
|
|
|
|
2018-05-24 16:09:20 +02:00
|
|
|
if with_freestyle:
|
2023-01-27 11:00:36 -08:00
|
|
|
layout.separator()
|
2018-05-24 16:09:20 +02:00
|
|
|
layout.operator("mesh.mark_freestyle_face").clear = False
|
|
|
|
|
layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Face/Face Data")
|
2018-05-24 16:09:20 +02:00
|
|
|
|
2009-10-12 21:06:03 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_faces(Menu):
|
2018-05-23 15:39:39 +02:00
|
|
|
bl_label = "Face"
|
2009-10-31 19:31:45 +00:00
|
|
|
bl_idname = "VIEW3D_MT_edit_mesh_faces"
|
|
|
|
|
|
2023-06-05 16:36:34 -03:00
|
|
|
def draw(self, context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2013-07-30 09:00:31 +00:00
|
|
|
|
2009-10-31 19:31:45 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
2024-03-15 10:04:03 +11:00
|
|
|
layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces")
|
|
|
|
|
layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals")
|
2023-11-09 21:32:16 -03:00
|
|
|
layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.inset")
|
2013-04-06 02:45:43 +00:00
|
|
|
layout.operator("mesh.poke")
|
2015-01-29 17:34:05 +01:00
|
|
|
props = layout.operator("mesh.quads_convert_to_tris")
|
|
|
|
|
props.quad_method = props.ngon_method = 'BEAUTY'
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("mesh.tris_convert_to_quads")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.solidify", text="Solidify Faces")
|
|
|
|
|
layout.operator("mesh.wireframe")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.fill")
|
|
|
|
|
layout.operator("mesh.fill_grid")
|
|
|
|
|
layout.operator("mesh.beautify_fill")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.intersect")
|
|
|
|
|
layout.operator("mesh.intersect_boolean")
|
2014-10-22 23:25:31 +02:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.face_split_by_edges")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.operator("mesh.faces_shade_smooth")
|
|
|
|
|
layout.operator("mesh.faces_shade_flat")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_faces_data")
|
2009-10-12 21:06:03 +00:00
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2019-05-22 00:27:01 +10:00
|
|
|
|
2019-05-07 08:45:01 -04:00
|
|
|
class VIEW3D_MT_edit_mesh_normals_select_strength(Menu):
|
|
|
|
|
bl_label = "Select by Face Strength"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("mesh.mod_weighted_strength", text="Weak")
|
|
|
|
|
props.set = False
|
|
|
|
|
props.face_strength = 'WEAK'
|
2019-05-07 08:45:01 -04:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("mesh.mod_weighted_strength", text="Medium")
|
|
|
|
|
props.set = False
|
|
|
|
|
props.face_strength = 'MEDIUM'
|
2019-05-07 08:45:01 -04:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("mesh.mod_weighted_strength", text="Strong")
|
|
|
|
|
props.set = False
|
|
|
|
|
props.face_strength = 'STRONG'
|
2019-05-07 08:45:01 -04:00
|
|
|
|
2019-05-22 00:27:01 +10:00
|
|
|
|
2019-05-07 08:45:01 -04:00
|
|
|
class VIEW3D_MT_edit_mesh_normals_set_strength(Menu):
|
2020-08-06 14:48:47 +02:00
|
|
|
bl_label = "Set Face Strength"
|
2019-05-07 08:45:01 -04:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("mesh.mod_weighted_strength", text="Weak")
|
|
|
|
|
props.set = True
|
|
|
|
|
props.face_strength = 'WEAK'
|
2019-05-07 08:45:01 -04:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("mesh.mod_weighted_strength", text="Medium")
|
|
|
|
|
props.set = True
|
|
|
|
|
props.face_strength = 'MEDIUM'
|
2019-05-07 08:45:01 -04:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = layout.operator("mesh.mod_weighted_strength", text="Strong")
|
|
|
|
|
props.set = True
|
|
|
|
|
props.face_strength = 'STRONG'
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2019-05-22 00:27:01 +10:00
|
|
|
|
2019-05-08 07:44:15 -04:00
|
|
|
class VIEW3D_MT_edit_mesh_normals_average(Menu):
|
|
|
|
|
bl_label = "Average"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.average_normals", text="Custom Normal").average_type = 'CUSTOM_NORMAL'
|
|
|
|
|
layout.operator("mesh.average_normals", text="Face Area").average_type = 'FACE_AREA'
|
|
|
|
|
layout.operator("mesh.average_normals", text="Corner Angle").average_type = 'CORNER_ANGLE'
|
|
|
|
|
|
2019-05-22 00:27:01 +10:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_normals(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Normals"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2019-05-20 13:38:33 -04:00
|
|
|
layout.operator("mesh.flip_normals", text="Flip")
|
2012-01-14 06:30:27 +00:00
|
|
|
layout.operator("mesh.normals_make_consistent", text="Recalculate Outside").inside = False
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("mesh.normals_make_consistent", text="Recalculate Inside").inside = True
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2020-10-07 08:04:53 -05:00
|
|
|
layout.operator("mesh.set_normals_from_faces", text="Set from Faces")
|
2019-05-31 16:24:58 +10:00
|
|
|
|
2019-08-22 14:53:44 +02:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2019-07-01 16:46:48 +10:00
|
|
|
layout.operator("transform.rotate_normal", text="Rotate...")
|
|
|
|
|
layout.operator("mesh.point_normals", text="Point to Target...")
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2019-05-31 16:24:58 +10:00
|
|
|
|
2018-05-25 22:24:24 +05:30
|
|
|
layout.operator("mesh.merge_normals", text="Merge")
|
|
|
|
|
layout.operator("mesh.split_normals", text="Split")
|
2024-12-26 12:40:50 +01:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_normals_average", text="Average", text_ctxt=i18n_contexts.id_mesh)
|
2018-05-25 22:24:24 +05:30
|
|
|
|
2019-05-01 15:44:26 +02:00
|
|
|
layout.separator()
|
2018-05-25 22:24:24 +05:30
|
|
|
|
2023-05-07 15:27:28 +02:00
|
|
|
layout.operator("mesh.normals_tools", text="Copy Vector").mode = 'COPY'
|
|
|
|
|
layout.operator("mesh.normals_tools", text="Paste Vector").mode = 'PASTE'
|
2018-05-25 22:24:24 +05:30
|
|
|
|
2020-04-07 15:12:18 +10:00
|
|
|
layout.operator("mesh.smooth_normals", text="Smooth Vectors")
|
2019-05-01 15:44:26 +02:00
|
|
|
layout.operator("mesh.normals_tools", text="Reset Vectors").mode = 'RESET'
|
2018-05-25 22:24:24 +05:30
|
|
|
|
2019-05-01 15:44:26 +02:00
|
|
|
layout.separator()
|
2018-05-25 22:24:24 +05:30
|
|
|
|
2020-08-06 14:48:47 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_normals_select_strength")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_mesh_normals_set_strength")
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Normals")
|
2018-05-25 22:24:24 +05:30
|
|
|
|
2018-04-24 21:07:05 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_mesh_shading(Menu):
|
|
|
|
|
bl_label = "Shading"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-04-24 21:07:05 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-06-26 14:29:21 +02:00
|
|
|
layout.operator("mesh.faces_shade_smooth", text="Smooth Faces")
|
|
|
|
|
layout.operator("mesh.faces_shade_flat", text="Flat Faces")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.mark_sharp", text="Smooth Edges").clear = True
|
|
|
|
|
layout.operator("mesh.mark_sharp", text="Sharp Edges")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
props = layout.operator("mesh.mark_sharp", text="Smooth Vertices")
|
2018-04-24 21:07:05 +02:00
|
|
|
props.use_verts = True
|
|
|
|
|
props.clear = True
|
2018-06-26 14:29:21 +02:00
|
|
|
|
|
|
|
|
layout.operator("mesh.mark_sharp", text="Sharp Vertices").use_verts = True
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Shading")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2018-04-24 16:54:38 +02:00
|
|
|
class VIEW3D_MT_edit_mesh_weights(Menu):
|
|
|
|
|
bl_label = "Weights"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2023-09-26 17:01:30 -04:00
|
|
|
layout = self.layout
|
|
|
|
|
VIEW3D_MT_paint_weight.draw_generic(layout, is_editmode=True)
|
|
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Weights")
|
2018-04-24 16:54:38 +02:00
|
|
|
|
|
|
|
|
|
2013-07-25 18:43:05 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_clean(Menu):
|
2017-10-30 22:36:51 +11:00
|
|
|
bl_label = "Clean Up"
|
2013-07-25 18:43:05 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2013-07-25 18:43:05 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2014-01-17 12:08:12 +11:00
|
|
|
layout.operator("mesh.delete_loose")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2016-07-08 23:35:27 +10:00
|
|
|
layout.operator("mesh.decimate")
|
2014-02-17 11:32:35 +11:00
|
|
|
layout.operator("mesh.dissolve_degenerate")
|
|
|
|
|
layout.operator("mesh.dissolve_limited")
|
2015-06-11 21:46:51 +10:00
|
|
|
layout.operator("mesh.face_make_planar")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-07-28 19:53:46 +00:00
|
|
|
layout.operator("mesh.vert_connect_nonplanar")
|
2015-02-02 09:04:31 +11:00
|
|
|
layout.operator("mesh.vert_connect_concave")
|
2017-02-09 16:25:04 -05:00
|
|
|
layout.operator("mesh.remove_doubles")
|
2014-02-17 11:32:35 +11:00
|
|
|
layout.operator("mesh.fill_holes")
|
2013-07-25 18:43:05 +00:00
|
|
|
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Clean Up")
|
|
|
|
|
|
2013-07-25 18:43:05 +00:00
|
|
|
|
2012-03-23 10:30:42 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_delete(Menu):
|
|
|
|
|
bl_label = "Delete"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2012-03-23 10:30:42 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_enum("mesh.delete", "type")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-06-15 13:33:28 +00:00
|
|
|
layout.operator("mesh.dissolve_verts")
|
|
|
|
|
layout.operator("mesh.dissolve_edges")
|
|
|
|
|
layout.operator("mesh.dissolve_faces")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
2013-05-08 13:48:57 +00:00
|
|
|
|
2013-01-30 05:19:27 +00:00
|
|
|
layout.operator("mesh.dissolve_limited")
|
2012-03-23 10:30:42 +00:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-01-30 05:19:27 +00:00
|
|
|
layout.operator("mesh.edge_collapse")
|
2014-05-29 15:28:09 +10:00
|
|
|
layout.operator("mesh.delete_edgeloop", text="Edge Loops")
|
2012-03-23 10:30:42 +00:00
|
|
|
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Delete")
|
|
|
|
|
|
2012-03-23 10:30:42 +00:00
|
|
|
|
2019-05-02 21:50:54 +10:00
|
|
|
class VIEW3D_MT_edit_mesh_merge(Menu):
|
|
|
|
|
bl_label = "Merge"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_enum("mesh.merge", "type")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("mesh.remove_doubles", text="By Distance")
|
|
|
|
|
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Merge")
|
|
|
|
|
|
2019-05-02 21:50:54 +10:00
|
|
|
|
2020-03-31 18:01:06 +11:00
|
|
|
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")
|
|
|
|
|
|
2023-09-26 17:01:30 -04:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path="Mesh/Split")
|
|
|
|
|
|
2020-03-31 18:01:06 +11:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
|
2009-10-31 19:31:45 +00:00
|
|
|
_operator_name = "mesh"
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2015-07-05 14:34:17 +10:00
|
|
|
|
2023-08-24 11:06:18 +02:00
|
|
|
class VIEW3D_MT_edit_greasepencil_delete(Menu):
|
|
|
|
|
bl_label = "Delete"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-11-17 10:35:56 +01:00
|
|
|
layout.operator("grease_pencil.delete")
|
2023-11-17 11:54:19 +01:00
|
|
|
|
2023-11-17 10:35:56 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-08-24 11:06:18 +02:00
|
|
|
layout.operator_enum("grease_pencil.dissolve", "type")
|
2023-09-12 14:48:18 +10:00
|
|
|
|
2023-10-26 16:52:31 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-09-12 14:48:18 +10:00
|
|
|
layout.operator(
|
|
|
|
|
"grease_pencil.delete_frame",
|
|
|
|
|
text="Delete Active Keyframe (Active Layer)",
|
|
|
|
|
).type = 'ACTIVE_FRAME'
|
|
|
|
|
layout.operator(
|
|
|
|
|
"grease_pencil.delete_frame",
|
|
|
|
|
text="Delete Active Keyframes (All Layers)",
|
|
|
|
|
).type = 'ALL_FRAMES'
|
2023-09-11 11:34:27 +02:00
|
|
|
|
2023-08-24 11:06:18 +02:00
|
|
|
|
2009-09-15 10:23:44 +00:00
|
|
|
# Edit Curve
|
|
|
|
|
# draw_curve is used by VIEW3D_MT_edit_curve and VIEW3D_MT_edit_surface
|
2009-10-31 23:35:56 +00:00
|
|
|
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw_curve(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform")
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2015-05-17 12:44:18 +02:00
|
|
|
layout.operator("curve.spin")
|
2012-05-12 20:50:46 +00:00
|
|
|
layout.operator("curve.duplicate_move")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-08-29 02:32:51 +00:00
|
|
|
layout.operator("curve.split")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("curve.separate")
|
2020-03-31 18:12:17 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("curve.cyclic_toggle")
|
2018-11-30 16:40:39 +11:00
|
|
|
layout.operator_menu_enum("curve.spline_type_set", "type")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_edit_curve_showhide")
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_curve_clean")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_curve_delete")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_curve(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Curve"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
draw = draw_curve
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_curve_ctrlpoints(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Control Points"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
edit_object = context.edit_object
|
|
|
|
|
|
2018-12-08 15:01:47 +11:00
|
|
|
if edit_object.type in {'CURVE', 'SURFACE'}:
|
2018-11-30 09:45:13 +11:00
|
|
|
layout.operator("curve.extrude_move")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator("curve.vertex_add")
|
2018-11-30 09:45:13 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curve.make_segment")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-12-07 14:57:54 +01:00
|
|
|
if edit_object.type == 'CURVE':
|
|
|
|
|
layout.operator("transform.tilt")
|
|
|
|
|
layout.operator("curve.tilt_clear")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-12-07 14:57:54 +01:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-12-07 14:57:54 +01:00
|
|
|
layout.operator_menu_enum("curve.handle_type_set", "type")
|
|
|
|
|
layout.operator("curve.normals_make_consistent")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-12-07 14:57:54 +01:00
|
|
|
layout.separator()
|
2009-11-16 13:59:27 +00:00
|
|
|
|
2018-11-30 09:45:13 +11:00
|
|
|
layout.operator("curve.smooth")
|
2018-12-07 14:57:54 +01:00
|
|
|
if edit_object.type == 'CURVE':
|
|
|
|
|
layout.operator("curve.smooth_tilt")
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("curve.smooth_radius")
|
|
|
|
|
layout.operator("curve.smooth_weight")
|
2018-11-30 09:45:13 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2012-05-15 15:28:59 +00:00
|
|
|
layout.menu("VIEW3D_MT_hook")
|
2009-11-16 13:59:27 +00:00
|
|
|
|
2016-11-12 18:57:40 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("object.vertex_parent_set")
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_curve_segments(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Segments"
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("curve.subdivide")
|
|
|
|
|
layout.operator("curve.switch_direction")
|
2009-12-26 09:36:50 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
|
2017-10-30 22:36:51 +11:00
|
|
|
class VIEW3D_MT_edit_curve_clean(Menu):
|
|
|
|
|
bl_label = "Clean Up"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2017-10-30 22:36:51 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("curve.decimate")
|
|
|
|
|
|
2009-12-26 09:36:50 +00:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_MT_edit_curve_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Curve"
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-11-30 09:45:13 +11:00
|
|
|
# TODO(campbell): match mesh vertex menu.
|
2018-12-18 07:54:32 +11:00
|
|
|
|
2009-12-24 10:39:30 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
|
|
|
|
|
2019-03-01 10:55:23 +11:00
|
|
|
# Add
|
2009-12-24 10:39:30 +00:00
|
|
|
layout.operator("curve.subdivide")
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("curve.extrude_move")
|
|
|
|
|
layout.operator("curve.make_segment")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("curve.duplicate_move")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-03-01 10:55:23 +11:00
|
|
|
# Transform
|
2019-03-04 10:17:45 +01:00
|
|
|
layout.operator("transform.transform", text="Radius").mode = 'CURVE_SHRINKFATTEN'
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("transform.tilt")
|
|
|
|
|
layout.operator("curve.tilt_clear")
|
|
|
|
|
layout.operator("curve.smooth")
|
|
|
|
|
layout.operator("curve.smooth_tilt")
|
|
|
|
|
layout.operator("curve.smooth_radius")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-03-01 10:55:23 +11:00
|
|
|
# Modify
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator_menu_enum("curve.spline_type_set", "type")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator_menu_enum("curve.handle_type_set", "type")
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("curve.cyclic_toggle")
|
|
|
|
|
layout.operator("curve.switch_direction")
|
2018-12-18 07:54:32 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("curve.normals_make_consistent")
|
2009-12-24 10:39:30 +00:00
|
|
|
layout.operator("curve.spline_weight_set")
|
|
|
|
|
layout.operator("curve.radius_set")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-03-01 10:55:23 +11:00
|
|
|
# Remove
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("curve.split")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("curve.decimate")
|
2020-02-26 16:25:25 +01:00
|
|
|
layout.operator("curve.separate")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("curve.dissolve_verts")
|
2019-02-28 18:09:32 +01:00
|
|
|
layout.operator("curve.delete", text="Delete Segment").type = 'SEGMENT'
|
|
|
|
|
layout.operator("curve.delete", text="Delete Point").type = 'VERT'
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2009-12-26 09:36:50 +00:00
|
|
|
|
2016-05-02 18:11:09 +10:00
|
|
|
class VIEW3D_MT_edit_curve_delete(Menu):
|
|
|
|
|
bl_label = "Delete"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2016-05-02 18:11:09 +10:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_enum("curve.delete", "type")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curve.dissolve_verts")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_curve_showhide(ShowHideMenu, Menu):
|
2009-10-31 19:31:45 +00:00
|
|
|
_operator_name = "curve"
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_surface(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Surface"
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 19:31:45 +00:00
|
|
|
draw = draw_curve
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
class VIEW3D_MT_edit_font_chars(Menu):
|
|
|
|
|
bl_label = "Special Characters"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2023-12-31 19:18:47 +01:00
|
|
|
layout.operator("font.text_insert", text="Copyright \u00A9").text = "\u00A9"
|
|
|
|
|
layout.operator("font.text_insert", text="Registered Trademark \u00AE").text = "\u00AE"
|
2019-03-20 10:51:37 +01:00
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.separator()
|
|
|
|
|
|
2023-12-31 19:18:47 +01:00
|
|
|
layout.operator("font.text_insert", text="Degree \u00B0").text = "\u00B0"
|
|
|
|
|
layout.operator("font.text_insert", text="Multiplication \u00D7").text = "\u00D7"
|
|
|
|
|
layout.operator("font.text_insert", text="Circle \u2022").text = "\u2022"
|
2020-04-04 12:41:58 -04:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-12-31 19:18:47 +01:00
|
|
|
layout.operator("font.text_insert", text="Superscript \u00B9").text = "\u00B9"
|
|
|
|
|
layout.operator("font.text_insert", text="Superscript \u00B2").text = "\u00B2"
|
|
|
|
|
layout.operator("font.text_insert", text="Superscript \u00B3").text = "\u00B3"
|
2020-04-04 12:41:58 -04:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-12-31 19:18:47 +01:00
|
|
|
layout.operator("font.text_insert", text="Guillemet \u00BB").text = "\u00BB"
|
|
|
|
|
layout.operator("font.text_insert", text="Guillemet \u00AB").text = "\u00AB"
|
|
|
|
|
layout.operator("font.text_insert", text="Per Mille \u2030").text = "\u2030"
|
2020-04-04 12:41:58 -04:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-12-31 19:18:47 +01:00
|
|
|
layout.operator("font.text_insert", text="Euro \u20AC").text = "\u20AC"
|
|
|
|
|
layout.operator("font.text_insert", text="Florin \u0192").text = "\u0192"
|
|
|
|
|
layout.operator("font.text_insert", text="Pound \u00A3").text = "\u00A3"
|
|
|
|
|
layout.operator("font.text_insert", text="Yen \u00A5").text = "\u00A5"
|
2020-04-04 12:41:58 -04:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2023-12-31 19:18:47 +01:00
|
|
|
layout.operator("font.text_insert", text="German Eszett \u00DF").text = "\u00DF"
|
|
|
|
|
layout.operator("font.text_insert", text="Inverted Question Mark \u00BF").text = "\u00BF"
|
|
|
|
|
layout.operator("font.text_insert", text="Inverted Exclamation Mark \u00A1").text = "\u00A1"
|
2020-02-26 22:26:40 +11:00
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2023-04-12 19:11:53 +02:00
|
|
|
layout.operator("font.change_spacing", text="Decrease Kerning").delta = -1.0
|
|
|
|
|
layout.operator("font.change_spacing", text="Increase Kerning").delta = 1.0
|
2020-02-26 22:26:40 +11:00
|
|
|
layout.operator("font.change_spacing", text="Reset Kerning").delta = -kerning
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
class VIEW3D_MT_edit_font_delete(Menu):
|
|
|
|
|
bl_label = "Delete"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
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')
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.text_paste_from_file")
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.operator("font.case_set", text="To Uppercase").case = 'UPPER'
|
|
|
|
|
layout.operator("font.case_set", text="To Lowercase").case = 'LOWER'
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-01-18 17:59:36 +01:00
|
|
|
layout.operator("FONT_OT_text_insert_unicode")
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.menu("VIEW3D_MT_edit_font_chars")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
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")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2020-04-04 12:41:58 -04:00
|
|
|
layout.menu("VIEW3D_MT_edit_font_delete")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_font_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Text"
|
2020-04-04 12:41:58 -04:00
|
|
|
|
|
|
|
|
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")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_meta(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Metaball"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform")
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("mball.duplicate_metaelems")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_edit_meta_showhide")
|
2018-10-10 09:41:44 +11:00
|
|
|
|
2020-08-03 17:18:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2018-10-10 09:41:44 +11:00
|
|
|
layout.operator("mball.delete_metaelems", text="Delete")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_meta_showhide(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Show/Hide"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2019-03-19 22:25:25 +01:00
|
|
|
layout.operator("mball.reveal_metaelems")
|
2012-04-24 17:50:01 +00:00
|
|
|
layout.operator("mball.hide_metaelems", text="Hide Selected").unselected = False
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("mball.hide_metaelems", text="Hide Unselected").unselected = True
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_lattice(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Lattice"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2017-10-19 15:38:34 +11:00
|
|
|
layout.separator()
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform")
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2012-10-13 10:42:38 +00:00
|
|
|
layout.operator_menu_enum("lattice.flip", "axis")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("lattice.make_regular")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2016-11-12 18:57:40 +01:00
|
|
|
layout.operator("object.vertex_parent_set")
|
|
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_armature(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Armature"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
edit_object = context.edit_object
|
|
|
|
|
arm = edit_object.data
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2012-05-06 06:37:07 +00:00
|
|
|
layout.menu("VIEW3D_MT_transform_armature")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_armature_roll")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("armature.extrude_move")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator("armature.click_extrude")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2010-08-20 06:09:58 +00:00
|
|
|
if arm.use_mirror_x:
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("armature.extrude_forked")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("armature.duplicate_move")
|
|
|
|
|
layout.operator("armature.fill")
|
2020-03-31 18:12:17 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2013-10-29 00:10:03 +00:00
|
|
|
layout.operator("armature.split")
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.operator("armature.separate")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("armature.subdivide", text="Subdivide")
|
|
|
|
|
layout.operator("armature.switch_direction", text="Switch Direction")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-02-14 18:32:04 +11:00
|
|
|
layout.operator("armature.symmetrize")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.menu("VIEW3D_MT_edit_armature_names")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-16 13:59:27 +00:00
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
2023-09-19 11:45:16 +02:00
|
|
|
layout.operator("armature.move_to_collection", text="Move to Bone Collection")
|
2023-09-19 17:43:26 +02:00
|
|
|
layout.menu("VIEW3D_MT_bone_collections")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.menu("VIEW3D_MT_edit_armature_parent")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2018-05-24 15:37:52 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2018-09-28 18:53:25 -03:00
|
|
|
layout.menu("VIEW3D_MT_edit_armature_delete")
|
2018-05-24 15:37:52 +02:00
|
|
|
|
2009-11-21 00:05:43 +00:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_MT_armature_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Armature"
|
2009-11-20 11:49:47 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2009-11-21 00:05:43 +00:00
|
|
|
|
2018-12-18 07:54:32 +11:00
|
|
|
edit_object = context.edit_object
|
|
|
|
|
arm = edit_object.data
|
|
|
|
|
|
2009-11-20 11:49:47 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
2009-11-21 00:05:43 +00:00
|
|
|
|
2019-03-20 10:17:55 +01:00
|
|
|
# Add
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("armature.subdivide", text="Subdivide")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("armature.duplicate_move", text="Duplicate")
|
|
|
|
|
layout.operator("armature.extrude_move")
|
|
|
|
|
if arm.use_mirror_x:
|
|
|
|
|
layout.operator("armature.extrude_forked")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("armature.fill")
|
|
|
|
|
|
2019-02-14 18:32:04 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2019-03-20 10:17:10 +01:00
|
|
|
# Modify
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
2019-02-14 18:32:04 +11:00
|
|
|
layout.operator("armature.symmetrize")
|
2019-03-20 10:17:10 +01:00
|
|
|
layout.operator("armature.switch_direction", text="Switch Direction")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.menu("VIEW3D_MT_edit_armature_names")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_armature_parent")
|
2009-11-21 00:05:43 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-11-21 00:05:43 +00:00
|
|
|
|
2019-03-20 10:17:55 +01:00
|
|
|
# Remove
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("armature.split")
|
2020-02-26 16:25:25 +01:00
|
|
|
layout.operator("armature.separate")
|
2018-12-18 07:54:32 +11:00
|
|
|
layout.operator("armature.dissolve")
|
|
|
|
|
layout.operator("armature.delete")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_armature_names(Menu):
|
|
|
|
|
bl_label = "Names"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-12-18 07:54:32 +11:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2009-11-20 11:49:47 +00:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2020-10-24 11:42:17 -07:00
|
|
|
layout.operator("armature.autoside_names", text="Auto-Name Left/Right").type = 'XAXIS'
|
|
|
|
|
layout.operator("armature.autoside_names", text="Auto-Name Front/Back").type = 'YAXIS'
|
|
|
|
|
layout.operator("armature.autoside_names", text="Auto-Name Top/Bottom").type = 'ZAXIS'
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("armature.flip_names", text="Flip Names")
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2009-11-21 00:05:43 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_armature_parent(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Parent"
|
2024-06-13 12:15:55 +02:00
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("armature.parent_set", text="Make")
|
|
|
|
|
layout.operator("armature.parent_clear", text="Clear")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_MT_edit_armature_roll(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Bone Roll"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-10-31 19:31:45 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2011-02-16 02:25:03 +00:00
|
|
|
layout.operator_menu_enum("armature.calculate_roll", "type")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-23 00:27:30 +00:00
|
|
|
layout.separator()
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("transform.transform", text="Set Roll").mode = 'BONE_ROLL'
|
2016-03-03 11:45:43 +11:00
|
|
|
layout.operator("armature.roll_clear")
|
2009-08-17 10:13:24 +00:00
|
|
|
|
2015-06-13 03:20:07 +10:00
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_armature_delete(Menu):
|
|
|
|
|
bl_label = "Delete"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2015-06-13 03:20:07 +10:00
|
|
|
layout = self.layout
|
2018-10-09 19:39:37 -03:00
|
|
|
layout.operator_context = 'EXEC_AREA'
|
2015-06-13 03:20:07 +10:00
|
|
|
|
2018-09-28 18:53:25 -03:00
|
|
|
layout.operator("armature.delete", text="Bones")
|
2015-06-13 03:20:07 +10:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2018-09-28 18:53:25 -03:00
|
|
|
layout.operator("armature.dissolve", text="Dissolve Bones")
|
2015-06-13 03:20:07 +10:00
|
|
|
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_MT_weight_grease_pencil(Menu):
|
|
|
|
|
bl_label = "Weights"
|
2018-08-30 12:22:55 +02:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-08-30 12:22:55 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.vertex_group_normalize_all", text="Normalize All")
|
|
|
|
|
layout.operator("grease_pencil.vertex_group_normalize", text="Normalize")
|
2018-08-30 12:22:55 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.separator()
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.weight_invert", text="Invert")
|
|
|
|
|
layout.operator("grease_pencil.vertex_group_smooth", text="Smooth")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.weight_sample", text="Sample Weight")
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_MT_edit_greasepencil_animation(Menu):
|
|
|
|
|
bl_label = "Animation"
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
def draw(self, context):
|
2018-07-31 10:22:19 +02:00
|
|
|
layout = self.layout
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.insert_blank_frame", text="Insert Blank Keyframe (Active Layer)")
|
|
|
|
|
layout.operator("grease_pencil.insert_blank_frame", text="Insert Blank Keyframe (All Layers)").all_layers = True
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("grease_pencil.frame_duplicate", text="Duplicate Active Keyframe (Active Layer)").all = False
|
2024-10-16 19:05:48 +02:00
|
|
|
layout.operator("grease_pencil.frame_duplicate", text="Duplicate Active Keyframe (All Layers)").all = True
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.active_frame_delete", text="Delete Active Keyframe (Active Layer)").all = False
|
2024-10-16 19:05:48 +02:00
|
|
|
layout.operator("grease_pencil.active_frame_delete", text="Delete Active Keyframe (All Layers)").all = True
|
2024-10-04 13:05:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_edit_greasepencil_showhide(Menu):
|
|
|
|
|
bl_label = "Show/Hide"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.layer_reveal", text="Show All Layers")
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.layer_hide", text="Hide Active Layer").unselected = False
|
|
|
|
|
layout.operator("grease_pencil.layer_hide", text="Hide Inactive Layers").unselected = True
|
2015-12-13 21:03:13 +13:00
|
|
|
|
2018-08-02 19:35:29 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_MT_edit_greasepencil_cleanup(Menu):
|
|
|
|
|
bl_label = "Clean Up"
|
2018-08-02 19:21:12 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
2024-10-04 13:05:09 +02:00
|
|
|
ob = context.object
|
|
|
|
|
|
2018-08-02 19:21:12 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.clean_loose")
|
|
|
|
|
layout.operator("grease_pencil.frame_clean_duplicate")
|
|
|
|
|
|
|
|
|
|
if ob.mode != 'PAINT_GREASE_PENCIL':
|
|
|
|
|
layout.operator("grease_pencil.stroke_merge_by_distance", text="Merge by Distance")
|
|
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.reproject")
|
2025-05-31 12:23:39 +02:00
|
|
|
layout.operator("grease_pencil.remove_fill_guides")
|
2015-12-13 21:03:13 +13:00
|
|
|
|
2018-08-02 19:35:29 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_MT_edit_greasepencil(Menu):
|
2019-08-09 17:36:27 +02:00
|
|
|
bl_label = "Grease Pencil"
|
2016-02-01 00:47:10 +11:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2015-12-13 21:03:13 +13:00
|
|
|
layout = self.layout
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("VIEW3D_MT_transform")
|
2019-08-09 17:36:27 +02:00
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("GREASE_PENCIL_MT_snap")
|
2015-12-13 21:03:13 +13:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("GREASE_PENCIL_MT_layer_active", text="Active Layer")
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_animation", text="Animation")
|
2025-01-21 13:36:37 +01:00
|
|
|
layout.operator("grease_pencil.interpolate_sequence", text="Interpolate Sequence").use_selection = True
|
2017-10-19 15:10:41 +11:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.duplicate_move", text="Duplicate")
|
2015-12-13 21:03:13 +13:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2025-03-14 12:37:25 +01:00
|
|
|
layout.operator("grease_pencil.stroke_split", text="Split")
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.copy", text="Copy", icon='COPYDOWN')
|
2025-02-07 16:17:16 +01:00
|
|
|
layout.operator("grease_pencil.paste", text="Paste", icon='PASTEDOWN').type = 'ACTIVE'
|
|
|
|
|
layout.operator("grease_pencil.paste", text="Paste by Layer").type = 'LAYER'
|
2019-08-09 17:36:27 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
2019-08-09 17:46:05 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_showhide")
|
|
|
|
|
layout.operator_menu_enum("grease_pencil.separate", "mode", text="Separate")
|
|
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_cleanup")
|
2025-05-31 22:38:33 +02:00
|
|
|
layout.operator("grease_pencil.outline", text="Outline")
|
2019-08-09 17:36:27 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("VIEW3D_MT_edit_greasepencil_delete")
|
2019-08-09 17:46:05 +02:00
|
|
|
|
Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools.
Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`,
and `Draw Mode`.
While Grease Pencil has many editing tools, including editing
multiple frames at the same time, for now, node tools only
allow editing the current frame.
Currently, the idea is that node tools can do arbitrary changes
to the drawings, but cannot do changes to the existing layer tree, e.g.
changing the order of layers, removing a layer or groups, etc.
All the node tool specific nodes like `Selection` and `Set Selection`
are adapted to work with Grease Pencil. In `Draw Mode`, we currently
interpret everything as selected.
The `Active Element` node has a `Layer` mode that provides the
index of the active layer (if there is one).
When `Auto-Key` is used, a new keyframe is created on the
current frame.
Locked/invisible layers cannot be edited with node tools.
Pull Request: https://projects.blender.org/blender/blender/pulls/136624
2025-05-05 10:41:21 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2019-08-09 17:36:27 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_MT_edit_greasepencil_stroke(Menu):
|
2019-08-09 17:36:27 +02:00
|
|
|
bl_label = "Stroke"
|
|
|
|
|
|
2020-09-15 10:43:33 +10:00
|
|
|
def draw(self, context):
|
2019-08-09 17:36:27 +02:00
|
|
|
layout = self.layout
|
2023-09-15 10:44:42 +10:00
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
settings = tool_settings.gpencil_sculpt
|
2019-08-09 17:46:05 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.stroke_subdivide", text="Subdivide")
|
|
|
|
|
layout.operator("grease_pencil.stroke_subdivide_smooth", text="Subdivide and Smooth")
|
2024-11-28 17:00:05 +01:00
|
|
|
layout.menu("GREASE_PENCIL_MT_stroke_simplify")
|
2025-05-31 22:38:33 +02:00
|
|
|
layout.operator("grease_pencil.outline", text="Outline")
|
2016-12-02 02:19:59 +13:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-07 20:08:32 -04:00
|
|
|
layout.operator_menu_enum("grease_pencil.join_selection", "type", text="Join")
|
2015-12-13 21:03:13 +13:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("GREASE_PENCIL_MT_move_to_layer")
|
|
|
|
|
layout.menu("VIEW3D_MT_grease_pencil_assign_material")
|
|
|
|
|
layout.operator("grease_pencil.set_active_material")
|
|
|
|
|
layout.operator_menu_enum("grease_pencil.reorder", text="Arrange", property="direction")
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.operator("grease_pencil.cyclical_set", text="Close").type = 'CLOSE'
|
|
|
|
|
layout.operator("grease_pencil.cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
|
|
|
|
|
layout.operator_menu_enum("grease_pencil.caps_set", text="Set Caps", property="type")
|
|
|
|
|
layout.operator("grease_pencil.stroke_switch_direction")
|
2024-12-09 11:04:16 +01:00
|
|
|
layout.operator("grease_pencil.set_start_point", text="Set Start Point")
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2021-06-02 16:41:13 +02:00
|
|
|
layout.separator()
|
2024-10-04 13:05:09 +02:00
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.set_uniform_thickness")
|
|
|
|
|
layout.operator("grease_pencil.set_uniform_opacity")
|
2024-08-16 19:50:34 +02:00
|
|
|
layout.prop(settings, "use_scale_thickness", text="Scale Thickness")
|
2024-01-04 15:25:49 +01:00
|
|
|
|
2024-06-17 13:56:13 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2025-06-04 11:48:15 +02:00
|
|
|
layout.operator_menu_enum("grease_pencil.convert_curve_type", text="Convert Type", property="type")
|
|
|
|
|
layout.operator("grease_pencil.set_curve_resolution", text="Set Resolution")
|
2024-06-17 13:56:13 +02:00
|
|
|
|
2024-09-19 14:19:34 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.reset_uvs")
|
|
|
|
|
|
Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools.
Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`,
and `Draw Mode`.
While Grease Pencil has many editing tools, including editing
multiple frames at the same time, for now, node tools only
allow editing the current frame.
Currently, the idea is that node tools can do arbitrary changes
to the drawings, but cannot do changes to the existing layer tree, e.g.
changing the order of layers, removing a layer or groups, etc.
All the node tool specific nodes like `Selection` and `Set Selection`
are adapted to work with Grease Pencil. In `Draw Mode`, we currently
interpret everything as selected.
The `Active Element` node has a `Layer` mode that provides the
index of the active layer (if there is one).
When `Auto-Key` is used, a new keyframe is created on the
current frame.
Locked/invisible layers cannot be edited with node tools.
Pull Request: https://projects.blender.org/blender/blender/pulls/136624
2025-05-05 10:41:21 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2023-10-27 12:13:46 +11:00
|
|
|
|
2023-10-26 16:52:31 +02:00
|
|
|
class VIEW3D_MT_edit_greasepencil_point(Menu):
|
|
|
|
|
bl_label = "Point"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2024-05-29 13:10:13 +02:00
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.extrude_move", text="Extrude")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-02-08 12:41:23 +01:00
|
|
|
layout.operator("grease_pencil.stroke_smooth", text="Smooth")
|
2023-10-26 16:52:31 +02:00
|
|
|
|
2024-04-30 14:03:31 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_greasepencil_vertex_group")
|
|
|
|
|
|
2024-06-17 14:04:04 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator_menu_enum("grease_pencil.set_handle_type", property="type")
|
2025-09-29 18:19:05 +02:00
|
|
|
layout.operator_menu_enum("grease_pencil.set_corner_type", property="corner_type")
|
2024-06-17 14:04:04 +02:00
|
|
|
|
Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools.
Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`,
and `Draw Mode`.
While Grease Pencil has many editing tools, including editing
multiple frames at the same time, for now, node tools only
allow editing the current frame.
Currently, the idea is that node tools can do arbitrary changes
to the drawings, but cannot do changes to the existing layer tree, e.g.
changing the order of layers, removing a layer or groups, etc.
All the node tool specific nodes like `Selection` and `Set Selection`
are adapted to work with Grease Pencil. In `Draw Mode`, we currently
interpret everything as selected.
The `Active Element` node has a `Layer` mode that provides the
index of the active layer (if there is one).
When `Auto-Key` is used, a new keyframe is created on the
current frame.
Locked/invisible layers cannot be edited with node tools.
Pull Request: https://projects.blender.org/blender/blender/pulls/136624
2025-05-05 10:41:21 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
2023-05-30 11:14:16 +02:00
|
|
|
|
2024-04-11 15:11:02 +02:00
|
|
|
class VIEW3D_MT_edit_curves_add(Menu):
|
|
|
|
|
bl_label = "Add"
|
2024-06-13 12:15:55 +02:00
|
|
|
bl_translation_context = i18n_contexts.operator_default
|
2024-04-11 15:11:02 +02:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2025-08-29 20:00:05 +02:00
|
|
|
layout.operator("curves.add_bezier", text="Bézier", icon='CURVE_BEZCURVE')
|
2024-04-11 15:11:02 +02:00
|
|
|
layout.operator("curves.add_circle", text="Circle", icon='CURVE_BEZCIRCLE')
|
|
|
|
|
|
|
|
|
|
|
2022-02-18 11:16:02 +01:00
|
|
|
class VIEW3D_MT_edit_curves(Menu):
|
|
|
|
|
bl_label = "Curves"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
2023-01-21 20:38:36 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.menu("VIEW3D_MT_transform")
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
|
|
|
|
|
2023-01-21 20:38:36 +01:00
|
|
|
layout.separator()
|
2025-03-03 16:33:00 +01:00
|
|
|
|
2023-12-11 15:44:59 -05:00
|
|
|
layout.operator("curves.duplicate_move")
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.operator("curves.extrude_move")
|
2025-03-03 11:08:28 -05:00
|
|
|
|
2023-12-11 15:44:59 -05:00
|
|
|
layout.separator()
|
2025-03-03 16:33:00 +01:00
|
|
|
|
2023-10-17 12:35:40 +02:00
|
|
|
layout.operator("curves.attribute_set")
|
2024-04-04 21:04:51 +02:00
|
|
|
layout.operator_menu_enum("curves.curve_type_set", "type")
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.operator("curves.cyclic_toggle")
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
2022-02-18 11:16:02 +01:00
|
|
|
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.separator()
|
2025-03-03 11:08:28 -05:00
|
|
|
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.operator("curves.separate")
|
|
|
|
|
layout.operator("curves.delete")
|
2022-02-18 11:16:02 +01:00
|
|
|
|
2025-03-03 11:08:28 -05:00
|
|
|
|
2024-04-10 13:08:50 +02:00
|
|
|
class VIEW3D_MT_edit_curves_control_points(Menu):
|
|
|
|
|
bl_label = "Control Points"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-05-28 11:37:22 +02:00
|
|
|
layout.operator("curves.extrude_move")
|
2024-04-10 13:08:50 +02:00
|
|
|
layout.operator_menu_enum("curves.handle_type_set", "type")
|
|
|
|
|
|
|
|
|
|
|
2024-04-05 13:23:22 +02:00
|
|
|
class VIEW3D_MT_edit_curves_segments(Menu):
|
|
|
|
|
bl_label = "Segments"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2024-04-05 13:50:09 +02:00
|
|
|
layout.operator("curves.subdivide")
|
2024-04-05 13:23:22 +02:00
|
|
|
layout.operator("curves.switch_direction")
|
|
|
|
|
|
|
|
|
|
|
2024-05-28 11:38:17 +02:00
|
|
|
class VIEW3D_MT_edit_curves_context_menu(Menu):
|
|
|
|
|
bl_label = "Curves"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
|
|
|
|
|
2025-03-03 16:33:00 +01:00
|
|
|
# Additive Operators
|
2024-05-28 11:38:17 +02:00
|
|
|
layout.operator("curves.subdivide")
|
2025-03-03 16:33:00 +01:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2024-05-28 11:38:17 +02:00
|
|
|
layout.operator("curves.extrude_move")
|
|
|
|
|
|
2024-10-31 10:42:24 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
2025-03-03 16:33:00 +01:00
|
|
|
# Deform Operators
|
|
|
|
|
layout.menu("VIEW3D_MT_mirror")
|
|
|
|
|
layout.menu("VIEW3D_MT_snap")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Modify Flags
|
|
|
|
|
layout.operator_menu_enum("curves.curve_type_set", "type")
|
2024-10-31 10:42:24 +01:00
|
|
|
layout.operator_menu_enum("curves.handle_type_set", "type")
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.operator("curves.cyclic_toggle")
|
|
|
|
|
layout.operator("curves.switch_direction")
|
2025-03-03 11:08:28 -05:00
|
|
|
|
2025-03-03 16:33:00 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Removal Operators
|
|
|
|
|
layout.operator("curves.separate")
|
|
|
|
|
layout.operator("curves.delete")
|
2024-10-31 10:42:24 +01:00
|
|
|
|
2025-02-24 11:32:59 +01:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("curves.split")
|
|
|
|
|
|
2024-05-28 11:38:17 +02:00
|
|
|
|
2023-06-28 12:52:45 -04:00
|
|
|
class VIEW3D_MT_edit_pointcloud(Menu):
|
|
|
|
|
bl_label = "Point Cloud"
|
|
|
|
|
|
2023-08-04 18:22:45 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2025-02-16 23:25:22 -05:00
|
|
|
layout.menu("VIEW3D_MT_transform")
|
|
|
|
|
layout.separator()
|
2025-02-19 17:11:08 +01:00
|
|
|
layout.operator("pointcloud.duplicate_move")
|
2025-02-17 11:35:34 -05:00
|
|
|
layout.separator()
|
2025-02-19 17:11:08 +01:00
|
|
|
layout.operator("pointcloud.attribute_set")
|
|
|
|
|
layout.operator("pointcloud.delete")
|
|
|
|
|
layout.operator("pointcloud.separate")
|
2023-08-04 18:22:45 +02:00
|
|
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
2023-06-28 12:52:45 -04:00
|
|
|
|
|
|
|
|
|
2018-06-20 16:32:31 +02:00
|
|
|
class VIEW3D_MT_object_mode_pie(Menu):
|
2018-06-07 20:46:12 +02:00
|
|
|
bl_label = "Mode"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-06-07 20:46:12 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
pie = layout.menu_pie()
|
2018-12-18 15:01:03 +11:00
|
|
|
pie.operator_enum("object.mode_set", "mode")
|
2018-06-07 20:46:12 +02:00
|
|
|
|
|
|
|
|
|
2018-06-20 16:32:31 +02:00
|
|
|
class VIEW3D_MT_view_pie(Menu):
|
2018-06-07 20:46:12 +02:00
|
|
|
bl_label = "View"
|
2018-06-20 16:32:31 +02:00
|
|
|
bl_idname = "VIEW3D_MT_view_pie"
|
2018-06-07 20:46:12 +02:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-06-07 20:46:12 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
pie = layout.menu_pie()
|
2018-12-18 15:01:03 +11:00
|
|
|
pie.operator_enum("view3d.view_axis", "type")
|
2018-07-06 11:17:50 +02:00
|
|
|
pie.operator("view3d.view_camera", text="View Camera", icon='CAMERA_DATA')
|
2018-06-07 20:46:12 +02:00
|
|
|
pie.operator("view3d.view_selected", text="View Selected", icon='ZOOM_SELECTED')
|
|
|
|
|
|
|
|
|
|
|
2019-05-14 15:05:19 +10:00
|
|
|
class VIEW3D_MT_transform_gizmo_pie(Menu):
|
|
|
|
|
bl_label = "View"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
# 1: Left
|
|
|
|
|
pie.operator("view3d.transform_gizmo_set", text="Move").type = {'TRANSLATE'}
|
|
|
|
|
# 2: Right
|
|
|
|
|
pie.operator("view3d.transform_gizmo_set", text="Rotate").type = {'ROTATE'}
|
|
|
|
|
# 3: Down
|
|
|
|
|
pie.operator("view3d.transform_gizmo_set", text="Scale").type = {'SCALE'}
|
|
|
|
|
# 4: Up
|
|
|
|
|
pie.prop(context.space_data, "show_gizmo", text="Show Gizmos", icon='GIZMO')
|
|
|
|
|
# 5: Up/Left
|
|
|
|
|
pie.operator("view3d.transform_gizmo_set", text="All").type = {'TRANSLATE', 'ROTATE', 'SCALE'}
|
|
|
|
|
|
|
|
|
|
|
2018-09-21 15:46:49 +02:00
|
|
|
class VIEW3D_MT_shading_pie(Menu):
|
|
|
|
|
bl_label = "Shading"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-09-21 17:01:10 +02:00
|
|
|
pie = layout.menu_pie()
|
2018-09-21 15:46:49 +02:00
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
|
2019-01-08 17:17:52 +11:00
|
|
|
pie.prop(view.shading, "type", expand=True)
|
2018-09-21 15:46:49 +02:00
|
|
|
|
|
|
|
|
|
2018-11-24 11:24:34 +11:00
|
|
|
class VIEW3D_MT_shading_ex_pie(Menu):
|
|
|
|
|
bl_label = "Shading"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
|
|
|
|
|
pie.prop_enum(view.shading, "type", value='WIREFRAME')
|
2018-11-26 01:00:05 +01:00
|
|
|
pie.prop_enum(view.shading, "type", value='SOLID')
|
2018-11-24 11:24:34 +11:00
|
|
|
|
2023-02-12 14:37:16 +11:00
|
|
|
# Note this duplicates "view3d.toggle_xray" logic, so we can see the active item: #58661.
|
2019-03-12 10:21:55 +11:00
|
|
|
if context.pose_object:
|
2018-12-05 15:19:52 +01:00
|
|
|
pie.prop(view.overlay, "show_xray_bone", icon='XRAY')
|
2018-12-05 11:50:35 +11:00
|
|
|
else:
|
2018-12-05 15:19:52 +01:00
|
|
|
xray_active = (
|
|
|
|
|
(context.mode == 'EDIT_MESH') or
|
|
|
|
|
(view.shading.type in {'SOLID', 'WIREFRAME'})
|
|
|
|
|
)
|
|
|
|
|
if xray_active:
|
|
|
|
|
sub = pie
|
2018-12-05 11:50:35 +11:00
|
|
|
else:
|
2018-12-05 15:19:52 +01:00
|
|
|
sub = pie.row()
|
|
|
|
|
sub.active = False
|
|
|
|
|
sub.prop(
|
|
|
|
|
view.shading,
|
|
|
|
|
"show_xray_wireframe" if (view.shading.type == 'WIREFRAME') else "show_xray",
|
|
|
|
|
text="Toggle X-Ray",
|
|
|
|
|
icon='XRAY',
|
|
|
|
|
)
|
2018-11-24 11:24:34 +11:00
|
|
|
|
|
|
|
|
pie.prop(view.overlay, "show_overlays", text="Toggle Overlays", icon='OVERLAY')
|
|
|
|
|
|
|
|
|
|
pie.prop_enum(view.shading, "type", value='MATERIAL')
|
|
|
|
|
pie.prop_enum(view.shading, "type", value='RENDERED')
|
|
|
|
|
|
|
|
|
|
|
2018-09-26 17:32:11 +02:00
|
|
|
class VIEW3D_MT_pivot_pie(Menu):
|
|
|
|
|
bl_label = "Pivot Point"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
2023-09-15 10:44:42 +10:00
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
2018-09-26 17:32:11 +02:00
|
|
|
obj = context.active_object
|
|
|
|
|
mode = context.mode
|
|
|
|
|
|
2023-09-15 10:44:42 +10:00
|
|
|
pie.prop_enum(tool_settings, "transform_pivot_point", value='BOUNDING_BOX_CENTER')
|
|
|
|
|
pie.prop_enum(tool_settings, "transform_pivot_point", value='CURSOR')
|
|
|
|
|
pie.prop_enum(tool_settings, "transform_pivot_point", value='INDIVIDUAL_ORIGINS')
|
|
|
|
|
pie.prop_enum(tool_settings, "transform_pivot_point", value='MEDIAN_POINT')
|
|
|
|
|
pie.prop_enum(tool_settings, "transform_pivot_point", value='ACTIVE_ELEMENT')
|
2018-09-26 17:32:11 +02:00
|
|
|
if (obj is None) or (mode in {'OBJECT', 'POSE', 'WEIGHT_PAINT'}):
|
2023-09-15 10:44:42 +10:00
|
|
|
pie.prop(tool_settings, "use_transform_pivot_point_align")
|
2025-01-03 14:47:57 +11:00
|
|
|
if mode in {'EDIT_GPENCIL', 'EDIT_GREASE_PENCIL'}:
|
2023-09-15 10:44:42 +10:00
|
|
|
pie.prop(tool_settings.gpencil_sculpt, "use_scale_thickness")
|
2018-09-26 17:32:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_orientations_pie(Menu):
|
|
|
|
|
bl_label = "Orientation"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
scene = context.scene
|
|
|
|
|
|
2018-12-21 21:29:04 +11:00
|
|
|
pie.prop(scene.transform_orientation_slots[0], "type", expand=True)
|
2018-09-26 17:32:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_MT_snap_pie(Menu):
|
|
|
|
|
bl_label = "Snap"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-09-26 17:32:11 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
2019-05-17 23:22:22 +02:00
|
|
|
pie.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid", icon='CURSOR')
|
2018-09-26 17:32:11 +02:00
|
|
|
pie.operator("view3d.snap_selected_to_grid", text="Selection to Grid", icon='RESTRICT_SELECT_OFF')
|
2019-05-17 23:22:22 +02:00
|
|
|
pie.operator("view3d.snap_cursor_to_selected", text="Cursor to Selected", icon='CURSOR')
|
2019-05-22 00:27:01 +10:00
|
|
|
pie.operator(
|
|
|
|
|
"view3d.snap_selected_to_cursor",
|
|
|
|
|
text="Selection to Cursor",
|
|
|
|
|
icon='RESTRICT_SELECT_OFF',
|
|
|
|
|
).use_offset = False
|
|
|
|
|
pie.operator(
|
|
|
|
|
"view3d.snap_selected_to_cursor",
|
|
|
|
|
text="Selection to Cursor (Keep Offset)",
|
|
|
|
|
icon='RESTRICT_SELECT_OFF',
|
|
|
|
|
).use_offset = True
|
2018-09-26 17:32:11 +02:00
|
|
|
pie.operator("view3d.snap_selected_to_active", text="Selection to Active", icon='RESTRICT_SELECT_OFF')
|
2019-05-17 23:22:22 +02:00
|
|
|
pie.operator("view3d.snap_cursor_to_center", text="Cursor to World Origin", icon='CURSOR')
|
|
|
|
|
pie.operator("view3d.snap_cursor_to_active", text="Cursor to Active", icon='CURSOR')
|
2018-09-26 17:32:11 +02:00
|
|
|
|
2018-09-27 09:41:18 +10:00
|
|
|
|
2018-09-26 17:32:11 +02:00
|
|
|
class VIEW3D_MT_proportional_editing_falloff_pie(Menu):
|
|
|
|
|
bl_label = "Proportional Editing Falloff"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
2023-09-15 10:44:42 +10:00
|
|
|
|
2018-09-26 17:32:11 +02:00
|
|
|
tool_settings = context.scene.tool_settings
|
|
|
|
|
|
|
|
|
|
pie.prop(tool_settings, "proportional_edit_falloff", expand=True)
|
|
|
|
|
|
2019-09-10 06:11:52 +10:00
|
|
|
|
2019-09-09 16:20:40 +02:00
|
|
|
class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
|
|
|
|
|
bl_label = "Mask Edit"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("paint.mask_flood_fill", text="Invert Mask")
|
|
|
|
|
props.mode = 'INVERT'
|
|
|
|
|
props = pie.operator("paint.mask_flood_fill", text="Clear Mask")
|
|
|
|
|
props.mode = 'VALUE'
|
|
|
|
|
props.value = 0.0
|
|
|
|
|
props = pie.operator("sculpt.mask_filter", text="Smooth Mask")
|
|
|
|
|
props.filter_type = 'SMOOTH'
|
|
|
|
|
props = pie.operator("sculpt.mask_filter", text="Sharpen Mask")
|
|
|
|
|
props.filter_type = 'SHARPEN'
|
|
|
|
|
props = pie.operator("sculpt.mask_filter", text="Grow Mask")
|
|
|
|
|
props.filter_type = 'GROW'
|
|
|
|
|
props = pie.operator("sculpt.mask_filter", text="Shrink Mask")
|
|
|
|
|
props.filter_type = 'SHRINK'
|
|
|
|
|
props = pie.operator("sculpt.mask_filter", text="Increase Contrast")
|
|
|
|
|
props.filter_type = 'CONTRAST_INCREASE'
|
|
|
|
|
props.auto_iteration_count = False
|
|
|
|
|
props = pie.operator("sculpt.mask_filter", text="Decrease Contrast")
|
|
|
|
|
props.filter_type = 'CONTRAST_DECREASE'
|
|
|
|
|
props.auto_iteration_count = False
|
2019-09-09 16:20:40 +02:00
|
|
|
|
2020-12-16 18:02:40 +11:00
|
|
|
|
2020-10-20 14:10:54 +02:00
|
|
|
class VIEW3D_MT_sculpt_automasking_pie(Menu):
|
|
|
|
|
bl_label = "Automasking"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
sculpt = tool_settings.sculpt
|
|
|
|
|
|
|
|
|
|
pie.prop(sculpt, "use_automasking_topology", text="Topology")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
2022-09-28 16:22:34 -07:00
|
|
|
pie.prop(sculpt, "use_automasking_cavity", text="Cavity")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_cavity_inverted", text="Cavity (Inverted)")
|
2022-09-28 23:21:56 -07:00
|
|
|
pie.prop(sculpt, "use_automasking_start_normal", text="Area Normal")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_view_normal", text="View Normal")
|
2020-10-20 14:10:54 +02:00
|
|
|
|
2020-10-02 10:10:01 +10:00
|
|
|
|
2024-10-15 11:35:57 +02:00
|
|
|
class VIEW3D_MT_grease_pencil_sculpt_automasking_pie(Menu):
|
|
|
|
|
bl_label = "Automasking"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
sculpt = tool_settings.gpencil_sculpt
|
|
|
|
|
|
|
|
|
|
pie.prop(sculpt, "use_automasking_stroke", text="Stroke")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_layer_stroke", text="Layer")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_material_stroke", text="Material")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_layer_active", text="Active Layer")
|
|
|
|
|
pie.prop(sculpt, "use_automasking_material_active", text="Active Material")
|
|
|
|
|
|
|
|
|
|
|
2020-03-05 14:53:23 +01:00
|
|
|
class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
|
2020-04-16 11:43:19 +10:00
|
|
|
|
2020-03-05 14:53:23 +01:00
|
|
|
bl_label = "Face Sets Edit"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("sculpt.face_sets_create", text="Face Set from Masked")
|
|
|
|
|
props.mode = 'MASKED'
|
2020-03-05 14:53:23 +01:00
|
|
|
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("sculpt.face_sets_create", text="Face Set from Visible")
|
|
|
|
|
props.mode = 'VISIBLE'
|
2020-03-05 14:53:23 +01:00
|
|
|
|
2023-12-06 11:19:25 -05:00
|
|
|
pie.operator("paint.visibility_invert", text="Invert Visible")
|
2020-03-05 14:53:23 +01:00
|
|
|
|
2024-03-06 05:25:43 +01:00
|
|
|
props = pie.operator("paint.hide_show_all", text="Show All")
|
2024-05-03 11:25:06 +10:00
|
|
|
props.action = 'SHOW'
|
2020-10-02 10:10:01 +10:00
|
|
|
|
2022-10-12 10:29:44 +11:00
|
|
|
|
2019-12-23 12:46:05 +03:00
|
|
|
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
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'ALL'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 2: Right
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'ALL'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 3: Down
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock Selected")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'SELECTED'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 4: Up
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Selected")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'SELECTED'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 5: Up/Left
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Unselected")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'UNSELECTED'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 6: Up/Right
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", text="Lock Only Selected")
|
|
|
|
|
props.action, props.mask = 'LOCK', 'INVERT_UNSELECTED'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 7: Down/Left
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", text="Lock Only Unselected")
|
|
|
|
|
props.action, props.mask = 'UNLOCK', 'INVERT_UNSELECTED'
|
2019-12-23 12:46:05 +03:00
|
|
|
# 8: Down/Right
|
2023-04-13 13:14:01 +10:00
|
|
|
props = pie.operator("object.vertex_group_lock", text="Invert Locks")
|
|
|
|
|
props.action, props.mask = 'INVERT', 'ALL'
|
2019-12-23 12:46:05 +03:00
|
|
|
|
|
|
|
|
|
2009-08-15 20:21:49 +00:00
|
|
|
# ********** Panel **********
|
2009-07-11 13:32:20 +00:00
|
|
|
|
2015-01-29 15:35:06 +11:00
|
|
|
|
2019-05-15 12:20:13 +10:00
|
|
|
class VIEW3D_PT_active_tool(Panel, ToolActivePanelHelper):
|
2019-04-29 22:50:14 +10:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "Tool"
|
2019-05-16 19:43:11 +10:00
|
|
|
# See comment below.
|
|
|
|
|
# bl_options = {'HIDE_HEADER'}
|
|
|
|
|
|
|
|
|
|
# Don't show in properties editor.
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.area.type == 'VIEW_3D'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# FIXME(campbell): remove this second panel once 'HIDE_HEADER' works with category tabs,
|
|
|
|
|
# Currently pinning allows ordering headerless panels below panels with headers.
|
|
|
|
|
class VIEW3D_PT_active_tool_duplicate(Panel, ToolActivePanelHelper):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "Tool"
|
|
|
|
|
bl_options = {'HIDE_HEADER'}
|
|
|
|
|
|
|
|
|
|
# Only show in properties editor.
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.area.type != 'VIEW_3D'
|
2019-04-29 22:50:14 +10:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_PT_view3d_properties(Panel):
|
2009-10-31 19:31:45 +00:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2018-09-27 16:22:50 +10:00
|
|
|
bl_category = "View"
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "View"
|
2009-10-31 19:31:45 +00:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
|
2018-07-06 18:22:55 +02:00
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False # No animation.
|
2009-10-31 19:31:45 +00:00
|
|
|
|
UI: Layout changes for new checkbox layout possibilities
Follow-up to previous commit.
Some examples:
{F8473507} {F8473508} {F8473509} {F8473510}
For more screenshots, please see D7430.
We use column or row headings here to bring more structure, and to give
the eye visual anchors which aid eye-scanning. The left-aligned
checkboxes likewise help with this. And we keep the adherence to the
center line, so the alignment matches up between the various buttons and
controls.
* Changes the property split percentage from 50/50% to 40/60%. This is
needed to give enough space for the checkboxes. But in most cases this
looks better anyway - see Transform panel. In some cases it simply
fills out the available space more efficently.
* Fix various hacks where we previously used manually defined splits.
When we did this, the alignment was never quite right, and the layout
code was a mess.
* Adds column headings to many places where a list of checkboxes all
share a common purpose or leading text.
* Add checkbox + value configurations various places where a checkbox
only serves to enable the value slider
* Removes most uses of grid flow layout. The grid flow layouts combine
poorly with column headings, and also they would mess alignment up
badly. The grid flow layouts also often made buttons and controls jump
around on the screen if you would just resize editors slightly,
causing visual confusion, making users lose their place. The logic for
at what time the list of items would re-flow was often flawed, jumping
to multiple columns too fast or too late - and frankly, the grid flow
layouts would often just look bad.
Maniphest Task: https://developer.blender.org/T65965
Differential Revision: https://developer.blender.org/D7430
Reviewed by: Brecht Van Lommel, Pablo Vazquez.
Most work here by William Reynish, few changes by Julian Eisel.
2020-04-17 16:54:03 +02:00
|
|
|
col = layout.column()
|
2011-05-14 17:50:33 +00:00
|
|
|
|
2018-07-06 18:22:55 +02:00
|
|
|
subcol = col.column()
|
|
|
|
|
subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
|
|
|
|
|
subcol.prop(view, "lens", text="Focal Length")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2013-08-23 20:41:21 +00:00
|
|
|
subcol = col.column(align=True)
|
2018-07-06 18:22:55 +02:00
|
|
|
subcol.prop(view, "clip_start", text="Clip Start")
|
2024-12-26 12:33:26 +01:00
|
|
|
subcol.prop(view, "clip_end", text="End", text_ctxt=i18n_contexts.id_camera)
|
2018-07-06 18:22:55 +02:00
|
|
|
|
2020-04-17 20:43:12 +02:00
|
|
|
layout.separator()
|
2019-01-24 17:20:04 +01:00
|
|
|
|
UI: Layout changes for new checkbox layout possibilities
Follow-up to previous commit.
Some examples:
{F8473507} {F8473508} {F8473509} {F8473510}
For more screenshots, please see D7430.
We use column or row headings here to bring more structure, and to give
the eye visual anchors which aid eye-scanning. The left-aligned
checkboxes likewise help with this. And we keep the adherence to the
center line, so the alignment matches up between the various buttons and
controls.
* Changes the property split percentage from 50/50% to 40/60%. This is
needed to give enough space for the checkboxes. But in most cases this
looks better anyway - see Transform panel. In some cases it simply
fills out the available space more efficently.
* Fix various hacks where we previously used manually defined splits.
When we did this, the alignment was never quite right, and the layout
code was a mess.
* Adds column headings to many places where a list of checkboxes all
share a common purpose or leading text.
* Add checkbox + value configurations various places where a checkbox
only serves to enable the value slider
* Removes most uses of grid flow layout. The grid flow layouts combine
poorly with column headings, and also they would mess alignment up
badly. The grid flow layouts also often made buttons and controls jump
around on the screen if you would just resize editors slightly,
causing visual confusion, making users lose their place. The logic for
at what time the list of items would re-flow was often flawed, jumping
to multiple columns too fast or too late - and frankly, the grid flow
layouts would often just look bad.
Maniphest Task: https://developer.blender.org/T65965
Differential Revision: https://developer.blender.org/D7430
Reviewed by: Brecht Van Lommel, Pablo Vazquez.
Most work here by William Reynish, few changes by Julian Eisel.
2020-04-17 16:54:03 +02:00
|
|
|
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="")
|
2018-07-06 18:22:55 +02:00
|
|
|
|
2024-06-03 19:17:21 +02:00
|
|
|
sub = col.row()
|
|
|
|
|
sub.active = view.region_3d.view_perspective == 'CAMERA'
|
|
|
|
|
sub.prop(view.overlay, "show_camera_passepartout", text="Passepartout")
|
|
|
|
|
|
2020-04-17 20:43:12 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(view, "use_render_border")
|
|
|
|
|
col.active = view.region_3d.view_perspective != 'CAMERA'
|
2018-07-06 18:22:55 +02:00
|
|
|
|
|
|
|
|
|
2019-03-07 12:53:45 +11:00
|
|
|
class VIEW3D_PT_view3d_lock(Panel):
|
2018-07-06 18:22:55 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2018-09-27 16:22:50 +10:00
|
|
|
bl_category = "View"
|
2019-03-07 12:46:17 +11:00
|
|
|
bl_label = "View Lock"
|
2018-07-06 18:22:55 +02:00
|
|
|
bl_parent_id = "VIEW3D_PT_view3d_properties"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False # No animation.
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
2010-04-27 06:47:12 +00:00
|
|
|
|
2012-10-16 11:57:46 +00:00
|
|
|
col = layout.column(align=True)
|
UI: Layout changes for new checkbox layout possibilities
Follow-up to previous commit.
Some examples:
{F8473507} {F8473508} {F8473509} {F8473510}
For more screenshots, please see D7430.
We use column or row headings here to bring more structure, and to give
the eye visual anchors which aid eye-scanning. The left-aligned
checkboxes likewise help with this. And we keep the adherence to the
center line, so the alignment matches up between the various buttons and
controls.
* Changes the property split percentage from 50/50% to 40/60%. This is
needed to give enough space for the checkboxes. But in most cases this
looks better anyway - see Transform panel. In some cases it simply
fills out the available space more efficently.
* Fix various hacks where we previously used manually defined splits.
When we did this, the alignment was never quite right, and the layout
code was a mess.
* Adds column headings to many places where a list of checkboxes all
share a common purpose or leading text.
* Add checkbox + value configurations various places where a checkbox
only serves to enable the value slider
* Removes most uses of grid flow layout. The grid flow layouts combine
poorly with column headings, and also they would mess alignment up
badly. The grid flow layouts also often made buttons and controls jump
around on the screen if you would just resize editors slightly,
causing visual confusion, making users lose their place. The logic for
at what time the list of items would re-flow was often flawed, jumping
to multiple columns too fast or too late - and frankly, the grid flow
layouts would often just look bad.
Maniphest Task: https://developer.blender.org/T65965
Differential Revision: https://developer.blender.org/D7430
Reviewed by: Brecht Van Lommel, Pablo Vazquez.
Most work here by William Reynish, few changes by Julian Eisel.
2020-04-17 16:54:03 +02:00
|
|
|
sub = col.column()
|
|
|
|
|
sub.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
|
2018-07-06 18:22:55 +02:00
|
|
|
|
UI: Layout changes for new checkbox layout possibilities
Follow-up to previous commit.
Some examples:
{F8473507} {F8473508} {F8473509} {F8473510}
For more screenshots, please see D7430.
We use column or row headings here to bring more structure, and to give
the eye visual anchors which aid eye-scanning. The left-aligned
checkboxes likewise help with this. And we keep the adherence to the
center line, so the alignment matches up between the various buttons and
controls.
* Changes the property split percentage from 50/50% to 40/60%. This is
needed to give enough space for the checkboxes. But in most cases this
looks better anyway - see Transform panel. In some cases it simply
fills out the available space more efficently.
* Fix various hacks where we previously used manually defined splits.
When we did this, the alignment was never quite right, and the layout
code was a mess.
* Adds column headings to many places where a list of checkboxes all
share a common purpose or leading text.
* Add checkbox + value configurations various places where a checkbox
only serves to enable the value slider
* Removes most uses of grid flow layout. The grid flow layouts combine
poorly with column headings, and also they would mess alignment up
badly. The grid flow layouts also often made buttons and controls jump
around on the screen if you would just resize editors slightly,
causing visual confusion, making users lose their place. The logic for
at what time the list of items would re-flow was often flawed, jumping
to multiple columns too fast or too late - and frankly, the grid flow
layouts would often just look bad.
Maniphest Task: https://developer.blender.org/T65965
Differential Revision: https://developer.blender.org/D7430
Reviewed by: Brecht Van Lommel, Pablo Vazquez.
Most work here by William Reynish, few changes by Julian Eisel.
2020-04-17 16:54:03 +02:00
|
|
|
sub.prop(view, "lock_object")
|
2018-07-06 18:22:55 +02:00
|
|
|
lock_object = view.lock_object
|
|
|
|
|
if lock_object:
|
|
|
|
|
if lock_object.type == 'ARMATURE':
|
UI: Layout changes for new checkbox layout possibilities
Follow-up to previous commit.
Some examples:
{F8473507} {F8473508} {F8473509} {F8473510}
For more screenshots, please see D7430.
We use column or row headings here to bring more structure, and to give
the eye visual anchors which aid eye-scanning. The left-aligned
checkboxes likewise help with this. And we keep the adherence to the
center line, so the alignment matches up between the various buttons and
controls.
* Changes the property split percentage from 50/50% to 40/60%. This is
needed to give enough space for the checkboxes. But in most cases this
looks better anyway - see Transform panel. In some cases it simply
fills out the available space more efficently.
* Fix various hacks where we previously used manually defined splits.
When we did this, the alignment was never quite right, and the layout
code was a mess.
* Adds column headings to many places where a list of checkboxes all
share a common purpose or leading text.
* Add checkbox + value configurations various places where a checkbox
only serves to enable the value slider
* Removes most uses of grid flow layout. The grid flow layouts combine
poorly with column headings, and also they would mess alignment up
badly. The grid flow layouts also often made buttons and controls jump
around on the screen if you would just resize editors slightly,
causing visual confusion, making users lose their place. The logic for
at what time the list of items would re-flow was often flawed, jumping
to multiple columns too fast or too late - and frankly, the grid flow
layouts would often just look bad.
Maniphest Task: https://developer.blender.org/T65965
Differential Revision: https://developer.blender.org/D7430
Reviewed by: Brecht Van Lommel, Pablo Vazquez.
Most work here by William Reynish, few changes by Julian Eisel.
2020-04-17 16:54:03 +02:00
|
|
|
sub.prop_search(
|
2018-07-06 18:22:55 +02:00
|
|
|
view, "lock_bone", lock_object.data,
|
|
|
|
|
"edit_bones" if lock_object.mode == 'EDIT'
|
|
|
|
|
else "bones",
|
2021-01-04 17:32:22 -06:00
|
|
|
text="Bone",
|
2018-07-06 18:22:55 +02:00
|
|
|
)
|
|
|
|
|
|
2021-01-04 17:32:22 -06:00
|
|
|
col = layout.column(heading="Lock", align=True)
|
|
|
|
|
if not lock_object:
|
|
|
|
|
col.prop(view, "lock_cursor", text="To 3D Cursor")
|
UI: Layout changes for new checkbox layout possibilities
Follow-up to previous commit.
Some examples:
{F8473507} {F8473508} {F8473509} {F8473510}
For more screenshots, please see D7430.
We use column or row headings here to bring more structure, and to give
the eye visual anchors which aid eye-scanning. The left-aligned
checkboxes likewise help with this. And we keep the adherence to the
center line, so the alignment matches up between the various buttons and
controls.
* Changes the property split percentage from 50/50% to 40/60%. This is
needed to give enough space for the checkboxes. But in most cases this
looks better anyway - see Transform panel. In some cases it simply
fills out the available space more efficently.
* Fix various hacks where we previously used manually defined splits.
When we did this, the alignment was never quite right, and the layout
code was a mess.
* Adds column headings to many places where a list of checkboxes all
share a common purpose or leading text.
* Add checkbox + value configurations various places where a checkbox
only serves to enable the value slider
* Removes most uses of grid flow layout. The grid flow layouts combine
poorly with column headings, and also they would mess alignment up
badly. The grid flow layouts also often made buttons and controls jump
around on the screen if you would just resize editors slightly,
causing visual confusion, making users lose their place. The logic for
at what time the list of items would re-flow was often flawed, jumping
to multiple columns too fast or too late - and frankly, the grid flow
layouts would often just look bad.
Maniphest Task: https://developer.blender.org/T65965
Differential Revision: https://developer.blender.org/D7430
Reviewed by: Brecht Van Lommel, Pablo Vazquez.
Most work here by William Reynish, few changes by Julian Eisel.
2020-04-17 16:54:03 +02:00
|
|
|
col.prop(view, "lock_camera", text="Camera to View")
|
2024-10-08 18:16:36 +02:00
|
|
|
col.prop(view.region_3d, "lock_rotation", text="Rotation")
|
2012-10-16 11:57:46 +00:00
|
|
|
|
2011-11-06 06:19:00 +00:00
|
|
|
|
|
|
|
|
class VIEW3D_PT_view3d_cursor(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2018-09-27 16:22:50 +10:00
|
|
|
bl_category = "View"
|
2011-11-06 06:19:00 +00:00
|
|
|
bl_label = "3D Cursor"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2019-03-01 12:35:48 +11:00
|
|
|
cursor = context.scene.cursor
|
2018-07-06 18:29:57 +02:00
|
|
|
|
2019-03-01 12:35:48 +11:00
|
|
|
layout.column().prop(cursor, "location", text="Location")
|
|
|
|
|
rotation_mode = cursor.rotation_mode
|
2019-02-26 00:58:35 +11:00
|
|
|
if rotation_mode == 'QUATERNION':
|
2019-03-01 12:35:48 +11:00
|
|
|
layout.column().prop(cursor, "rotation_quaternion", text="Rotation")
|
2019-02-26 00:58:35 +11:00
|
|
|
elif rotation_mode == 'AXIS_ANGLE':
|
2019-03-01 12:35:48 +11:00
|
|
|
layout.column().prop(cursor, "rotation_axis_angle", text="Rotation")
|
2019-02-26 00:58:35 +11:00
|
|
|
else:
|
2019-03-01 12:35:48 +11:00
|
|
|
layout.column().prop(cursor, "rotation_euler", text="Rotation")
|
|
|
|
|
layout.prop(cursor, "rotation_mode", text="")
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2009-11-14 13:35:44 +00:00
|
|
|
|
2018-11-15 11:35:14 -02:00
|
|
|
class VIEW3D_PT_collections(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
2019-04-16 14:52:44 +02:00
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "View"
|
2019-04-30 18:19:45 -03:00
|
|
|
bl_label = "Collections"
|
2019-04-18 19:14:19 +02:00
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
2018-11-15 11:35:14 -02:00
|
|
|
|
2019-08-19 14:25:29 -03:00
|
|
|
def _draw_collection(self, layout, view_layer, use_local_collections, collection, index):
|
2018-11-15 11:35:14 -02:00
|
|
|
need_separator = index
|
|
|
|
|
for child in collection.children:
|
|
|
|
|
index += 1
|
|
|
|
|
|
|
|
|
|
if child.exclude:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if child.collection.hide_viewport:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if need_separator:
|
|
|
|
|
layout.separator()
|
|
|
|
|
need_separator = False
|
|
|
|
|
|
|
|
|
|
icon = 'BLANK1'
|
2019-03-17 21:13:25 +11:00
|
|
|
# has_objects = True
|
2018-11-15 11:35:14 -02:00
|
|
|
if child.has_selected_objects(view_layer):
|
|
|
|
|
icon = 'LAYER_ACTIVE'
|
|
|
|
|
elif child.has_objects():
|
|
|
|
|
icon = 'LAYER_USED'
|
2018-11-15 13:32:03 -02:00
|
|
|
else:
|
2019-03-17 21:13:25 +11:00
|
|
|
# has_objects = False
|
|
|
|
|
pass
|
2018-11-15 13:32:03 -02:00
|
|
|
|
2018-11-15 11:35:14 -02:00
|
|
|
row = layout.row()
|
2019-08-19 14:25:29 -03:00
|
|
|
row.use_property_decorate = False
|
2018-11-15 13:32:03 -02:00
|
|
|
sub = row.split(factor=0.98)
|
|
|
|
|
subrow = sub.row()
|
|
|
|
|
subrow.alignment = 'LEFT'
|
2019-01-30 09:03:37 +11:00
|
|
|
subrow.operator(
|
|
|
|
|
"object.hide_collection", text=child.name, icon=icon, emboss=False,
|
|
|
|
|
).collection_index = index
|
2018-11-15 13:32:03 -02:00
|
|
|
|
|
|
|
|
sub = row.split()
|
|
|
|
|
subrow = sub.row(align=True)
|
|
|
|
|
subrow.alignment = 'RIGHT'
|
2019-08-19 14:25:29 -03:00
|
|
|
if not use_local_collections:
|
|
|
|
|
subrow.active = collection.is_visible # Parent collection runtime visibility
|
|
|
|
|
subrow.prop(child, "hide_viewport", text="", emboss=False)
|
|
|
|
|
else:
|
2019-10-12 10:22:09 +11:00
|
|
|
subrow.active = collection.visible_get() # Parent collection runtime visibility
|
2019-08-19 14:25:29 -03:00
|
|
|
icon = 'HIDE_OFF' if child.visible_get() else 'HIDE_ON'
|
|
|
|
|
props = subrow.operator("object.hide_collection", text="", icon=icon, emboss=False)
|
|
|
|
|
props.collection_index = index
|
|
|
|
|
props.toggle = True
|
2018-11-15 11:35:14 -02:00
|
|
|
|
|
|
|
|
for child in collection.children:
|
2019-08-19 14:25:29 -03:00
|
|
|
index = self._draw_collection(layout, view_layer, use_local_collections, child, index)
|
2018-11-15 11:35:14 -02:00
|
|
|
|
|
|
|
|
return index
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-11-15 13:32:03 -02:00
|
|
|
layout.use_property_split = False
|
2018-11-15 11:35:14 -02:00
|
|
|
|
2019-08-19 14:25:29 -03:00
|
|
|
view = context.space_data
|
2018-11-15 11:35:14 -02:00
|
|
|
view_layer = context.view_layer
|
2019-08-19 14:25:29 -03:00
|
|
|
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.prop(view, "use_local_collections")
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-08-11 22:41:04 +10:00
|
|
|
# We pass index 0 here because the index is increased
|
2018-11-15 11:35:14 -02:00
|
|
|
# so the first real index is 1
|
|
|
|
|
# And we start with index as 1 because we skip the master collection
|
2019-08-19 14:25:29 -03:00
|
|
|
self._draw_collection(layout, view_layer, view.use_local_collections, view_layer.layer_collection, 0)
|
2018-11-15 11:35:14 -02:00
|
|
|
|
|
|
|
|
|
2018-07-09 17:00:09 +02:00
|
|
|
class VIEW3D_PT_object_type_visibility(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
2018-07-11 13:24:04 +02:00
|
|
|
bl_region_type = 'HEADER'
|
2023-08-25 22:17:48 +02:00
|
|
|
bl_label = "Selectability & Visibility"
|
|
|
|
|
bl_ui_units_x = 8
|
2018-07-09 17:00:09 +02:00
|
|
|
|
2022-05-03 18:30:43 +10:00
|
|
|
# Allows derived classes to pass view data other than context.space_data.
|
2022-04-30 16:23:43 +09:00
|
|
|
# This is used by the official VR add-on, which passes XrSessionSettings
|
|
|
|
|
# since VR has a 3D view that only exists for the duration of the VR session.
|
2022-05-18 17:40:19 +10:00
|
|
|
def draw_ex(self, _context, view, show_select):
|
2018-07-09 17:00:09 +02:00
|
|
|
layout = self.layout
|
2018-07-10 20:25:50 +02:00
|
|
|
layout.use_property_split = True
|
2020-10-07 19:48:45 -05:00
|
|
|
layout.use_property_decorate = False
|
2018-07-10 20:25:50 +02:00
|
|
|
|
2023-08-25 22:17:48 +02:00
|
|
|
layout.label(text="Selectability & Visibility")
|
2020-10-19 10:55:05 -07:00
|
|
|
layout.separator()
|
2023-08-25 22:17:48 +02:00
|
|
|
col = layout.column(align=True)
|
2018-07-09 17:00:09 +02:00
|
|
|
|
2018-11-09 13:14:16 +11:00
|
|
|
attr_object_types = (
|
2023-08-29 14:55:10 +10:00
|
|
|
("mesh", "Mesh", 'OUTLINER_OB_MESH'),
|
|
|
|
|
("curve", "Curve", 'OUTLINER_OB_CURVE'),
|
|
|
|
|
("surf", "Surface", 'OUTLINER_OB_SURFACE'),
|
|
|
|
|
("meta", "Meta", 'OUTLINER_OB_META'),
|
|
|
|
|
("font", "Text", 'OUTLINER_OB_FONT'),
|
|
|
|
|
("curves", "Hair Curves", 'OUTLINER_OB_CURVES'),
|
|
|
|
|
("pointcloud", "Point Cloud", 'OUTLINER_OB_POINTCLOUD'),
|
|
|
|
|
("volume", "Volume", 'OUTLINER_OB_VOLUME'),
|
|
|
|
|
("grease_pencil", "Grease Pencil", 'OUTLINER_OB_GREASEPENCIL'),
|
|
|
|
|
("armature", "Armature", 'OUTLINER_OB_ARMATURE'),
|
|
|
|
|
("lattice", "Lattice", 'OUTLINER_OB_LATTICE'),
|
|
|
|
|
("empty", "Empty", 'OUTLINER_OB_EMPTY'),
|
|
|
|
|
("light", "Light", 'OUTLINER_OB_LIGHT'),
|
|
|
|
|
("light_probe", "Light Probe", 'OUTLINER_OB_LIGHTPROBE'),
|
|
|
|
|
("camera", "Camera", 'OUTLINER_OB_CAMERA'),
|
|
|
|
|
("speaker", "Speaker", 'OUTLINER_OB_SPEAKER'),
|
2018-11-09 13:14:16 +11:00
|
|
|
)
|
|
|
|
|
|
2023-08-25 22:17:48 +02:00
|
|
|
for attr, attr_name, attr_icon in attr_object_types:
|
2018-07-12 10:54:30 +02:00
|
|
|
if attr is None:
|
2018-07-12 10:48:18 +02:00
|
|
|
col.separator()
|
2018-07-12 10:54:30 +02:00
|
|
|
continue
|
2018-07-09 17:00:09 +02:00
|
|
|
|
2020-06-26 12:30:03 +10:00
|
|
|
attr_v = "show_object_viewport_" + attr
|
2018-11-09 11:20:45 +01:00
|
|
|
icon_v = 'HIDE_OFF' if getattr(view, attr_v) else 'HIDE_ON'
|
2018-07-12 10:48:18 +02:00
|
|
|
|
2018-07-12 10:54:30 +02:00
|
|
|
row = col.row(align=True)
|
2023-08-25 22:17:48 +02:00
|
|
|
row.label(text=attr_name, icon=attr_icon)
|
2022-04-30 16:23:43 +09:00
|
|
|
|
|
|
|
|
if show_select:
|
|
|
|
|
attr_s = "show_object_select_" + attr
|
|
|
|
|
icon_s = 'RESTRICT_SELECT_OFF' if getattr(view, attr_s) else 'RESTRICT_SELECT_ON'
|
|
|
|
|
|
|
|
|
|
rowsub = row.row(align=True)
|
|
|
|
|
rowsub.active = getattr(view, attr_v)
|
|
|
|
|
rowsub.prop(view, attr_s, text="", icon=icon_s, emboss=False)
|
|
|
|
|
|
2023-08-25 22:17:48 +02:00
|
|
|
row.prop(view, attr_v, text="", icon=icon_v, emboss=False)
|
|
|
|
|
|
2022-04-30 16:23:43 +09:00
|
|
|
def draw(self, context):
|
|
|
|
|
view = context.space_data
|
|
|
|
|
self.draw_ex(context, view, True)
|
2018-07-09 17:00:09 +02:00
|
|
|
|
|
|
|
|
|
2018-04-29 08:47:14 +02:00
|
|
|
class VIEW3D_PT_shading(Panel):
|
2009-10-31 19:31:45 +00:00
|
|
|
bl_space_type = 'VIEW_3D'
|
2018-05-02 12:05:40 +02:00
|
|
|
bl_region_type = 'HEADER'
|
2018-04-29 08:47:14 +02:00
|
|
|
bl_label = "Shading"
|
2018-12-21 11:40:47 +11:00
|
|
|
bl_ui_units_x = 12
|
2009-10-31 19:31:45 +00:00
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
@classmethod
|
|
|
|
|
def get_shading(cls, context):
|
|
|
|
|
# Get settings from 3D viewport or OpenGL render engine
|
|
|
|
|
view = context.space_data
|
|
|
|
|
if view.type == 'VIEW_3D':
|
|
|
|
|
return view.shading
|
|
|
|
|
else:
|
|
|
|
|
return context.scene.display.shading
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2019-04-13 12:14:12 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.label(text="Viewport Shading")
|
2018-06-18 08:15:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_shading_lighting(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Lighting"
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_shading"
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2018-09-21 14:10:06 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
2023-10-07 18:29:50 +11:00
|
|
|
if shading.type in {'SOLID', 'MATERIAL'}:
|
|
|
|
|
return True
|
|
|
|
|
if shading.type == 'RENDERED':
|
|
|
|
|
engine = context.scene.render.engine
|
2025-06-13 12:36:14 +02:00
|
|
|
if engine == 'BLENDER_EEVEE':
|
2023-10-07 18:29:50 +11:00
|
|
|
return True
|
|
|
|
|
return False
|
2018-09-21 14:10:06 +02:00
|
|
|
|
2018-04-29 08:47:14 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-07-11 11:43:56 +02:00
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
2018-04-29 08:47:14 +02:00
|
|
|
|
2018-07-13 20:11:57 +02:00
|
|
|
col = layout.column()
|
2025-05-14 16:24:51 +02:00
|
|
|
split = col.split(factor=0.95)
|
2018-07-13 20:11:57 +02:00
|
|
|
|
2018-06-21 14:56:00 +02:00
|
|
|
if shading.type == 'SOLID':
|
2025-05-14 16:24:51 +02:00
|
|
|
col.row().prop(shading, "light", expand=True)
|
2018-07-13 20:11:57 +02:00
|
|
|
col = split.column()
|
|
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
split = layout.split(factor=0.95)
|
2018-07-13 20:11:57 +02:00
|
|
|
col = split.column()
|
|
|
|
|
sub = col.row()
|
|
|
|
|
|
2018-05-03 15:31:03 +02:00
|
|
|
if shading.light == 'STUDIO':
|
2018-12-21 12:47:44 +11:00
|
|
|
prefs = context.preferences
|
|
|
|
|
system = prefs.system
|
2018-11-29 20:57:09 +01:00
|
|
|
|
2019-02-11 17:49:35 +11:00
|
|
|
if not system.use_studio_light_edit:
|
2023-09-05 10:49:20 +10:00
|
|
|
sub.scale_y = 0.6 # Smaller studio-light preview.
|
2019-01-02 18:18:54 +11:00
|
|
|
sub.template_icon_view(shading, "studio_light", scale_popup=3.0)
|
2018-11-29 21:33:14 +01:00
|
|
|
else:
|
2019-05-22 00:27:01 +10:00
|
|
|
sub.prop(
|
|
|
|
|
system,
|
|
|
|
|
"use_studio_light_edit",
|
|
|
|
|
text="Disable Studio Light Edit",
|
|
|
|
|
icon='NONE',
|
|
|
|
|
toggle=True,
|
|
|
|
|
)
|
2018-07-13 20:11:57 +02:00
|
|
|
|
2018-11-29 20:57:09 +01:00
|
|
|
col = split.column()
|
2024-05-24 14:08:31 +10:00
|
|
|
col.operator("screen.userpref_show", emboss=False, text="", icon='PREFERENCES').section = 'LIGHTS'
|
2018-07-13 20:11:57 +02:00
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
split = layout.split(factor=0.95)
|
2018-07-13 20:11:57 +02:00
|
|
|
col = split.column()
|
2018-11-29 21:33:14 +01:00
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
row = col.row(align=True)
|
2018-12-20 13:01:40 +11:00
|
|
|
row.prop(shading, "use_world_space_lighting", text="", icon='WORLD', toggle=True)
|
2025-05-14 16:24:51 +02:00
|
|
|
row = row.row(align=True)
|
2018-11-29 20:57:09 +01:00
|
|
|
row.active = shading.use_world_space_lighting
|
|
|
|
|
row.prop(shading, "studiolight_rotate_z", text="Rotation")
|
|
|
|
|
col = split.column() # to align properly with above
|
2018-05-04 14:07:00 +02:00
|
|
|
|
2018-06-05 08:15:30 +02:00
|
|
|
elif shading.light == 'MATCAP':
|
2018-11-29 21:33:14 +01:00
|
|
|
sub.scale_y = 0.6 # smaller matcap preview
|
2019-01-02 18:18:54 +11:00
|
|
|
sub.template_icon_view(shading, "studio_light", scale_popup=3.0)
|
2018-07-13 20:11:57 +02:00
|
|
|
|
|
|
|
|
col = split.column()
|
2024-05-24 14:08:31 +10:00
|
|
|
col.operator("screen.userpref_show", emboss=False, text="", icon='PREFERENCES').section = 'LIGHTS'
|
2018-12-18 15:01:03 +11:00
|
|
|
col.operator("view3d.toggle_matcap_flip", emboss=False, text="", icon='ARROW_LEFTRIGHT')
|
2018-06-05 08:15:30 +02:00
|
|
|
|
2018-06-21 14:56:00 +02:00
|
|
|
elif shading.type == 'MATERIAL':
|
2018-07-06 18:53:51 +02:00
|
|
|
col.prop(shading, "use_scene_lights")
|
|
|
|
|
col.prop(shading, "use_scene_world")
|
2019-08-27 15:47:30 +02:00
|
|
|
col = layout.column()
|
2025-05-14 16:24:51 +02:00
|
|
|
split = col.split(factor=0.95)
|
2018-07-06 18:53:51 +02:00
|
|
|
|
|
|
|
|
if not shading.use_scene_world:
|
2019-08-27 15:47:30 +02:00
|
|
|
col = split.column()
|
|
|
|
|
sub = col.row()
|
|
|
|
|
sub.scale_y = 0.6
|
|
|
|
|
sub.template_icon_view(shading, "studio_light", scale_popup=3)
|
|
|
|
|
|
|
|
|
|
col = split.column()
|
2024-05-24 14:08:31 +10:00
|
|
|
col.operator("screen.userpref_show", emboss=False, text="", icon='PREFERENCES').section = 'LIGHTS'
|
2019-08-27 15:47:30 +02:00
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
split = layout.split(factor=0.95)
|
2019-08-27 15:47:30 +02:00
|
|
|
col = split.column()
|
2020-09-18 00:42:24 +02:00
|
|
|
|
2023-07-03 15:34:11 +02:00
|
|
|
engine = context.scene.render.engine
|
2020-09-18 00:42:24 +02:00
|
|
|
row = col.row()
|
2024-07-15 11:59:26 +02:00
|
|
|
if engine == 'BLENDER_WORKBENCH':
|
2023-07-03 15:34:11 +02:00
|
|
|
row.prop(shading, "use_studiolight_view_rotation", text="", icon='WORLD', toggle=True)
|
|
|
|
|
row = row.row()
|
2020-09-18 00:42:24 +02:00
|
|
|
row.prop(shading, "studiolight_rotate_z", text="Rotation")
|
|
|
|
|
|
2019-09-04 16:22:47 +02:00
|
|
|
col.prop(shading, "studiolight_intensity")
|
2019-08-27 15:47:30 +02:00
|
|
|
col.prop(shading, "studiolight_background_alpha")
|
2024-03-28 12:18:37 +01:00
|
|
|
col.prop(shading, "studiolight_background_blur")
|
2019-08-27 15:47:30 +02:00
|
|
|
col = split.column() # to align properly with above
|
|
|
|
|
|
|
|
|
|
elif shading.type == 'RENDERED':
|
|
|
|
|
col.prop(shading, "use_scene_lights_render")
|
|
|
|
|
col.prop(shading, "use_scene_world_render")
|
|
|
|
|
|
|
|
|
|
if not shading.use_scene_world_render:
|
2018-07-13 20:11:57 +02:00
|
|
|
col = layout.column()
|
2025-05-14 16:24:51 +02:00
|
|
|
split = col.split(factor=0.95)
|
2018-07-13 20:11:57 +02:00
|
|
|
|
|
|
|
|
col = split.column()
|
|
|
|
|
sub = col.row()
|
|
|
|
|
sub.scale_y = 0.6
|
2019-01-02 18:18:54 +11:00
|
|
|
sub.template_icon_view(shading, "studio_light", scale_popup=3)
|
2018-07-13 20:11:57 +02:00
|
|
|
|
|
|
|
|
col = split.column()
|
2024-05-24 14:08:31 +10:00
|
|
|
col.operator("screen.userpref_show", emboss=False, text="", icon='PREFERENCES').section = 'LIGHTS'
|
2018-07-13 20:11:57 +02:00
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
split = layout.split(factor=0.95)
|
2019-08-27 15:47:30 +02:00
|
|
|
col = split.column()
|
|
|
|
|
col.prop(shading, "studiolight_rotate_z", text="Rotation")
|
2019-09-04 16:22:47 +02:00
|
|
|
col.prop(shading, "studiolight_intensity")
|
2019-08-27 15:47:30 +02:00
|
|
|
col.prop(shading, "studiolight_background_alpha")
|
2024-03-28 12:18:37 +01:00
|
|
|
col.prop(shading, "studiolight_background_blur")
|
2019-08-27 15:47:30 +02:00
|
|
|
col = split.column() # to align properly with above
|
2018-06-18 08:15:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_shading_color(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2025-05-14 16:24:51 +02:00
|
|
|
bl_label = "Wireframe Color"
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_shading"
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2018-08-19 20:25:36 +02:00
|
|
|
def _draw_color_type(self, context):
|
2018-06-18 08:15:29 +02:00
|
|
|
layout = self.layout
|
2018-07-11 11:43:56 +02:00
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
layout.grid_flow(row_major=True, columns=3, align=True).prop(shading, "color_type", expand=True)
|
2018-06-18 08:15:29 +02:00
|
|
|
if shading.color_type == 'SINGLE':
|
2018-12-18 15:01:03 +11:00
|
|
|
layout.row().prop(shading, "single_color", text="")
|
2018-07-27 15:05:46 +02:00
|
|
|
|
2018-08-19 20:25:36 +02:00
|
|
|
def _draw_background_color(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
|
2018-08-28 12:34:51 +10:00
|
|
|
layout.row().label(text="Background")
|
2018-12-18 15:01:03 +11:00
|
|
|
layout.row().prop(shading, "background_type", expand=True)
|
2018-07-27 15:05:46 +02:00
|
|
|
if shading.background_type == 'VIEWPORT':
|
|
|
|
|
layout.row().prop(shading, "background_color", text="")
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2018-08-19 20:25:36 +02:00
|
|
|
def draw(self, context):
|
2023-08-28 11:04:40 +02:00
|
|
|
layout = self.layout
|
2018-09-21 15:44:04 +02:00
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
2023-08-28 11:04:40 +02:00
|
|
|
|
|
|
|
|
self.layout.row().prop(shading, "wireframe_color_type", expand=True)
|
|
|
|
|
self.layout.separator()
|
|
|
|
|
|
|
|
|
|
if shading.type == 'SOLID':
|
2025-05-14 16:24:51 +02:00
|
|
|
layout.row().label(text="Object Color")
|
2018-09-21 15:44:04 +02:00
|
|
|
self._draw_color_type(context)
|
2018-10-04 14:35:18 +02:00
|
|
|
self.layout.separator()
|
2023-08-28 11:04:40 +02:00
|
|
|
self._draw_background_color(context)
|
|
|
|
|
elif shading.type == 'WIREFRAME':
|
|
|
|
|
self._draw_background_color(context)
|
2018-08-19 20:25:36 +02:00
|
|
|
|
2018-06-18 08:15:29 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_PT_shading_options(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Options"
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_shading"
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2019-05-15 12:03:26 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
return shading.type in {'WIREFRAME', 'SOLID'}
|
|
|
|
|
|
2018-06-18 08:15:29 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2018-07-11 16:05:05 +02:00
|
|
|
col = layout.column()
|
2018-06-18 08:15:29 +02:00
|
|
|
|
2019-05-15 12:03:26 +02:00
|
|
|
if shading.type == 'SOLID':
|
2018-12-19 11:23:21 +11:00
|
|
|
col.prop(shading, "show_backface_culling")
|
|
|
|
|
|
2025-05-14 16:24:51 +02:00
|
|
|
if shading.type in {'WIREFRAME', 'SOLID'}:
|
|
|
|
|
row = col.split()
|
|
|
|
|
row.prop(shading, "show_object_outline")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = shading.show_object_outline
|
|
|
|
|
sub.prop(shading, "object_outline_color", text="")
|
|
|
|
|
|
2025-07-25 15:30:46 +02:00
|
|
|
if shading.type == 'SOLID' and shading.light in {'STUDIO', 'MATCAP'}:
|
|
|
|
|
sub = col.row()
|
|
|
|
|
studio_light = shading.selected_studio_light
|
|
|
|
|
sub.active = (studio_light is not None) and studio_light.has_specular_highlight_pass
|
|
|
|
|
sub.prop(shading, "show_specular_highlight", text="Specular Lighting")
|
2025-05-14 16:24:51 +02:00
|
|
|
|
2019-04-20 19:01:46 +02:00
|
|
|
row = col.row(align=True)
|
2018-10-01 18:56:16 +02:00
|
|
|
|
2018-09-26 20:31:14 +02:00
|
|
|
if shading.type == 'WIREFRAME':
|
2018-10-04 14:35:18 +02:00
|
|
|
row.prop(shading, "show_xray_wireframe", text="")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = shading.show_xray_wireframe
|
|
|
|
|
sub.prop(shading, "xray_alpha_wireframe", text="X-Ray")
|
2018-11-08 18:58:00 +01:00
|
|
|
elif shading.type == 'SOLID':
|
2018-10-04 14:35:18 +02:00
|
|
|
row.prop(shading, "show_xray", text="")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = shading.show_xray
|
|
|
|
|
sub.prop(shading, "xray_alpha", text="X-Ray")
|
2019-05-22 00:27:01 +10:00
|
|
|
# X-ray mode is off when alpha is 1.0
|
2019-04-11 19:43:06 +02:00
|
|
|
xray_active = shading.show_xray and shading.xray_alpha != 1
|
2018-06-21 14:56:00 +02:00
|
|
|
|
2019-04-20 19:01:46 +02:00
|
|
|
row = col.row(align=True)
|
2018-09-21 14:10:06 +02:00
|
|
|
row.prop(shading, "show_shadows", text="")
|
2019-04-11 19:43:06 +02:00
|
|
|
row.active = not xray_active
|
2018-09-21 14:10:06 +02:00
|
|
|
sub = row.row(align=True)
|
2018-11-08 18:58:00 +01:00
|
|
|
sub.active = shading.show_shadows
|
2018-09-21 14:10:06 +02:00
|
|
|
sub.prop(shading, "shadow_intensity", text="Shadow")
|
2018-07-11 16:05:05 +02:00
|
|
|
sub.popover(
|
2018-09-21 14:10:06 +02:00
|
|
|
panel="VIEW3D_PT_shading_options_shadow",
|
2018-10-01 10:45:50 +02:00
|
|
|
icon='PREFERENCES',
|
2019-04-13 12:44:34 +02:00
|
|
|
text="",
|
2018-07-11 16:05:05 +02:00
|
|
|
)
|
|
|
|
|
|
2019-01-25 21:03:50 +01:00
|
|
|
row = col.row()
|
2019-04-11 19:43:06 +02:00
|
|
|
row.active = not xray_active
|
2020-10-24 11:42:17 -07:00
|
|
|
row.prop(shading, "use_dof", text="Depth of Field")
|
2019-01-25 21:03:50 +01:00
|
|
|
|
2018-07-11 16:05:05 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_PT_shading_options_shadow(Panel):
|
|
|
|
|
bl_label = "Shadow Settings"
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2025-05-14 16:24:51 +02:00
|
|
|
bl_ui_units_x = 12
|
2018-07-11 16:05:05 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
scene = context.scene
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
2025-05-14 16:24:51 +02:00
|
|
|
col.prop(scene.display, "light_direction", text="Direction")
|
|
|
|
|
col.prop(scene.display, "shadow_shift", text="Offset")
|
|
|
|
|
col.prop(scene.display, "shadow_focus", text="Focus")
|
2018-07-11 16:05:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_shading_options_ssao(Panel):
|
|
|
|
|
bl_label = "SSAO Settings"
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
scene = context.scene
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(scene.display, "matcap_ssao_samples")
|
|
|
|
|
col.prop(scene.display, "matcap_ssao_distance")
|
|
|
|
|
col.prop(scene.display, "matcap_ssao_attenuation")
|
2018-05-25 08:06:36 +02:00
|
|
|
|
2018-04-29 08:47:14 +02:00
|
|
|
|
2025-02-05 17:08:55 +01:00
|
|
|
class VIEW3D_PT_shading_cavity(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Cavity"
|
|
|
|
|
bl_parent_id = "VIEW3D_PT_shading"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
return shading.type in {'SOLID'}
|
|
|
|
|
|
|
|
|
|
def draw_header(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
xray_active = shading.show_xray and shading.xray_alpha != 1
|
|
|
|
|
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.active = not xray_active
|
|
|
|
|
row.prop(shading, "show_cavity")
|
|
|
|
|
if shading.show_cavity:
|
|
|
|
|
row.prop(shading, "cavity_type", text="Type")
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
xray_active = shading.show_xray and shading.xray_alpha != 1
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = not xray_active
|
|
|
|
|
|
|
|
|
|
if shading.show_cavity:
|
|
|
|
|
if shading.cavity_type in {'WORLD', 'BOTH'}:
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.label(text="World Space")
|
|
|
|
|
row.popover(
|
|
|
|
|
panel="VIEW3D_PT_shading_options_ssao",
|
|
|
|
|
icon='PREFERENCES',
|
|
|
|
|
text="",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(shading, "cavity_ridge_factor", text="Ridge")
|
|
|
|
|
row.prop(shading, "cavity_valley_factor", text="Valley")
|
|
|
|
|
|
|
|
|
|
if shading.cavity_type in {'SCREEN', 'BOTH'}:
|
|
|
|
|
col.label(text="Screen Space")
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(shading, "curvature_ridge_factor", text="Ridge")
|
|
|
|
|
row.prop(shading, "curvature_valley_factor", text="Valley")
|
|
|
|
|
|
|
|
|
|
|
2019-11-08 16:47:33 +01:00
|
|
|
class VIEW3D_PT_shading_render_pass(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Render Pass"
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_shading"
|
2025-06-13 12:36:14 +02:00
|
|
|
COMPAT_ENGINES = {'BLENDER_EEVEE'}
|
2019-11-08 16:47:33 +01:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2019-12-16 14:29:03 +11:00
|
|
|
return (
|
|
|
|
|
(context.space_data.shading.type == 'MATERIAL') or
|
|
|
|
|
(context.engine in cls.COMPAT_ENGINES and context.space_data.shading.type == 'RENDERED')
|
|
|
|
|
)
|
2019-11-08 16:47:33 +01:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
shading = context.space_data.shading
|
|
|
|
|
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.prop(shading, "render_pass", text="")
|
|
|
|
|
|
|
|
|
|
|
2022-08-10 09:14:22 +02:00
|
|
|
class VIEW3D_PT_shading_compositor(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Compositor"
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_shading"
|
2023-02-23 17:23:13 +01:00
|
|
|
bl_order = 10
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2023-01-06 14:50:39 +02:00
|
|
|
return context.space_data.shading.type in {'MATERIAL', 'RENDERED'}
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
shading = context.space_data.shading
|
2022-11-24 09:25:44 +02:00
|
|
|
row = self.layout.row()
|
2022-11-23 13:26:46 +02:00
|
|
|
row.prop(shading, "use_compositor", expand=True)
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
|
2019-04-13 12:23:07 +02:00
|
|
|
class VIEW3D_PT_gizmo_display(Panel):
|
2018-04-29 08:47:14 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
2018-05-02 12:05:40 +02:00
|
|
|
bl_region_type = 'HEADER'
|
2021-11-09 11:42:15 -05:00
|
|
|
bl_label = "Gizmos"
|
2020-10-19 10:55:05 -07:00
|
|
|
bl_ui_units_x = 8
|
2018-07-11 13:00:05 +02:00
|
|
|
|
2009-10-31 19:31:45 +00:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2019-04-13 20:36:53 +02:00
|
|
|
scene = context.scene
|
2009-10-31 19:31:45 +00:00
|
|
|
view = context.space_data
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2018-05-03 10:55:28 +02:00
|
|
|
col = layout.column()
|
2019-04-13 12:23:07 +02:00
|
|
|
col.label(text="Viewport Gizmos")
|
2020-10-19 10:55:05 -07:00
|
|
|
col.separator()
|
2018-05-03 10:55:28 +02:00
|
|
|
|
2019-04-13 12:23:07 +02:00
|
|
|
col.active = view.show_gizmo
|
|
|
|
|
colsub = col.column()
|
|
|
|
|
colsub.prop(view, "show_gizmo_navigate", text="Navigate")
|
|
|
|
|
colsub.prop(view, "show_gizmo_tool", text="Active Tools")
|
Geometry Nodes: support attaching gizmos to input values
This adds support for attaching gizmos for input values. The goal is to make it
easier for users to set input values intuitively in the 3D viewport.
We went through multiple different possible designs until we settled on the one
implemented here. We picked it for it's flexibility and ease of use when using
geometry node assets. The core principle in the design is that **gizmos are
attached to existing input values instead of being the input value themselves**.
This actually fits the existing concept of gizmos in Blender well, but may be a
bit unintutitive in a node setup at first. The attachment is done using links in
the node editor.
The most basic usage of the node is to link a Value node to the new Linear Gizmo
node. This attaches the gizmo to the input value and allows you to change it
from the 3D view. The attachment is indicated by the gizmo icon in the sockets
which are controlled by a gizmo as well as the back-link (notice the double
link) when the gizmo is active.
The core principle makes it straight forward to control the same node setup from
the 3D view with gizmos, or by manually changing input values, or by driving the
input values procedurally.
If the input value is controlled indirectly by other inputs, it's often possible
to **automatically propagate** the gizmo to the actual input.
Backpropagation does not work for all nodes, although more nodes can be
supported over time.
This patch adds the first three gizmo nodes which cover common use cases:
* **Linear Gizmo**: Creates a gizmo that controls a float or integer value using
a linear movement of e.g. an arrow in the 3D viewport.
* **Dial Gizmo**: Creates a circular gizmo in the 3D viewport that can be
rotated to change the attached angle input.
* **Transform Gizmo**: Creates a simple gizmo for location, rotation and scale.
In the future, more built-in gizmos and potentially the ability for custom
gizmos could be added.
All gizmo nodes have a **Transform** geometry output. Using it is optional but
it is recommended when the gizmo is used to control inputs that affect a
geometry. When it is used, Blender will automatically transform the gizmos
together with the geometry that they control. To achieve this, the output should
be merged with the generated geometry using the *Join Geometry* node. The data
contained in *Transform* output is not visible geometry, but just internal
information that helps Blender to give a better user experience when using
gizmos.
The gizmo nodes have a multi-input socket. This allows **controlling multiple
values** with the same gizmo.
Only a small set of **gizmo shapes** is supported initially. It might be
extended in the future but one goal is to give the gizmos used by different node
group assets a familiar look and feel. A similar constraint exists for
**colors**. Currently, one can choose from a fixed set of colors which can be
modified in the theme settings.
The set of **visible gizmos** is determined by a multiple factors because it's
not really feasible to show all possible gizmos at all times. To see any of the
geometry nodes gizmos, the "Active Modifier" option has to be enabled in the
"Viewport Gizmos" popover. Then all gizmos are drawn for which at least one of
the following is true:
* The gizmo controls an input of the active modifier of the active object.
* The gizmo controls a value in a selected node in an open node editor.
* The gizmo controls a pinned value in an open node editor. Pinning works by
clicking the gizmo icon next to the value.
Pull Request: https://projects.blender.org/blender/blender/pulls/112677
2024-07-10 16:18:47 +02:00
|
|
|
colsub.prop(view, "show_gizmo_modifier", text="Active Modifier")
|
2019-04-13 20:36:53 +02:00
|
|
|
colsub.prop(view, "show_gizmo_context", text="Active Object")
|
|
|
|
|
|
2019-04-19 12:26:11 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
2020-08-20 10:34:55 -04:00
|
|
|
col.active = view.show_gizmo and view.show_gizmo_context
|
2019-04-19 12:26:11 +02:00
|
|
|
col.label(text="Object Gizmos")
|
|
|
|
|
col.prop(scene.transform_orientation_slots[1], "type", text="")
|
I18n: extract and disambiguate a few messages
Extract
- Add to Quick Favorites tooltip.
- "Mask", the name of a newly created mask (DATA_).
- "New" in the context of the new mask ID button.
- A few strings using BLI_STR_UTF8_ defines were not extracted.
Take the special characters out of the translation macros.
- "External" menu items from the filebrowser's Files context
menu (right-click on a file). These items were already extracted,
but not translated.
Improve
- Separate formatted error message "%s is not compatible with
["the specified", "any"] 'refresh' options" into two messages.
Disambiguate
- Use Action context for new F-modifiers' names. This is already used
for the "type" operator prop.
- Translate ImportHelper's default confirmation text using the
Operator context, as it uses the operator name which is extracted
with this context.
- "Scale" can be a noun, the scale of something, or a verb, to scale
something. The latter mostly uses the Operator context, so apply
this context to verbs, and the default contexts to nouns.
- "Scale Influence" can mean "Influence on Scale" (tracking
stabilization) and "to Scale the Influence" (dynamic paint canvas).
- "Object Line Art" as type of Line Art to add, as opposed to the
active object's Line Art settings.
- Float to Integer node: use NodeTree context for the node label, as
this is already extracted and used for the enum.
Do not translate
- Sequencer labels containing only a string formatting field.
Some issues reported by Gabriel Gazzán and Ye Gui.
Pull Request: https://projects.blender.org/blender/blender/pulls/122283
2024-05-27 19:33:35 +02:00
|
|
|
col.prop(view, "show_gizmo_object_translate", text="Move", text_ctxt=i18n_contexts.operator_default)
|
|
|
|
|
col.prop(view, "show_gizmo_object_rotate", text="Rotate", text_ctxt=i18n_contexts.operator_default)
|
|
|
|
|
col.prop(view, "show_gizmo_object_scale", text="Scale", text_ctxt=i18n_contexts.operator_default)
|
2019-04-19 12:26:11 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
2019-04-14 13:11:17 +02:00
|
|
|
|
|
|
|
|
# Match order of object type visibility
|
2019-04-19 12:26:11 +02:00
|
|
|
col = layout.column()
|
2020-08-20 10:34:55 -04:00
|
|
|
col.active = view.show_gizmo
|
2019-04-19 12:26:11 +02:00
|
|
|
col.label(text="Empty")
|
|
|
|
|
col.prop(view, "show_gizmo_empty_image", text="Image")
|
|
|
|
|
col.prop(view, "show_gizmo_empty_force_field", text="Force Field")
|
|
|
|
|
col.label(text="Light")
|
|
|
|
|
col.prop(view, "show_gizmo_light_size", text="Size")
|
|
|
|
|
col.prop(view, "show_gizmo_light_look_at", text="Look At")
|
|
|
|
|
col.label(text="Camera")
|
|
|
|
|
col.prop(view, "show_gizmo_camera_lens", text="Lens")
|
|
|
|
|
col.prop(view, "show_gizmo_camera_dof_distance", text="Focus Distance")
|
2019-04-13 12:23:07 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Overlays"
|
2025-10-05 23:35:14 +02:00
|
|
|
bl_ui_units_x = 14
|
2019-04-13 12:23:07 +02:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2019-04-13 12:23:07 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.label(text="Viewport Overlays")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
class VIEW3D_PT_overlay_guides(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay"
|
2018-07-11 13:00:05 +02:00
|
|
|
bl_label = "Guides"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
2019-08-19 11:49:07 -03:00
|
|
|
scene = context.scene
|
|
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
overlay = view.overlay
|
|
|
|
|
shading = view.shading
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
2018-07-11 18:38:39 +02:00
|
|
|
col.active = display_all
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
split = col.split()
|
2018-06-10 15:22:47 +02:00
|
|
|
sub = split.column()
|
2019-04-17 11:35:20 +02:00
|
|
|
|
|
|
|
|
row = sub.row()
|
|
|
|
|
row_el = row.column()
|
|
|
|
|
row_el.prop(overlay, "show_ortho_grid", text="Grid")
|
2019-12-02 15:12:10 +11:00
|
|
|
grid_active = bool(
|
2019-05-22 00:27:01 +10:00
|
|
|
view.region_quadviews or
|
|
|
|
|
(view.region_3d.is_orthographic_side_view and not view.region_3d.is_perspective)
|
|
|
|
|
)
|
2019-04-17 11:35:20 +02:00
|
|
|
row_el.active = grid_active
|
2023-01-30 09:32:47 +01:00
|
|
|
row.prop(overlay, "show_floor", text="Floor", text_ctxt=i18n_contexts.editor_view3d)
|
2019-04-17 11:35:20 +02:00
|
|
|
|
|
|
|
|
if overlay.show_floor or overlay.show_ortho_grid:
|
|
|
|
|
sub = col.row(align=True)
|
2019-05-22 00:27:01 +10:00
|
|
|
sub.active = (
|
|
|
|
|
(overlay.show_floor and not view.region_3d.is_orthographic_side_view) or
|
|
|
|
|
(overlay.show_ortho_grid and grid_active)
|
|
|
|
|
)
|
2019-04-17 11:35:20 +02:00
|
|
|
sub.prop(overlay, "grid_scale", text="Scale")
|
2019-08-19 11:49:07 -03:00
|
|
|
sub = sub.row(align=True)
|
|
|
|
|
sub.active = scene.unit_settings.system == 'NONE'
|
2019-04-17 11:35:20 +02:00
|
|
|
sub.prop(overlay, "grid_subdivisions", text="Subdivisions")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
2018-07-11 10:38:01 +02:00
|
|
|
sub = split.column()
|
2018-07-11 13:00:05 +02:00
|
|
|
row = sub.row()
|
|
|
|
|
row.label(text="Axes")
|
2018-07-11 10:38:01 +02:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
subrow = row.row(align=True)
|
|
|
|
|
subrow.prop(overlay, "show_axis_x", text="X", toggle=True)
|
|
|
|
|
subrow.prop(overlay, "show_axis_y", text="Y", toggle=True)
|
|
|
|
|
subrow.prop(overlay, "show_axis_z", text="Z", toggle=True)
|
2018-07-11 10:38:01 +02:00
|
|
|
|
|
|
|
|
split = col.split()
|
|
|
|
|
sub = split.column()
|
2018-07-12 10:07:32 +02:00
|
|
|
sub.prop(overlay, "show_text", text="Text Info")
|
2020-04-24 11:05:40 -07:00
|
|
|
sub.prop(overlay, "show_stats", text="Statistics")
|
2024-05-27 18:16:04 +02:00
|
|
|
if view.region_3d.view_perspective == 'CAMERA':
|
|
|
|
|
sub.prop(overlay, "show_camera_guides", text="Camera Guides")
|
2020-04-24 11:05:40 -07:00
|
|
|
|
2018-07-11 18:33:48 +02:00
|
|
|
sub = split.column()
|
2018-07-12 10:07:32 +02:00
|
|
|
sub.prop(overlay, "show_cursor", text="3D Cursor")
|
2020-04-24 11:05:40 -07:00
|
|
|
sub.prop(overlay, "show_annotation", text="Annotations")
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
if shading.type == 'MATERIAL':
|
2020-03-03 09:58:48 +01:00
|
|
|
row = col.row()
|
|
|
|
|
row.active = shading.render_pass == 'COMBINED'
|
|
|
|
|
row.prop(overlay, "show_look_dev")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_object(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay"
|
2018-07-11 13:00:05 +02:00
|
|
|
bl_label = "Objects"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
2018-07-11 18:38:39 +02:00
|
|
|
display_all = overlay.show_overlays
|
2025-09-29 16:48:35 +02:00
|
|
|
mode = context.mode
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
2018-07-11 18:38:39 +02:00
|
|
|
col.active = display_all
|
|
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
split = col.split()
|
|
|
|
|
|
|
|
|
|
sub = split.column(align=True)
|
2018-10-05 09:41:48 +10:00
|
|
|
sub.prop(overlay, "show_extras", text="Extras")
|
2023-03-07 15:12:35 +01:00
|
|
|
subsub = sub.column()
|
|
|
|
|
subsub.active = overlay.show_extras
|
|
|
|
|
subsub.prop(overlay, "show_light_colors")
|
2018-06-10 15:22:47 +02:00
|
|
|
sub.prop(overlay, "show_relationship_lines")
|
2018-07-11 13:58:10 +02:00
|
|
|
sub.prop(overlay, "show_outline_selected")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
sub = split.column(align=True)
|
|
|
|
|
sub.prop(overlay, "show_bones", text="Bones")
|
2018-06-10 15:22:47 +02:00
|
|
|
sub.prop(overlay, "show_motion_paths")
|
2025-09-29 16:48:35 +02:00
|
|
|
|
2025-09-30 10:45:29 +10:00
|
|
|
can_show_object_origins = mode not in {
|
2025-09-29 16:48:35 +02:00
|
|
|
'PAINT_TEXTURE',
|
|
|
|
|
'PAINT_2D',
|
|
|
|
|
'SCULPT',
|
|
|
|
|
'PAINT_VERTEX',
|
|
|
|
|
'PAINT_WEIGHT',
|
|
|
|
|
'SCULPT_CURVES',
|
|
|
|
|
'PAINT_GREASE_PENCIL',
|
|
|
|
|
'VERTEX_GREASE_PENCIL',
|
|
|
|
|
'WEIGHT_GREASE_PENCIL',
|
2025-09-30 10:45:29 +10:00
|
|
|
'SCULPT_GREASE_PENCIL',
|
|
|
|
|
}
|
2025-09-29 16:48:35 +02:00
|
|
|
subsub = sub.column()
|
|
|
|
|
subsub.active = can_show_object_origins
|
|
|
|
|
subsub.prop(overlay, "show_object_origins", text="Origins")
|
2018-07-11 18:51:04 +02:00
|
|
|
subsub = sub.column()
|
2025-09-29 16:48:35 +02:00
|
|
|
subsub.active = can_show_object_origins and overlay.show_object_origins
|
2018-07-11 19:00:24 +02:00
|
|
|
subsub.prop(overlay, "show_object_origins_all", text="Origins (All)")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_geometry(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay"
|
2018-07-11 13:00:05 +02:00
|
|
|
bl_label = "Geometry"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
2018-07-11 18:38:39 +02:00
|
|
|
display_all = overlay.show_overlays
|
2018-09-28 12:05:25 -03:00
|
|
|
is_wireframes = view.shading.type == 'WIREFRAME'
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
col = layout.column()
|
2018-07-11 18:38:39 +02:00
|
|
|
col.active = display_all
|
2018-07-11 13:00:05 +02:00
|
|
|
|
2019-04-20 19:01:46 +02:00
|
|
|
row = col.row(align=True)
|
2018-09-28 12:05:25 -03:00
|
|
|
if not is_wireframes:
|
|
|
|
|
row.prop(overlay, "show_wireframes", text="")
|
2018-07-11 16:06:19 +02:00
|
|
|
sub = row.row()
|
2018-09-28 12:05:25 -03:00
|
|
|
sub.active = overlay.show_wireframes or is_wireframes
|
2018-07-11 13:58:10 +02:00
|
|
|
sub.prop(overlay, "wireframe_threshold", text="Wireframe")
|
2020-11-13 08:07:07 +01:00
|
|
|
sub.prop(overlay, "wireframe_opacity", text="Opacity")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
2020-09-18 19:20:22 +02:00
|
|
|
row = col.row(align=True)
|
2021-05-18 00:51:11 +02:00
|
|
|
|
|
|
|
|
# These properties should be always available in the UI for all modes
|
|
|
|
|
# other than Object.
|
|
|
|
|
# Even when the Fade Inactive Geometry overlay is not affecting the
|
|
|
|
|
# current active object depending on its mode, it will always affect
|
|
|
|
|
# the rest of the scene.
|
2021-05-06 19:16:10 +02:00
|
|
|
if context.mode != 'OBJECT':
|
2020-09-22 18:12:12 +02:00
|
|
|
row.prop(overlay, "show_fade_inactive", text="")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = overlay.show_fade_inactive
|
|
|
|
|
sub.prop(overlay, "fade_inactive_alpha", text="Fade Inactive Geometry")
|
2018-06-05 19:35:08 +02:00
|
|
|
|
2020-11-03 18:20:37 -06:00
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
col.prop(overlay, "show_face_orientation")
|
|
|
|
|
|
2018-12-19 10:55:53 +11:00
|
|
|
# sub.prop(overlay, "show_onion_skins")
|
2018-07-11 16:06:19 +02:00
|
|
|
|
2023-12-19 14:19:39 +01:00
|
|
|
|
2023-12-19 13:30:16 +01:00
|
|
|
class VIEW3D_PT_overlay_viewer_node(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_parent_id = "VIEW3D_PT_overlay"
|
|
|
|
|
bl_label = "Viewer Node"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.active = view.show_viewer
|
|
|
|
|
row.prop(overlay, "show_viewer_attribute", text="")
|
|
|
|
|
subrow = row.row(align=True)
|
|
|
|
|
subrow.active = overlay.show_viewer_attribute
|
|
|
|
|
subrow.prop(overlay, "viewer_attribute_opacity", text="Color Opacity")
|
|
|
|
|
|
|
|
|
|
row = col.row(align=True)
|
2025-08-25 18:04:22 +02:00
|
|
|
row.active = view.show_viewer and overlay.show_text
|
2023-12-19 13:30:16 +01:00
|
|
|
row.prop(overlay, "show_viewer_text", text="Attribute Text")
|
2018-06-05 19:35:08 +02:00
|
|
|
|
2023-12-19 14:19:39 +01:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
class VIEW3D_PT_overlay_motion_tracking(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay"
|
2018-07-11 13:00:05 +02:00
|
|
|
bl_label = "Motion Tracking"
|
2018-07-05 15:01:04 +02:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
def draw_header(self, context):
|
2020-08-20 10:34:55 -04:00
|
|
|
layout = self.layout
|
2018-07-11 13:00:05 +02:00
|
|
|
view = context.space_data
|
2020-08-20 10:34:55 -04:00
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
layout.active = display_all
|
|
|
|
|
layout.prop(view, "show_reconstruction", text=self.bl_label)
|
2010-04-04 14:52:15 +00:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
2018-07-11 18:46:08 +02:00
|
|
|
overlay = view.overlay
|
2018-07-11 18:38:39 +02:00
|
|
|
display_all = overlay.show_overlays
|
2010-04-04 14:52:15 +00:00
|
|
|
|
2018-07-11 13:00:05 +02:00
|
|
|
col = layout.column()
|
2018-07-11 18:38:39 +02:00
|
|
|
col.active = display_all
|
2018-06-05 15:34:37 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
if view.show_reconstruction:
|
2018-07-11 13:00:05 +02:00
|
|
|
split = col.split()
|
|
|
|
|
|
|
|
|
|
sub = split.column(align=True)
|
2018-06-10 15:22:47 +02:00
|
|
|
sub.active = view.show_reconstruction
|
|
|
|
|
sub.prop(view, "show_camera_path", text="Camera Path")
|
2018-07-11 13:00:05 +02:00
|
|
|
|
|
|
|
|
sub = split.column()
|
|
|
|
|
sub.prop(view, "show_bundle_names", text="Marker Names")
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
2020-08-20 10:34:55 -04:00
|
|
|
col.active = display_all
|
2021-02-24 13:15:48 -06:00
|
|
|
col.label(text="Tracks")
|
2018-07-11 13:00:05 +02:00
|
|
|
row = col.row(align=True)
|
2018-09-03 18:58:41 +02:00
|
|
|
row.prop(view, "tracks_display_type", text="")
|
|
|
|
|
row.prop(view, "tracks_display_size", text="Size")
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_edit_mesh(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2018-07-11 18:38:39 +02:00
|
|
|
bl_label = "Mesh Edit Mode"
|
2025-08-07 11:09:56 +02:00
|
|
|
bl_ui_units_x = 14
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_MESH'
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Mesh Edit Mode Overlays")
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
view = context.space_data
|
2019-09-10 05:58:02 +10:00
|
|
|
shading = view.shading
|
2018-06-10 15:22:47 +02:00
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
2018-05-06 12:17:53 +02:00
|
|
|
|
2021-01-29 16:41:15 +11:00
|
|
|
is_any_solid_shading = not (shading.show_xray or (shading.type == 'WIREFRAME'))
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2025-08-07 11:09:56 +02:00
|
|
|
row = col.row(align=True)
|
2025-08-08 06:32:03 +00:00
|
|
|
row.prop(overlay, "show_edge_bevel_weight", text="Bevel", icon='EDGE_BEVEL', toggle=True)
|
|
|
|
|
row.prop(overlay, "show_edge_crease", text="Crease", icon='EDGE_CREASE', toggle=True)
|
|
|
|
|
row.prop(overlay, "show_edge_seams", text="Seam", icon='EDGE_SEAM', toggle=True)
|
2025-08-07 11:09:56 +02:00
|
|
|
row.prop(
|
|
|
|
|
overlay,
|
|
|
|
|
"show_edge_sharp",
|
|
|
|
|
text="Sharp",
|
2025-08-08 06:32:03 +00:00
|
|
|
icon='EDGE_SHARP',
|
2025-08-07 11:09:56 +02:00
|
|
|
text_ctxt=i18n_contexts.plural,
|
2025-08-08 06:32:03 +00:00
|
|
|
toggle=True,
|
|
|
|
|
)
|
2025-08-07 11:09:56 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
2018-06-10 15:22:47 +02:00
|
|
|
split = col.split()
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
sub = split.column()
|
2018-09-24 23:18:02 +02:00
|
|
|
sub.prop(overlay, "show_faces", text="Faces")
|
2018-08-30 16:21:03 +10:00
|
|
|
sub = split.column()
|
2021-01-29 16:41:15 +11:00
|
|
|
sub.active = is_any_solid_shading
|
2018-09-24 23:18:02 +02:00
|
|
|
sub.prop(overlay, "show_face_center", text="Center")
|
2018-06-05 15:34:37 +02:00
|
|
|
|
2025-01-15 16:05:44 +01:00
|
|
|
col.prop(overlay, "show_extra_indices", text="Indices")
|
2019-06-14 13:55:27 +10:00
|
|
|
|
2018-06-05 15:34:37 +02:00
|
|
|
|
2018-07-11 18:38:39 +02:00
|
|
|
class VIEW3D_PT_overlay_edit_mesh_shading(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay_edit_mesh"
|
2018-07-11 18:38:39 +02:00
|
|
|
bl_label = "Shading"
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2018-07-11 18:38:39 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_MESH'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
2019-05-28 13:00:40 +02:00
|
|
|
shading = view.shading
|
2018-07-11 18:38:39 +02:00
|
|
|
overlay = view.overlay
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
statvis = tool_settings.statvis
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2018-07-11 18:38:39 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
2023-03-03 00:35:45 +01:00
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(overlay, "show_retopology", text="")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = overlay.show_retopology
|
|
|
|
|
sub.prop(overlay, "retopology_offset", text="Retopology")
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
col.prop(overlay, "show_weight", text="Vertex Group Weights")
|
2018-06-10 15:22:47 +02:00
|
|
|
if overlay.show_weight:
|
2018-09-27 18:38:07 +03:00
|
|
|
row = col.split(factor=0.33)
|
2018-07-11 18:38:39 +02:00
|
|
|
row.label(text="Zero Weights")
|
2018-09-27 18:38:07 +03:00
|
|
|
sub = row.row()
|
|
|
|
|
sub.prop(tool_settings, "vertex_group_user", expand=True)
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2019-05-28 13:00:40 +02:00
|
|
|
if shading.type == 'WIREFRAME':
|
2019-05-28 15:12:29 +02:00
|
|
|
xray = shading.show_xray_wireframe and shading.xray_alpha_wireframe < 1.0
|
2019-05-28 13:00:40 +02:00
|
|
|
elif shading.type == 'SOLID':
|
2019-05-28 15:12:29 +02:00
|
|
|
xray = shading.show_xray and shading.xray_alpha < 1.0
|
2019-05-28 13:00:40 +02:00
|
|
|
else:
|
|
|
|
|
xray = False
|
|
|
|
|
statvis_active = not xray
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.active = statvis_active
|
2023-12-11 00:23:03 +01:00
|
|
|
row.prop(overlay, "show_statvis")
|
2018-09-24 23:18:02 +02:00
|
|
|
if overlay.show_statvis:
|
2018-07-11 18:38:39 +02:00
|
|
|
col = col.column()
|
2019-05-28 13:00:40 +02:00
|
|
|
col.active = statvis_active
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
sub = col.split()
|
|
|
|
|
sub.label(text="Type")
|
|
|
|
|
sub.prop(statvis, "type", text="")
|
|
|
|
|
|
2018-06-05 15:34:37 +02:00
|
|
|
statvis_type = statvis.type
|
|
|
|
|
if statvis_type == 'OVERHANG':
|
2018-07-11 18:38:39 +02:00
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(statvis, "overhang_min", text="Minimum")
|
|
|
|
|
row.prop(statvis, "overhang_max", text="Maximum")
|
|
|
|
|
col.row().prop(statvis, "overhang_axis", expand=True)
|
2018-06-05 15:34:37 +02:00
|
|
|
elif statvis_type == 'THICKNESS':
|
2018-07-11 18:38:39 +02:00
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(statvis, "thickness_min", text="Minimum")
|
|
|
|
|
row.prop(statvis, "thickness_max", text="Maximum")
|
|
|
|
|
col.prop(statvis, "thickness_samples")
|
2018-06-05 15:34:37 +02:00
|
|
|
elif statvis_type == 'INTERSECT':
|
|
|
|
|
pass
|
|
|
|
|
elif statvis_type == 'DISTORT':
|
2018-07-11 18:38:39 +02:00
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(statvis, "distort_min", text="Minimum")
|
|
|
|
|
row.prop(statvis, "distort_max", text="Maximum")
|
2018-06-05 15:34:37 +02:00
|
|
|
elif statvis_type == 'SHARP':
|
2018-07-11 18:38:39 +02:00
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(statvis, "sharp_min", text="Minimum")
|
|
|
|
|
row.prop(statvis, "sharp_max", text="Maximum")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_edit_mesh_measurement(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay_edit_mesh"
|
2018-07-11 18:38:39 +02:00
|
|
|
bl_label = "Measurement"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_MESH'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
split = col.split()
|
|
|
|
|
|
|
|
|
|
sub = split.column()
|
2018-09-24 23:18:02 +02:00
|
|
|
sub.prop(overlay, "show_extra_edge_length", text="Edge Length")
|
|
|
|
|
sub.prop(overlay, "show_extra_edge_angle", text="Edge Angle")
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
sub = split.column()
|
2018-09-24 23:18:02 +02:00
|
|
|
sub.prop(overlay, "show_extra_face_area", text="Face Area")
|
|
|
|
|
sub.prop(overlay, "show_extra_face_angle", text="Face Angle")
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_edit_mesh_normals(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay_edit_mesh"
|
2018-07-11 18:38:39 +02:00
|
|
|
bl_label = "Normals"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_MESH'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
row = col.row(align=True)
|
2018-10-01 10:45:50 +02:00
|
|
|
row.prop(overlay, "show_vertex_normals", text="", icon='NORMALS_VERTEX')
|
|
|
|
|
row.prop(overlay, "show_split_normals", text="", icon='NORMALS_VERTEX_FACE')
|
|
|
|
|
row.prop(overlay, "show_face_normals", text="", icon='NORMALS_FACE')
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = overlay.show_vertex_normals or overlay.show_face_normals or overlay.show_split_normals
|
2021-08-04 10:52:51 +02:00
|
|
|
if overlay.use_normals_constant_screen_size:
|
|
|
|
|
sub.prop(overlay, "normals_constant_screen_size", text="Size")
|
|
|
|
|
else:
|
|
|
|
|
sub.prop(overlay, "normals_length", text="Size")
|
|
|
|
|
|
|
|
|
|
row.prop(overlay, "use_normals_constant_screen_size", text="", icon='FIXED_SIZE')
|
|
|
|
|
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_edit_mesh_freestyle(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay_edit_mesh"
|
2018-07-11 18:38:39 +02:00
|
|
|
bl_label = "Freestyle"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_MESH' and bpy.app.build_options.freestyle
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
row = col.row()
|
2018-09-24 23:18:02 +02:00
|
|
|
row.prop(overlay, "show_freestyle_edge_marks", text="Edge Marks")
|
|
|
|
|
row.prop(overlay, "show_freestyle_face_marks", text="Face Marks")
|
2018-07-11 18:38:39 +02:00
|
|
|
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
class VIEW3D_PT_overlay_edit_curve(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2018-07-31 12:59:48 +10:00
|
|
|
bl_label = "Curve Edit Mode"
|
2018-05-07 15:10:11 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_CURVE'
|
2018-05-06 12:17:53 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Curve Edit Mode Overlays")
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
row = col.row()
|
2020-05-26 10:37:47 +02:00
|
|
|
row.prop(overlay, "display_handle", text="Handles")
|
2018-12-14 16:35:51 +01:00
|
|
|
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "show_curve_normals", text="")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = overlay.show_curve_normals
|
|
|
|
|
sub.prop(overlay, "normals_length", text="Normals")
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
|
2024-10-08 21:17:16 +02:00
|
|
|
class VIEW3D_PT_overlay_edit_curves(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Curves Edit Mode"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'EDIT_CURVES'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
|
|
|
|
layout.label(text="Curves Edit Mode Overlays")
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "display_handle", text="Handles")
|
|
|
|
|
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
class VIEW3D_PT_overlay_sculpt(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_context = ".sculpt_mode"
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Sculpt"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2023-09-15 10:44:43 +10:00
|
|
|
return context.mode == 'SCULPT'
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
2019-04-20 11:58:44 +02:00
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Sculpt Mode Overlays")
|
|
|
|
|
|
2019-04-20 19:01:03 +02:00
|
|
|
row = layout.row(align=True)
|
2023-02-15 13:11:04 +11:00
|
|
|
row.prop(overlay, "show_sculpt_mask", text="")
|
2019-04-20 19:01:03 +02:00
|
|
|
sub = row.row()
|
2023-02-15 13:11:04 +11:00
|
|
|
sub.active = overlay.show_sculpt_mask
|
2019-04-20 19:01:03 +02:00
|
|
|
sub.prop(overlay, "sculpt_mode_mask_opacity", text="Mask")
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2020-03-05 14:53:23 +01:00
|
|
|
row = layout.row(align=True)
|
2023-02-15 13:11:04 +11:00
|
|
|
row.prop(overlay, "show_sculpt_face_sets", text="")
|
2020-03-05 14:53:23 +01:00
|
|
|
sub = row.row()
|
2023-02-15 13:11:04 +11:00
|
|
|
sub.active = overlay.show_sculpt_face_sets
|
2020-03-05 14:53:23 +01:00
|
|
|
row.prop(overlay, "sculpt_mode_face_sets_opacity", text="Face Sets")
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2022-06-22 18:58:25 -05:00
|
|
|
class VIEW3D_PT_overlay_sculpt_curves(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_context = ".curves_sculpt"
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Sculpt"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2023-09-15 10:44:43 +10:00
|
|
|
return context.mode == 'SCULPT_CURVES'
|
2022-06-22 18:58:25 -05:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Curve Sculpt Overlays")
|
|
|
|
|
|
2022-06-22 18:58:25 -05:00
|
|
|
row = layout.row(align=True)
|
2022-07-07 08:06:30 -05:00
|
|
|
row.active = overlay.show_overlays
|
2022-06-22 18:58:25 -05:00
|
|
|
row.prop(overlay, "sculpt_mode_mask_opacity", text="Selection Opacity")
|
|
|
|
|
|
2023-02-14 18:10:11 +01:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.active = overlay.show_overlays
|
2023-02-15 13:11:04 +11:00
|
|
|
row.prop(overlay, "show_sculpt_curves_cage", text="")
|
2023-02-14 18:10:11 +01:00
|
|
|
subrow = row.row(align=True)
|
2023-02-15 13:11:04 +11:00
|
|
|
subrow.active = overlay.show_sculpt_curves_cage
|
2023-02-14 18:10:11 +01:00
|
|
|
subrow.prop(overlay, "sculpt_curves_cage_opacity", text="Cage Opacity")
|
|
|
|
|
|
2022-06-22 18:58:25 -05:00
|
|
|
|
2022-01-06 15:42:45 +03:00
|
|
|
class VIEW3D_PT_overlay_bones(Panel):
|
2018-06-10 15:22:47 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2022-01-06 15:42:45 +03:00
|
|
|
bl_label = "Bones"
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def is_using_wireframe(context):
|
|
|
|
|
mode = context.mode
|
|
|
|
|
|
2022-01-07 14:39:01 +11:00
|
|
|
if mode in {'POSE', 'PAINT_WEIGHT'}:
|
2022-01-06 15:42:45 +03:00
|
|
|
armature = context.pose_object
|
|
|
|
|
elif mode == 'EDIT_ARMATURE':
|
|
|
|
|
armature = context.edit_object
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return armature and armature.display_type == 'WIRE'
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2018-11-23 13:17:10 +11:00
|
|
|
mode = context.mode
|
|
|
|
|
return (
|
|
|
|
|
(mode == 'POSE') or
|
2022-01-06 15:42:45 +03:00
|
|
|
(mode == 'PAINT_WEIGHT' and context.pose_object) or
|
2023-09-26 23:33:15 +02:00
|
|
|
(mode == 'EDIT_ARMATURE' and
|
2022-01-06 15:42:45 +03:00
|
|
|
VIEW3D_PT_overlay_bones.is_using_wireframe(context))
|
2018-11-23 13:17:10 +11:00
|
|
|
)
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2025-06-12 16:43:03 +02:00
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
2018-06-10 15:22:47 +02:00
|
|
|
view = context.space_data
|
2018-11-23 13:17:10 +11:00
|
|
|
mode = context.mode
|
2018-06-10 15:22:47 +02:00
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Armature Overlays")
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
2018-07-11 18:54:42 +02:00
|
|
|
|
2018-11-23 13:17:10 +11:00
|
|
|
if mode == 'POSE':
|
|
|
|
|
row = col.row()
|
2018-11-23 13:46:40 +11:00
|
|
|
row.prop(overlay, "show_xray_bone", text="")
|
2018-11-23 13:17:10 +11:00
|
|
|
sub = row.row()
|
2018-11-23 13:46:40 +11:00
|
|
|
sub.active = display_all and overlay.show_xray_bone
|
|
|
|
|
sub.prop(overlay, "xray_alpha_bone", text="Fade Geometry")
|
2022-01-06 15:42:45 +03:00
|
|
|
elif mode == 'PAINT_WEIGHT':
|
2018-11-23 13:17:10 +11:00
|
|
|
row = col.row()
|
2018-11-23 13:46:40 +11:00
|
|
|
row.prop(overlay, "show_xray_bone")
|
2025-06-12 16:43:03 +02:00
|
|
|
row = col.row()
|
|
|
|
|
row.active = shading.type == 'WIREFRAME'
|
|
|
|
|
row.prop(overlay, "bone_wire_alpha")
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
|
2019-07-17 13:50:24 +02:00
|
|
|
class VIEW3D_PT_overlay_texture_paint(Panel):
|
2018-06-10 15:22:47 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2019-07-17 13:50:24 +02:00
|
|
|
bl_label = "Texture Paint"
|
2018-06-10 15:22:47 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2019-07-17 13:50:24 +02:00
|
|
|
return context.mode == 'PAINT_TEXTURE'
|
2018-06-10 15:22:47 +02:00
|
|
|
|
2019-07-17 13:50:24 +02:00
|
|
|
def draw(self, context):
|
2018-06-22 10:37:38 +02:00
|
|
|
layout = self.layout
|
2019-07-17 13:50:24 +02:00
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Texture Paint Overlays")
|
|
|
|
|
|
2019-07-17 13:50:24 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
col.prop(overlay, "texture_paint_mode_opacity")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_overlay_vertex_paint(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Vertex Paint"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'PAINT_VERTEX'
|
2018-06-22 10:37:38 +02:00
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
|
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Vertex Paint Overlays")
|
|
|
|
|
|
2018-06-10 15:22:47 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2020-09-01 12:55:52 -04:00
|
|
|
col.prop(overlay, "vertex_paint_mode_opacity")
|
2019-07-17 13:50:24 +02:00
|
|
|
col.prop(overlay, "show_paint_wire")
|
2018-06-22 10:37:38 +02:00
|
|
|
|
2018-09-27 18:38:07 +03:00
|
|
|
|
2019-07-17 13:50:24 +02:00
|
|
|
class VIEW3D_PT_overlay_weight_paint(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Weight Paint"
|
2023-09-14 21:20:48 +02:00
|
|
|
bl_ui_units_x = 12
|
2019-07-17 13:50:24 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
return context.mode == 'PAINT_WEIGHT'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
display_all = overlay.show_overlays
|
2023-04-13 13:14:03 +10:00
|
|
|
tool_settings = context.tool_settings
|
2019-07-17 13:50:24 +02:00
|
|
|
|
2023-09-14 21:20:48 +02:00
|
|
|
layout.label(text="Weight Paint Overlays")
|
|
|
|
|
|
2019-07-17 13:50:24 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = display_all
|
|
|
|
|
|
|
|
|
|
col.prop(overlay, "weight_paint_mode_opacity", text="Opacity")
|
|
|
|
|
row = col.split(factor=0.33)
|
|
|
|
|
row.label(text="Zero Weights")
|
|
|
|
|
sub = row.row()
|
2023-04-13 13:14:03 +10:00
|
|
|
sub.prop(tool_settings, "vertex_group_user", expand=True)
|
2018-09-27 18:38:07 +03:00
|
|
|
|
2019-07-17 13:50:24 +02:00
|
|
|
col.prop(overlay, "show_wpaint_contours")
|
|
|
|
|
col.prop(overlay, "show_paint_wire")
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2010-01-30 03:22:22 +00:00
|
|
|
|
2018-07-03 14:05:07 +02:00
|
|
|
class VIEW3D_PT_snapping(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Snapping"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
2018-12-17 17:26:47 +11:00
|
|
|
tool_settings = context.tool_settings
|
2018-07-03 14:05:07 +02:00
|
|
|
obj = context.active_object
|
|
|
|
|
object_mode = 'OBJECT' if obj is None else obj.mode
|
|
|
|
|
|
|
|
|
|
layout = self.layout
|
|
|
|
|
col = layout.column()
|
2023-06-06 19:35:57 +02:00
|
|
|
|
2024-03-25 13:35:52 +01:00
|
|
|
col.label(text="Snap Base")
|
2023-06-06 19:35:57 +02:00
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "snap_target", expand=True)
|
|
|
|
|
|
2024-03-25 13:35:52 +01:00
|
|
|
col.label(text="Snap Target")
|
2023-06-06 19:35:57 +02:00
|
|
|
col.prop(tool_settings, "snap_elements_base", expand=True)
|
|
|
|
|
|
2024-03-25 13:35:52 +01:00
|
|
|
col.label(text="Snap Target for Individual Elements")
|
2023-06-06 19:35:57 +02:00
|
|
|
col.prop(tool_settings, "snap_elements_individual", expand=True)
|
2018-07-03 14:05:07 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
2023-06-06 19:35:57 +02:00
|
|
|
|
2024-10-09 22:52:28 +02:00
|
|
|
if 'INCREMENT' in tool_settings.snap_elements:
|
|
|
|
|
col.prop(tool_settings, "use_snap_grid_absolute")
|
|
|
|
|
|
2023-06-06 19:35:57 +02:00
|
|
|
if 'VOLUME' in tool_settings.snap_elements:
|
|
|
|
|
col.prop(tool_settings, "use_snap_peel_object")
|
Transform Snap: nearest face snap mode, snapping options, refactoring.
This commit adds a new face nearest snapping mode, adds new snapping
options, and (lightly) refactors code around snapping.
The new face nearest snapping mode will snap transformed geometry to the
nearest surface in world space. In contrast, the original face snapping
mode uses projection (raycasting) to snap source to target geometry.
Face snapping therefore only works with what is visible, while nearest
face snapping can snap geometry to occluded parts of the scene. This new
mode is critical for retopology work, where some of the target mesh
might be occluded (ex: sliding an edge loop that wraps around the
backside of target mesh).
The nearest face snapping mode has two options: "Snap to Same Target"
and "Face Nearest Steps". When the Snap to Same Object option is
enabled, the selected source geometry will stay near the target that it
is nearest before editing started, which prevents the source geometry
from snapping to other targets. The Face Nearest Steps divides the
overall transformation for each vertex into n smaller transformations,
then applies those n transformations with surface snapping interlacing
each step. This steps option handles transformations that cross U-shaped
targets better.
The new snapping options allow the artist to better control which target
objects (objects to which the edited geometry is snapped) are considered
when snapping. In particular, the only option for filtering target
objects was a "Project onto Self", which allowed the currently edited
mesh to be considered as a target. Now, the artist can choose any
combination of the following to be considered as a target: the active
object, any edited object that isn't active (see note below), any non-
edited object. Additionally, the artist has another snapping option to
exclude objects that are not selectable as potential targets.
The Snapping Options dropdown has been lightly reorganized to allow for
the additional options.
Included in this patch:
- Snap target selection is more controllable for artist with additional
snapping options.
- Renamed a few of the snap-related functions to better reflect what
they actually do now. For example, `applySnapping` implies that this
handles the snapping, while `applyProject` implies something entirely
different is done there. However, better names would be
`applySnappingAsGroup` and `applySnappingIndividual`, respectively,
where `applySnappingIndividual` previously only does Face snapping.
- Added an initial coordinate parameter to snapping functions so that
the nearest target before transforming can be determined(for "Snap to
Same Object"), and so the transformation can be broken into smaller
steps (for "Face Nearest Steps").
- Separated the BVH Tree getter code from mesh/edit mesh to its own
function to reduce code duplication.
- Added icon for nearest face snapping.
- The original "Project onto Self" was actually not correct! This option
should be called "Project onto Active" instead, but that only matters
when editing multiple meshes at the same time. This patch makes this
change in the UI.
Reviewed By: Campbell Barton, Germano Cavalcante
Differential Revision: https://developer.blender.org/D14591
2022-06-29 20:52:00 -04:00
|
|
|
|
2023-06-06 19:35:57 +02:00
|
|
|
if 'FACE_NEAREST' in tool_settings.snap_elements:
|
|
|
|
|
col.prop(tool_settings, "use_snap_to_same_target")
|
|
|
|
|
if object_mode == 'EDIT':
|
|
|
|
|
col.prop(tool_settings, "snap_face_nearest_steps")
|
2018-07-03 14:05:07 +02:00
|
|
|
|
2023-06-06 19:35:57 +02:00
|
|
|
col.separator()
|
Transform Snap: nearest face snap mode, snapping options, refactoring.
This commit adds a new face nearest snapping mode, adds new snapping
options, and (lightly) refactors code around snapping.
The new face nearest snapping mode will snap transformed geometry to the
nearest surface in world space. In contrast, the original face snapping
mode uses projection (raycasting) to snap source to target geometry.
Face snapping therefore only works with what is visible, while nearest
face snapping can snap geometry to occluded parts of the scene. This new
mode is critical for retopology work, where some of the target mesh
might be occluded (ex: sliding an edge loop that wraps around the
backside of target mesh).
The nearest face snapping mode has two options: "Snap to Same Target"
and "Face Nearest Steps". When the Snap to Same Object option is
enabled, the selected source geometry will stay near the target that it
is nearest before editing started, which prevents the source geometry
from snapping to other targets. The Face Nearest Steps divides the
overall transformation for each vertex into n smaller transformations,
then applies those n transformations with surface snapping interlacing
each step. This steps option handles transformations that cross U-shaped
targets better.
The new snapping options allow the artist to better control which target
objects (objects to which the edited geometry is snapped) are considered
when snapping. In particular, the only option for filtering target
objects was a "Project onto Self", which allowed the currently edited
mesh to be considered as a target. Now, the artist can choose any
combination of the following to be considered as a target: the active
object, any edited object that isn't active (see note below), any non-
edited object. Additionally, the artist has another snapping option to
exclude objects that are not selectable as potential targets.
The Snapping Options dropdown has been lightly reorganized to allow for
the additional options.
Included in this patch:
- Snap target selection is more controllable for artist with additional
snapping options.
- Renamed a few of the snap-related functions to better reflect what
they actually do now. For example, `applySnapping` implies that this
handles the snapping, while `applyProject` implies something entirely
different is done there. However, better names would be
`applySnappingAsGroup` and `applySnappingIndividual`, respectively,
where `applySnappingIndividual` previously only does Face snapping.
- Added an initial coordinate parameter to snapping functions so that
the nearest target before transforming can be determined(for "Snap to
Same Object"), and so the transformation can be broken into smaller
steps (for "Face Nearest Steps").
- Separated the BVH Tree getter code from mesh/edit mesh to its own
function to reduce code duplication.
- Added icon for nearest face snapping.
- The original "Project onto Self" was actually not correct! This option
should be called "Project onto Active" instead, but that only matters
when editing multiple meshes at the same time. This patch makes this
change in the UI.
Reviewed By: Campbell Barton, Germano Cavalcante
Differential Revision: https://developer.blender.org/D14591
2022-06-29 20:52:00 -04:00
|
|
|
|
2023-06-06 19:35:57 +02:00
|
|
|
col.prop(tool_settings, "use_snap_align_rotation")
|
|
|
|
|
col.prop(tool_settings, "use_snap_backface_culling")
|
2023-03-31 17:30:26 -03:00
|
|
|
|
2023-06-06 19:35:57 +02:00
|
|
|
col.separator()
|
Transform Snap: nearest face snap mode, snapping options, refactoring.
This commit adds a new face nearest snapping mode, adds new snapping
options, and (lightly) refactors code around snapping.
The new face nearest snapping mode will snap transformed geometry to the
nearest surface in world space. In contrast, the original face snapping
mode uses projection (raycasting) to snap source to target geometry.
Face snapping therefore only works with what is visible, while nearest
face snapping can snap geometry to occluded parts of the scene. This new
mode is critical for retopology work, where some of the target mesh
might be occluded (ex: sliding an edge loop that wraps around the
backside of target mesh).
The nearest face snapping mode has two options: "Snap to Same Target"
and "Face Nearest Steps". When the Snap to Same Object option is
enabled, the selected source geometry will stay near the target that it
is nearest before editing started, which prevents the source geometry
from snapping to other targets. The Face Nearest Steps divides the
overall transformation for each vertex into n smaller transformations,
then applies those n transformations with surface snapping interlacing
each step. This steps option handles transformations that cross U-shaped
targets better.
The new snapping options allow the artist to better control which target
objects (objects to which the edited geometry is snapped) are considered
when snapping. In particular, the only option for filtering target
objects was a "Project onto Self", which allowed the currently edited
mesh to be considered as a target. Now, the artist can choose any
combination of the following to be considered as a target: the active
object, any edited object that isn't active (see note below), any non-
edited object. Additionally, the artist has another snapping option to
exclude objects that are not selectable as potential targets.
The Snapping Options dropdown has been lightly reorganized to allow for
the additional options.
Included in this patch:
- Snap target selection is more controllable for artist with additional
snapping options.
- Renamed a few of the snap-related functions to better reflect what
they actually do now. For example, `applySnapping` implies that this
handles the snapping, while `applyProject` implies something entirely
different is done there. However, better names would be
`applySnappingAsGroup` and `applySnappingIndividual`, respectively,
where `applySnappingIndividual` previously only does Face snapping.
- Added an initial coordinate parameter to snapping functions so that
the nearest target before transforming can be determined(for "Snap to
Same Object"), and so the transformation can be broken into smaller
steps (for "Face Nearest Steps").
- Separated the BVH Tree getter code from mesh/edit mesh to its own
function to reduce code duplication.
- Added icon for nearest face snapping.
- The original "Project onto Self" was actually not correct! This option
should be called "Project onto Active" instead, but that only matters
when editing multiple meshes at the same time. This patch makes this
change in the UI.
Reviewed By: Campbell Barton, Germano Cavalcante
Differential Revision: https://developer.blender.org/D14591
2022-06-29 20:52:00 -04:00
|
|
|
|
2023-06-06 19:35:57 +02:00
|
|
|
if obj:
|
|
|
|
|
col.label(text="Target Selection")
|
|
|
|
|
col_targetsel = col.column(align=True)
|
|
|
|
|
if object_mode == 'EDIT' and obj.type not in {'LATTICE', 'META', 'FONT'}:
|
|
|
|
|
col_targetsel.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_self",
|
|
|
|
|
text="Include Active",
|
|
|
|
|
icon='EDITMODE_HLT',
|
|
|
|
|
)
|
|
|
|
|
col_targetsel.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_edit",
|
|
|
|
|
text="Include Edited",
|
|
|
|
|
icon='OUTLINER_DATA_MESH',
|
|
|
|
|
)
|
|
|
|
|
col_targetsel.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_nonedit",
|
|
|
|
|
text="Include Non-Edited",
|
|
|
|
|
icon='OUTLINER_OB_MESH',
|
|
|
|
|
)
|
|
|
|
|
col_targetsel.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_selectable",
|
|
|
|
|
text="Exclude Non-Selectable",
|
|
|
|
|
icon='RESTRICT_SELECT_OFF',
|
|
|
|
|
)
|
2018-07-03 14:05:07 +02:00
|
|
|
|
2018-12-18 11:54:02 +01:00
|
|
|
col.label(text="Affect")
|
|
|
|
|
row = col.row(align=True)
|
I18n: extract and disambiguate a few messages
Extract
- Add to Quick Favorites tooltip.
- "Mask", the name of a newly created mask (DATA_).
- "New" in the context of the new mask ID button.
- A few strings using BLI_STR_UTF8_ defines were not extracted.
Take the special characters out of the translation macros.
- "External" menu items from the filebrowser's Files context
menu (right-click on a file). These items were already extracted,
but not translated.
Improve
- Separate formatted error message "%s is not compatible with
["the specified", "any"] 'refresh' options" into two messages.
Disambiguate
- Use Action context for new F-modifiers' names. This is already used
for the "type" operator prop.
- Translate ImportHelper's default confirmation text using the
Operator context, as it uses the operator name which is extracted
with this context.
- "Scale" can be a noun, the scale of something, or a verb, to scale
something. The latter mostly uses the Operator context, so apply
this context to verbs, and the default contexts to nouns.
- "Scale Influence" can mean "Influence on Scale" (tracking
stabilization) and "to Scale the Influence" (dynamic paint canvas).
- "Object Line Art" as type of Line Art to add, as opposed to the
active object's Line Art settings.
- Float to Integer node: use NodeTree context for the node label, as
this is already extracted and used for the enum.
Do not translate
- Sequencer labels containing only a string formatting field.
Some issues reported by Gabriel Gazzán and Ye Gui.
Pull Request: https://projects.blender.org/blender/blender/pulls/122283
2024-05-27 19:33:35 +02:00
|
|
|
row.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_translate",
|
|
|
|
|
text="Move",
|
|
|
|
|
text_ctxt=i18n_contexts.operator_default,
|
2025-01-14 12:46:40 +11:00
|
|
|
toggle=True,
|
|
|
|
|
)
|
2025-03-21 11:08:26 +00:00
|
|
|
row.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_rotate",
|
|
|
|
|
text="Rotate",
|
|
|
|
|
text_ctxt=i18n_contexts.operator_default,
|
|
|
|
|
toggle=True,
|
|
|
|
|
)
|
|
|
|
|
row.prop(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"use_snap_scale",
|
|
|
|
|
text="Scale",
|
|
|
|
|
text_ctxt=i18n_contexts.operator_default,
|
|
|
|
|
toggle=True,
|
|
|
|
|
)
|
2024-03-09 16:50:06 +11:00
|
|
|
col.label(text="Rotation Increment")
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "snap_angle_increment_3d", text="")
|
|
|
|
|
row.prop(tool_settings, "snap_angle_increment_3d_precision", text="")
|
2018-12-18 11:54:02 +01:00
|
|
|
|
2018-07-03 14:05:07 +02:00
|
|
|
|
2024-05-14 19:00:58 +02:00
|
|
|
class VIEW3D_PT_sculpt_snapping(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Snapping"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
col = layout.column()
|
|
|
|
|
|
|
|
|
|
col.label(text="Rotation Increment")
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "snap_angle_increment_3d", text="")
|
|
|
|
|
|
|
|
|
|
|
2019-04-30 13:42:18 +10:00
|
|
|
class VIEW3D_PT_proportional_edit(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Proportional Editing"
|
|
|
|
|
bl_ui_units_x = 8
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
col = layout.column()
|
2025-01-14 12:46:40 +11:00
|
|
|
col.active = (
|
|
|
|
|
tool_settings.use_proportional_edit_objects if context.mode == 'OBJECT' else
|
|
|
|
|
tool_settings.use_proportional_edit
|
|
|
|
|
)
|
2019-04-30 13:42:18 +10:00
|
|
|
|
|
|
|
|
if context.mode != 'OBJECT':
|
|
|
|
|
col.prop(tool_settings, "use_proportional_connected")
|
|
|
|
|
sub = col.column()
|
|
|
|
|
sub.active = not tool_settings.use_proportional_connected
|
|
|
|
|
sub.prop(tool_settings, "use_proportional_projected")
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col.prop(tool_settings, "proportional_edit_falloff", expand=True)
|
2023-05-04 16:39:22 +02:00
|
|
|
col.prop(tool_settings, "proportional_distance")
|
2019-04-30 13:42:18 +10:00
|
|
|
|
|
|
|
|
|
2018-07-03 14:05:07 +02:00
|
|
|
class VIEW3D_PT_transform_orientations(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Transform Orientations"
|
2018-07-04 02:23:52 +02:00
|
|
|
bl_ui_units_x = 8
|
2018-07-03 14:05:07 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-08-28 12:34:51 +10:00
|
|
|
layout.label(text="Transform Orientations")
|
2018-07-03 14:05:07 +02:00
|
|
|
|
|
|
|
|
scene = context.scene
|
2018-12-19 20:51:04 +11:00
|
|
|
orient_slot = scene.transform_orientation_slots[0]
|
|
|
|
|
orientation = orient_slot.custom_orientation
|
2018-07-03 14:05:07 +02:00
|
|
|
|
2018-07-03 14:23:47 +02:00
|
|
|
row = layout.row()
|
|
|
|
|
col = row.column()
|
2018-12-19 20:51:04 +11:00
|
|
|
col.prop(orient_slot, "type", expand=True)
|
2018-10-01 10:45:50 +02:00
|
|
|
row.operator("transform.create_orientation", text="", icon='ADD', emboss=False).use = True
|
2018-07-03 14:05:07 +02:00
|
|
|
|
|
|
|
|
if orientation:
|
|
|
|
|
row = layout.row(align=False)
|
2018-12-20 13:01:40 +11:00
|
|
|
row.prop(orientation, "name", text="", icon='OBJECT_ORIGIN')
|
2018-07-03 14:05:07 +02:00
|
|
|
row.operator("transform.delete_orientation", text="", icon='X', emboss=False)
|
|
|
|
|
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_PT_grease_pencil_origin(Panel):
|
2018-09-20 18:50:07 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2018-09-20 22:51:34 +02:00
|
|
|
bl_label = "Stroke Placement"
|
2018-09-20 18:50:07 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2018-12-17 17:26:47 +11:00
|
|
|
tool_settings = context.tool_settings
|
2018-11-01 16:42:34 +01:00
|
|
|
|
2018-09-20 22:51:34 +02:00
|
|
|
layout.label(text="Stroke Placement")
|
2018-09-20 18:50:07 +02:00
|
|
|
|
|
|
|
|
row = layout.row()
|
|
|
|
|
col = row.column()
|
2018-12-17 17:26:47 +11:00
|
|
|
col.prop(tool_settings, "gpencil_stroke_placement_view3d", expand=True)
|
2018-11-01 16:42:34 +01:00
|
|
|
|
2018-12-17 17:26:47 +11:00
|
|
|
if tool_settings.gpencil_stroke_placement_view3d == 'SURFACE':
|
2018-11-01 16:42:34 +01:00
|
|
|
row = layout.row()
|
|
|
|
|
row.label(text="Offset")
|
|
|
|
|
row = layout.row()
|
2024-06-17 13:50:41 +02:00
|
|
|
row.prop(tool_settings, "gpencil_surface_offset", text="")
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.prop(tool_settings, "use_gpencil_project_only_selected")
|
2018-11-01 16:42:34 +01:00
|
|
|
|
2018-12-17 17:26:47 +11:00
|
|
|
if tool_settings.gpencil_stroke_placement_view3d == 'STROKE':
|
2018-11-01 16:42:34 +01:00
|
|
|
row = layout.row()
|
|
|
|
|
row.label(text="Target")
|
|
|
|
|
row = layout.row()
|
2018-12-17 17:26:47 +11:00
|
|
|
row.prop(tool_settings, "gpencil_stroke_snap_mode", expand=True)
|
2018-09-20 18:50:07 +02:00
|
|
|
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_PT_grease_pencil_lock(Panel):
|
2018-09-21 08:51:04 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2018-11-05 16:28:37 +01:00
|
|
|
bl_label = "Drawing Plane"
|
2018-09-21 08:51:04 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2023-04-13 13:14:03 +10:00
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
|
2018-11-05 16:28:37 +01:00
|
|
|
layout.label(text="Drawing Plane")
|
2018-09-21 08:51:04 +02:00
|
|
|
|
|
|
|
|
row = layout.row()
|
|
|
|
|
col = row.column()
|
2023-04-13 13:14:03 +10:00
|
|
|
col.prop(tool_settings.gpencil_sculpt, "lock_axis", expand=True)
|
2018-09-21 08:51:04 +02:00
|
|
|
|
2019-01-21 10:41:39 +11:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_PT_grease_pencil_guide(Panel):
|
2019-01-11 19:15:23 +01:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Guides"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
settings = context.tool_settings.gpencil_sculpt.guide
|
2018-09-21 08:51:04 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.label(text="Guides")
|
2019-01-21 10:41:39 +11:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
col = layout.column()
|
|
|
|
|
col.active = settings.use_guide
|
|
|
|
|
col.prop(settings, "type", expand=True)
|
2019-01-21 10:41:39 +11:00
|
|
|
|
2019-09-06 14:07:26 +01:00
|
|
|
if settings.type in {'ISO', 'PARALLEL', 'RADIAL'}:
|
2019-01-11 19:15:23 +01:00
|
|
|
col.prop(settings, "angle")
|
|
|
|
|
row = col.row(align=True)
|
2019-01-21 10:41:39 +11:00
|
|
|
|
|
|
|
|
col.prop(settings, "use_snapping")
|
2019-01-11 19:15:23 +01:00
|
|
|
if settings.use_snapping:
|
2019-01-21 10:41:39 +11:00
|
|
|
|
2019-06-22 11:08:12 +10:00
|
|
|
if settings.type == 'RADIAL':
|
2019-01-11 19:15:23 +01:00
|
|
|
col.prop(settings, "angle_snap")
|
|
|
|
|
else:
|
|
|
|
|
col.prop(settings, "spacing")
|
2019-01-21 10:41:39 +11:00
|
|
|
|
2019-09-06 14:07:26 +01:00
|
|
|
if settings.type in {'CIRCULAR', 'RADIAL'} or settings.use_snapping:
|
2019-07-07 09:38:52 +02:00
|
|
|
col.label(text="Reference Point")
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(settings, "reference_point", expand=True)
|
|
|
|
|
if settings.reference_point == 'CUSTOM':
|
|
|
|
|
col.prop(settings, "location", text="Custom Location")
|
|
|
|
|
elif settings.reference_point == 'OBJECT':
|
|
|
|
|
col.prop(settings, "reference_object", text="Object Location")
|
|
|
|
|
if not settings.reference_object:
|
|
|
|
|
col.label(text="No object selected, using cursor")
|
2019-01-11 19:15:23 +01:00
|
|
|
|
2019-01-21 10:41:39 +11:00
|
|
|
|
2023-12-07 11:42:06 +01:00
|
|
|
class VIEW3D_PT_overlay_grease_pencil_options(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2024-09-23 13:11:22 +02:00
|
|
|
bl_label = "Grease Pencil Options"
|
2023-12-07 11:42:06 +01:00
|
|
|
bl_ui_units_x = 13
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
|
|
|
|
return ob and ob.type == 'GREASEPENCIL'
|
2023-12-07 11:42:06 +01:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
|
2024-03-29 10:08:59 +11:00
|
|
|
ob = context.object
|
|
|
|
|
|
2025-01-14 12:46:40 +11:00
|
|
|
layout.label(
|
|
|
|
|
text={
|
|
|
|
|
'PAINT_GREASE_PENCIL': iface_("Draw Grease Pencil"),
|
|
|
|
|
'EDIT_GREASE_PENCIL': iface_("Edit Grease Pencil"),
|
|
|
|
|
'WEIGHT_GREASE_PENCIL': iface_("Weight Grease Pencil"),
|
|
|
|
|
'OBJECT': iface_("Grease Pencil"),
|
|
|
|
|
'SCULPT_GREASE_PENCIL': iface_("Sculpt Grease Pencil"),
|
|
|
|
|
'VERTEX_GREASE_PENCIL': iface_("Vertex Grease Pencil"),
|
|
|
|
|
}[context.mode],
|
|
|
|
|
translate=False
|
|
|
|
|
)
|
2023-12-07 11:42:06 +01:00
|
|
|
|
2025-05-01 17:43:17 +02:00
|
|
|
split = layout.split()
|
|
|
|
|
col = split.column()
|
|
|
|
|
col.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
|
|
|
|
|
col = split.column()
|
|
|
|
|
col.active = overlay.use_gpencil_onion_skin
|
|
|
|
|
col.prop(overlay, "use_gpencil_onion_skin_active_object", text="Active Object Only")
|
2024-04-03 15:34:40 +02:00
|
|
|
|
2024-07-11 15:38:10 +02:00
|
|
|
col = layout.column()
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "use_gpencil_fade_layers", text="")
|
|
|
|
|
sub = row.row()
|
|
|
|
|
sub.active = overlay.use_gpencil_fade_layers
|
|
|
|
|
sub.prop(overlay, "gpencil_fade_layer", text="Fade Inactive Layers", slider=True)
|
|
|
|
|
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "use_gpencil_fade_objects", text="")
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.active = overlay.use_gpencil_fade_objects
|
|
|
|
|
sub.prop(overlay, "gpencil_fade_objects", text="Fade Inactive Objects", slider=True)
|
|
|
|
|
sub.prop(overlay, "use_gpencil_fade_gp_objects", text="", icon='OUTLINER_OB_GREASEPENCIL')
|
|
|
|
|
|
2024-10-04 19:20:00 +02:00
|
|
|
if ob.mode in {'EDIT', 'SCULPT_GREASE_PENCIL', 'WEIGHT_GREASE_PENCIL', 'VERTEX_GREASE_PENCIL'}:
|
2023-12-07 11:42:06 +01:00
|
|
|
split = layout.split()
|
|
|
|
|
col = split.column()
|
|
|
|
|
col.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
|
2024-07-11 15:38:10 +02:00
|
|
|
col = split.column()
|
|
|
|
|
col.prop(overlay, "use_gpencil_multiedit_line_only", text="Only in Multiframe")
|
2025-08-02 15:37:59 +02:00
|
|
|
row = layout.row()
|
|
|
|
|
row.prop(overlay, "display_handle", text="Handles")
|
2024-07-11 15:38:10 +02:00
|
|
|
|
|
|
|
|
if ob.mode == 'EDIT':
|
|
|
|
|
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")
|
|
|
|
|
|
2024-10-04 19:20:00 +02:00
|
|
|
if ob.mode in {'PAINT_GREASE_PENCIL', 'VERTEX_GREASE_PENCIL'}:
|
2024-07-11 15:38:10 +02:00
|
|
|
layout.label(text="Vertex Paint")
|
|
|
|
|
row = layout.row()
|
|
|
|
|
shading = VIEW3D_PT_shading.get_shading(context)
|
|
|
|
|
row.enabled = shading.type not in {'WIREFRAME', 'RENDERED'}
|
|
|
|
|
row.prop(overlay, "gpencil_vertex_paint_opacity", text="Opacity", slider=True)
|
2023-12-07 11:42:06 +01:00
|
|
|
|
|
|
|
|
|
2024-09-27 16:58:38 +02:00
|
|
|
class VIEW3D_PT_overlay_grease_pencil_canvas_options(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_parent_id = "VIEW3D_PT_overlay_grease_pencil_options"
|
|
|
|
|
bl_label = "Canvas"
|
|
|
|
|
bl_ui_units_x = 13
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
ob = context.object
|
|
|
|
|
return ob and ob.type == 'GREASEPENCIL'
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = overlay.use_gpencil_grid
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "use_gpencil_grid", text="")
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.prop(overlay, "gpencil_grid_opacity", text="Canvas", slider=True)
|
|
|
|
|
sub.prop(overlay, "use_gpencil_canvas_xray", text="", icon='XRAY')
|
|
|
|
|
|
|
|
|
|
col = col.column(align=True)
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(overlay, "gpencil_grid_subdivisions")
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(overlay, "gpencil_grid_color", text="")
|
|
|
|
|
|
|
|
|
|
col = col.column(align=True)
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "gpencil_grid_scale", text="Scale", expand=True)
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(overlay, "gpencil_grid_offset", text="Offset", expand=True)
|
|
|
|
|
|
|
|
|
|
|
2018-04-29 08:47:14 +02:00
|
|
|
class VIEW3D_PT_quad_view(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2018-11-21 21:41:00 +01:00
|
|
|
bl_category = "View"
|
2018-04-29 08:47:14 +02:00
|
|
|
bl_label = "Quad View"
|
|
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
2009-08-22 11:51:26 +00:00
|
|
|
|
2018-04-29 08:47:14 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
view = context.space_data
|
|
|
|
|
return view.region_quadviews
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
view = context.space_data
|
|
|
|
|
|
|
|
|
|
region = view.region_quadviews[2]
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.prop(region, "lock_rotation")
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.enabled = region.lock_rotation
|
|
|
|
|
row.prop(region, "show_sync_view")
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.enabled = region.lock_rotation and region.show_sync_view
|
|
|
|
|
row.prop(region, "use_box_clip")
|
2009-10-31 23:35:56 +00:00
|
|
|
|
2010-01-31 14:46:28 +00:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
# Annotation properties
|
2018-08-22 16:59:04 +02:00
|
|
|
class VIEW3D_PT_grease_pencil(AnnotationDataPanel, Panel):
|
2018-07-31 10:22:19 +02:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2018-09-27 16:22:50 +10:00
|
|
|
bl_category = "View"
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
|
# NOTE: this is just a wrapper around the generic GP Panel
|
|
|
|
|
|
|
|
|
|
|
2018-11-28 19:19:01 +01:00
|
|
|
class VIEW3D_PT_annotation_onion(AnnotationOnionSkin, Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "View"
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_grease_pencil"
|
2018-11-28 19:19:01 +01:00
|
|
|
|
|
|
|
|
# NOTE: this is just a wrapper around the generic GP Panel
|
|
|
|
|
|
|
|
|
|
|
2018-11-27 15:23:12 +11:00
|
|
|
class TOPBAR_PT_annotation_layers(Panel, AnnotationDataPanel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Layers"
|
|
|
|
|
bl_ui_units_x = 14
|
|
|
|
|
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
class VIEW3D_PT_view3d_stereo(Panel):
|
2013-09-12 13:01:36 +00:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2018-10-26 20:30:41 +02:00
|
|
|
bl_category = "View"
|
2015-04-06 10:40:12 -03:00
|
|
|
bl_label = "Stereoscopy"
|
2013-09-12 13:01:36 +00:00
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
2013-09-12 19:51:31 +00:00
|
|
|
|
2013-09-12 13:01:36 +00:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2015-04-06 10:40:12 -03:00
|
|
|
scene = context.scene
|
|
|
|
|
|
|
|
|
|
multiview = scene.render.use_multiview
|
2018-07-07 08:53:00 +02:00
|
|
|
return multiview
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2013-09-12 13:01:36 +00:00
|
|
|
view = context.space_data
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
|
basic_stereo = context.scene.render.views_format == 'STEREO_3D'
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.row().prop(view, "stereo_3d_camera", expand=True)
|
|
|
|
|
|
2021-02-24 13:15:48 -06:00
|
|
|
col.label(text="Display")
|
2015-04-06 10:40:12 -03:00
|
|
|
row = col.row()
|
|
|
|
|
row.active = basic_stereo
|
|
|
|
|
row.prop(view, "show_stereo_3d_cameras")
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.active = basic_stereo
|
|
|
|
|
split = row.split()
|
|
|
|
|
split.prop(view, "show_stereo_3d_convergence_plane")
|
|
|
|
|
split = row.split()
|
|
|
|
|
split.prop(view, "stereo_3d_convergence_plane_alpha", text="Alpha")
|
|
|
|
|
split.active = view.show_stereo_3d_convergence_plane
|
|
|
|
|
row = col.row()
|
|
|
|
|
split = row.split()
|
|
|
|
|
split.prop(view, "show_stereo_3d_volume")
|
|
|
|
|
split = row.split()
|
2019-03-06 13:54:51 -03:00
|
|
|
split.active = view.show_stereo_3d_volume
|
2015-04-06 10:40:12 -03:00
|
|
|
split.prop(view, "stereo_3d_volume_alpha", text="Alpha")
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class VIEW3D_PT_context_properties(Panel):
|
2009-11-18 20:01:35 +00:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
2019-04-30 00:14:11 +10:00
|
|
|
bl_category = "Item"
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Properties"
|
2010-08-26 01:05:37 +00:00
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
2009-11-18 20:01:35 +00:00
|
|
|
|
2019-04-19 07:51:14 +02:00
|
|
|
@staticmethod
|
2010-08-05 21:58:57 +00:00
|
|
|
def _active_context_member(context):
|
2009-11-18 20:01:35 +00:00
|
|
|
obj = context.object
|
|
|
|
|
if obj:
|
2018-06-19 09:25:05 +02:00
|
|
|
object_mode = obj.mode
|
|
|
|
|
if object_mode == 'POSE':
|
2009-11-24 17:12:32 +00:00
|
|
|
return "active_pose_bone"
|
2018-06-19 09:25:05 +02:00
|
|
|
elif object_mode == 'EDIT' and obj.type == 'ARMATURE':
|
2009-11-23 13:06:26 +00:00
|
|
|
return "active_bone"
|
2009-11-18 20:01:35 +00:00
|
|
|
else:
|
2009-11-23 13:06:26 +00:00
|
|
|
return "object"
|
|
|
|
|
|
|
|
|
|
return ""
|
2009-11-28 23:37:56 +00:00
|
|
|
|
2010-08-09 01:37:09 +00:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2014-06-06 14:38:07 +02:00
|
|
|
import rna_prop_ui
|
2010-08-09 01:37:09 +00:00
|
|
|
member = cls._active_context_member(context)
|
2014-06-06 14:38:07 +02:00
|
|
|
|
2009-11-23 13:06:26 +00:00
|
|
|
if member:
|
2014-06-06 14:38:07 +02:00
|
|
|
context_member, member = rna_prop_ui.rna_idprop_context_value(context, member, object)
|
|
|
|
|
return context_member and rna_prop_ui.rna_idprop_has_properties(context_member)
|
2009-11-23 13:06:26 +00:00
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
import rna_prop_ui
|
2011-07-11 05:50:49 +00:00
|
|
|
member = VIEW3D_PT_context_properties._active_context_member(context)
|
2009-11-18 20:01:35 +00:00
|
|
|
|
2009-11-23 13:06:26 +00:00
|
|
|
if member:
|
2009-11-18 20:01:35 +00:00
|
|
|
# Draw with no edit button
|
PyAPI: use keyword only arguments
Use keyword only arguments for the following functions.
- addon_utils.module_bl_info 2nd arg `info_basis`.
- addon_utils.modules 1st `module_cache`, 2nd arg `refresh`.
- addon_utils.modules_refresh 1st arg `module_cache`.
- bl_app_template_utils.activate 1nd arg `template_id`.
- bl_app_template_utils.import_from_id 2nd arg `ignore_not_found`.
- bl_app_template_utils.import_from_path 2nd arg `ignore_not_found`.
- bl_keymap_utils.keymap_from_toolbar.generate 2nd & 3rd args `use_fallback_keys` & `use_reset`.
- bl_keymap_utils.platform_helpers.keyconfig_data_oskey_from_ctrl 2nd arg `filter_fn`.
- bl_ui_utils.bug_report_url.url_prefill_from_blender 1st arg `addon_info`.
- bmesh.types.BMFace.copy 1st & 2nd args `verts`, `edges`.
- bmesh.types.BMesh.calc_volume 1st arg `signed`.
- bmesh.types.BMesh.from_mesh 2nd..4th args `face_normals`, `use_shape_key`, `shape_key_index`.
- bmesh.types.BMesh.from_object 3rd & 4th args `cage`, `face_normals`.
- bmesh.types.BMesh.transform 2nd arg `filter`.
- bmesh.types.BMesh.update_edit_mesh 2nd & 3rd args `loop_triangles`, `destructive`.
- bmesh.types.{BMVertSeq,BMEdgeSeq,BMFaceSeq}.sort 1st & 2nd arg `key`, `reverse`.
- bmesh.utils.face_split 4th..6th args `coords`, `use_exist`, `example`.
- bpy.data.libraries.load 2nd..4th args `link`, `relative`, `assets_only`.
- bpy.data.user_map 1st..3rd args `subset`, `key_types, `value_types`.
- bpy.msgbus.subscribe_rna 5th arg `options`.
- bpy.path.abspath 2nd & 3rd args `start` & `library`.
- bpy.path.clean_name 2nd arg `replace`.
- bpy.path.ensure_ext 3rd arg `case_sensitive`.
- bpy.path.module_names 2nd arg `recursive`.
- bpy.path.relpath 2nd arg `start`.
- bpy.types.EditBone.transform 2nd & 3rd arg `scale`, `roll`.
- bpy.types.Operator.as_keywords 1st arg `ignore`.
- bpy.types.Struct.{keyframe_insert,keyframe_delete} 2nd..5th args `index`, `frame`, `group`, `options`.
- bpy.types.WindowManager.popup_menu 2nd & 3rd arg `title`, `icon`.
- bpy.types.WindowManager.popup_menu_pie 3rd & 4th arg `title`, `icon`.
- bpy.utils.app_template_paths 1st arg `subdir`.
- bpy.utils.app_template_paths 1st arg `subdir`.
- bpy.utils.blend_paths 1st..3rd args `absolute`, `packed`, `local`.
- bpy.utils.execfile 2nd arg `mod`.
- bpy.utils.keyconfig_set 2nd arg `report`.
- bpy.utils.load_scripts 1st & 2nd `reload_scripts` & `refresh_scripts`.
- bpy.utils.preset_find 3rd & 4th args `display_name`, `ext`.
- bpy.utils.resource_path 2nd & 3rd arg `major`, `minor`.
- bpy.utils.script_paths 1st..4th args `subdir`, `user_pref`, `check_all`, `use_user`.
- bpy.utils.smpte_from_frame 2nd & 3rd args `fps`, `fps_base`.
- bpy.utils.smpte_from_seconds 2nd & 3rd args `fps`, `fps_base`.
- bpy.utils.system_resource 2nd arg `subdir`.
- bpy.utils.time_from_frame 2nd & 3rd args `fps`, `fps_base`.
- bpy.utils.time_to_frame 2nd & 3rd args `fps`, `fps_base`.
- bpy.utils.units.to_string 4th..6th `precision`, `split_unit`, `compatible_unit`.
- bpy.utils.units.to_value 4th arg `str_ref_unit`.
- bpy.utils.user_resource 2nd & 3rd args `subdir`, `create`
- bpy_extras.view3d_utils.location_3d_to_region_2d 4th arg `default`.
- bpy_extras.view3d_utils.region_2d_to_origin_3d 4th arg `clamp`.
- gpu.offscreen.unbind 1st arg `restore`.
- gpu_extras.batch.batch_for_shader 4th arg `indices`.
- gpu_extras.batch.presets.draw_circle_2d 4th arg `segments`.
- gpu_extras.presets.draw_circle_2d 4th arg `segments`.
- imbuf.types.ImBuf.resize 2nd arg `resize`.
- imbuf.write 2nd arg `filepath`.
- mathutils.kdtree.KDTree.find 2nd arg `filter`.
- nodeitems_utils.NodeCategory 3rd & 4th arg `descriptions`, `items`.
- nodeitems_utils.NodeItem 2nd..4th args `label`, `settings`, `poll`.
- nodeitems_utils.NodeItemCustom 1st & 2nd arg `poll`, `draw`.
- rna_prop_ui.draw 5th arg `use_edit`.
- rna_prop_ui.rna_idprop_ui_get 2nd arg `create`.
- rna_prop_ui.rna_idprop_ui_prop_clear 3rd arg `remove`.
- rna_prop_ui.rna_idprop_ui_prop_get 3rd arg `create`.
- rna_xml.xml2rna 2nd arg `root_rna`.
- rna_xml.xml_file_write 4th arg `skip_typemap`.
2021-06-08 18:03:14 +10:00
|
|
|
rna_prop_ui.draw(self.layout, context, member, object, use_edit=False)
|
2011-03-24 03:02:34 +00:00
|
|
|
|
2017-10-19 11:24:01 +11:00
|
|
|
|
2025-04-09 14:41:01 +02:00
|
|
|
class VIEW3D_PT_active_spline(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "Item"
|
|
|
|
|
bl_label = "Active Spline"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
ob = context.object
|
2025-04-15 08:43:03 +08:00
|
|
|
if ob is None or ob.type not in {'CURVE', 'SURFACE'} or ob.mode != 'EDIT':
|
2025-04-09 14:41:01 +02:00
|
|
|
return False
|
|
|
|
|
curve = ob.data
|
|
|
|
|
return curve.splines.active is not None
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
|
|
|
|
|
curve = context.object.data
|
|
|
|
|
act_spline = curve.splines.active
|
|
|
|
|
is_surf = type(curve) is SurfaceCurve
|
|
|
|
|
is_poly = (act_spline.type == 'POLY')
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
|
|
|
|
|
if is_poly:
|
|
|
|
|
# These settings are below but its easier to have
|
|
|
|
|
# polys set aside since they use so few settings
|
|
|
|
|
|
|
|
|
|
col.prop(act_spline, "use_cyclic_u")
|
|
|
|
|
col.prop(act_spline, "use_smooth")
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
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(heading="Bézier", align=True)
|
|
|
|
|
# sub.active = (not act_spline.use_cyclic_u)
|
|
|
|
|
sub.prop(act_spline, "use_bezier_u", text="U")
|
|
|
|
|
|
|
|
|
|
if is_surf:
|
|
|
|
|
subsub = sub.column()
|
|
|
|
|
subsub.prop(act_spline, "use_bezier_v", text="V")
|
|
|
|
|
|
|
|
|
|
sub = col.column(heading="Endpoint", align=True)
|
|
|
|
|
sub.prop(act_spline, "use_endpoint_u", text="U")
|
|
|
|
|
|
|
|
|
|
if is_surf:
|
|
|
|
|
subsub = sub.column()
|
|
|
|
|
subsub.prop(act_spline, "use_endpoint_v", text="V")
|
|
|
|
|
|
|
|
|
|
sub = col.column(align=True)
|
|
|
|
|
sub.prop(act_spline, "order_u", text="Order U")
|
|
|
|
|
|
|
|
|
|
if is_surf:
|
|
|
|
|
sub.prop(act_spline, "order_v", text="V")
|
|
|
|
|
|
|
|
|
|
sub = col.column(align=True)
|
|
|
|
|
sub.prop(act_spline, "resolution_u", text="Resolution U")
|
|
|
|
|
if is_surf:
|
|
|
|
|
sub.prop(act_spline, "resolution_v", text="V")
|
|
|
|
|
|
|
|
|
|
if act_spline.type == 'BEZIER':
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
sub = col.column()
|
|
|
|
|
sub.active = (curve.dimensions == '3D')
|
|
|
|
|
sub.prop(act_spline, "tilt_interpolation", text="Interpolation Tilt")
|
|
|
|
|
|
|
|
|
|
col.prop(act_spline, "radius_interpolation", text="Radius")
|
|
|
|
|
|
|
|
|
|
layout.prop(act_spline, "use_smooth")
|
|
|
|
|
if act_spline.type == 'NURBS':
|
|
|
|
|
col = None
|
|
|
|
|
for direction in range(2):
|
|
|
|
|
message = act_spline.valid_message(direction)
|
|
|
|
|
if not message:
|
|
|
|
|
continue
|
|
|
|
|
if col is None:
|
|
|
|
|
layout.separator()
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.label(text=message, icon='INFO')
|
|
|
|
|
del col
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 12:04:45 +01:00
|
|
|
class VIEW3D_PT_grease_pencil_multi_frame(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Multi Frame"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
|
|
|
|
|
settings = tool_settings.gpencil_sculpt
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(settings, "use_multiframe_falloff")
|
|
|
|
|
|
|
|
|
|
# Falloff curve
|
|
|
|
|
if settings.use_multiframe_falloff:
|
|
|
|
|
layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
|
|
|
|
|
|
|
|
|
|
|
2023-12-01 13:12:10 +01:00
|
|
|
class VIEW3D_MT_greasepencil_material_active(Menu):
|
|
|
|
|
bl_label = "Active Material"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
ob = context.active_object
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
for slot in ob.material_slots:
|
|
|
|
|
mat = slot.material
|
|
|
|
|
if not mat:
|
|
|
|
|
continue
|
|
|
|
|
mat.id_data.preview_ensure()
|
|
|
|
|
if mat and mat.id_data and mat.id_data.preview:
|
|
|
|
|
icon = mat.id_data.preview.icon_id
|
|
|
|
|
layout.operator("grease_pencil.set_material", text=mat.name, icon_value=icon).slot = mat.name
|
|
|
|
|
|
|
|
|
|
|
2024-01-12 13:40:00 +01:00
|
|
|
class VIEW3D_MT_grease_pencil_assign_material(Menu):
|
|
|
|
|
bl_label = "Assign Material"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
ob = context.active_object
|
|
|
|
|
mat_active = ob.active_material
|
|
|
|
|
|
|
|
|
|
if len(ob.material_slots) == 0:
|
|
|
|
|
row = layout.row()
|
|
|
|
|
row.label(text="No Materials")
|
|
|
|
|
row.enabled = False
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
for slot in ob.material_slots:
|
|
|
|
|
mat = slot.material
|
|
|
|
|
if mat:
|
2025-01-14 12:46:40 +11:00
|
|
|
layout.operator(
|
|
|
|
|
"grease_pencil.stroke_material_set", text=mat.name,
|
|
|
|
|
icon='LAYER_ACTIVE' if mat == mat_active else 'BLANK1',
|
|
|
|
|
).material = mat.name
|
2024-01-12 13:40:00 +01:00
|
|
|
|
|
|
|
|
|
2023-10-26 16:52:31 +02:00
|
|
|
class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
|
|
|
|
|
bl_label = ""
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
|
|
|
|
|
is_stroke_mode = tool_settings.gpencil_selectmode_edit == 'STROKE'
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
|
|
|
|
|
|
|
|
|
row = layout.row()
|
|
|
|
|
|
2024-10-11 10:05:22 +02:00
|
|
|
if is_stroke_mode:
|
2023-10-26 16:52:31 +02:00
|
|
|
col = row.column(align=True)
|
2024-10-11 10:05:22 +02:00
|
|
|
col.label(text="Stroke", icon='GP_SELECT_STROKES')
|
2023-10-26 16:52:31 +02:00
|
|
|
|
2024-04-16 12:21:29 +02:00
|
|
|
col.separator()
|
|
|
|
|
|
2023-10-26 16:52:31 +02:00
|
|
|
# Main Strokes Operators
|
2024-01-11 12:06:28 +01:00
|
|
|
col.operator("grease_pencil.stroke_subdivide", text="Subdivide")
|
|
|
|
|
col.operator("grease_pencil.stroke_subdivide_smooth", text="Subdivide and Smooth")
|
2023-10-26 16:52:31 +02:00
|
|
|
col.operator("grease_pencil.stroke_simplify", text="Simplify")
|
2025-05-31 22:38:33 +02:00
|
|
|
col.operator("grease_pencil.outline", text="Outline")
|
2023-10-26 16:52:31 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
# Deform Operators
|
2024-10-11 10:05:22 +02:00
|
|
|
col.operator("grease_pencil.stroke_smooth", text="Smooth")
|
2024-10-03 18:14:58 +02:00
|
|
|
col.operator("transform.transform", text="Shrink/Fatten").mode = 'CURVE_SHRINKFATTEN'
|
2023-10-26 16:52:31 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2024-10-11 10:05:22 +02:00
|
|
|
col.menu("GREASE_PENCIL_MT_move_to_layer")
|
|
|
|
|
col.menu("VIEW3D_MT_grease_pencil_assign_material")
|
|
|
|
|
col.operator("grease_pencil.set_active_material", text="Set as Active Material")
|
|
|
|
|
col.operator_menu_enum("grease_pencil.reorder", text="Arrange", property="direction")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col.menu("VIEW3D_MT_mirror")
|
2024-02-08 12:41:23 +01:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2024-04-30 14:03:31 +02:00
|
|
|
# Copy/paste
|
2024-02-08 12:41:23 +01:00
|
|
|
col.operator("grease_pencil.duplicate_move", text="Duplicate")
|
2025-02-07 16:17:16 +01:00
|
|
|
col.operator("grease_pencil.copy", text="Copy", icon='COPYDOWN')
|
|
|
|
|
col.operator("grease_pencil.paste", text="Paste", icon='PASTEDOWN').type = 'ACTIVE'
|
|
|
|
|
col.operator("grease_pencil.paste", text="Paste by Layer").type = 'LAYER'
|
2023-10-26 16:52:31 +02:00
|
|
|
|
2024-02-06 12:06:48 +01:00
|
|
|
col.separator()
|
|
|
|
|
|
2024-05-02 12:51:30 +02:00
|
|
|
col.operator("grease_pencil.extrude_move", text="Extrude")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2024-02-06 12:06:48 +01:00
|
|
|
col.operator("grease_pencil.separate", text="Separate").mode = 'SELECTED'
|
2025-06-04 11:48:15 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
col.operator_menu_enum("grease_pencil.convert_curve_type", text="Convert Type", property="type")
|
|
|
|
|
layout.operator("grease_pencil.set_curve_resolution", text="Convert Type")
|
2024-10-11 10:05:22 +02:00
|
|
|
else:
|
2023-10-26 16:52:31 +02:00
|
|
|
col = row.column(align=True)
|
2024-10-11 10:05:22 +02:00
|
|
|
col.label(text="Point", icon='GP_SELECT_POINTS')
|
2023-10-26 16:52:31 +02:00
|
|
|
|
2024-04-16 12:21:29 +02:00
|
|
|
col.separator()
|
|
|
|
|
|
2023-10-26 16:52:31 +02:00
|
|
|
# Main Strokes Operators
|
2024-01-11 12:06:28 +01:00
|
|
|
col.operator("grease_pencil.stroke_subdivide", text="Subdivide")
|
|
|
|
|
col.operator("grease_pencil.stroke_subdivide_smooth", text="Subdivide and Smooth")
|
2023-10-26 16:52:31 +02:00
|
|
|
col.operator("grease_pencil.stroke_simplify", text="Simplify")
|
2025-05-31 22:38:33 +02:00
|
|
|
col.operator("grease_pencil.outline", text="Outline")
|
2023-10-26 16:52:31 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
# Deform Operators
|
2024-10-11 10:05:22 +02:00
|
|
|
col.operator("transform.tosphere", text="To Sphere")
|
|
|
|
|
col.operator("transform.shear", text="Shear")
|
|
|
|
|
col.operator("transform.bend", text="Bend")
|
|
|
|
|
col.operator("transform.push_pull", text="Push/Pull")
|
2024-10-03 18:14:58 +02:00
|
|
|
col.operator("transform.transform", text="Shrink/Fatten").mode = 'CURVE_SHRINKFATTEN'
|
2024-10-11 10:05:22 +02:00
|
|
|
col.operator("grease_pencil.stroke_smooth", text="Smooth Points")
|
2024-12-09 11:04:16 +01:00
|
|
|
col.operator("grease_pencil.set_start_point", text="Set Start Point")
|
2025-09-30 13:00:04 +02:00
|
|
|
col.operator_menu_enum("grease_pencil.set_corner_type", property="corner_type")
|
2023-10-26 16:52:31 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2025-06-28 16:34:42 +02:00
|
|
|
col.menu("VIEW3D_MT_mirror", text="Mirror", text_ctxt=i18n_contexts.operator_default)
|
2023-10-26 16:52:31 +02:00
|
|
|
|
2024-02-06 12:06:48 +01:00
|
|
|
col.separator()
|
|
|
|
|
|
2024-04-30 14:03:31 +02:00
|
|
|
# Copy/paste
|
|
|
|
|
col.operator("grease_pencil.copy", text="Copy", icon='COPYDOWN')
|
|
|
|
|
col.operator("grease_pencil.paste", text="Paste", icon='PASTEDOWN')
|
2024-02-08 12:41:23 +01:00
|
|
|
col.operator("grease_pencil.duplicate_move", text="Duplicate")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2024-05-02 12:51:30 +02:00
|
|
|
col.operator("grease_pencil.extrude_move", text="Extrude")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
2025-03-14 12:37:25 +01:00
|
|
|
col.operator("grease_pencil.stroke_split", text="Split")
|
2024-02-06 12:06:48 +01:00
|
|
|
col.operator("grease_pencil.separate", text="Separate").mode = 'SELECTED'
|
|
|
|
|
|
2024-10-11 10:05:22 +02:00
|
|
|
# Removal Operators
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col.operator_enum("grease_pencil.dissolve", "type")
|
2023-10-26 16:52:31 +02:00
|
|
|
|
2025-06-04 11:48:15 +02:00
|
|
|
col.separator()
|
|
|
|
|
col.operator_menu_enum("grease_pencil.convert_curve_type", text="Convert Type", property="type")
|
|
|
|
|
|
2024-10-11 12:07:09 +03:00
|
|
|
|
2024-08-08 16:03:09 +02:00
|
|
|
class GREASE_PENCIL_MT_Layers(Menu):
|
|
|
|
|
bl_label = "Layers"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
grease_pencil = context.active_object.data
|
|
|
|
|
|
|
|
|
|
layout.operator("grease_pencil.layer_add", text="New Layer", icon='ADD')
|
|
|
|
|
|
|
|
|
|
if not grease_pencil.layers:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
# Display layers in layer stack order. The last layer is the top most layer.
|
|
|
|
|
for i in range(len(grease_pencil.layers) - 1, -1, -1):
|
|
|
|
|
layer = grease_pencil.layers[i]
|
|
|
|
|
if layer == grease_pencil.layers.active:
|
2024-10-29 16:56:11 +01:00
|
|
|
icon = 'DOT'
|
2024-08-08 16:03:09 +02:00
|
|
|
else:
|
|
|
|
|
icon = 'NONE'
|
|
|
|
|
layout.operator("grease_pencil.layer_active", text=layer.name, icon=icon).layer = i
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_PT_greasepencil_draw_context_menu(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Draw"
|
|
|
|
|
bl_ui_units_x = 12
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
settings = tool_settings.gpencil_paint
|
|
|
|
|
brush = settings.brush
|
|
|
|
|
gp_settings = brush.gpencil_settings
|
|
|
|
|
|
|
|
|
|
is_pin_vertex = gp_settings.brush_draw_mode == 'VERTEXCOLOR'
|
2025-06-06 23:40:13 +02:00
|
|
|
is_vertex = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_brush_type == 'TINT' or is_pin_vertex
|
2024-08-08 16:03:09 +02:00
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type not in {'ERASE', 'CUTTER', 'EYEDROPPER'} and is_vertex:
|
2024-08-08 16:03:09 +02:00
|
|
|
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()
|
|
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type not in {'FILL', 'CUTTER', 'ERASE'}:
|
2025-07-07 11:12:01 +02:00
|
|
|
if brush.use_locked_size == 'VIEW':
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(brush, "size", slider=True)
|
|
|
|
|
row.prop(brush, "use_pressure_size", text="", icon='STYLUS_PRESSURE')
|
|
|
|
|
else:
|
|
|
|
|
row = layout.row(align=True)
|
2025-08-30 00:18:41 +02:00
|
|
|
row.prop(brush, "unprojected_size", text="Size", slider=True)
|
2025-07-07 11:12:01 +02:00
|
|
|
row.prop(brush, "use_pressure_size", text="", icon='STYLUS_PRESSURE')
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type == 'ERASE':
|
2025-07-07 11:12:01 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(brush, "size", slider=True)
|
|
|
|
|
row.prop(brush, "use_pressure_size", text="", icon='STYLUS_PRESSURE')
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type not in {'ERASE', 'FILL', 'CUTTER'}:
|
2025-07-07 11:12:01 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(brush, "strength", slider=True)
|
|
|
|
|
row.prop(brush, "use_pressure_strength", text="", icon='STYLUS_PRESSURE')
|
2024-08-08 16:03:09 +02:00
|
|
|
|
|
|
|
|
layer = context.object.data.layers.active
|
|
|
|
|
|
|
|
|
|
if layer:
|
|
|
|
|
layout.label(text="Active Layer")
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.operator_context = 'EXEC_REGION_WIN'
|
2024-10-29 16:56:11 +01:00
|
|
|
row.menu("GREASE_PENCIL_MT_Layers", text="", icon='OUTLINER_DATA_GP_LAYER')
|
2024-08-29 17:16:44 +10:00
|
|
|
row.prop(layer, "name", text="")
|
2024-08-08 16:03:09 +02:00
|
|
|
row.operator("grease_pencil.layer_remove", text="", icon='X')
|
|
|
|
|
|
|
|
|
|
layout.label(text="Active Material")
|
|
|
|
|
row = layout.row(align=True)
|
2024-08-29 17:16:44 +10:00
|
|
|
row.menu("VIEW3D_MT_greasepencil_material_active", text="", icon='MATERIAL')
|
2024-08-08 16:03:09 +02:00
|
|
|
ob = context.active_object
|
|
|
|
|
if ob.active_material:
|
2024-08-29 17:16:44 +10:00
|
|
|
row.prop(ob.active_material, "name", text="")
|
2024-08-08 16:03:09 +02:00
|
|
|
|
2024-08-12 09:47:02 -04:00
|
|
|
|
2024-08-12 13:05:13 +02:00
|
|
|
class VIEW3D_PT_greasepencil_sculpt_context_menu(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Sculpt"
|
|
|
|
|
bl_ui_units_x = 12
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
tool_settings = context.tool_settings
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
paint = tool_settings.gpencil_sculpt_paint
|
|
|
|
|
brush = paint.brush
|
2024-08-12 13:05:13 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
ups = paint.unified_paint_settings
|
2024-08-12 13:05:13 +02:00
|
|
|
size_owner = ups if ups.use_unified_size else brush
|
|
|
|
|
strength_owner = ups if ups.use_unified_strength else brush
|
2025-07-07 11:12:01 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(size_owner, "size", text="")
|
|
|
|
|
row.prop(brush, "use_pressure_size", text="", icon='STYLUS_PRESSURE')
|
|
|
|
|
row.prop(ups, "use_unified_size", text="", icon='BRUSHES_ALL')
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(strength_owner, "strength", text="")
|
|
|
|
|
row.prop(brush, "use_pressure_strength", text="", icon='STYLUS_PRESSURE')
|
|
|
|
|
row.prop(ups, "use_unified_strength", text="", icon='BRUSHES_ALL')
|
2024-08-12 13:05:13 +02:00
|
|
|
|
|
|
|
|
layer = context.object.data.layers.active
|
|
|
|
|
|
|
|
|
|
if layer:
|
|
|
|
|
layout.label(text="Active Layer")
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.operator_context = 'EXEC_REGION_WIN'
|
2024-10-29 16:56:11 +01:00
|
|
|
row.menu("GREASE_PENCIL_MT_Layers", text="", icon='OUTLINER_DATA_GP_LAYER')
|
2024-08-29 17:16:44 +10:00
|
|
|
row.prop(layer, "name", text="")
|
2024-08-12 13:05:13 +02:00
|
|
|
row.operator("grease_pencil.layer_remove", text="", icon='X')
|
|
|
|
|
|
2024-08-08 16:03:09 +02:00
|
|
|
|
2024-09-16 12:02:30 +02:00
|
|
|
class VIEW3D_PT_greasepencil_vertex_paint_context_menu(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Vertex Paint"
|
|
|
|
|
bl_ui_units_x = 12
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
settings = tool_settings.gpencil_vertex_paint
|
|
|
|
|
brush = settings.brush
|
|
|
|
|
gp_settings = brush.gpencil_settings
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_vertex_brush_type in {'DRAW', 'REPLACE'}:
|
2024-09-16 12:02:30 +02:00
|
|
|
split = layout.split(factor=0.1)
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
split.prop(settings.unified_paint_settings, "color", text="")
|
|
|
|
|
split.template_color_picker(settings.unified_paint_settings, "color", value_slider=True)
|
2024-09-16 12:02:30 +02:00
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.separator()
|
|
|
|
|
col.prop(gp_settings, "vertex_mode", text="")
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
row = col.row(align=True)
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
row.prop(settings.unified_paint_settings, "size", text="Radius")
|
2024-09-16 12:02:30 +02:00
|
|
|
row.prop(brush, "use_pressure_size", text="", icon='STYLUS_PRESSURE')
|
|
|
|
|
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_vertex_brush_type in {'DRAW', 'BLUR', 'SMEAR'}:
|
2025-08-18 00:27:35 +02:00
|
|
|
ups = settings.unified_paint_settings
|
2025-07-07 11:12:01 +02:00
|
|
|
strength_owner = ups if ups.use_unified_strength else brush
|
2024-09-16 12:02:30 +02:00
|
|
|
row = layout.row(align=True)
|
2025-07-07 11:12:01 +02:00
|
|
|
row.prop(strength_owner, "strength", text="")
|
2024-09-16 12:02:30 +02:00
|
|
|
row.prop(brush, "use_pressure_strength", text="", icon='STYLUS_PRESSURE')
|
2025-07-07 11:12:01 +02:00
|
|
|
row.prop(ups, "use_unified_strength", text="", icon='BRUSHES_ALL')
|
2024-09-16 12:02:30 +02:00
|
|
|
|
|
|
|
|
layer = context.object.data.layers.active
|
|
|
|
|
|
|
|
|
|
if layer:
|
|
|
|
|
layout.label(text="Active Layer")
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.operator_context = 'EXEC_REGION_WIN'
|
2024-10-29 16:56:11 +01:00
|
|
|
row.menu("GREASE_PENCIL_MT_Layers", text="", icon='OUTLINER_DATA_GP_LAYER')
|
2024-09-16 12:02:30 +02:00
|
|
|
row.prop(layer, "name", text="")
|
|
|
|
|
row.operator("grease_pencil.layer_remove", text="", icon='X')
|
|
|
|
|
|
|
|
|
|
|
2024-10-03 13:42:54 +02:00
|
|
|
class VIEW3D_PT_greasepencil_weight_context_menu(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Weight Paint"
|
|
|
|
|
bl_ui_units_x = 12
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
settings = tool_settings.gpencil_weight_paint
|
|
|
|
|
brush = settings.brush
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
# Weight settings
|
|
|
|
|
brush_basic_grease_pencil_weight_settings(layout, context, brush)
|
|
|
|
|
|
2020-04-30 16:12:34 +02:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class VIEW3D_PT_grease_pencil_sculpt_automasking(Panel):
|
2022-11-08 16:55:59 +01:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2024-10-01 16:37:07 +02:00
|
|
|
bl_label = "Auto-Masking"
|
2022-11-08 16:55:59 +01:00
|
|
|
bl_ui_units_x = 10
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.scene.tool_settings
|
2023-04-13 13:14:03 +10:00
|
|
|
|
2024-10-01 16:37:07 +02:00
|
|
|
layout.label(text="Auto-Masking")
|
2022-11-08 16:55:59 +01:00
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(tool_settings.gpencil_sculpt, "use_automasking_stroke", text="Stroke")
|
|
|
|
|
col.prop(tool_settings.gpencil_sculpt, "use_automasking_layer_stroke", text="Layer")
|
|
|
|
|
col.prop(tool_settings.gpencil_sculpt, "use_automasking_material_stroke", text="Material")
|
|
|
|
|
col.separator()
|
|
|
|
|
col.prop(tool_settings.gpencil_sculpt, "use_automasking_layer_active", text="Active Layer")
|
|
|
|
|
col.prop(tool_settings.gpencil_sculpt, "use_automasking_material_active", text="Active Material")
|
|
|
|
|
|
|
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_PT_paint_vertex_context_menu(Panel):
|
2019-03-04 20:10:11 +11:00
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Vertex Paint"
|
2019-03-04 20:10:11 +11:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
2019-03-12 15:29:18 +11:00
|
|
|
brush = context.tool_settings.vertex_paint.brush
|
2019-05-04 15:03:42 +02:00
|
|
|
capabilities = brush.vertex_paint_capabilities
|
|
|
|
|
|
|
|
|
|
if capabilities.has_color:
|
|
|
|
|
split = layout.split(factor=0.1)
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(split, context, brush, "color", text="")
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color_picker(split, context, brush, "color", value_slider=True)
|
|
|
|
|
layout.prop(brush, "blend", text="")
|
|
|
|
|
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"size",
|
|
|
|
|
unified_name="use_unified_size",
|
|
|
|
|
pressure_name="use_pressure_size",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
unified_name="use_unified_strength",
|
|
|
|
|
pressure_name="use_pressure_strength",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
|
|
|
|
|
2019-03-04 20:10:11 +11:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_PT_paint_texture_context_menu(Panel):
|
2019-03-04 20:10:11 +11:00
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Texture Paint"
|
2019-03-04 20:10:11 +11:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI:
- All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together.
- The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa.
- Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel.
- UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header.
- 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off.
- Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke.
- Display (now Cursor) panel was reorganized, settings renamed.
- 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True.
- Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity.
- De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow.
- A few more tweaks - see D5928 for the extensive list.
Most of the patch is written by Demeter Dzadik, with some additions by myself
Differential Revision: https://developer.blender.org/D5928
Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
2019-12-14 18:48:18 +01:00
|
|
|
|
2019-03-12 15:29:18 +11:00
|
|
|
brush = context.tool_settings.image_paint.brush
|
2019-03-20 17:04:57 +01:00
|
|
|
capabilities = brush.image_paint_capabilities
|
|
|
|
|
|
2019-05-04 15:03:42 +02:00
|
|
|
if capabilities.has_color:
|
|
|
|
|
split = layout.split(factor=0.1)
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(split, context, brush, "color", text="")
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color_picker(split, context, brush, "color", value_slider=True)
|
|
|
|
|
layout.prop(brush, "blend", text="")
|
|
|
|
|
|
2019-03-20 17:04:57 +01:00
|
|
|
if capabilities.has_radius:
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"size",
|
|
|
|
|
unified_name="use_unified_size",
|
|
|
|
|
pressure_name="use_pressure_size",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
unified_name="use_unified_strength",
|
|
|
|
|
pressure_name="use_pressure_strength",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
2019-03-04 20:10:11 +11:00
|
|
|
|
|
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_PT_paint_weight_context_menu(Panel):
|
2019-03-04 20:10:11 +11:00
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Weights"
|
2019-03-04 20:10:11 +11:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
2019-03-11 14:34:07 +01:00
|
|
|
layout = self.layout
|
2019-03-11 15:01:07 +01:00
|
|
|
|
2019-03-12 15:29:18 +11:00
|
|
|
brush = context.tool_settings.weight_paint.brush
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"weight",
|
|
|
|
|
unified_name="use_unified_weight",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"size",
|
|
|
|
|
unified_name="use_unified_size",
|
|
|
|
|
pressure_name="use_pressure_size",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
unified_name="use_unified_strength",
|
|
|
|
|
pressure_name="use_pressure_strength",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
2019-03-04 20:10:11 +11:00
|
|
|
|
|
|
|
|
|
2022-10-17 11:17:42 +02:00
|
|
|
class VIEW3D_PT_sculpt_automasking(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Auto-Masking"
|
|
|
|
|
bl_ui_units_x = 10
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
sculpt = tool_settings.sculpt
|
|
|
|
|
layout.label(text="Auto-Masking")
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(sculpt, "use_automasking_topology", text="Topology")
|
|
|
|
|
col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
|
|
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
2024-09-24 18:02:30 +02:00
|
|
|
row = col.row()
|
|
|
|
|
row.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
|
|
|
|
|
|
|
|
|
|
if sculpt.use_automasking_boundary_edges:
|
|
|
|
|
props = row.operator("sculpt.mask_from_boundary", text="Create Mask")
|
|
|
|
|
props.settings_source = 'SCENE'
|
|
|
|
|
props.boundary_mode = 'MESH'
|
|
|
|
|
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
|
|
|
|
|
|
|
|
|
if sculpt.use_automasking_boundary_face_sets:
|
|
|
|
|
props = row.operator("sculpt.mask_from_boundary", text="Create Mask")
|
|
|
|
|
props.settings_source = 'SCENE'
|
|
|
|
|
props.boundary_mode = 'FACE_SETS'
|
2022-10-17 11:17:42 +02:00
|
|
|
|
|
|
|
|
if sculpt.use_automasking_boundary_edges or sculpt.use_automasking_boundary_face_sets:
|
2024-01-29 15:39:34 +01:00
|
|
|
col.prop(sculpt, "automasking_boundary_edges_propagation_steps")
|
2022-10-17 11:17:42 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
row = col.row()
|
|
|
|
|
row.prop(sculpt, "use_automasking_cavity", text="Cavity")
|
|
|
|
|
|
|
|
|
|
is_cavity_active = sculpt.use_automasking_cavity or sculpt.use_automasking_cavity_inverted
|
|
|
|
|
|
|
|
|
|
if is_cavity_active:
|
2022-11-15 08:39:06 -08:00
|
|
|
props = row.operator("sculpt.mask_from_cavity", text="Create Mask")
|
2023-05-15 20:53:17 +10:00
|
|
|
props.settings_source = 'SCENE'
|
2022-10-17 11:17:42 +02:00
|
|
|
|
|
|
|
|
col.prop(sculpt, "use_automasking_cavity_inverted", text="Cavity (inverted)")
|
|
|
|
|
|
|
|
|
|
if is_cavity_active:
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(sculpt, "automasking_cavity_factor", text="Factor")
|
|
|
|
|
col.prop(sculpt, "automasking_cavity_blur_steps", text="Blur")
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.prop(sculpt, "use_automasking_custom_cavity_curve", text="Custom Curve")
|
|
|
|
|
|
|
|
|
|
if sculpt.use_automasking_custom_cavity_curve:
|
2025-09-09 04:00:03 +02:00
|
|
|
col.template_curve_mapping(sculpt, "automasking_cavity_curve", brush=True)
|
2022-10-17 11:17:42 +02:00
|
|
|
|
|
|
|
|
col.separator()
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(sculpt, "use_automasking_view_normal", text="View Normal")
|
|
|
|
|
|
|
|
|
|
if sculpt.use_automasking_view_normal:
|
|
|
|
|
col.prop(sculpt, "use_automasking_view_occlusion", text="Occlusion")
|
|
|
|
|
subcol = col.column(align=True)
|
|
|
|
|
subcol.active = not sculpt.use_automasking_view_occlusion
|
|
|
|
|
subcol.prop(sculpt, "automasking_view_normal_limit", text="Limit")
|
|
|
|
|
subcol.prop(sculpt, "automasking_view_normal_falloff", text="Falloff")
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.prop(sculpt, "use_automasking_start_normal", text="Area Normal")
|
|
|
|
|
|
|
|
|
|
if sculpt.use_automasking_start_normal:
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(sculpt, "automasking_start_normal_limit", text="Limit")
|
|
|
|
|
col.prop(sculpt, "automasking_start_normal_falloff", text="Falloff")
|
|
|
|
|
|
|
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class VIEW3D_PT_sculpt_context_menu(Panel):
|
2019-03-04 20:10:11 +11:00
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Sculpt"
|
2019-03-04 20:10:11 +11:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2019-03-11 15:01:07 +01:00
|
|
|
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
paint = context.tool_settings.sculpt
|
|
|
|
|
brush = paint.brush
|
2019-03-20 17:04:57 +01:00
|
|
|
capabilities = brush.sculpt_capabilities
|
2019-03-11 15:01:07 +01:00
|
|
|
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
if capabilities.has_color:
|
|
|
|
|
split = layout.split(factor=0.1)
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(split, context, brush, "color", text="")
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color_picker(split, context, brush, "color", value_slider=True)
|
|
|
|
|
layout.prop(brush, "blend", text="")
|
|
|
|
|
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
ups = paint.unified_paint_settings
|
2022-03-13 17:45:16 -04:00
|
|
|
size = "size"
|
|
|
|
|
size_owner = ups if ups.use_unified_size else brush
|
|
|
|
|
if size_owner.use_locked_size == 'SCENE':
|
2025-08-30 00:18:41 +02:00
|
|
|
size = "unprojected_size"
|
2022-03-15 12:59:00 +11:00
|
|
|
|
2019-12-16 14:29:03 +11:00
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
2022-03-13 17:45:16 -04:00
|
|
|
size,
|
2019-12-16 14:29:03 +11:00
|
|
|
unified_name="use_unified_size",
|
|
|
|
|
pressure_name="use_pressure_size",
|
2025-08-30 00:18:41 +02:00
|
|
|
text="Size",
|
2019-12-16 14:29:03 +11:00
|
|
|
slider=True,
|
|
|
|
|
)
|
|
|
|
|
UnifiedPaintPanel.prop_unified(
|
|
|
|
|
layout,
|
|
|
|
|
context,
|
|
|
|
|
brush,
|
|
|
|
|
"strength",
|
|
|
|
|
unified_name="use_unified_strength",
|
|
|
|
|
pressure_name="use_pressure_strength",
|
|
|
|
|
slider=True,
|
|
|
|
|
)
|
2019-03-04 20:10:11 +11:00
|
|
|
|
2019-03-20 17:04:57 +01:00
|
|
|
if capabilities.has_auto_smooth:
|
|
|
|
|
layout.prop(brush, "auto_smooth_factor", slider=True)
|
|
|
|
|
|
|
|
|
|
if capabilities.has_normal_weight:
|
|
|
|
|
layout.prop(brush, "normal_weight", slider=True)
|
|
|
|
|
|
|
|
|
|
if capabilities.has_pinch_factor:
|
2020-02-10 21:44:33 +01:00
|
|
|
text = "Pinch"
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.sculpt_brush_type in {'BLOB', 'SNAKE_HOOK'}:
|
2020-02-10 21:44:33 +01:00
|
|
|
text = "Magnify"
|
|
|
|
|
layout.prop(brush, "crease_pinch_factor", slider=True, text=text)
|
2019-03-20 17:04:57 +01:00
|
|
|
|
|
|
|
|
if capabilities.has_rake_factor:
|
|
|
|
|
layout.prop(brush, "rake_factor", slider=True)
|
|
|
|
|
|
|
|
|
|
if capabilities.has_plane_offset:
|
|
|
|
|
layout.prop(brush, "plane_offset", slider=True)
|
|
|
|
|
layout.prop(brush, "plane_trim", slider=True, text="Distance")
|
|
|
|
|
|
|
|
|
|
if capabilities.has_height:
|
|
|
|
|
layout.prop(brush, "height", slider=True, text="Height")
|
2019-03-04 20:10:11 +11:00
|
|
|
|
2019-04-09 23:16:11 +10:00
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
class TOPBAR_PT_grease_pencil_materials(GreasePencilMaterialsPanel, Panel):
|
2018-11-27 15:23:12 +11:00
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Materials"
|
|
|
|
|
bl_ui_units_x = 14
|
|
|
|
|
|
2019-03-08 15:30:22 -03:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
ob = context.object
|
2024-10-04 13:05:09 +02:00
|
|
|
return ob and ob.type == 'GREASEPENCIL'
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2020-10-02 10:15:51 +10:00
|
|
|
|
2024-09-10 18:56:31 +02:00
|
|
|
class TOPBAR_PT_grease_pencil_vertex_color(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Color Attribute"
|
|
|
|
|
bl_ui_units_x = 10
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
ob = context.object
|
2024-10-04 14:41:45 +02:00
|
|
|
return ob and ob.type == 'GREASEPENCIL'
|
2024-09-10 18:56:31 +02:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False
|
|
|
|
|
|
2024-10-04 14:41:45 +02:00
|
|
|
ob = context.object
|
2024-10-04 19:20:00 +02:00
|
|
|
if ob.mode == 'PAINT_GREASE_PENCIL':
|
2024-10-04 14:41:45 +02:00
|
|
|
paint = context.scene.tool_settings.gpencil_paint
|
2024-10-04 19:20:00 +02:00
|
|
|
elif ob.mode == 'VERTEX_GREASE_PENCIL':
|
2024-10-04 14:41:45 +02:00
|
|
|
paint = context.scene.tool_settings.gpencil_vertex_paint
|
2024-11-08 10:21:24 +01:00
|
|
|
use_unified_paint = (ob.mode != 'PAINT_GREASE_PENCIL')
|
2024-10-04 14:41:45 +02:00
|
|
|
|
Paint: Make UnifiedPaintSettings a per-mode instead of scene-wide value
Historically, the `UnifiedPaintSettings` struct has been used to
provide users the ability to set brush values at a scene level. Examples
of such attributes are the brush size, strength, and color, to name a
few.
Instead of these values being shared across all of the grease pencil,
mesh painting, and curves sculpting modes. This commit migrates the
data to the `Paint` struct, meaning that each individual mode (e.g.
Sculpt, Vertex Paint, Grease Pencil Draw) now has the ability to change
these values without affecting other modes.
While this change is large, the majority of the work is simply
refactoring access to the `UnifiedPaintSetting` struct. to ensure the
correct property is being retrieved.
Resolves #134077
Pull Request: https://projects.blender.org/blender/blender/pulls/139766
2025-06-21 02:35:14 +02:00
|
|
|
ups = paint.unified_paint_settings
|
2024-10-04 14:41:45 +02:00
|
|
|
brush = paint.brush
|
2024-11-08 10:21:24 +01:00
|
|
|
prop_owner = ups if use_unified_paint and ups.use_unified_color else brush
|
2024-09-10 18:56:31 +02:00
|
|
|
|
|
|
|
|
col = layout.column()
|
2024-10-04 14:41:45 +02:00
|
|
|
col.template_color_picker(prop_owner, "color", value_slider=True)
|
2024-09-10 18:56:31 +02:00
|
|
|
|
|
|
|
|
sub_row = layout.row(align=True)
|
2024-11-08 10:21:24 +01:00
|
|
|
if use_unified_paint:
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(sub_row, context, brush, "color", text="")
|
|
|
|
|
UnifiedPaintPanel.prop_unified_color(sub_row, context, brush, "secondary_color", text="")
|
|
|
|
|
else:
|
|
|
|
|
sub_row.prop(brush, "color", text="")
|
|
|
|
|
sub_row.prop(brush, "secondary_color", text="")
|
2024-09-10 18:56:31 +02:00
|
|
|
|
2024-10-04 14:48:09 +02:00
|
|
|
sub_row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
|
2024-09-10 18:56:31 +02:00
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
2024-10-04 14:41:45 +02:00
|
|
|
row.template_ID(paint, "palette", new="palette.new")
|
|
|
|
|
if paint.palette:
|
|
|
|
|
layout.template_palette(paint, "palette", color=True)
|
2024-10-21 12:48:14 +02:00
|
|
|
|
2024-10-21 10:26:44 +02:00
|
|
|
gp_settings = brush.gpencil_settings
|
2025-06-06 23:40:13 +02:00
|
|
|
if brush.gpencil_brush_type in {'DRAW', 'FILL'}:
|
2024-10-21 10:26:44 +02:00
|
|
|
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")
|
2024-09-10 18:56:31 +02:00
|
|
|
|
|
|
|
|
|
2022-05-11 15:47:49 +02:00
|
|
|
class VIEW3D_PT_curves_sculpt_add_shape(Panel):
|
|
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Curves Sculpt Add Curve Options"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False # No animation.
|
|
|
|
|
|
|
|
|
|
settings = UnifiedPaintPanel.paint_settings(context)
|
|
|
|
|
brush = settings.brush
|
|
|
|
|
|
|
|
|
|
col = layout.column(heading="Interpolate", align=True)
|
2024-02-28 12:13:15 +11:00
|
|
|
col.prop(brush.curves_sculpt_settings, "use_length_interpolate", text="Length")
|
|
|
|
|
col.prop(brush.curves_sculpt_settings, "use_radius_interpolate", text="Radius")
|
|
|
|
|
col.prop(brush.curves_sculpt_settings, "use_shape_interpolate", text="Shape")
|
|
|
|
|
col.prop(brush.curves_sculpt_settings, "use_point_count_interpolate", text="Point Count")
|
2022-05-11 15:47:49 +02:00
|
|
|
|
|
|
|
|
col = layout.column()
|
2024-02-28 12:13:15 +11:00
|
|
|
col.active = not brush.curves_sculpt_settings.use_length_interpolate
|
2022-05-11 15:47:49 +02:00
|
|
|
col.prop(brush.curves_sculpt_settings, "curve_length", text="Length")
|
|
|
|
|
|
2024-02-27 18:22:03 +01:00
|
|
|
col = layout.column()
|
2024-02-28 12:13:15 +11:00
|
|
|
col.active = not brush.curves_sculpt_settings.use_radius_interpolate
|
2024-02-27 18:22:03 +01:00
|
|
|
col.prop(brush.curves_sculpt_settings, "curve_radius", text="Radius")
|
|
|
|
|
|
2022-05-11 15:47:49 +02:00
|
|
|
col = layout.column()
|
2024-02-28 12:13:15 +11:00
|
|
|
col.active = not brush.curves_sculpt_settings.use_point_count_interpolate
|
2022-05-11 15:47:49 +02:00
|
|
|
col.prop(brush.curves_sculpt_settings, "points_per_curve", text="Points")
|
|
|
|
|
|
|
|
|
|
|
2023-02-15 10:42:30 +01:00
|
|
|
class VIEW3D_PT_curves_sculpt_parameter_falloff(Panel):
|
|
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Curves Sculpt Parameter Falloff"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
settings = UnifiedPaintPanel.paint_settings(context)
|
|
|
|
|
brush = settings.brush
|
|
|
|
|
|
2025-09-09 04:00:03 +02:00
|
|
|
layout.template_curve_mapping(
|
|
|
|
|
brush.curves_sculpt_settings,
|
|
|
|
|
"curve_parameter_falloff",
|
2025-09-29 20:11:29 +02:00
|
|
|
brush=True,
|
|
|
|
|
show_presets=True)
|
2023-02-15 10:42:30 +01:00
|
|
|
|
|
|
|
|
|
2022-05-11 15:47:49 +02:00
|
|
|
class VIEW3D_PT_curves_sculpt_grow_shrink_scaling(Panel):
|
|
|
|
|
# Only for popover, these are dummy values.
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'WINDOW'
|
|
|
|
|
bl_label = "Curves Grow/Shrink Scaling"
|
|
|
|
|
bl_ui_units_x = 12
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False # No animation.
|
|
|
|
|
|
|
|
|
|
settings = UnifiedPaintPanel.paint_settings(context)
|
|
|
|
|
brush = settings.brush
|
|
|
|
|
|
2024-02-28 12:13:15 +11:00
|
|
|
layout.prop(brush.curves_sculpt_settings, "use_uniform_scale")
|
2022-05-11 15:47:49 +02:00
|
|
|
layout.prop(brush.curves_sculpt_settings, "minimum_length")
|
|
|
|
|
|
|
|
|
|
|
2022-09-02 18:30:48 +02:00
|
|
|
class VIEW3D_PT_viewport_debug(Panel):
|
|
|
|
|
bl_space_type = 'VIEW_3D'
|
|
|
|
|
bl_region_type = 'HEADER'
|
2023-09-29 14:32:54 +10:00
|
|
|
bl_parent_id = "VIEW3D_PT_overlay"
|
2022-09-02 18:30:48 +02:00
|
|
|
bl_label = "Viewport Debug"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
prefs = context.preferences
|
|
|
|
|
return prefs.experimental.use_viewport_debug
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
view = context.space_data
|
|
|
|
|
overlay = view.overlay
|
|
|
|
|
|
|
|
|
|
layout.prop(overlay, "use_debug_freeze_view_culling")
|
|
|
|
|
|
|
|
|
|
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
class View3DAssetShelf(BrushAssetShelf):
|
|
|
|
|
bl_space_type = "VIEW_3D"
|
|
|
|
|
|
|
|
|
|
|
2025-02-04 14:51:17 +11:00
|
|
|
class AssetShelfHiddenByDefault:
|
2024-10-04 12:21:05 +02:00
|
|
|
# Take #BrushAssetShelf.bl_options but remove the 'DEFAULT_VISIBLE' flag.
|
|
|
|
|
bl_options = {option for option in BrushAssetShelf.bl_options if option != 'DEFAULT_VISIBLE'}
|
|
|
|
|
|
|
|
|
|
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
class VIEW3D_AST_brush_sculpt(View3DAssetShelf, bpy.types.AssetShelf):
|
|
|
|
|
mode = 'SCULPT'
|
|
|
|
|
mode_prop = "use_paint_sculpt"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "sculpt_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_AST_brush_sculpt_curves(View3DAssetShelf, bpy.types.AssetShelf):
|
|
|
|
|
mode = 'SCULPT_CURVES'
|
|
|
|
|
mode_prop = "use_paint_sculpt_curves"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "curves_sculpt_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_AST_brush_vertex_paint(View3DAssetShelf, bpy.types.AssetShelf):
|
|
|
|
|
mode = 'VERTEX_PAINT'
|
|
|
|
|
mode_prop = "use_paint_vertex"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "vertex_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
2024-10-04 12:21:05 +02:00
|
|
|
class VIEW3D_AST_brush_weight_paint(AssetShelfHiddenByDefault, View3DAssetShelf, bpy.types.AssetShelf):
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
mode = 'WEIGHT_PAINT'
|
|
|
|
|
mode_prop = "use_paint_weight"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "weight_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_AST_brush_texture_paint(View3DAssetShelf, bpy.types.AssetShelf):
|
|
|
|
|
mode = 'TEXTURE_PAINT'
|
|
|
|
|
mode_prop = "use_paint_image"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "image_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
2025-09-22 15:56:52 +02:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
if not super().poll(context):
|
|
|
|
|
return False
|
|
|
|
|
# bl_space_type from #View3DAssetShelf is ignored for popup asset shelves.
|
|
|
|
|
# Avoid this to be called from the Image Editor (both
|
|
|
|
|
# #IMAGE_AST_brush_paint and #VIEW3D_AST_brush_texture_paint are included
|
|
|
|
|
# in the #km_image_paint keymap). See #145987.
|
|
|
|
|
return context.space_data.type != 'IMAGE_EDITOR'
|
|
|
|
|
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
class VIEW3D_AST_brush_gpencil_paint(View3DAssetShelf, bpy.types.AssetShelf):
|
|
|
|
|
mode = 'PAINT_GREASE_PENCIL'
|
|
|
|
|
mode_prop = "use_paint_grease_pencil"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "gpencil_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class VIEW3D_AST_brush_gpencil_sculpt(View3DAssetShelf, bpy.types.AssetShelf):
|
2024-10-04 19:20:00 +02:00
|
|
|
mode = 'SCULPT_GREASE_PENCIL'
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
mode_prop = "use_sculpt_grease_pencil"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "gpencil_sculpt_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
2024-10-04 12:21:05 +02:00
|
|
|
class VIEW3D_AST_brush_gpencil_vertex(AssetShelfHiddenByDefault, View3DAssetShelf, bpy.types.AssetShelf):
|
2024-10-04 19:20:00 +02:00
|
|
|
mode = 'VERTEX_GREASE_PENCIL'
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
mode_prop = "use_vertex_grease_pencil"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "gpencil_vertex_brush_type"
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
|
|
|
|
|
|
2024-10-04 12:21:05 +02:00
|
|
|
class VIEW3D_AST_brush_gpencil_weight(AssetShelfHiddenByDefault, View3DAssetShelf, bpy.types.AssetShelf):
|
2024-10-04 19:20:00 +02:00
|
|
|
mode = 'WEIGHT_GREASE_PENCIL'
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
mode_prop = "use_weight_grease_pencil"
|
2024-09-20 18:08:53 +02:00
|
|
|
brush_type_prop = "gpencil_weight_brush_type"
|
2023-08-03 17:10:25 +02:00
|
|
|
|
|
|
|
|
|
2017-03-18 20:03:24 +11:00
|
|
|
classes = (
|
|
|
|
|
VIEW3D_HT_header,
|
2019-04-18 21:13:22 +02:00
|
|
|
VIEW3D_HT_tool_header,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_editor_menus,
|
|
|
|
|
VIEW3D_MT_transform,
|
|
|
|
|
VIEW3D_MT_transform_object,
|
|
|
|
|
VIEW3D_MT_transform_armature,
|
|
|
|
|
VIEW3D_MT_mirror,
|
|
|
|
|
VIEW3D_MT_snap,
|
|
|
|
|
VIEW3D_MT_uv_map,
|
|
|
|
|
VIEW3D_MT_view,
|
2018-11-29 23:44:37 -02:00
|
|
|
VIEW3D_MT_view_local,
|
2017-10-19 12:35:58 +11:00
|
|
|
VIEW3D_MT_view_cameras,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_view_navigation,
|
|
|
|
|
VIEW3D_MT_view_align,
|
|
|
|
|
VIEW3D_MT_view_align_selected,
|
2017-10-19 12:35:58 +11:00
|
|
|
VIEW3D_MT_view_viewpoint,
|
2019-03-06 16:43:37 +01:00
|
|
|
VIEW3D_MT_view_regions,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_select_object,
|
|
|
|
|
VIEW3D_MT_select_object_more_less,
|
|
|
|
|
VIEW3D_MT_select_pose,
|
|
|
|
|
VIEW3D_MT_select_pose_more_less,
|
|
|
|
|
VIEW3D_MT_select_particle,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_edit_mesh,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_mesh_select_similar,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_edit_mesh_select_by_trait,
|
|
|
|
|
VIEW3D_MT_edit_mesh_select_more_less,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_select_edit_mesh,
|
|
|
|
|
VIEW3D_MT_select_edit_curve,
|
|
|
|
|
VIEW3D_MT_select_edit_surface,
|
|
|
|
|
VIEW3D_MT_select_edit_text,
|
|
|
|
|
VIEW3D_MT_select_edit_metaball,
|
2019-03-20 10:51:37 +01:00
|
|
|
VIEW3D_MT_edit_lattice_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_select_edit_lattice,
|
|
|
|
|
VIEW3D_MT_select_edit_armature,
|
2023-06-21 17:28:39 +02:00
|
|
|
VIEW3D_MT_select_edit_grease_pencil,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_select_paint_mask,
|
|
|
|
|
VIEW3D_MT_select_paint_mask_vertex,
|
2025-02-19 17:11:08 +01:00
|
|
|
VIEW3D_MT_select_edit_pointcloud,
|
2023-02-20 11:51:16 +01:00
|
|
|
VIEW3D_MT_edit_curves_select_more_less,
|
2022-02-18 11:16:02 +01:00
|
|
|
VIEW3D_MT_select_edit_curves,
|
2022-05-31 19:00:24 +02:00
|
|
|
VIEW3D_MT_select_sculpt_curves,
|
2018-08-29 15:02:21 +02:00
|
|
|
VIEW3D_MT_mesh_add,
|
|
|
|
|
VIEW3D_MT_curve_add,
|
|
|
|
|
VIEW3D_MT_surface_add,
|
2019-03-20 10:51:37 +01:00
|
|
|
VIEW3D_MT_edit_metaball_context_menu,
|
2018-08-29 15:02:21 +02:00
|
|
|
VIEW3D_MT_metaball_add,
|
|
|
|
|
TOPBAR_MT_edit_curve_add,
|
|
|
|
|
TOPBAR_MT_edit_armature_add,
|
|
|
|
|
VIEW3D_MT_armature_add,
|
|
|
|
|
VIEW3D_MT_light_add,
|
|
|
|
|
VIEW3D_MT_lightprobe_add,
|
|
|
|
|
VIEW3D_MT_camera_add,
|
2020-03-17 14:41:48 +01:00
|
|
|
VIEW3D_MT_volume_add,
|
2023-05-31 18:00:26 +02:00
|
|
|
VIEW3D_MT_grease_pencil_add,
|
2025-09-19 11:26:14 +10:00
|
|
|
VIEW3D_MT_lattice_add,
|
2024-12-23 22:31:33 +01:00
|
|
|
VIEW3D_MT_empty_add,
|
2018-08-29 15:02:21 +02:00
|
|
|
VIEW3D_MT_add,
|
2018-11-27 15:23:12 +11:00
|
|
|
VIEW3D_MT_image_add,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_object,
|
|
|
|
|
VIEW3D_MT_object_animation,
|
2021-10-26 18:53:40 +02:00
|
|
|
VIEW3D_MT_object_asset,
|
2018-04-24 20:46:18 +02:00
|
|
|
VIEW3D_MT_object_rigid_body,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_object_clear,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_MT_object_context_menu,
|
2021-01-25 17:49:02 +11:00
|
|
|
VIEW3D_MT_object_convert,
|
2018-04-25 07:25:08 +02:00
|
|
|
VIEW3D_MT_object_shading,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_object_apply,
|
2018-05-25 08:07:43 +02:00
|
|
|
VIEW3D_MT_object_relations,
|
2022-08-16 15:42:04 +02:00
|
|
|
VIEW3D_MT_object_liboverride,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_object_parent,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_object_track,
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
VIEW3D_MT_object_collection,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_object_constraints,
|
2024-05-01 14:15:53 +02:00
|
|
|
VIEW3D_MT_object_modifiers,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_object_quick_effects,
|
Objects: restore H key per object hiding.
H hides selected objects, Shift+H hides unselected objects, and Alt+H
reveals hidden objects.
This hiding state is distinct from restrict viewport and render, and
meant for temporarily hiding objects without affecting more persistent
collection hiding.
Object hiding is per view-layer, same as selection. It affects the
viewport and any preview renders in there, but not final renders.
In the outliner, different icons are now used for temporary hiding, and
restrict viewport and render. Hidden objects are greyed out.
Remaining design issues:
* For lamps we probably still want to keep their effect on the scene,
currently they are fully disabled by hiding. Arguably mesh lights or
even objects being reflected or casting shadows are not that different
but perhaps the special lamp exception from local view should remain.
* We need a feature still to disabled this hiding for specific viewports,
for render or animation preview where you want to see the entire scene
while working in another view.
* We need a new icon for restrict viewport, for now it uses a grid similar
to the 2.4 icon.
* Hiding objects does not preserve selection state as it did in 2.7,
it's probably convenient to support this again?
2018-05-14 23:36:56 +02:00
|
|
|
VIEW3D_MT_object_showhide,
|
2020-08-30 13:34:27 +10:00
|
|
|
VIEW3D_MT_object_cleanup,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_make_single_user,
|
|
|
|
|
VIEW3D_MT_make_links,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_paint_vertex,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_hook,
|
|
|
|
|
VIEW3D_MT_vertex_group,
|
2024-04-30 14:03:31 +02:00
|
|
|
VIEW3D_MT_greasepencil_vertex_group,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_paint_weight,
|
2020-03-20 20:04:11 -04:00
|
|
|
VIEW3D_MT_paint_weight_lock,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_sculpt,
|
2019-09-26 15:58:33 +02:00
|
|
|
VIEW3D_MT_sculpt_set_pivot,
|
2024-06-03 16:36:32 +02:00
|
|
|
VIEW3D_MT_sculpt_transform,
|
|
|
|
|
VIEW3D_MT_sculpt_showhide,
|
|
|
|
|
VIEW3D_MT_sculpt_trim,
|
2019-10-05 22:17:22 +02:00
|
|
|
VIEW3D_MT_mask,
|
2020-03-05 14:53:23 +01:00
|
|
|
VIEW3D_MT_face_sets,
|
Sculpt: Face Sets Init operator
This operator initializes all face sets in the sculpt at once using
different mesh properties. It can create face sets by mesh connectivity,
material slots, face normals, UV seams, creases, sharp edges, bevel
weights and face maps.
For properties that are already in the faces, this is implemented as a
loop. Properties that depend on edge attributes use a similar operation
to sculpt flood fill, but using face adjacency instead of edge vertex
connectivity.
As Multires also stores the face sets in the base mesh, this should work
in the face sets Multires implementation without any changes.
This is implemented as a separate operator as this resets the visibility
and creates all face sets at once, while the create face set operator
creates a single face sets, leaving the rest of the face sets in the
mesh as they are.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D7209
2020-03-21 23:24:53 +01:00
|
|
|
VIEW3D_MT_face_sets_init,
|
2021-03-12 21:35:56 +01:00
|
|
|
VIEW3D_MT_random_mask,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_particle,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_MT_particle_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_particle_showhide,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_pose,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_pose_transform,
|
|
|
|
|
VIEW3D_MT_pose_slide,
|
|
|
|
|
VIEW3D_MT_pose_propagate,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_pose_motion,
|
Anim: replace Bone Groups & Armature Layers with Bone Collections
Armature layers (the 32 little dots) and bone groups are replaced with
Bone Collections:
- Bone collections are stored on the armature, and have a name that is
unique within that armature.
- An armature can have an arbitrary number of bone collections (instead
of the fixed 32 layers).
- Bones can be assigned to zero or more bone collections.
- Bone collections have a visibility setting, just like objects in scene
collections.
- When a bone is in at least one collection, and all its collections in
are hidden, the bone is hidden. In other cases (in any visible
collection, or in no collection at all), the bone visibility is
determined by its own 'hidden' flag.
- For now, bone collections cannot be nested; they are a flat list just
like bone groups were. Nestability of bone collections is intended to
be implemented in a later 4.x release.
- Since bone collections are defined on the armature, they can be used
from both pose mode and edit mode.
Versioning converts bone groups and armature layers to new bone
collections. Layers that do not contain any bones are skipped. The old
data structures remain in DNA and are unaltered, for limited forward
compatibility. That way at least a save with Blender 4.0 will not
immediately erase the bone group and armature layers and their bone
assignments.
Shortcuts:
- M/Shift+M in pose/edit mode: move to collection (M) and add to
collection (shift+M). This works similar to the M/Shift+M menus for
objects & scene collections.
- Ctrl+G in pose mode shows a port of the old 'bone groups' menu. This
is likely to be removed in the near future, as the functionality
overlaps with the M/Shift+M menus.
This is the first commit of a series; the bone collections feature will
be improved before the Blender 4.0 release. See #108941 for more info.
Pull request: https://projects.blender.org/blender/blender/pulls/109976
2023-08-22 12:15:54 +02:00
|
|
|
VIEW3D_MT_bone_collections,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_pose_ik,
|
|
|
|
|
VIEW3D_MT_pose_constraints,
|
2020-04-06 21:45:41 -04:00
|
|
|
VIEW3D_MT_pose_names,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_MT_pose_showhide,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_pose_apply,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_MT_pose_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_bone_options_toggle,
|
|
|
|
|
VIEW3D_MT_bone_options_enable,
|
|
|
|
|
VIEW3D_MT_bone_options_disable,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_MT_edit_mesh_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_mesh_select_mode,
|
2017-10-19 14:45:56 +11:00
|
|
|
VIEW3D_MT_edit_mesh_select_linked,
|
|
|
|
|
VIEW3D_MT_edit_mesh_select_loops,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_mesh_extrude,
|
|
|
|
|
VIEW3D_MT_edit_mesh_vertices,
|
|
|
|
|
VIEW3D_MT_edit_mesh_edges,
|
|
|
|
|
VIEW3D_MT_edit_mesh_faces,
|
2018-05-24 15:37:52 +02:00
|
|
|
VIEW3D_MT_edit_mesh_faces_data,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_mesh_normals,
|
2019-05-07 08:45:01 -04:00
|
|
|
VIEW3D_MT_edit_mesh_normals_select_strength,
|
|
|
|
|
VIEW3D_MT_edit_mesh_normals_set_strength,
|
2019-05-08 07:44:15 -04:00
|
|
|
VIEW3D_MT_edit_mesh_normals_average,
|
2018-04-24 21:07:05 +02:00
|
|
|
VIEW3D_MT_edit_mesh_shading,
|
2018-04-24 16:54:38 +02:00
|
|
|
VIEW3D_MT_edit_mesh_weights,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_mesh_clean,
|
|
|
|
|
VIEW3D_MT_edit_mesh_delete,
|
2019-05-02 21:50:54 +10:00
|
|
|
VIEW3D_MT_edit_mesh_merge,
|
2020-03-31 18:01:06 +11:00
|
|
|
VIEW3D_MT_edit_mesh_split,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_mesh_showhide,
|
2023-12-01 13:12:10 +01:00
|
|
|
VIEW3D_MT_greasepencil_material_active,
|
2023-07-03 16:34:30 +02:00
|
|
|
VIEW3D_MT_paint_grease_pencil,
|
2024-09-10 18:56:31 +02:00
|
|
|
VIEW3D_MT_paint_vertex_grease_pencil,
|
2023-12-01 12:55:30 +01:00
|
|
|
VIEW3D_MT_edit_greasepencil_showhide,
|
2024-03-25 12:17:03 +01:00
|
|
|
VIEW3D_MT_edit_greasepencil_cleanup,
|
2024-05-14 14:40:37 +02:00
|
|
|
VIEW3D_MT_weight_grease_pencil,
|
2023-10-26 16:52:31 +02:00
|
|
|
VIEW3D_MT_greasepencil_edit_context_menu,
|
2024-01-12 13:40:00 +01:00
|
|
|
VIEW3D_MT_grease_pencil_assign_material,
|
2023-05-30 11:14:16 +02:00
|
|
|
VIEW3D_MT_edit_greasepencil,
|
2023-08-24 11:06:18 +02:00
|
|
|
VIEW3D_MT_edit_greasepencil_delete,
|
2023-07-18 11:54:34 +02:00
|
|
|
VIEW3D_MT_edit_greasepencil_stroke,
|
2023-10-26 16:52:31 +02:00
|
|
|
VIEW3D_MT_edit_greasepencil_point,
|
2023-10-13 14:07:21 +02:00
|
|
|
VIEW3D_MT_edit_greasepencil_animation,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_curve,
|
|
|
|
|
VIEW3D_MT_edit_curve_ctrlpoints,
|
|
|
|
|
VIEW3D_MT_edit_curve_segments,
|
2017-10-30 22:36:51 +11:00
|
|
|
VIEW3D_MT_edit_curve_clean,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_MT_edit_curve_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_curve_delete,
|
|
|
|
|
VIEW3D_MT_edit_curve_showhide,
|
|
|
|
|
VIEW3D_MT_edit_surface,
|
|
|
|
|
VIEW3D_MT_edit_font,
|
2020-04-04 12:41:58 -04:00
|
|
|
VIEW3D_MT_edit_font_chars,
|
2020-02-26 22:26:40 +11:00
|
|
|
VIEW3D_MT_edit_font_kerning,
|
2020-04-04 12:41:58 -04:00
|
|
|
VIEW3D_MT_edit_font_delete,
|
|
|
|
|
VIEW3D_MT_edit_font_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_meta,
|
|
|
|
|
VIEW3D_MT_edit_meta_showhide,
|
|
|
|
|
VIEW3D_MT_edit_lattice,
|
|
|
|
|
VIEW3D_MT_edit_armature,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_MT_armature_context_menu,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_armature_parent,
|
|
|
|
|
VIEW3D_MT_edit_armature_roll,
|
2018-12-18 07:54:32 +11:00
|
|
|
VIEW3D_MT_edit_armature_names,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_MT_edit_armature_delete,
|
2022-02-18 11:16:02 +01:00
|
|
|
VIEW3D_MT_edit_curves,
|
2024-04-11 15:11:02 +02:00
|
|
|
VIEW3D_MT_edit_curves_add,
|
2024-04-05 13:23:22 +02:00
|
|
|
VIEW3D_MT_edit_curves_segments,
|
2024-04-10 13:08:50 +02:00
|
|
|
VIEW3D_MT_edit_curves_control_points,
|
2024-05-28 11:38:17 +02:00
|
|
|
VIEW3D_MT_edit_curves_context_menu,
|
2023-06-28 12:52:45 -04:00
|
|
|
VIEW3D_MT_edit_pointcloud,
|
2018-06-20 16:32:31 +02:00
|
|
|
VIEW3D_MT_object_mode_pie,
|
|
|
|
|
VIEW3D_MT_view_pie,
|
2019-05-14 15:05:19 +10:00
|
|
|
VIEW3D_MT_transform_gizmo_pie,
|
2018-09-21 15:46:49 +02:00
|
|
|
VIEW3D_MT_shading_pie,
|
2018-11-24 11:24:34 +11:00
|
|
|
VIEW3D_MT_shading_ex_pie,
|
2018-09-26 17:32:11 +02:00
|
|
|
VIEW3D_MT_pivot_pie,
|
|
|
|
|
VIEW3D_MT_snap_pie,
|
|
|
|
|
VIEW3D_MT_orientations_pie,
|
|
|
|
|
VIEW3D_MT_proportional_editing_falloff_pie,
|
2019-09-09 16:20:40 +02:00
|
|
|
VIEW3D_MT_sculpt_mask_edit_pie,
|
2020-10-20 14:10:54 +02:00
|
|
|
VIEW3D_MT_sculpt_automasking_pie,
|
2024-10-15 11:35:57 +02:00
|
|
|
VIEW3D_MT_grease_pencil_sculpt_automasking_pie,
|
2019-12-23 12:46:05 +03:00
|
|
|
VIEW3D_MT_wpaint_vgroup_lock_pie,
|
2020-03-05 14:53:23 +01:00
|
|
|
VIEW3D_MT_sculpt_face_sets_edit_pie,
|
2022-04-07 12:49:13 +02:00
|
|
|
VIEW3D_MT_sculpt_curves,
|
2019-04-29 22:50:14 +10:00
|
|
|
VIEW3D_PT_active_tool,
|
2019-05-16 19:43:11 +10:00
|
|
|
VIEW3D_PT_active_tool_duplicate,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_PT_view3d_properties,
|
2019-03-07 12:53:45 +11:00
|
|
|
VIEW3D_PT_view3d_lock,
|
2017-03-18 20:03:24 +11:00
|
|
|
VIEW3D_PT_view3d_cursor,
|
2018-11-15 11:35:14 -02:00
|
|
|
VIEW3D_PT_collections,
|
2018-07-09 17:00:09 +02:00
|
|
|
VIEW3D_PT_object_type_visibility,
|
2018-07-31 10:22:19 +02:00
|
|
|
VIEW3D_PT_grease_pencil,
|
2018-11-28 19:19:01 +01:00
|
|
|
VIEW3D_PT_annotation_onion,
|
2024-02-13 12:04:45 +01:00
|
|
|
VIEW3D_PT_grease_pencil_multi_frame,
|
2024-10-04 13:05:09 +02:00
|
|
|
VIEW3D_PT_grease_pencil_sculpt_automasking,
|
2018-04-29 08:47:14 +02:00
|
|
|
VIEW3D_PT_quad_view,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_PT_view3d_stereo,
|
2018-04-29 08:47:14 +02:00
|
|
|
VIEW3D_PT_shading,
|
2018-06-18 08:15:29 +02:00
|
|
|
VIEW3D_PT_shading_lighting,
|
|
|
|
|
VIEW3D_PT_shading_color,
|
|
|
|
|
VIEW3D_PT_shading_options,
|
2018-07-11 16:05:05 +02:00
|
|
|
VIEW3D_PT_shading_options_shadow,
|
|
|
|
|
VIEW3D_PT_shading_options_ssao,
|
2025-02-05 17:08:55 +01:00
|
|
|
VIEW3D_PT_shading_cavity,
|
2019-11-08 16:47:33 +01:00
|
|
|
VIEW3D_PT_shading_render_pass,
|
2022-08-10 09:14:22 +02:00
|
|
|
VIEW3D_PT_shading_compositor,
|
2019-04-13 12:23:07 +02:00
|
|
|
VIEW3D_PT_gizmo_display,
|
2018-04-29 09:44:57 +02:00
|
|
|
VIEW3D_PT_overlay,
|
2018-07-11 13:00:05 +02:00
|
|
|
VIEW3D_PT_overlay_guides,
|
|
|
|
|
VIEW3D_PT_overlay_object,
|
|
|
|
|
VIEW3D_PT_overlay_geometry,
|
2023-12-19 13:30:16 +01:00
|
|
|
VIEW3D_PT_overlay_viewer_node,
|
2018-07-11 13:00:05 +02:00
|
|
|
VIEW3D_PT_overlay_motion_tracking,
|
2018-06-10 15:22:47 +02:00
|
|
|
VIEW3D_PT_overlay_edit_mesh,
|
2018-07-11 18:38:39 +02:00
|
|
|
VIEW3D_PT_overlay_edit_mesh_shading,
|
|
|
|
|
VIEW3D_PT_overlay_edit_mesh_measurement,
|
|
|
|
|
VIEW3D_PT_overlay_edit_mesh_normals,
|
|
|
|
|
VIEW3D_PT_overlay_edit_mesh_freestyle,
|
2018-06-10 15:22:47 +02:00
|
|
|
VIEW3D_PT_overlay_edit_curve,
|
2024-10-08 21:17:16 +02:00
|
|
|
VIEW3D_PT_overlay_edit_curves,
|
2019-07-17 13:50:24 +02:00
|
|
|
VIEW3D_PT_overlay_texture_paint,
|
|
|
|
|
VIEW3D_PT_overlay_vertex_paint,
|
|
|
|
|
VIEW3D_PT_overlay_weight_paint,
|
2022-01-06 15:42:45 +03:00
|
|
|
VIEW3D_PT_overlay_bones,
|
2018-06-10 15:22:47 +02:00
|
|
|
VIEW3D_PT_overlay_sculpt,
|
2022-06-22 18:58:25 -05:00
|
|
|
VIEW3D_PT_overlay_sculpt_curves,
|
2018-07-03 14:05:07 +02:00
|
|
|
VIEW3D_PT_snapping,
|
2024-05-14 19:00:58 +02:00
|
|
|
VIEW3D_PT_sculpt_snapping,
|
2019-04-30 13:42:18 +10:00
|
|
|
VIEW3D_PT_proportional_edit,
|
2024-10-04 13:05:09 +02:00
|
|
|
VIEW3D_PT_grease_pencil_origin,
|
|
|
|
|
VIEW3D_PT_grease_pencil_lock,
|
|
|
|
|
VIEW3D_PT_grease_pencil_guide,
|
2018-07-03 14:05:07 +02:00
|
|
|
VIEW3D_PT_transform_orientations,
|
2023-12-07 11:42:06 +01:00
|
|
|
VIEW3D_PT_overlay_grease_pencil_options,
|
2024-09-27 16:58:38 +02:00
|
|
|
VIEW3D_PT_overlay_grease_pencil_canvas_options,
|
2017-03-20 02:34:32 +11:00
|
|
|
VIEW3D_PT_context_properties,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_PT_paint_vertex_context_menu,
|
|
|
|
|
VIEW3D_PT_paint_texture_context_menu,
|
|
|
|
|
VIEW3D_PT_paint_weight_context_menu,
|
2022-10-17 11:17:42 +02:00
|
|
|
VIEW3D_PT_sculpt_automasking,
|
2019-03-12 10:59:57 +11:00
|
|
|
VIEW3D_PT_sculpt_context_menu,
|
2024-10-04 13:05:09 +02:00
|
|
|
TOPBAR_PT_grease_pencil_materials,
|
2024-09-10 18:56:31 +02:00
|
|
|
TOPBAR_PT_grease_pencil_vertex_color,
|
2018-11-27 15:23:12 +11:00
|
|
|
TOPBAR_PT_annotation_layers,
|
2022-05-11 15:47:49 +02:00
|
|
|
VIEW3D_PT_curves_sculpt_add_shape,
|
2023-02-15 10:42:30 +01:00
|
|
|
VIEW3D_PT_curves_sculpt_parameter_falloff,
|
2022-05-11 15:47:49 +02:00
|
|
|
VIEW3D_PT_curves_sculpt_grow_shrink_scaling,
|
2022-09-02 18:30:48 +02:00
|
|
|
VIEW3D_PT_viewport_debug,
|
2025-04-09 14:41:01 +02:00
|
|
|
VIEW3D_PT_active_spline,
|
Sculpt/Paint: New asset based brush management workflow
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
2024-07-08 13:09:57 +02:00
|
|
|
VIEW3D_AST_brush_sculpt,
|
|
|
|
|
VIEW3D_AST_brush_sculpt_curves,
|
|
|
|
|
VIEW3D_AST_brush_vertex_paint,
|
|
|
|
|
VIEW3D_AST_brush_weight_paint,
|
|
|
|
|
VIEW3D_AST_brush_texture_paint,
|
|
|
|
|
VIEW3D_AST_brush_gpencil_paint,
|
|
|
|
|
VIEW3D_AST_brush_gpencil_sculpt,
|
|
|
|
|
VIEW3D_AST_brush_gpencil_vertex,
|
|
|
|
|
VIEW3D_AST_brush_gpencil_weight,
|
2024-08-08 16:03:09 +02:00
|
|
|
GREASE_PENCIL_MT_Layers,
|
|
|
|
|
VIEW3D_PT_greasepencil_draw_context_menu,
|
2024-08-12 13:05:13 +02:00
|
|
|
VIEW3D_PT_greasepencil_sculpt_context_menu,
|
2024-09-16 12:02:30 +02:00
|
|
|
VIEW3D_PT_greasepencil_vertex_paint_context_menu,
|
2024-10-03 13:42:54 +02:00
|
|
|
VIEW3D_PT_greasepencil_weight_context_menu,
|
2017-03-18 20:03:24 +11:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": # only for live edit.
|
|
|
|
|
from bpy.utils import register_class
|
|
|
|
|
for cls in classes:
|
|
|
|
|
register_class(cls)
|