Sculpt: Convert all Scrape, Fill, Flatten brushes to Plane brush

Previously, the bundled essential brushes in Sculpt Mode were changed
from the Scrape, Fill, and Flatten types to the Plane brush type. This
commit does the same thing programmatically and removes the now old code
related to these obsolete brushes.

Resolves #134076

Pull Request: https://projects.blender.org/blender/blender/pulls/138022
This commit is contained in:
Sean Kim
2025-04-29 22:20:49 +02:00
committed by Sean Kim
parent 385a8a4d6a
commit 922e40eefe
9 changed files with 58 additions and 424 deletions

View File

@@ -27,7 +27,7 @@
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 55
#define BLENDER_FILE_SUBVERSION 56
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@@ -1519,9 +1519,7 @@ bool supports_accumulate(const Brush &brush)
SCULPT_BRUSH_TYPE_CLAY_STRIPS,
SCULPT_BRUSH_TYPE_CLAY_THUMB,
SCULPT_BRUSH_TYPE_ROTATE,
SCULPT_BRUSH_TYPE_PLANE,
SCULPT_BRUSH_TYPE_SCRAPE,
SCULPT_BRUSH_TYPE_FLATTEN);
SCULPT_BRUSH_TYPE_PLANE);
}
bool supports_topology_rake(const Brush &brush)
{
@@ -1592,10 +1590,7 @@ bool supports_plane_offset(const Brush &brush)
SCULPT_BRUSH_TYPE_CLAY,
SCULPT_BRUSH_TYPE_CLAY_STRIPS,
SCULPT_BRUSH_TYPE_CLAY_THUMB,
SCULPT_BRUSH_TYPE_PLANE,
SCULPT_BRUSH_TYPE_FILL,
SCULPT_BRUSH_TYPE_FLATTEN,
SCULPT_BRUSH_TYPE_SCRAPE);
SCULPT_BRUSH_TYPE_PLANE);
}
bool supports_random_texture_angle(const Brush &brush)
{
@@ -1631,9 +1626,6 @@ bool supports_secondary_cursor_color(const Brush &brush)
SCULPT_BRUSH_TYPE_PINCH,
SCULPT_BRUSH_TYPE_CREASE,
SCULPT_BRUSH_TYPE_LAYER,
SCULPT_BRUSH_TYPE_FLATTEN,
SCULPT_BRUSH_TYPE_FILL,
SCULPT_BRUSH_TYPE_SCRAPE,
SCULPT_BRUSH_TYPE_MASK);
}
bool supports_smooth_stroke(const Brush &brush)
@@ -1672,9 +1664,6 @@ bool supports_inverted_direction(const Brush &brush)
SCULPT_BRUSH_TYPE_BLOB,
SCULPT_BRUSH_TYPE_CREASE,
SCULPT_BRUSH_TYPE_PLANE,
SCULPT_BRUSH_TYPE_FLATTEN,
SCULPT_BRUSH_TYPE_FILL,
SCULPT_BRUSH_TYPE_SCRAPE,
SCULPT_BRUSH_TYPE_CLAY,
SCULPT_BRUSH_TYPE_PINCH,
SCULPT_BRUSH_TYPE_MASK);
@@ -1697,9 +1686,6 @@ bool supports_tilt(const Brush &brush)
return ELEM(brush.sculpt_brush_type,
SCULPT_BRUSH_TYPE_DRAW,
SCULPT_BRUSH_TYPE_DRAW_SHARP,
SCULPT_BRUSH_TYPE_FLATTEN,
SCULPT_BRUSH_TYPE_FILL,
SCULPT_BRUSH_TYPE_SCRAPE,
SCULPT_BRUSH_TYPE_PLANE,
SCULPT_BRUSH_TYPE_CLAY_STRIPS);
}

View File

