Blender V4.5
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
43#include "UI_interface.hh"
44#include "UI_resources.hh"
45
46#include <cmath>
47#include <cstdlib>
48
50
63
64static const float fill_filter_default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
65
67 {int(FilterType::Fill), "FILL", 0, "Fill", "Fill with a specific color"},
68 {int(FilterType::Hue), "HUE", 0, "Hue", "Change hue"},
69 {int(FilterType::Saturation), "SATURATION", 0, "Saturation", "Change saturation"},
70 {int(FilterType::Value), "VALUE", 0, "Value", "Change value"},
71 {int(FilterType::Brightness), "BRIGHTNESS", 0, "Brightness", "Change brightness"},
72 {int(FilterType::Contrast), "CONTRAST", 0, "Contrast", "Change contrast"},
73 {int(FilterType::Smooth), "SMOOTH", 0, "Smooth", "Smooth colors"},
74 {int(FilterType::Red), "RED", 0, "Red", "Change red channel"},
75 {int(FilterType::Green), "GREEN", 0, "Green", "Change green channel"},
76 {int(FilterType::Blue), "BLUE", 0, "Blue", "Change blue channel"},
77 {0, nullptr, 0, nullptr, nullptr},
78};
79
88
90 const float min,
91 const float max)
92{
93 for (float &factor : factors) {
94 factor = std::clamp(factor, min, max);
95 }
96}
97
98static void color_filter_task(const Depsgraph &depsgraph,
99 Object &ob,
101 const Span<int> corner_verts,
102 const GroupedSpan<int> vert_to_face_map,
103 const MeshAttributeData &attribute_data,
104 const FilterType mode,
105 const float filter_strength,
106 const float *filter_fill_color,
107 const bke::pbvh::MeshNode &node,
108 LocalData &tls,
109 bke::GSpanAttributeWriter &color_attribute)
110{
111 SculptSession &ss = *ob.sculpt;
112
113 const Span<float4> orig_colors = orig_color_data_get_mesh(ob, node);
114
115 const Span<int> verts = node.verts();
116
117 tls.factors.resize(verts.size());
118 const MutableSpan<float> factors = tls.factors;
119 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
121 depsgraph, ob, ss.filter_cache->automasking.get(), node, verts, factors);
122 scale_factors(factors, filter_strength);
123
124 tls.new_colors.resize(verts.size());
125 const MutableSpan<float4> new_colors = tls.new_colors;
126
127 /* Copy alpha. */
128 for (const int i : verts.index_range()) {
129 new_colors[i][3] = orig_colors[i][3];
130 }
131
132 switch (mode) {
133 case FilterType::Fill: {
134 clamp_factors(factors, 0.0f, 1.0f);
135 for (const int i : verts.index_range()) {
136 float fill_color_rgba[4];
137 copy_v3_v3(fill_color_rgba, filter_fill_color);
138 fill_color_rgba[3] = 1.0f;
139 mul_v4_fl(fill_color_rgba, factors[i]);
140 blend_color_mix_float(new_colors[i], orig_colors[i], fill_color_rgba);
141 }
142 break;
143 }
144 case FilterType::Hue: {
145 for (const int i : verts.index_range()) {
146 float3 hsv_color;
147 rgb_to_hsv_v(orig_colors[i], hsv_color);
148 const float hue = hsv_color[0];
149 hsv_color[0] = fmod((hsv_color[0] + fabs(factors[i])) - hue, 1);
150 hsv_to_rgb_v(hsv_color, new_colors[i]);
151 }
152 break;
153 }
155 for (const int i : verts.index_range()) {
156 float3 hsv_color;
157 rgb_to_hsv_v(orig_colors[i], hsv_color);
158
159 if (hsv_color[1] > 0.001f) {
160 hsv_color[1] = std::clamp(hsv_color[1] + factors[i] * hsv_color[1], 0.0f, 1.0f);
161 hsv_to_rgb_v(hsv_color, new_colors[i]);
162 }
163 else {
164 copy_v3_v3(new_colors[i], orig_colors[i]);
165 }
166 }
167 break;
168 }
169 case FilterType::Value: {
170 for (const int i : verts.index_range()) {
171 float3 hsv_color;
172 rgb_to_hsv_v(orig_colors[i], hsv_color);
173 hsv_color[2] = std::clamp(hsv_color[2] + factors[i], 0.0f, 1.0f);
174 hsv_to_rgb_v(hsv_color, new_colors[i]);
175 }
176 break;
177 }
178 case FilterType::Red: {
179 for (const int i : verts.index_range()) {
180 copy_v3_v3(new_colors[i], orig_colors[i]);
181 new_colors[i][0] = std::clamp(orig_colors[i][0] + factors[i], 0.0f, 1.0f);
182 }
183 break;
184 }
185 case FilterType::Green: {
186 for (const int i : verts.index_range()) {
187 copy_v3_v3(new_colors[i], orig_colors[i]);
188 new_colors[i][1] = std::clamp(orig_colors[i][1] + factors[i], 0.0f, 1.0f);
189 }
190 break;
191 }
192 case FilterType::Blue: {
193 for (const int i : verts.index_range()) {
194 copy_v3_v3(new_colors[i], orig_colors[i]);
195 new_colors[i][2] = std::clamp(orig_colors[i][2] + factors[i], 0.0f, 1.0f);
196 }
197 break;
198 }
200 clamp_factors(factors, -1.0f, 1.0f);
201 for (const int i : verts.index_range()) {
202 const float brightness = factors[i];
203 const float contrast = 0;
204 float delta = contrast / 2.0f;
205 const float gain = 1.0f - delta * 2.0f;
206 delta *= -1;
207 const float offset = gain * (brightness + delta);
208 for (int component = 0; component < 3; component++) {
209 new_colors[i][component] = std::clamp(
210 gain * orig_colors[i][component] + offset, 0.0f, 1.0f);
211 }
212 }
213 break;
214 }
216 clamp_factors(factors, -1.0f, 1.0f);
217 for (const int i : verts.index_range()) {
218 const float brightness = 0;
219 const float contrast = factors[i];
220 float delta = contrast / 2.0f;
221 float gain = 1.0f - delta * 2.0f;
222
223 float offset;
224 if (contrast > 0) {
225 gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
226 offset = gain * (brightness - delta);
227 }
228 else {
229 delta *= -1;
230 offset = gain * (brightness + delta);
231 }
232 for (int component = 0; component < 3; component++) {
233 new_colors[i][component] = std::clamp(
234 gain * orig_colors[i][component] + offset, 0.0f, 1.0f);
235 }
236 }
237 break;
238 }
239 case FilterType::Smooth: {
240 clamp_factors(factors, -1.0f, 1.0f);
241
242 tls.colors.resize(verts.size());
243 const MutableSpan<float4> colors = tls.colors;
244 for (const int i : verts.index_range()) {
245 colors[i] = color_vert_get(faces,
246 corner_verts,
247 vert_to_face_map,
248 color_attribute.span,
249 color_attribute.domain,
250 verts[i]);
251 }
252
254 corner_verts,
255 vert_to_face_map,
256 {},
257 verts,
259 tls.neighbor_data);
260
261 tls.average_colors.resize(verts.size());
262 const MutableSpan<float4> average_colors = tls.average_colors;
264 corner_verts,
265 vert_to_face_map,
266 color_attribute.span,
267 color_attribute.domain,
268 neighbors,
269 average_colors);
270
271 for (const int i : verts.index_range()) {
272 const int vert = verts[i];
273
274 if (factors[i] < 0.0f) {
275 interp_v4_v4v4(average_colors[i], average_colors[i], colors[i], 0.5f);
276 }
277
278 bool copy_alpha = colors[i][3] == average_colors[i][3];
279
280 if (factors[i] < 0.0f) {
281 float4 delta_color;
282
283 /* Unsharp mask. */
284 copy_v4_v4(delta_color, ss.filter_cache->pre_smoothed_color[vert]);
285 delta_color -= average_colors[i];
286
287 copy_v4_v4(new_colors[i], colors[i]);
288 madd_v4_v4fl(new_colors[i], delta_color, factors[i]);
289 }
290 else {
291 blend_color_interpolate_float(new_colors[i], colors[i], average_colors[i], factors[i]);
292 }
293
294 new_colors[i] = math::clamp(new_colors[i], 0.0f, 1.0f);
295
296 /* Prevent accumulated numeric error from corrupting alpha. */
297 if (copy_alpha) {
298 new_colors[i][3] = average_colors[i][3];
299 }
300 }
301 break;
302 }
303 }
304
305 for (const int i : verts.index_range()) {
307 corner_verts,
308 vert_to_face_map,
309 color_attribute.domain,
310 verts[i],
311 new_colors[i],
312 color_attribute.span);
313 }
314}
315
316static void sculpt_color_presmooth_init(const Mesh &mesh, Object &object)
317{
318 SculptSession &ss = *object.sculpt;
319 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
321 const IndexMask &node_mask = ss.filter_cache->node_mask;
322 const OffsetIndices<int> faces = mesh.faces();
323 const Span<int> corner_verts = mesh.corner_verts();
324 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
325 const bke::GAttributeReader color_attribute = active_color_attribute(mesh);
326 const GVArraySpan colors = *color_attribute;
327
328 if (ss.filter_cache->pre_smoothed_color.is_empty()) {
330 }
331 const MutableSpan<float4> pre_smoothed_color = ss.filter_cache->pre_smoothed_color;
332
333 node_mask.foreach_index(GrainSize(1), [&](const int i) {
334 for (const int vert : nodes[i].verts()) {
335 pre_smoothed_color[vert] = color_vert_get(
336 faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, vert);
337 }
338 });
339
340 struct LocalData {
343 Vector<float4> averaged_colors;
344 };
346 for ([[maybe_unused]] const int iteration : IndexRange(2)) {
347 node_mask.foreach_index(GrainSize(1), [&](const int i) {
348 LocalData &tls = all_tls.local();
349 const Span<int> verts = nodes[i].verts();
350
352 corner_verts,
353 vert_to_face_map,
354 {},
355 verts,
357 tls.neighbor_data);
358
359 tls.averaged_colors.resize(verts.size());
360 const MutableSpan<float4> averaged_colors = tls.averaged_colors;
361 smooth::neighbor_data_average_mesh(pre_smoothed_color.as_span(), neighbors, averaged_colors);
362
363 for (const int i : verts.index_range()) {
364 pre_smoothed_color[verts[i]] = math::interpolate(
365 pre_smoothed_color[verts[i]], averaged_colors[i], 0.5f);
366 }
367 });
368 }
369}
370
372{
373 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
374 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
375 SculptSession &ss = *ob.sculpt;
378
379 const FilterType mode = FilterType(RNA_enum_get(op->ptr, "type"));
380 float filter_strength = RNA_float_get(op->ptr, "strength");
381 float fill_color[3];
382
383 RNA_float_get_array(op->ptr, "fill_color", fill_color);
384 IMB_colormanagement_srgb_to_scene_linear_v3(fill_color, fill_color);
385
386 Mesh &mesh = *static_cast<Mesh *>(ob.data);
387 if (filter_strength < 0.0 && ss.filter_cache->pre_smoothed_color.is_empty()) {
389 }
390
391 const IndexMask &node_mask = ss.filter_cache->node_mask;
392 if (auto_mask::is_enabled(sd, ob, nullptr) && ss.filter_cache->automasking &&
394 {
395 ss.filter_cache->automasking->calc_cavity_factor(depsgraph, ob, node_mask);
396 }
397
398 const OffsetIndices<int> faces = mesh.faces();
399 const Span<int> corner_verts = mesh.corner_verts();
400 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
402 const MeshAttributeData attribute_data(mesh);
403
405 node_mask.foreach_index(GrainSize(1), [&](const int i) {
406 LocalData &tls = all_tls.local();
408 ob,
409 faces,
410 corner_verts,
411 vert_to_face_map,
412 attribute_data,
413 mode,
414 filter_strength,
415 fill_color,
416 nodes[i],
417 tls,
418 color_attribute);
419 });
420 pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
421 color_attribute.finish();
423}
424
426{
427 SculptSession &ss = *ob.sculpt;
428
429 undo::push_end(ob);
430 MEM_delete(ss.filter_cache);
431 ss.filter_cache = nullptr;
433}
434
436 wmOperator *op,
437 const wmEvent *event)
438{
440 SculptSession &ss = *ob.sculpt;
441
442 if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
444 return OPERATOR_FINISHED;
445 }
446
447 if (event->type != MOUSEMOVE) {
449 }
450
451 const float len = (event->prev_press_xy[0] - event->xy[0]) * 0.001f;
452 float filter_strength = ss.filter_cache->start_filter_strength * -len;
453 RNA_float_set(op->ptr, "strength", filter_strength);
454
456
458}
459
461{
462 const Scene &scene = *CTX_data_scene(C);
464 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
465 View3D *v3d = CTX_wm_view3d(C);
466
467 const Base *base = CTX_data_active_base(C);
468 if (!BKE_base_is_visible(v3d, base)) {
469 return OPERATOR_CANCELLED;
470 }
471
472 int mval[2];
473 RNA_int_get_array(op->ptr, "start_mouse", mval);
474 float mval_fl[2] = {float(mval[0]), float(mval[1])};
475
476 const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
477 if (use_automasking) {
478 if (v3d) {
479 /* Update the active face set manually as the paint cursor is not enabled when using the Mesh
480 * Filter Tool. */
482 cursor_geometry_info_update(C, &cgi, mval_fl, false);
483 }
484 }
485
486 /* Disable for multires and dyntopo for now */
487 if (!color_supported_check(scene, ob, op->reports)) {
488 return OPERATOR_CANCELLED;
489 }
490
491 /* Ensure that we have a PBVH to be able to push changes on only visible nodes. */
493
494 undo::push_begin(scene, ob, op);
496
497 /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the potential
498 * creation of color layer data. */
501
503 ob,
504 sd,
506 mval_fl,
507 RNA_float_get(op->ptr, "area_normal_radius"),
508 RNA_float_get(op->ptr, "strength"));
509 const SculptSession &ss = *ob.sculpt;
510 filter::Cache *filter_cache = ss.filter_cache;
512 if (auto_mask::is_enabled(sd, ob, nullptr)) {
514 }
515
517}
518
532
534 wmOperator *op,
535 const wmEvent *event)
536{
538 View3D *v3d = CTX_wm_view3d(C);
539 if (v3d && v3d->shading.type == OB_SOLID) {
541 }
542
543 RNA_int_set_array(op->ptr, "start_mouse", event->mval);
544
546 return OPERATOR_CANCELLED;
547 }
548
550
553}
554
556{
558 const int value = RNA_property_enum_get(ptr, prop);
559 const char *ui_name = nullptr;
560
561 RNA_property_enum_name_gettexted(nullptr, ptr, prop, value, &ui_name);
562 return ui_name;
563}
564
566{
567 uiLayout *layout = op->layout;
568
569 layout->prop(op->ptr, "strength", UI_ITEM_NONE, std::nullopt, ICON_NONE);
570
571 if (FilterType(RNA_enum_get(op->ptr, "type")) == FilterType::Fill) {
572 layout->prop(op->ptr, "fill_color", UI_ITEM_NONE, std::nullopt, ICON_NONE);
573 }
574}
575
577{
578 /* identifiers */
579 ot->name = "Filter Color";
580 ot->idname = "SCULPT_OT_color_filter";
581 ot->description = "Applies a filter to modify the active color attribute";
582
583 /* API callbacks. */
587 ot->poll = SCULPT_mode_poll;
590
592
593 /* rna */
595
597 ot->srna, "type", prop_color_filter_types, int(FilterType::Fill), "Filter Type", "");
598
599 PropertyRNA *prop = RNA_def_float_color(ot->srna,
600 "fill_color",
601 3,
603 0.0f,
604 FLT_MAX,
605 "Fill Color",
606 "",
607 0.0f,
608 1.0f);
611}
612
613} // 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:344
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2657
void BKE_sculpt_color_layer_create_if_needed(Object *object)
Definition paint.cc:2633
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)
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
Read Guarded memory(de)allocation.
@ PROP_COLOR_GAMMA
Definition RNA_types.hh:260
#define C
Definition RandGen.cpp:29
#define UI_ITEM_NONE
@ KM_RELEASE
Definition WM_types.hh:309
@ 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:600
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
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:2877
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2912
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, const 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:6809
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:7607
bool color_supported_check(const Scene &scene, Object &object, ReportList *reports)
Definition sculpt.cc:5459
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7504
bool cursor_geometry_info_update(bContext *C, CursorGeometryInfo *out, const float2 &mval, const bool use_sampled_normal)
Definition sculpt.cc:4664
void flush_update_done(const bContext *C, Object &ob, const UpdateType update_type)
Definition sculpt.cc:5131
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:5083
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:3660
#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:438
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:754
short val
Definition WM_types.hh:756
int mval[2]
Definition WM_types.hh:760
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:4227
wmOperatorType * ot
Definition wm_files.cc:4226