Fix T71100: Node Wrangler creates nodes on linked node trees
[blender-addons.git] / space_view3d_brush_menus / stroke_menu.py
blob48174de87666abff3e277169ee785e5ba8944a53
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 import bpy
4 from bpy.types import Menu
5 from . import utils_core
6 from .brushes import brush_datapath
8 # stroke methods: 'AIRBRUSH' 'ANCHORED' 'SPACE' 'DRAG_DOT' 'DOTS' 'LINE' 'CURVE'
10 class PaintCurvesMenu(Menu):
11 bl_label = "Paint Curves"
12 bl_idname = "VIEW3D_MT_sv3_paint_curves_menu"
14 def draw(self, context):
15 mode = utils_core.get_mode()
16 layout = self.layout
17 colum_n = utils_core.addon_settings()
19 layout.row().label(text="Paint Curves")
20 layout.row().separator()
22 has_brush = utils_core.get_brush_link(context, types="brush")
24 has_current_curve = has_brush.paint_curve if has_brush else None
25 current_curve = has_current_curve.name if has_current_curve else ''
27 column_flow = layout.column_flow(columns=colum_n)
29 if len(bpy.data.paint_curves) != 0:
30 for x, item in enumerate(bpy.data.paint_curves):
31 utils_core.menuprop(
32 column_flow.row(),
33 item.name,
34 'bpy.data.paint_curves["%s"]' % item.name,
35 brush_datapath[mode] + ".paint_curve",
36 icon='RADIOBUT_OFF',
37 disable=True,
38 disable_icon='RADIOBUT_ON',
39 custom_disable_exp=(item.name, current_curve),
40 path=True
43 else:
44 layout.row().label(text="No Paint Curves Available", icon="INFO")
46 class StrokeOptionsMenu(Menu):
47 bl_label = "Stroke Options"
48 bl_idname = "VIEW3D_MT_sv3_stroke_options"
50 @classmethod
51 def poll(self, context):
52 return utils_core.get_mode() in (
53 'SCULPT', 'VERTEX_PAINT',
54 'WEIGHT_PAINT', 'TEXTURE_PAINT',
55 'PARTICLE_EDIT'
58 def init(self):
59 has_brush = utils_core.get_brush_link(bpy.context, types="brush")
60 if utils_core.get_mode() == 'SCULPT':
61 settings = bpy.context.tool_settings.sculpt
63 elif utils_core.get_mode() == 'VERTEX_PAINT':
64 settings = bpy.context.tool_settings.vertex_paint
66 elif utils_core.get_mode() == 'WEIGHT_PAINT':
67 settings = bpy.context.tool_settings.weight_paint
69 elif utils_core.get_mode() == 'TEXTURE_PAINT':
70 settings = bpy.context.tool_settings.image_paint
72 else:
73 settings = None
75 stroke_method = has_brush.stroke_method if has_brush else None
77 return settings, has_brush, stroke_method
79 def draw(self, context):
80 settings, brush, stroke_method = self.init()
81 layout = self.layout
83 layout.row().menu(StrokeMethodMenu.bl_idname)
84 layout.row().separator()
86 if stroke_method:
88 if stroke_method in ('SPACE', 'LINE') and brush:
89 layout.row().prop(brush, "spacing",
90 text=utils_core.PIW + "Spacing", slider=True)
92 elif stroke_method == 'AIRBRUSH' and brush:
93 layout.row().prop(brush, "rate",
94 text=utils_core.PIW + "Rate", slider=True)
96 elif stroke_method == 'ANCHORED' and brush:
97 layout.row().prop(brush, "use_edge_to_edge")
99 elif stroke_method == 'CURVE' and brush:
100 has_current_curve = brush.paint_curve if brush else None
101 current_curve = has_current_curve.name if has_current_curve else 'No Curve Selected'
103 layout.row().menu(PaintCurvesMenu.bl_idname, text=current_curve,
104 icon='CURVE_BEZCURVE')
105 layout.row().operator("paintcurve.new", icon='ADD')
106 layout.row().operator("paintcurve.draw")
108 layout.row().separator()
110 layout.row().prop(brush, "spacing",
111 text=utils_core.PIW + "Spacing",
112 slider=True)
114 else:
115 pass
117 if utils_core.get_mode() == 'SCULPT' and stroke_method in ('DRAG_DOT', 'ANCHORED'):
118 pass
119 else:
120 if brush:
121 layout.row().prop(brush, "jitter",
122 text=utils_core.PIW + "Jitter", slider=True)
124 layout.row().prop(settings, "input_samples",
125 text=utils_core.PIW + "Input Samples", slider=True)
127 if stroke_method in ('DOTS', 'SPACE', 'AIRBRUSH') and brush:
128 layout.row().separator()
130 layout.row().prop(brush, "use_smooth_stroke", toggle=True)
132 if brush.use_smooth_stroke:
133 layout.row().prop(brush, "smooth_stroke_radius",
134 text=utils_core.PIW + "Radius", slider=True)
135 layout.row().prop(brush, "smooth_stroke_factor",
136 text=utils_core.PIW + "Factor", slider=True)
137 else:
138 layout.row().label(text="No Stroke Options available", icon="INFO")
141 class StrokeMethodMenu(Menu):
142 bl_label = "Stroke Method"
143 bl_idname = "VIEW3D_MT_sv3_stroke_method"
145 def init(self):
146 has_brush = utils_core.get_brush_link(bpy.context, types="brush")
147 if utils_core.get_mode() == 'SCULPT':
148 path = "tool_settings.sculpt.brush.stroke_method"
150 elif utils_core.get_mode() == 'VERTEX_PAINT':
151 path = "tool_settings.vertex_paint.brush.stroke_method"
153 elif utils_core.get_mode() == 'WEIGHT_PAINT':
154 path = "tool_settings.weight_paint.brush.stroke_method"
156 elif utils_core.get_mode() == 'TEXTURE_PAINT':
157 path = "tool_settings.image_paint.brush.stroke_method"
159 else:
160 path = ""
162 return has_brush, path
164 def draw(self, context):
165 brush, path = self.init()
166 layout = self.layout
168 layout.row().label(text="Stroke Method")
169 layout.row().separator()
171 if brush:
172 # add the menu items dynamically based on values in enum property
173 for tool in brush.bl_rna.properties['stroke_method'].enum_items:
174 if tool.identifier in ('ANCHORED', 'DRAG_DOT') and \
175 utils_core.get_mode() in ('VERTEX_PAINT',
176 'WEIGHT_PAINT'):
177 continue
179 utils_core.menuprop(
180 layout.row(), tool.name, tool.identifier, path,
181 icon='RADIOBUT_OFF', disable=True,
182 disable_icon='RADIOBUT_ON'
184 else:
185 layout.row().label(text="No Stroke Method available", icon="INFO")
188 classes = (
189 PaintCurvesMenu,
190 StrokeOptionsMenu,
191 StrokeMethodMenu
194 def register():
195 for cls in classes:
196 bpy.utils.register_class(cls)
198 def unregister():
199 for cls in classes:
200 bpy.utils.unregister_class(cls)