@@ -7178,6 +7178,52 @@ static void version_set_uv_face_overlay_defaults(Main *bmain)
}
}
static void version_convert_sculpt_planar_brushes(Main *bmain)
{
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (ELEM(brush->sculpt_brush_type,
SCULPT_BRUSH_TYPE_FLATTEN,
SCULPT_BRUSH_TYPE_FILL,
SCULPT_BRUSH_TYPE_SCRAPE))
{
if (brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_FLATTEN) {
brush->plane_height = 1.0f;
brush->plane_depth = 1.0f;
brush->area_radius_factor = 1.0f;
brush->plane_inversion_mode = BRUSH_PLANE_INVERT_DISPLACEMENT;
}
if (brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_FILL) {
brush->plane_height = 0.0f;
brush->plane_depth = 1.0f;
brush->plane_inversion_mode = brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL ?
BRUSH_PLANE_SWAP_HEIGHT_AND_DEPTH :
BRUSH_PLANE_INVERT_DISPLACEMENT;
}
if (brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_SCRAPE) {
brush->plane_height = 1.0f;
brush->plane_depth = 0.0f;
brush->plane_inversion_mode = brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL ?
BRUSH_PLANE_SWAP_HEIGHT_AND_DEPTH :
BRUSH_PLANE_INVERT_DISPLACEMENT;
}
if (brush->flag & BRUSH_PLANE_TRIM) {
brush->plane_height *= brush->plane_trim;
brush->plane_depth *= brush->plane_trim;
}
brush->stabilize_normal = (brush->flag & BRUSH_ORIGINAL_NORMAL) ? 1.0f : 0.0f;
brush->stabilize_plane = (brush->flag & BRUSH_ORIGINAL_PLANE) ? 1.0f : 0.0f;
brush->flag &= ~BRUSH_ORIGINAL_NORMAL;
brush->flag &= ~BRUSH_ORIGINAL_PLANE;
brush->sculpt_brush_type = SCULPT_BRUSH_TYPE_PLANE;
}
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@@ -9903,6 +9949,10 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 56)) {
version_convert_sculpt_planar_brushes(bmain);
}
/* Always run this versioning (keep at the bottom of the function). Meshes are written with the
* legacy format which always needs to be converted to the new format on file load. To be moved
* to a subversion check in 5.0. */

View File

@@ -154,7 +154,6 @@ set(SRC
brushes/multires_displacement_smear.cc
brushes/pinch.cc
brushes/plane.cc
brushes/plane_legacy.cc
brushes/relax.cc
brushes/rotate.cc
brushes/smooth.cc

View File

@@ -113,14 +113,6 @@ void do_enhance_details_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask);
void do_fill_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask);
void do_flatten_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
const IndexMask &node_mask);
void do_plane_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
@@ -182,10 +174,6 @@ void do_rotate_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask);
void do_scrape_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask);
/** Smooth positions with neighboring vertices. */
void do_smooth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,

View File

