Blender V5.0
sculpt_filter_color.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
12#include "BLI_math_color.h"
14#include "BLI_math_vector.hh"
15
16#include "BLT_translation.hh"
17
18#include "BKE_attribute.hh"
19#include "BKE_context.hh"
20#include "BKE_layer.hh"
21#include "BKE_mesh.hh"
22#include "BKE_paint.hh"
23#include "BKE_paint_bvh.hh"
24
26
27#include "WM_api.hh"
28#include "WM_types.hh"
29
30#include "ED_paint.hh"
31
32#include "mesh_brush_common.hh"
33#include "sculpt_automask.hh"
34#include "sculpt_color.hh"
35#include "sculpt_filter.hh"
36#include "sculpt_intern.hh"
37#include "sculpt_smooth.hh"
38#include "sculpt_undo.hh"
39
40#include "RNA_access.hh"
41#include "RNA_define.hh"
42
44#include "UI_resources.hh"
45
46#include <cmath>
47
49
62
63static const float fill_filter_default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
64
66 {int(FilterType::Fill), "FILL", 0, "Fill", "Fill with a specific color"},
67 {int(FilterType::Hue), "HUE", 0, "Hue", "Change hue"},
68 {int(FilterType::Saturation), "SATURATION", 0, "Saturation", "Change saturation"},
69 {int(FilterType::Value), "VALUE", 0, "Value", "Change value"},
70 {int(FilterType::Brightness), "BRIGHTNESS", 0, "Brightness", "Change brightness"},
71 {int(FilterType::Contrast), "CONTRAST", 0, "Contrast", "Change contrast"},
72 {int(FilterType::Smooth), "SMOOTH", 0, "Smooth", "Smooth colors"},
73 {int(FilterType::Red), "RED", 0, "Red", "Change red channel"},
74 {int(FilterType::Green), "GREEN", 0, "Green", "Change green channel"},
75 {int(FilterType::Blue), "BLUE", 0, "Blue", "Change blue channel"},
76 {0, nullptr, 0, nullptr, nullptr},
77};
78
87
89 const float min,
90 const float max)
91{
92 for (float &factor : factors) {
93 factor = std::clamp(factor, min, max);
94 }
95}
96
97static void color_filter_task(const Depsgraph &depsgraph,
98 Object &ob,
100 const Span<int> corner_verts,
101 const GroupedSpan<int> vert_to_face_map,
102 const MeshAttributeData &attribute_data,
103 const FilterType mode,
104 const float filter_strength,
105 const float *filter_fill_color,
106 const bke::pbvh::MeshNode &node,
107 LocalData &tls,
108 bke::GSpanAttributeWriter &color_attribute)
109{
110 SculptSession &ss = *ob.sculpt;
111
112 const Span<float4> orig_colors = orig_color_data_get_mesh(ob, node);
113
114 const Span<int> verts = node.verts();
115
116 tls.factors.resize(verts.size());
117 const MutableSpan<float> factors = tls.factors;
118 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
120 depsgraph, ob, ss.filter_cache->automasking.get(), node, verts, factors);
121 scale_factors(factors, filter_strength);
122
123 tls.new_colors.resize(verts.size());
124 const MutableSpan<float4> new_colors = tls.new_colors;
125
126 /* Copy alpha. */
127 for (const int i : verts.index_range()) {
128 new_colors[i][3] = orig_colors[i][3];
129 }
130
131 switch (mode) {
132 case FilterType::Fill: {
133 clamp_factors(factors, 0.0f, 1.0f);
134 for (const int i : verts.index_range()) {
135 float fill_color_rgba[4];
136 copy_v3_v3(fill_color_rgba, filter_fill_color);
137 fill_color_rgba[3] = 1.0f;
138 mul_v4_fl(fill_color_rgba, factors[i]);
139 blend_color_mix_float(new_colors[i], orig_colors[i], fill_color_rgba);
140 }
141 break;
142 }
143 case FilterType::Hue: {
144 for (const int i : verts.index_range()) {
145 float3 hsv_color;
146 rgb_to_hsv_v(orig_colors[i], hsv_color);
147 const float hue = hsv_color[0];
148 hsv_color[0] = fmod((hsv_color[0] + fabs(factors[i])) - hue, 1);
149 hsv_to_rgb_v(hsv_color, new_colors[i]);
150 }
151 break;
152 }
154 for (const int i : verts.index_range()) {
155 float3 hsv_color;
156 rgb_to_hsv_v(orig_colors[i], hsv_color);
157
158 if (hsv_color[1] > 0.001f) {
159 hsv_color[1] = std::clamp(hsv_color[1] + factors[i] * hsv_color[1], 0.0f, 1.0f);
160 hsv_to_rgb_v(hsv_color, new_colors[i]);
161 }
162 else {
163 copy_v3_v3(new_colors[i], orig_colors[i]);
164 }
165 }
166 break;
167 }
168 case FilterType::Value: {
169 for (const int i : verts.index_range()) {
170 float3 hsv_color;
171 rgb_to_hsv_v(orig_colors[i], hsv_color);
172 hsv_color[2] = std::clamp(hsv_color[2] + factors[i], 0.0f, 1.0f);
173 hsv_to_rgb_v(hsv_color, new_colors[i]);
174 }
175 break;
176 }
177 case FilterType::Red: {
178 for (const int i : verts.index_range()) {
179 copy_v3_v3(new_colors[i], orig_colors[i]);
180 new_colors[i][0] = std::clamp(orig_colors[i][0] + factors[i], 0.0f, 1.0f);
181 }
182 break;
183 }
184 case FilterType::Green: {
185 for (const int i : verts.index_range()) {
186 copy_v3_v3(new_colors[i], orig_colors[i]);
187 new_colors[i][1] = std::clamp(orig_colors[i][1] + factors[i], 0.0f, 1.0f);
188 }
189 break;
190 }
191 case FilterType::Blue: {
192 for (const int i : verts.index_range()) {
193 copy_v3_v3(new_colors[i], orig_colors[i]);
194 new_colors[i][2] = std::clamp(orig_colors[i][2] + factors[i], 0.0f, 1.0f);
195 }
196 break;
197 }
199 clamp_factors(factors, -1.0f, 1.0f);
200 for (const int i : verts.index_range()) {
201 const float brightness = factors[i];
202 const float contrast = 0;
203 float delta = contrast / 2.0f;
204 const float gain = 1.0f - delta * 2.0f;
205 delta *= -1;
206 const float offset = gain * (brightness + delta);
207 for (int component = 0; component < 3; component++) {
208 new_colors[i][component] = std::clamp(
209 gain * orig_colors[i][component] + offset, 0.0f, 1.0f);
210 }
211 }
212 break;
213 }
215 clamp_factors(factors, -1.0f, 1.0f);
216 for (const int i : verts.index_range()) {
217 const float brightness = 0;
218 const float contrast = factors[i];
219 float delta = contrast / 2.0f;
220 float gain = 1.0f - delta * 2.0f;
221
222 float offset;
223 if (contrast > 0) {
224 gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
225 offset = gain * (brightness - delta);
226 }
227 else {
228 delta *= -1;
229 offset = gain * (brightness + delta);
230 }
231 for (int component = 0; component < 3; component++) {
232 new_colors[i][component] = std::clamp(
233 gain * orig_colors[i][component] + offset, 0.0f, 1.0f);
234 }
235 }
236 break;
237 }
238 case FilterType::Smooth: {
239 clamp_factors(factors, -1.0f, 1.0f);
240
241 tls.colors.resize(verts.size());
242 const MutableSpan<float4> colors = tls.colors;
243 for (const int i : verts.index_range()) {
244 colors[i] = color_vert_get(faces,
245 corner_verts,
246 vert_to_face_map,
247 color_attribute.span,
248 color_attribute.domain,
249 verts[i]);
250 }
251
253 corner_verts,
254 vert_to_face_map,
255 {},
256 verts,
258 tls.neighbor_data);
259
260 tls.average_colors.resize(verts.size());
261 const MutableSpan<float4> average_colors = tls.average_colors;
263 corner_verts,
264 vert_to_face_map,
265 color_attribute.span,
266 color_attribute.domain,
267 neighbors,
268 average_colors);
269
270 for (const int i : verts.index_range()) {
271 const int vert = verts[i];
272
273 if (factors[i] < 0.0f) {
274 interp_v4_v4v4(average_colors[i], average_colors[i], colors[i], 0.5f);
275 }
276
277 bool copy_alpha = colors[i][3] == average_colors[i][3];
278
279 if (factors[i] < 0.0f) {
280 float4 delta_color;
281
282 /* Unsharp mask. */
283 copy_v4_v4(delta_color, ss.filter_cache->pre_smoothed_color[vert]);
284 delta_color -= average_colors[i];
285
286 copy_v4_v4(new_colors[i], colors[i]);
287 madd_v4_v4fl(new_colors[i], delta_color, factors[i]);
288 }
289 else {
290 blend_color_interpolate_float(new_colors[i], colors[i], average_colors[i], factors[i]);
291 }
292
293 new_colors[i] = math::clamp(new_colors[i], 0.0f, 1.0f);
294
295 /* Prevent accumulated numeric error from corrupting alpha. */
296 if (copy_alpha) {
297 new_colors[i][3] = average_colors[i][3];
298 }
299 }
300 break;
301 }
302 }
303
304 for (const int i : verts.index_range()) {
306 corner_verts,
307 vert_to_face_map,
308 color_attribute.domain,
309 verts[i],
310 new_colors[i],
311 color_attribute.span);
312 }
313}
314
315static void sculpt_color_presmooth_init(const Mesh &mesh, Object &object)
316{
317 SculptSession &ss = *object.sculpt;
318 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
320 const IndexMask &node_mask = ss.filter_cache->node_mask;
321 const OffsetIndices<int> faces = mesh.faces();
322 const Span<int> corner_verts = mesh.corner_verts();
323 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
324 const bke::GAttributeReader color_attribute = active_color_attribute(mesh);
325 const GVArraySpan colors = *color_attribute;
326
327 if (ss.filter_cache->pre_smoothed_color.is_empty()) {
329 }
330 const MutableSpan<float4> pre_smoothed_color = ss.filter_cache->pre_smoothed_color;
331
332 node_mask.foreach_index(GrainSize(1), [&](const int i) {
333 for (const int vert : nodes[i].verts()) {
334 pre_smoothed_color[vert] = color_vert_get(
335 faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, vert);
336 }
337 });
338
339 struct LocalData {
342 Vector<float4> averaged_colors;
343 };
345 for ([[maybe_unused]] const int iteration : IndexRange(2)) {
346 node_mask.foreach_index(GrainSize(1), [&](const int i) {
347 LocalData &tls = all_tls.local();
348 const Span<int> verts = nodes[i].verts();
349
351 corner_verts,
352 vert_to_face_map,
353 {},
354 verts,
356 tls.neighbor_data);
357
358 tls.averaged_colors.resize(verts.size());
359 const MutableSpan<float4> averaged_colors = tls.averaged_colors;
360 smooth::neighbor_data_average_mesh(pre_smoothed_color.as_span(), neighbors, averaged_colors);
361
362 for (const int i : verts.index_range()) {
363 pre_smoothed_color[verts[i]] = math::interpolate(
364 pre_smoothed_color[verts[i]], averaged_colors[i], 0.5f);
365 }
366 });
367 }
368}
369
371{
372 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
373 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
374 SculptSession &ss = *ob.sculpt;
377
378 const FilterType mode = FilterType(RNA_enum_get(op->ptr, "type"));
379 float filter_strength = RNA_float_get(op->ptr, "strength");
380 float fill_color[3];
381
382 RNA_float_get_array(op->ptr, "fill_color", fill_color);
383
384 Mesh &mesh = *static_cast<Mesh *>(ob.data);
385 if (filter_strength < 0.0 && ss.filter_cache->pre_smoothed_color.is_empty()) {
387 }
388
389 const IndexMask &node_mask = ss.filter_cache->node_mask;
390 if (auto_mask::is_enabled(sd, ob, nullptr) && ss.filter_cache->automasking &&
392 {
393 ss.filter_cache->automasking->calc_cavity_factor(depsgraph, ob, node_mask);
394 }
395
396 const OffsetIndices<int> faces = mesh.faces();
397 const Span<int> corner_verts = mesh.corner_verts();
398 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
400 const MeshAttributeData attribute_data(mesh);
401
403 node_mask.foreach_index(GrainSize(1), [&](const int i) {
404 LocalData &tls = all_tls.local();
406 ob,
407 faces,
408 corner_verts,
409 vert_to_face_map,
410 attribute_data,
411 mode,
412 filter_strength,
413 fill_color,
414 nodes[i],
415 tls,
416 color_attribute);
417 });
418 pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
419 color_attribute.finish();
421}
422
424{
425 SculptSession &ss = *ob.sculpt;
426
427 undo::push_end(ob);
428 MEM_delete(ss.filter_cache);
429 ss.filter_cache = nullptr;
431}
432
434 wmOperator *op,
435 const wmEvent *event)
436{
438 SculptSession &ss = *ob.sculpt;
439
440 if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
442 return OPERATOR_FINISHED;
443 }
444
445 if (event->type != MOUSEMOVE) {
447 }
448
449 const float len = (event->prev_press_xy[0] - event->xy[0]) * 0.001f;
450 float filter_strength = ss.filter_cache->start_filter_strength * -len;
451 RNA_float_set(op->ptr, "strength", filter_strength);
452
454
456}
457
459{
460 const Scene &scene = *CTX_data_scene(C);
463 View3D *v3d = CTX_wm_view3d(C);
464
465 const Base *base = CTX_data_active_base(C);
466 if (!BKE_base_is_visible(v3d, base)) {
467 return OPERATOR_CANCELLED;
468 }
469
470 int mval[2];
471 RNA_int_get_array(op->ptr, "start_mouse", mval);
472 float mval_fl[2] = {float(mval[0]), float(mval[1])};
473
474 const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
475 if (use_automasking) {
476 if (v3d) {
477 /* Update the active face set manually as the paint cursor is not enabled when using the Mesh
478 * Filter Tool. */
480 cursor_geometry_info_update(C, &cgi, mval_fl, false);
481 }
482 }
483
484 /* Disable for multires and dyntopo for now */
485 if (!color_supported_check(scene, ob, op->reports)) {
486 return OPERATOR_CANCELLED;
487 }
488
489 /* Ensure that we have a PBVH to be able to push changes on only visible nodes. */
491
492 undo::push_begin(scene, ob, op);
494
495 /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the potential
496 * creation of color layer data. */
499
501 ob,
502 sd,
504 mval_fl,
505 RNA_float_get(op->ptr, "area_normal_radius"),
506 RNA_float_get(op->ptr, "strength"));
507 const SculptSession &ss = *ob.sculpt;
508 filter::Cache *filter_cache = ss.filter_cache;
510 if (auto_mask::is_enabled(sd, ob, nullptr)) {
512 }
513
515}
516
530
532 wmOperator *op,
533 const wmEvent *event)
534{
536 View3D *v3d = CTX_wm_view3d(C);
537 if (v3d && v3d->shading.type == OB_SOLID) {
539 }
540
541 RNA_int_set_array(op->ptr, "start_mouse", event->mval);
542
544 return OPERATOR_CANCELLED;
545 }
546
548
551}
552
554{
556 const int value = RNA_property_enum_get(ptr, prop);
557 const char *ui_name = nullptr;
558
559 RNA_property_enum_name_gettexted(nullptr, ptr, prop, value, &ui_name);
560 return ui_name;
561}
562
564{
565 uiLayout *layout = op->layout;
566
567 layout->prop(op->ptr, "strength", UI_ITEM_NONE, std::nullopt, ICON_NONE);
568
569 if (FilterType(RNA_enum_get(op->ptr, "type")) == FilterType::Fill) {
570 layout->prop(op->ptr, "fill_color", UI_ITEM_NONE, std::nullopt, ICON_NONE);
571 }
572}
573
575{
576 /* identifiers */
577 ot->name = "Filter Color";
578 ot->idname = "SCULPT_OT_color_filter";
579 ot->description = "Applies a filter to modify the active color attribute";
580
581 /* API callbacks. */
585 ot->poll = SCULPT_mode_poll;
588
590
591 /* rna */
593
595 ot->srna, "type", prop_color_filter_types, int(FilterType::Fill), "Filter Type", "");
596
597 PropertyRNA *prop = RNA_def_float_color(ot->srna,
598 "fill_color",
599 3,
601 0.0f,
602 FLT_MAX,
603 "Fill Color",
604 "",
605 0.0f,
606 1.0f);
609}
610
611} // namespace blender::ed::sculpt_paint::color
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
#define SCULPT_FACE_SET_NONE
Definition BKE_paint.hh:324
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2797
void BKE_sculpt_color_layer_create_if_needed(Object *object)
Definition paint.cc:2773
A BVH for high poly meshes.
#define BLI_NOINLINE
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v4_v4v4(float r[4], const float a[4], const float b[4], float t)
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f)
#define BLT_I18NCONTEXT_ID_MESH
@ BRUSH_AUTOMASKING_CAVITY_ALL
@ OB_SOLID
@ V3D_SHADING_VERTEX_COLOR
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_image_paint_brush_type_update_sticky_shading_color(bContext *C, Object *ob)
Read Guarded memory(de)allocation.
@ PROP_COLOR
Definition RNA_types.hh:260
#define C
Definition RandGen.cpp:29
#define UI_ITEM_NONE
@ KM_RELEASE
Definition WM_types.hh:312
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
BPy_StructRNA * depsgraph
void resize(const int64_t new_size)
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
Definition pbvh.cc:676
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
nullptr float
static float verts[][3]
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float2 fabs(const float2 a)
static char faces[256]
pbvh::Tree & pbvh_ensure(Depsgraph &depsgraph, Object &object)
Definition paint.cc:3017
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
Cache & filter_cache_ensure(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh)
static std::string sculpt_color_filter_get_name(wmOperatorType *, PointerRNA *ptr)
static const float fill_filter_default_color[4]
static void color_filter_task(const Depsgraph &depsgraph, Object &ob, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const FilterType mode, const float filter_strength, const float *filter_fill_color, const bke::pbvh::MeshNode &node, LocalData &tls, bke::GSpanAttributeWriter &color_attribute)
static BLI_NOINLINE void clamp_factors(const MutableSpan< float > factors, const float min, const float max)
float4 color_vert_get(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, GSpan color_attribute, bke::AttrDomain color_domain, int vert)
void color_vert_set(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, bke::AttrDomain color_domain, int vert, const float4 &color, GMutableSpan color_attribute)
static int sculpt_color_filter_init(bContext *C, wmOperator *op)
void SCULPT_OT_color_filter(wmOperatorType *ot)
bke::GAttributeReader active_color_attribute(const Mesh &mesh)
static void sculpt_color_presmooth_init(const Mesh &mesh, Object &object)
static void sculpt_color_filter_end(bContext *C, Object &ob)
static wmOperatorStatus sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus sculpt_color_filter_exec(bContext *C, wmOperator *op)
static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
static void sculpt_color_filter_ui(bContext *, wmOperator *op)
static EnumPropertyItem prop_color_filter_types[]
static wmOperatorStatus sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void cache_init(bContext *C, Object &ob, Sculpt &sd, undo::Type undo_type, const float mval_fl[2], float area_normal_radius, float start_strength)
void register_operator_props(wmOperatorType *ot)
void neighbor_data_average_mesh(const Span< T > src, const GroupedSpan< int > vert_neighbors, const MutableSpan< T > dst)
void neighbor_color_average(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const GSpan color_attribute, const bke::AttrDomain color_domain, const GroupedSpan< int > vert_neighbors, const MutableSpan< float4 > smooth_colors)
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void fill_factor_from_hide_and_mask(Span< bool > hide_vert, Span< float > mask, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6823
GroupedSpan< int > calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, Vector< int > &r_offset_data, Vector< int > &r_data)
Definition sculpt.cc:7597
bool color_supported_check(const Scene &scene, Object &object, ReportList *reports)
Definition sculpt.cc:5474
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7512
bool cursor_geometry_info_update(bContext *C, CursorGeometryInfo *out, const float2 &mval, const bool use_sampled_normal)
Definition sculpt.cc:4685
void flush_update_done(const bContext *C, Object &ob, const UpdateType update_type)
Definition sculpt.cc:5146
Span< float4 > orig_color_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void flush_update_step(const bContext *C, const UpdateType update_type)
Definition sculpt.cc:5098
T clamp(const T &a, const T &min, const T &max)
T interpolate(const T &a, const T &b, const FactorT &t)
VecBase< float, 4 > float4
VecBase< float, 3 > float3
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
bool SCULPT_mode_poll(bContext *C)
Definition sculpt.cc:3677
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
struct SculptSession * sculpt
blender::ed::sculpt_paint::filter::Cache * filter_cache
Definition BKE_paint.hh:418
View3DShading shading
std::unique_ptr< auto_mask::Cache > automasking
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int mval[2]
Definition WM_types.hh:763
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ MOUSEMOVE
@ LEFTMOUSE
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237