Import Images: bump minimum Blender version after API change
[blender-addons.git] / space_view3d_brush_menus / stroke_menu.py
blob84c16cc449a90bd53b5c0186f88ee07402c7b8cc
1 # SPDX-FileCopyrightText: 2017-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 import bpy
6 from bpy.types import Menu
7 from . import utils_core
8 from .brushes import brush_datapath
10 # stroke methods: 'AIRBRUSH' 'ANCHORED' 'SPACE' 'DRAG_DOT' 'DOTS' 'LINE' 'CURVE'
12 class PaintCurvesMenu(Menu):
13 bl_label = "Paint Curves"
14 bl_idname = "VIEW3D_MT_sv3_paint_curves_menu"
16 def draw(self, context):
17 mode = utils_core.get_mode()
18 layout = self.layout
19 colum_n = utils_core.addon_settings()
21 layout.row().label(text="Paint Curves")
22 layout.row().separator()
24 has_brush = utils_core.get_brush_link(context, types="brush")
26 has_current_curve = has_brush.paint_curve if has_brush else None
27 current_curve = has_current_curve.name if has_current_curve else ''
29 column_flow = layout.column_flow(columns=colum_n)
31 if len(bpy.data.paint_curves) != 0:
32 for x, item in enumerate(bpy.data.paint_curves):
33 utils_core.menuprop(
34 column_flow.row(),
35 item.name,
36 'bpy.data.paint_curves["%s"]' % item.name,
37 brush_datapath[mode] + ".paint_curve",
38 icon='RADIOBUT_OFF',
39 disable=True,
40 disable_icon='RADIOBUT_ON',
41 custom_disable_exp=(item.name, current_curve),
42 path=True
45 else:
46 layout.row().label(text="No Paint Curves Available", icon="INFO")
48 class StrokeOptionsMenu(Menu):
49 bl_label = "Stroke Options"
50 bl_idname = "VIEW3D_MT_sv3_stroke_options"
52 @classmethod
53 def poll(self, context):
54 return utils_core.get_mode() in (
55 'SCULPT', 'VERTEX_PAINT',
56 'WEIGHT_PAINT', 'TEXTURE_PAINT',
57 'PARTICLE_EDIT'
60 def init(self):
61 has_brush = utils_core.get_brush_link(bpy.context, types="brush")
62 if utils_core.get_mode() == 'SCULPT':
63 settings = bpy.context.tool_settings.sculpt
65 elif utils_core.get_mode() == 'VERTEX_PAINT':
66 settings = bpy.context.tool_settings.vertex_paint
68 elif utils_core.get_mode() == 'WEIGHT_PAINT':
69 settings = bpy.context.tool_settings.weight_paint
71 elif utils_core.get_mode() == 'TEXTURE_PAINT':
72 settings = bpy.context.tool_settings.image_paint
74 else:
75 settings = None
77 stroke_method = has_brush.stroke_method if has_brush else None
79 return settings, has_brush, stroke_method
81 def draw(self, context):
82 settings, brush, stroke_method = self.init()
83 layout = self.layout
85 layout.row().menu(StrokeMethodMenu.bl_idname)
86 layout.row().separator()
88 if stroke_method:
90 if stroke_method in ('SPACE', 'LINE') and brush:
91 layout.row().prop(brush, "spacing",
92 text=utils_core.PIW + "Spacing", slider=True)
94 elif stroke_method == 'AIRBRUSH' and brush:
95 layout.row().prop(brush, "rate",
96 text=utils_core.PIW + "Rate", slider=True)
98 elif stroke_method == 'ANCHORED' and brush:
99 layout.row().prop(brush, "use_edge_to_edge")
101 elif stroke_method == 'CURVE' and brush:
102 has_current_curve = brush.paint_curve if brush else None
103 current_curve = has_current_curve.name if has_current_curve else 'No Curve Selected'
105 layout.row().menu(PaintCurvesMenu.bl_idname, text=current_curve,
106 icon='CURVE_BEZCURVE')
107 layout.row().operator("paintcurve.new", icon='ADD')
108 layout.row().operator("paintcurve.draw")
110 layout.row().separator()
112 layout.row().prop(brush, "spacing",
113 text=utils_core.PIW + "Spacing",
114 slider=True)
116 else:
117 pass
119 if utils_core.get_mode() == 'SCULPT' and stroke_method in ('DRAG_DOT', 'ANCHORED'):
120 pass
121 else:
122 if brush:
123 layout.row().prop(brush, "jitter",
124 text=utils_core.PIW + "Jitter", slider=True)
126 layout.row().prop(settings, "input_samples",
127 text=utils_core.PIW + "Input Samples", slider=True)
129 if stroke_method in ('DOTS', 'SPACE', 'AIRBRUSH') and brush:
130 layout.row().separator()
132 layout.row().prop(brush, "use_smooth_stroke", toggle=True)
134 if brush.use_smooth_stroke:
135 layout.row().prop(brush, "smooth_stroke_radius",
136 text=utils_core.PIW + "Radius", slider=True)
137 layout.row().prop(brush, "smooth_stroke_factor",
138 text=utils_core.PIW + "Factor", slider=True)
139 else:
140 layout.row().label(text="No Stroke Options available", icon="INFO")
143 class StrokeMethodMenu(Menu):
144 bl_label = "Stroke Method"
145 bl_idname = "VIEW3D_MT_sv3_stroke_method"
147 def init(self):
148 has_brush = utils_core.get_brush_link(bpy.context, types="brush")
149 if utils_core.get_mode() == 'SCULPT':
150 path = "tool_settings.sculpt.brush.stroke_method"
152 elif utils_core.get_mode() == 'VERTEX_PAINT':
153 path = "tool_settings.vertex_paint.brush.stroke_method"
155 elif utils_core.get_mode() == 'WEIGHT_PAINT':
156 path = "tool_settings.weight_paint.brush.stroke_method"
158 elif utils_core.get_mode() == 'TEXTURE_PAINT':
159 path = "tool_settings.image_paint.brush.stroke_method"
161 else:
162 path = ""
164 return has_brush, path
166 def draw(self, context):
167 brush, path = self.init()
168 layout = self.layout
170 layout.row().label(text="Stroke Method")
171 layout.row().separator()
173 if brush:
174 # add the menu items dynamically based on values in enum property
175 for tool in brush.bl_rna.properties['stroke_method'].enum_items:
176 if tool.identifier in ('ANCHORED', 'DRAG_DOT') and \
177 utils_core.get_mode() in ('VERTEX_PAINT',
178 'WEIGHT_PAINT'):
179 continue
181 utils_core.menuprop(
182 layout.row(), tool.name, tool.identifier, path,
183 icon='RADIOBUT_OFF', disable=True,
184 disable_icon='RADIOBUT_ON'
186 else:
187 layout.row().label(text="No Stroke Method available", icon="INFO")
190 classes = (
191 PaintCurvesMenu,
192 StrokeOptionsMenu,
193 StrokeMethodMenu
196 def register():
197 for cls in classes:
198 bpy.utils.register_class(cls)
200 def unregister():
201 for cls in classes:
202 bpy.utils.unregister_class(cls)