@@ -1,313 +0,0 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*
* "Plane" related brushes, all three of these perform a similar displacement with an optional
* additional filtering step.
*/
#include "editors/sculpt_paint/brushes/brushes.hh"
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_mesh.hh"
#include "BKE_paint.hh"
#include "BKE_paint_bvh.hh"
#include "BKE_subdiv_ccg.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_geom.h"
#include "BLI_task.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_automask.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "bmesh.hh"
namespace blender::ed::sculpt_paint::brushes {
inline namespace plane_legacy_cc {
using IndexedFilterFn =
FunctionRef<void(Span<float3>, Span<int>, const float4 &, MutableSpan<float>)>;
using GenericFilterFn = FunctionRef<void(Span<float3>, const float4 &, MutableSpan<float>)>;
struct LocalData {
Vector<float3> positions;
Vector<float> factors;
Vector<float> distances;
Vector<float3> translations;
};
static void calc_faces(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
const float4 &plane,
const float strength,
const MeshAttributeData &attribute_data,
const Span<float3> vert_normals,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const PositionDeformData &position_data,
const IndexedFilterFn filter)
{
SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
const Span<int> verts = node.verts();
calc_factors_common_mesh_indexed(depsgraph,
brush,
object,
attribute_data,
position_data.eval,
vert_normals,
node,
tls.factors,
tls.distances);
scale_factors(tls.factors, strength);
filter(position_data.eval, verts, plane, tls.factors);
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
calc_translations_to_plane(position_data.eval, verts, plane, translations);
filter_plane_trim_limit_factors(brush, cache, translations, tls.factors);
scale_translations(translations, tls.factors);
clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
position_data.deform(translations, verts);
}
static void calc_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::GridsNode &node,
LocalData &tls,
const GenericFilterFn filter)
{
SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const Span<int> grids = node.grids();
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
calc_factors_common_grids(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
scale_factors(tls.factors, strength);
filter(positions, plane, tls.factors);
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
calc_translations_to_plane(positions, plane, translations);
filter_plane_trim_limit_factors(brush, cache, translations, tls.factors);
scale_translations(translations, tls.factors);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
}
static void calc_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::BMeshNode &node,
LocalData &tls,
const GenericFilterFn filter)
{
SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
calc_factors_common_bmesh(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
scale_factors(tls.factors, strength);
filter(positions, plane, tls.factors);
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
calc_translations_to_plane(positions, plane, translations);
filter_plane_trim_limit_factors(brush, cache, translations, tls.factors);
scale_translations(translations, tls.factors);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
}
static void do_plane_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask,
const float direction,
const IndexedFilterFn indexed_filter,
const GenericFilterFn generic_filter)
{
const SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 area_no;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
area_no = tilt_apply_to_normal(area_no, *ss.cache, brush.tilt_strength_factor);
const float offset = brush_plane_offset_get(brush, ss);
const float displace = direction * ss.cache->radius * offset;
area_co += area_no * ss.cache->scale * displace;
float4 plane;
plane_from_point_normal_v3(plane, area_co, area_no);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
const Mesh &mesh = *static_cast<Mesh *>(object.data);
const MeshAttributeData attribute_data(mesh);
const PositionDeformData position_data(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
LocalData &tls = all_tls.local();
calc_faces(depsgraph,
sd,
brush,
plane,
ss.cache->bstrength,
attribute_data,
vert_normals,
nodes[i],
object,
tls,
position_data,
indexed_filter);
bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
LocalData &tls = all_tls.local();
calc_grids(depsgraph,
sd,
object,
brush,
plane,
ss.cache->bstrength,
nodes[i],
tls,
generic_filter);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
LocalData &tls = all_tls.local();
calc_bmesh(depsgraph,
sd,
object,
brush,
plane,
ss.cache->bstrength,
nodes[i],
tls,
generic_filter);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
break;
}
}
pbvh.tag_positions_changed(node_mask);
pbvh.flush_bounds_to_parents();
}
} // namespace plane_legacy_cc
void do_flatten_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask)
{
do_plane_brush(
depsgraph,
sd,
object,
node_mask,
1.0f,
[](const Span<float3> /*vert_positions*/,
const Span<int> /*verts*/,
const float4 & /*plane*/,
const MutableSpan<float> /*factors*/) {},
[](const Span<float3> /*positions*/,
const float4 & /*plane*/,
const MutableSpan<float> /*factors*/) {});
}
void do_fill_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask)
{
do_plane_brush(
depsgraph,
sd,
object,
node_mask,
1.0f,
[](const Span<float3> vert_positions,
const Span<int> verts,
const float4 &plane,
const MutableSpan<float> factors) {
filter_above_plane_factors(vert_positions, verts, plane, factors);
},
[](const Span<float3> positions, const float4 &plane, const MutableSpan<float> factors) {
filter_above_plane_factors(positions, plane, factors);
});
}
void do_scrape_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const IndexMask &node_mask)
{
do_plane_brush(
depsgraph,
sd,
object,
node_mask,
-1.0f,
[](const Span<float3> vert_positions,
const Span<int> verts,
const float4 &plane,
const MutableSpan<float> factors) {
filter_below_plane_factors(vert_positions, verts, plane, factors);
},
[](const Span<float3> positions, const float4 &plane, const MutableSpan<float> factors) {
filter_below_plane_factors(positions, plane, factors);
});
}
} // namespace blender::ed::sculpt_paint::brushes

View File

