76 {0,
nullptr, 0,
nullptr,
nullptr},
92 for (
float &factor : factors) {
93 factor = std::clamp(factor,
min,
max);
104 const float filter_strength,
105 const float *filter_fill_color,
127 for (
const int i :
verts.index_range()) {
128 new_colors[
i][3] = orig_colors[
i][3];
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;
144 for (
const int i :
verts.index_range()) {
147 const float hue = hsv_color[0];
148 hsv_color[0] =
fmod((hsv_color[0] +
fabs(factors[
i])) - hue, 1);
154 for (
const int i :
verts.index_range()) {
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);
169 for (
const int i :
verts.index_range()) {
172 hsv_color[2] = std::clamp(hsv_color[2] + factors[
i], 0.0f, 1.0f);
178 for (
const int i :
verts.index_range()) {
180 new_colors[
i][0] = std::clamp(orig_colors[
i][0] + factors[
i], 0.0f, 1.0f);
185 for (
const int i :
verts.index_range()) {
187 new_colors[
i][1] = std::clamp(orig_colors[
i][1] + factors[
i], 0.0f, 1.0f);
192 for (
const int i :
verts.index_range()) {
194 new_colors[
i][2] = std::clamp(orig_colors[
i][2] + factors[
i], 0.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;
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);
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;
224 gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
225 offset = gain * (brightness - delta);
229 offset = gain * (brightness + delta);
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);
243 for (
const int i :
verts.index_range()) {
247 color_attribute.
span,
265 color_attribute.
span,
270 for (
const int i :
verts.index_range()) {
271 const int vert =
verts[
i];
273 if (factors[
i] < 0.0f) {
277 bool copy_alpha = colors[
i][3] == average_colors[
i][3];
279 if (factors[
i] < 0.0f) {
284 delta_color -= average_colors[
i];
297 new_colors[
i][3] = average_colors[
i][3];
304 for (
const int i :
verts.index_range()) {
311 color_attribute.
span);
332 node_mask.foreach_index(
GrainSize(1), [&](
const int i) {
335 faces, corner_verts, vert_to_face_map, colors, color_attribute.
domain, vert);
345 for ([[maybe_unused]]
const int iteration :
IndexRange(2)) {
346 node_mask.foreach_index(
GrainSize(1), [&](
const int i) {
358 tls.averaged_colors.resize(
verts.size());
362 for (
const int i :
verts.index_range()) {
364 pre_smoothed_color[
verts[
i]], averaged_colors[
i], 0.5f);
385 if (filter_strength < 0.0 && ss.filter_cache->pre_smoothed_color.is_empty()) {
449 const float len = (
event->prev_press_xy[0] -
event->xy[0]) * 0.001f;
472 float mval_fl[2] = {
float(mval[0]),
float(mval[1])};
475 if (use_automasking) {
557 const char *ui_name =
nullptr;
577 ot->name =
"Filter Color";
578 ot->idname =
"SCULPT_OT_color_filter";
579 ot->description =
"Applies a filter to modify the active color attribute";
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
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
void BKE_sculpt_color_layer_create_if_needed(Object *object)
A BVH for high poly meshes.
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
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
@ V3D_SHADING_VERTEX_COLOR
void ED_image_paint_brush_type_update_sticky_shading_color(bContext *C, Object *ob)
Read Guarded memory(de)allocation.
BPy_StructRNA * depsgraph
void resize(const int64_t new_size)
constexpr Span< T > as_span() const
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float2 fabs(const float2 a)
pbvh::Tree & pbvh_ensure(Depsgraph &depsgraph, Object &object)
pbvh::Tree * pbvh_get(Object &object)
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_end(Object &ob)
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)
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)
bool color_supported_check(const Scene &scene, Object &object, ReportList *reports)
void scale_factors(MutableSpan< float > factors, float strength)
bool cursor_geometry_info_update(bContext *C, CursorGeometryInfo *out, const float2 &mval, const bool use_sampled_normal)
void flush_update_done(const bContext *C, Object &ob, const UpdateType update_type)
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)
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)
struct SculptSession * sculpt
blender::ed::sculpt_paint::filter::Cache * filter_cache
Span< int > verts() const
VArraySpan< bool > hide_vert
Vector< int > neighbor_data
Vector< int > neighbor_offsets
Vector< float4 > new_colors
Vector< float4 > average_colors
float start_filter_strength
std::unique_ptr< auto_mask::Cache > automasking
Array< float4 > pre_smoothed_color
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)
struct ReportList * reports
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)