@@ -1296,12 +1296,7 @@ static float area_normal_and_center_get_position_radius(const SculptSession &ss,
float test_radius = ss.cache ? ss.cache->radius : ss.cursor_radius;
if (brush.ob_mode == OB_MODE_SCULPT) {
/* Layer brush produces artifacts with normal and area radius */
if (ELEM(brush.sculpt_brush_type,
SCULPT_BRUSH_TYPE_PLANE,
SCULPT_BRUSH_TYPE_SCRAPE,
SCULPT_BRUSH_TYPE_FILL) &&
brush.area_radius_factor > 0.0f)
{
if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_PLANE && brush.area_radius_factor > 0.0f) {
test_radius *= brush.area_radius_factor;
if (ss.cache && brush.flag2 & BRUSH_AREA_RADIUS_PRESSURE) {
test_radius *= ss.cache->pressure;
@@ -2150,14 +2145,6 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph,
*/
static float brush_flip(const Brush &brush, const blender::ed::sculpt_paint::StrokeCache &cache)
{
/* The Fill and Scrape brushes do not invert direction when this flag is set. The behavior of
* the brush completely changes. */
if (ELEM(brush.sculpt_brush_type, SCULPT_BRUSH_TYPE_FILL, SCULPT_BRUSH_TYPE_SCRAPE) &&
brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL)
{
return 1.0f;
}
const float dir = (brush.flag & BRUSH_DIR_IN) ? -1.0f : 1.0f;
const float pen_flip = cache.pen_flip ? -1.0f : 1.0f;
const float invert = cache.invert ? -1.0f : 1.0f;
@@ -2276,18 +2263,6 @@ static float brush_strength(const Sculpt &sd,
else {
return 0.5f * alpha * pressure * overlap * feather;
}
case SCULPT_BRUSH_TYPE_FILL:
case SCULPT_BRUSH_TYPE_SCRAPE:
case SCULPT_BRUSH_TYPE_FLATTEN:
if (flip > 0.0f) {
overlap = (1.0f + overlap) / 2.0f;
return alpha * flip * pressure * overlap * feather;
}
else {
/* Reduce strength for DEEPEN, PEAKS, and CONTRAST. */
return 0.5f * alpha * flip * pressure * overlap * feather;
}
case SCULPT_BRUSH_TYPE_SMOOTH:
return flip * alpha * pressure * feather;
@@ -3381,9 +3356,6 @@ static void do_brush_action(const Depsgraph &depsgraph,
case SCULPT_BRUSH_TYPE_LAYER:
brushes::do_layer_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_BRUSH_TYPE_FLATTEN:
brushes::do_flatten_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_BRUSH_TYPE_CLAY:
brushes::do_clay_brush(depsgraph, sd, ob, node_mask);
break;
@@ -3402,22 +3374,6 @@ static void do_brush_action(const Depsgraph &depsgraph,
case SCULPT_BRUSH_TYPE_CLAY_THUMB:
brushes::do_clay_thumb_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_BRUSH_TYPE_FILL:
if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
brushes::do_scrape_brush(depsgraph, sd, ob, node_mask);
}
else {
brushes::do_fill_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_BRUSH_TYPE_SCRAPE:
if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
brushes::do_fill_brush(depsgraph, sd, ob, node_mask);
}
else {
brushes::do_scrape_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_BRUSH_TYPE_MASK:
switch ((BrushMaskTool)brush.mask_tool) {
case BRUSH_MASK_DRAW:
@@ -3825,18 +3781,12 @@ static const char *sculpt_brush_type_name(const Sculpt &sd)
return "Thumb Brush";
case SCULPT_BRUSH_TYPE_LAYER:
return "Layer Brush";
case SCULPT_BRUSH_TYPE_FLATTEN:
return "Flatten Brush";
case SCULPT_BRUSH_TYPE_CLAY:
return "Clay Brush";
case SCULPT_BRUSH_TYPE_CLAY_STRIPS:
return "Clay Strips Brush";
case SCULPT_BRUSH_TYPE_CLAY_THUMB:
return "Clay Thumb Brush";
case SCULPT_BRUSH_TYPE_FILL:
return "Fill Brush";
case SCULPT_BRUSH_TYPE_SCRAPE:
return "Scrape Brush";
case SCULPT_BRUSH_TYPE_SNAKE_HOOK:
return "Snake Hook Brush";
case SCULPT_BRUSH_TYPE_ROTATE:

View File

@@ -425,10 +425,14 @@ typedef enum eBrushSculptType {
SCULPT_BRUSH_TYPE_INFLATE = 4,
SCULPT_BRUSH_TYPE_GRAB = 5,
SCULPT_BRUSH_TYPE_LAYER = 6,
#ifdef DNA_DEPRECATED_ALLOW
SCULPT_BRUSH_TYPE_FLATTEN = 7,
#endif
SCULPT_BRUSH_TYPE_CLAY = 8,
#ifdef DNA_DEPRECATED_ALLOW
SCULPT_BRUSH_TYPE_FILL = 9,
SCULPT_BRUSH_TYPE_SCRAPE = 10,
#endif
SCULPT_BRUSH_TYPE_NUDGE = 11,
SCULPT_BRUSH_TYPE_THUMB = 12,
SCULPT_BRUSH_TYPE_SNAKE_HOOK = 13,

View File

@@ -158,9 +158,6 @@ const EnumPropertyItem rna_enum_brush_sculpt_brush_type_items[] = {
{SCULPT_BRUSH_TYPE_CREASE, "CREASE", 0, "Crease", ""},
RNA_ENUM_ITEM_SEPR,
{SCULPT_BRUSH_TYPE_SMOOTH, "SMOOTH", 0, "Smooth", ""},
{SCULPT_BRUSH_TYPE_FLATTEN, "FLATTEN", 0, "Flatten", ""},
{SCULPT_BRUSH_TYPE_FILL, "FILL", 0, "Fill", ""},
{SCULPT_BRUSH_TYPE_SCRAPE, "SCRAPE", 0, "Scrape", ""},
{SCULPT_BRUSH_TYPE_PLANE, "PLANE", 0, "Plane", ""},
{SCULPT_BRUSH_TYPE_MULTIPLANE_SCRAPE, "MULTIPLANE_SCRAPE", 0, "Multi-plane Scrape", ""},
{SCULPT_BRUSH_TYPE_PINCH, "PINCH", 0, "Pinch", ""},
@@ -796,24 +793,6 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C,
PaintMode mode = BKE_paintmode_get_active_from_context(C);
/* sculpt mode */
static const EnumPropertyItem prop_flatten_contrast_items[] = {
{BRUSH_DIR_IN, "CONTRAST", ICON_ADD, "Contrast", "Subtract effect of brush"},
{0, "FLATTEN", ICON_REMOVE, "Flatten", "Add effect of brush"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem prop_fill_deepen_items[] = {
{0, "FILL", ICON_ADD, "Fill", "Add effect of brush"},
{BRUSH_DIR_IN, "DEEPEN", ICON_REMOVE, "Deepen", "Subtract effect of brush"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem prop_scrape_peaks_items[] = {
{0, "SCRAPE", ICON_ADD, "Scrape", "Add effect of brush"},
{BRUSH_DIR_IN, "PEAKS", ICON_REMOVE, "Peaks", "Subtract effect of brush"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem prop_pinch_magnify_items[] = {
{BRUSH_DIR_IN, "MAGNIFY", ICON_ADD, "Magnify", "Subtract effect of brush"},
{0, "PINCH", ICON_REMOVE, "Pinch", "Add effect of brush"},
@@ -873,15 +852,6 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C,
return rna_enum_dummy_DEFAULT_items;
}
case SCULPT_BRUSH_TYPE_FLATTEN:
return prop_flatten_contrast_items;
case SCULPT_BRUSH_TYPE_FILL:
return prop_fill_deepen_items;
case SCULPT_BRUSH_TYPE_SCRAPE:
return prop_scrape_peaks_items;
case SCULPT_BRUSH_TYPE_PINCH:
return prop_pinch_magnify_items;