mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Refactor: Paint: Migrate automask settings to Paint struct
Currently, automasking is only used inside Sculpt mode. In preparation for further changes needed to expose the functionality to the 3D Texture Paint brush, this PR migrates the values from being stored on the `Sculpt` struct to the `MeshAutomaskingSettings`, stored as a pointer on the `Paint` struct. We do not default initialize these values, as it is specifically relevant for Sculpt, Vertex Paint, Weight Paint, and Texture Paint. Part of #156409 Pull Request: https://projects.blender.org/blender/blender/pulls/156494
This commit is contained in:
parent
d2f8313973
commit
6783ea037d
16 changed files with 432 additions and 292 deletions
|
|
@ -1002,7 +1002,7 @@ class VIEW3D_HT_header(Header):
|
|||
layout.popover(
|
||||
panel="VIEW3D_PT_sculpt_automasking",
|
||||
text="",
|
||||
icon=VIEW3D_HT_header._sculpt_automasking_icon(tool_settings.sculpt),
|
||||
icon=VIEW3D_HT_header._mesh_paint_automasking_icon(tool_settings.sculpt),
|
||||
)
|
||||
|
||||
elif object_mode == 'VERTEX_PAINT':
|
||||
|
|
@ -1108,16 +1108,16 @@ class VIEW3D_HT_header(Header):
|
|||
sub.popover(panel="VIEW3D_PT_shading", text="")
|
||||
|
||||
@staticmethod
|
||||
def _sculpt_automasking_icon(sculpt):
|
||||
def _mesh_paint_automasking_icon(paint):
|
||||
automask_enabled = (
|
||||
sculpt.use_automasking_topology or
|
||||
sculpt.use_automasking_face_sets or
|
||||
sculpt.use_automasking_boundary_edges or
|
||||
sculpt.use_automasking_boundary_face_sets or
|
||||
sculpt.use_automasking_cavity or
|
||||
sculpt.use_automasking_cavity_inverted or
|
||||
sculpt.use_automasking_start_normal or
|
||||
sculpt.use_automasking_view_normal
|
||||
paint.mesh_automasking_settings.use_automasking_topology or
|
||||
paint.mesh_automasking_settings.use_automasking_face_sets or
|
||||
paint.mesh_automasking_settings.use_automasking_boundary_edges or
|
||||
paint.mesh_automasking_settings.use_automasking_boundary_face_sets or
|
||||
paint.mesh_automasking_settings.use_automasking_cavity or
|
||||
paint.mesh_automasking_settings.use_automasking_cavity_inverted or
|
||||
paint.mesh_automasking_settings.use_automasking_start_normal or
|
||||
paint.mesh_automasking_settings.use_automasking_view_normal
|
||||
)
|
||||
|
||||
return 'CLIPUV_DEHLT' if automask_enabled else 'CLIPUV_HLT'
|
||||
|
|
@ -6250,16 +6250,18 @@ class VIEW3D_MT_sculpt_automasking_pie(Menu):
|
|||
pie = layout.menu_pie()
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
sculpt = tool_settings.sculpt
|
||||
paint = tool_settings.sculpt
|
||||
|
||||
pie.prop(sculpt, "use_automasking_topology", text="Topology")
|
||||
pie.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
|
||||
pie.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
pie.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
pie.prop(sculpt, "use_automasking_cavity", text="Cavity")
|
||||
pie.prop(sculpt, "use_automasking_cavity_inverted", text="Cavity (Inverted)")
|
||||
pie.prop(sculpt, "use_automasking_start_normal", text="Area Normal")
|
||||
pie.prop(sculpt, "use_automasking_view_normal", text="View Normal")
|
||||
settings = paint.mesh_automasking_settings
|
||||
|
||||
pie.prop(settings, "use_automasking_topology", text="Topology")
|
||||
pie.prop(settings, "use_automasking_face_sets", text="Face Sets")
|
||||
pie.prop(settings, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
pie.prop(settings, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
pie.prop(settings, "use_automasking_cavity", text="Cavity")
|
||||
pie.prop(settings, "use_automasking_cavity_inverted", text="Cavity (Inverted)")
|
||||
pie.prop(settings, "use_automasking_start_normal", text="Area Normal")
|
||||
pie.prop(settings, "use_automasking_view_normal", text="View Normal")
|
||||
|
||||
|
||||
class VIEW3D_MT_grease_pencil_sculpt_automasking_pie(Menu):
|
||||
|
|
@ -8883,79 +8885,82 @@ class VIEW3D_PT_sculpt_automasking(Panel):
|
|||
layout = self.layout
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
sculpt = tool_settings.sculpt
|
||||
paint = tool_settings.sculpt
|
||||
|
||||
settings = paint.mesh_automasking_settings
|
||||
|
||||
layout.label(text="Auto-Masking")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(sculpt, "use_automasking_topology", text="Topology")
|
||||
col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
|
||||
col.prop(settings, "use_automasking_topology", text="Topology")
|
||||
col.prop(settings, "use_automasking_face_sets", text="Face Sets")
|
||||
|
||||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row()
|
||||
row.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
row.prop(settings, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
|
||||
if sculpt.use_automasking_boundary_edges:
|
||||
if settings.use_automasking_boundary_edges:
|
||||
props = row.operator("sculpt.mask_from_boundary", text="Create Mask")
|
||||
props.settings_source = 'SCENE'
|
||||
props.boundary_mode = 'MESH'
|
||||
|
||||
row = col.row()
|
||||
row.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
row.prop(settings, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
|
||||
if sculpt.use_automasking_boundary_face_sets:
|
||||
if settings.use_automasking_boundary_face_sets:
|
||||
props = row.operator("sculpt.mask_from_boundary", text="Create Mask")
|
||||
props.settings_source = 'SCENE'
|
||||
props.boundary_mode = 'FACE_SETS'
|
||||
|
||||
if sculpt.use_automasking_boundary_edges or sculpt.use_automasking_boundary_face_sets:
|
||||
col.prop(sculpt, "automasking_boundary_edges_propagation_steps")
|
||||
if settings.use_automasking_boundary_edges or settings.use_automasking_boundary_face_sets:
|
||||
col.prop(settings, "boundary_edges_propagation_steps")
|
||||
|
||||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row()
|
||||
row.prop(sculpt, "use_automasking_cavity", text="Cavity")
|
||||
row.prop(settings, "use_automasking_cavity", text="Cavity")
|
||||
|
||||
is_cavity_active = sculpt.use_automasking_cavity or sculpt.use_automasking_cavity_inverted
|
||||
is_cavity_active = settings.use_automasking_cavity or settings.use_automasking_cavity_inverted
|
||||
|
||||
if is_cavity_active:
|
||||
props = row.operator("sculpt.mask_from_cavity", text="Create Mask")
|
||||
props.settings_source = 'SCENE'
|
||||
|
||||
col.prop(sculpt, "use_automasking_cavity_inverted", text="Cavity (inverted)")
|
||||
col.prop(settings, "use_automasking_cavity_inverted", text="Cavity (inverted)")
|
||||
|
||||
if is_cavity_active:
|
||||
col = layout.column(align=True)
|
||||
col.prop(sculpt, "automasking_cavity_factor", text="Factor")
|
||||
col.prop(sculpt, "automasking_cavity_blur_steps", text="Blur")
|
||||
col.prop(settings, "cavity_factor", text="Factor")
|
||||
col.prop(settings, "cavity_blur_steps", text="Blur")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(sculpt, "use_automasking_custom_cavity_curve", text="Custom Curve")
|
||||
col.prop(settings, "use_automasking_custom_cavity_curve", text="Custom Curve")
|
||||
|
||||
if sculpt.use_automasking_custom_cavity_curve:
|
||||
col.template_curve_mapping(sculpt, "automasking_cavity_curve", brush=True)
|
||||
if settings.use_automasking_custom_cavity_curve:
|
||||
col.template_curve_mapping(settings, "cavity_curve", brush=True)
|
||||
|
||||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(sculpt, "use_automasking_view_normal", text="View Normal")
|
||||
col.prop(settings, "use_automasking_view_normal", text="View Normal")
|
||||
|
||||
if sculpt.use_automasking_view_normal:
|
||||
col.prop(sculpt, "use_automasking_view_occlusion", text="Occlusion")
|
||||
if settings.use_automasking_view_normal:
|
||||
col.prop(settings, "use_automasking_view_occlusion", text="Occlusion")
|
||||
subcol = col.column(align=True)
|
||||
subcol.active = not sculpt.use_automasking_view_occlusion
|
||||
subcol.prop(sculpt, "automasking_view_normal_limit", text="Limit")
|
||||
subcol.prop(sculpt, "automasking_view_normal_falloff", text="Falloff")
|
||||
subcol.active = not settings.use_automasking_view_occlusion
|
||||
subcol.prop(settings, "view_normal_limit", text="Limit")
|
||||
subcol.prop(settings, "view_normal_falloff", text="Falloff")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(sculpt, "use_automasking_start_normal", text="Area Normal")
|
||||
col.prop(settings, "use_automasking_start_normal", text="Area Normal")
|
||||
|
||||
if sculpt.use_automasking_start_normal:
|
||||
if settings.use_automasking_start_normal:
|
||||
col = layout.column(align=True)
|
||||
col.prop(sculpt, "automasking_start_normal_limit", text="Limit")
|
||||
col.prop(sculpt, "automasking_start_normal_falloff", text="Falloff")
|
||||
col.prop(settings, "start_normal_limit", text="Limit")
|
||||
col.prop(settings, "start_normal_falloff", text="Falloff")
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_context_menu(Panel):
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace blender {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 17
|
||||
#define BLENDER_FILE_SUBVERSION 18
|
||||
|
||||
/* 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
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ void BKE_paint_settings_foreach_mode(ToolSettings *ts, FunctionRef<void(Paint *p
|
|||
|
||||
void BKE_paint_cavity_curve_preset(Paint *paint, int preset);
|
||||
|
||||
void BKE_paint_mesh_automasking_settings_ensure(Paint &paint);
|
||||
|
||||
eObjectMode BKE_paint_object_mode_from_paintmode(PaintMode mode);
|
||||
bool BKE_paint_ensure_from_paintmode(Scene *sce, PaintMode mode);
|
||||
Paint *BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode);
|
||||
|
|
@ -651,7 +653,6 @@ bool BKE_paint_canvas_image_get(PaintModeSettings *settings,
|
|||
ImageUser **r_image_user);
|
||||
std::optional<StringRef> BKE_paint_canvas_uvmap_name_get(const PaintModeSettings *settings,
|
||||
Object *ob);
|
||||
void BKE_sculpt_cavity_curves_ensure(Sculpt *sd);
|
||||
CurveMapping *BKE_sculpt_default_cavity_curve();
|
||||
CurveMapping *BKE_paint_default_curve();
|
||||
|
||||
|
|
|
|||
|
|
@ -1684,6 +1684,7 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
|||
|
||||
paint = &data->paint;
|
||||
paint_init_data(*paint);
|
||||
BKE_paint_mesh_automasking_settings_ensure(*paint);
|
||||
}
|
||||
else if (reinterpret_cast<GpPaint **>(r_paint) == &ts->gp_paint) {
|
||||
GpPaint *data = MEM_new<GpPaint>(__func__);
|
||||
|
|
@ -1735,9 +1736,17 @@ void BKE_paint_brushes_ensure(Main *bmain, Paint *paint)
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_paint_mesh_automasking_settings_ensure(Paint &paint)
|
||||
{
|
||||
if (!paint.mesh_automasking_settings) {
|
||||
paint.mesh_automasking_settings = MEM_new<MeshAutomaskingSettings>(__func__);
|
||||
paint.mesh_automasking_settings->cavity_curve = BKE_sculpt_default_cavity_curve();
|
||||
paint.mesh_automasking_settings->cavity_curve_op = BKE_sculpt_default_cavity_curve();
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_paint_init(Main *bmain, Scene *sce, PaintMode mode, const bool ensure_brushes)
|
||||
{
|
||||
|
||||
BKE_paint_ensure_from_paintmode(sce, mode);
|
||||
Paint *paint = BKE_paint_get_active_from_paintmode(sce, mode);
|
||||
|
||||
|
|
@ -1748,6 +1757,10 @@ void BKE_paint_init(Main *bmain, Scene *sce, PaintMode mode, const bool ensure_b
|
|||
if (!paint->cavity_curve) {
|
||||
BKE_paint_cavity_curve_preset(paint, CURVE_PRESET_LINE);
|
||||
}
|
||||
|
||||
if (mode == PaintMode::Sculpt) {
|
||||
BKE_paint_mesh_automasking_settings_ensure(*paint);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_paint_free(Paint *paint)
|
||||
|
|
@ -1767,6 +1780,13 @@ void BKE_paint_free(Paint *paint)
|
|||
BKE_curvemapping_free(paint->unified_paint_settings.curve_rand_hue);
|
||||
BKE_curvemapping_free(paint->unified_paint_settings.curve_rand_saturation);
|
||||
BKE_curvemapping_free(paint->unified_paint_settings.curve_rand_value);
|
||||
|
||||
if (paint->mesh_automasking_settings) {
|
||||
BKE_curvemapping_free(paint->mesh_automasking_settings->cavity_curve);
|
||||
BKE_curvemapping_free(paint->mesh_automasking_settings->cavity_curve_op);
|
||||
MEM_delete(paint->mesh_automasking_settings);
|
||||
}
|
||||
|
||||
MEM_SAFE_DELETE(paint->runtime);
|
||||
}
|
||||
|
||||
|
|
@ -1803,6 +1823,15 @@ void BKE_paint_copy(const Paint *src, Paint *dst, const int flag)
|
|||
id_us_plus(id_cast<ID *>(dst->palette));
|
||||
}
|
||||
|
||||
if (src->mesh_automasking_settings) {
|
||||
dst->mesh_automasking_settings = MEM_new<MeshAutomaskingSettings>(
|
||||
__func__, dna::shallow_copy(*src->mesh_automasking_settings));
|
||||
dst->mesh_automasking_settings->cavity_curve = BKE_curvemapping_copy(
|
||||
src->mesh_automasking_settings->cavity_curve);
|
||||
dst->mesh_automasking_settings->cavity_curve_op = BKE_curvemapping_copy(
|
||||
src->mesh_automasking_settings->cavity_curve_op);
|
||||
}
|
||||
|
||||
dst->runtime = MEM_new<bke::PaintRuntime>(__func__);
|
||||
if (src->runtime) {
|
||||
dst->runtime->paint_mode = src->runtime->paint_mode;
|
||||
|
|
@ -1944,6 +1973,18 @@ void BKE_paint_blend_write(BlendWriter *writer, Paint *paint)
|
|||
if (paint->unified_paint_settings.curve_rand_value) {
|
||||
BKE_curvemapping_blend_write(writer, paint->unified_paint_settings.curve_rand_value);
|
||||
}
|
||||
|
||||
if (paint->mesh_automasking_settings) {
|
||||
writer->write_struct(paint->mesh_automasking_settings);
|
||||
MeshAutomaskingSettings &automasking_settings = *paint->mesh_automasking_settings;
|
||||
if (automasking_settings.cavity_curve) {
|
||||
BKE_curvemapping_blend_write(writer, automasking_settings.cavity_curve);
|
||||
}
|
||||
|
||||
if (automasking_settings.cavity_curve_op) {
|
||||
BKE_curvemapping_blend_write(writer, automasking_settings.cavity_curve_op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Paint *paint)
|
||||
|
|
@ -2000,6 +2041,23 @@ void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Pain
|
|||
BKE_curvemapping_init(ups->curve_rand_value);
|
||||
}
|
||||
|
||||
BLO_read_struct(reader, MeshAutomaskingSettings, &paint->mesh_automasking_settings);
|
||||
if (paint->mesh_automasking_settings) {
|
||||
MeshAutomaskingSettings &automasking_settings = *paint->mesh_automasking_settings;
|
||||
|
||||
BLO_read_struct(reader, CurveMapping, &automasking_settings.cavity_curve);
|
||||
if (automasking_settings.cavity_curve) {
|
||||
BKE_curvemapping_blend_read(reader, automasking_settings.cavity_curve);
|
||||
BKE_curvemapping_init(automasking_settings.cavity_curve);
|
||||
}
|
||||
|
||||
BLO_read_struct(reader, CurveMapping, &automasking_settings.cavity_curve_op);
|
||||
if (automasking_settings.cavity_curve_op) {
|
||||
BKE_curvemapping_blend_read(reader, automasking_settings.cavity_curve_op);
|
||||
BKE_curvemapping_init(automasking_settings.cavity_curve_op);
|
||||
}
|
||||
}
|
||||
|
||||
paint->runtime = MEM_new<bke::PaintRuntime>(__func__);
|
||||
|
||||
paint_runtime_init(scene->toolsettings, paint);
|
||||
|
|
@ -2746,21 +2804,9 @@ void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_sculpt_cavity_curves_ensure(Sculpt *sd)
|
||||
{
|
||||
if (!sd->automasking_cavity_curve) {
|
||||
sd->automasking_cavity_curve = BKE_sculpt_default_cavity_curve();
|
||||
}
|
||||
|
||||
if (!sd->automasking_cavity_curve_op) {
|
||||
sd->automasking_cavity_curve_op = BKE_sculpt_default_cavity_curve();
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_sculpt_toolsettings_data_ensure(Main *bmain, Scene *scene)
|
||||
{
|
||||
BKE_paint_ensure(scene->toolsettings, reinterpret_cast<Paint **>(&scene->toolsettings->sculpt));
|
||||
BKE_paint_brushes_ensure(bmain, &scene->toolsettings->sculpt->paint);
|
||||
BKE_paint_init(bmain, scene, PaintMode::Sculpt, true);
|
||||
|
||||
Sculpt *sd = scene->toolsettings->sculpt;
|
||||
|
||||
|
|
@ -2770,13 +2816,6 @@ void BKE_sculpt_toolsettings_data_ensure(Main *bmain, Scene *scene)
|
|||
* reasons. Don't add more checks here, do it properly
|
||||
* in blenloader.
|
||||
*/
|
||||
if (sd->automasking_start_normal_limit == 0.0f) {
|
||||
sd->automasking_start_normal_limit = defaults.automasking_start_normal_limit;
|
||||
sd->automasking_start_normal_falloff = defaults.automasking_start_normal_falloff;
|
||||
|
||||
sd->automasking_view_normal_limit = defaults.automasking_view_normal_limit;
|
||||
sd->automasking_view_normal_falloff = defaults.automasking_view_normal_limit;
|
||||
}
|
||||
|
||||
if (sd->detail_percent == 0.0f) {
|
||||
sd->detail_percent = defaults.detail_percent;
|
||||
|
|
@ -2798,10 +2837,6 @@ void BKE_sculpt_toolsettings_data_ensure(Main *bmain, Scene *scene)
|
|||
if (!sd->paint.tile_offset[2]) {
|
||||
sd->paint.tile_offset[2] = 1.0f;
|
||||
}
|
||||
|
||||
if (!sd->automasking_cavity_curve || !sd->automasking_cavity_curve_op) {
|
||||
BKE_sculpt_cavity_curves_ensure(sd);
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_sculpt_object_deformed(Object *object, const bool for_construction)
|
||||
|
|
|
|||
|
|
@ -1407,8 +1407,6 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
sce->toolsettings->sculpt->automasking_cavity_curve_op);
|
||||
BKE_curvemapping_init(sce->toolsettings->sculpt->automasking_cavity_curve_op);
|
||||
}
|
||||
|
||||
BKE_sculpt_cavity_curves_ensure(sce->toolsettings->sculpt);
|
||||
}
|
||||
|
||||
/* Relink grease pencil interpolation curves. */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "BLI_sys_types.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_colortools.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
|
@ -406,6 +407,27 @@ void blo_do_versions_520(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 502, 18)) {
|
||||
for (Scene &scene : bmain->scenes) {
|
||||
if (scene.toolsettings->sculpt) {
|
||||
Sculpt &sculpt = *scene.toolsettings->sculpt;
|
||||
MeshAutomaskingSettings *settings = MEM_new<MeshAutomaskingSettings>(__func__);
|
||||
settings->flags = sculpt.automasking_flags;
|
||||
settings->boundary_edges_propagation_steps =
|
||||
sculpt.automasking_boundary_edges_propagation_steps;
|
||||
settings->cavity_blur_steps = sculpt.automasking_cavity_blur_steps;
|
||||
settings->cavity_factor = sculpt.automasking_cavity_factor;
|
||||
settings->start_normal_limit = sculpt.automasking_start_normal_limit;
|
||||
settings->start_normal_falloff = sculpt.automasking_start_normal_falloff;
|
||||
settings->view_normal_limit = sculpt.automasking_view_normal_limit;
|
||||
settings->view_normal_falloff = sculpt.automasking_view_normal_falloff;
|
||||
settings->cavity_curve = BKE_curvemapping_copy(sculpt.automasking_cavity_curve);
|
||||
settings->cavity_curve_op = BKE_curvemapping_copy(sculpt.automasking_cavity_curve_op);
|
||||
|
||||
scene.toolsettings->sculpt->paint.mesh_automasking_settings = settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
|
|
|
|||
|
|
@ -3251,8 +3251,8 @@ static void do_brush_action(const Depsgraph &depsgraph,
|
|||
return;
|
||||
}
|
||||
|
||||
if (auto_mask::is_enabled(sd, ob, &brush)) {
|
||||
auto_mask::Cache &cache = auto_mask::stroke_cache_ensure(depsgraph, sd, &brush, ob);
|
||||
if (auto_mask::is_enabled(sd.paint, ob, &brush)) {
|
||||
auto_mask::Cache &cache = auto_mask::stroke_cache_ensure(depsgraph, sd.paint, &brush, ob);
|
||||
if (cache.settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
|
||||
cache.calc_cavity_factor(depsgraph, ob, node_mask);
|
||||
}
|
||||
|
|
@ -4305,7 +4305,7 @@ static bool sculpt_needs_connectivity_info(const Sculpt &sd,
|
|||
{
|
||||
SculptSession &ss = *object.runtime->sculpt_session;
|
||||
const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object);
|
||||
if (pbvh && auto_mask::is_enabled(sd, object, &brush)) {
|
||||
if (pbvh && auto_mask::is_enabled(sd.paint, object, &brush)) {
|
||||
return true;
|
||||
}
|
||||
return ((ss.cache && ss.cache->toggle_settings.alt_smooth) ||
|
||||
|
|
|
|||
|
|
@ -108,20 +108,20 @@ const Cache *active_cache_get(const SculptSession &ss);
|
|||
* data is also stored at the vertex level prior to the stroke starting.
|
||||
*/
|
||||
std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
const Brush *brush,
|
||||
Object &ob);
|
||||
|
||||
/** If the FilterCache#automask cache doesn't exist, create and return it. */
|
||||
Cache &filter_cache_ensure(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob);
|
||||
Cache &filter_cache_ensure(const Depsgraph &depsgraph, const Paint &paint, Object &ob);
|
||||
/** If the StrokeCache#automask cache doesn't exist, create and return it. */
|
||||
Cache &stroke_cache_ensure(const Depsgraph &depsgraph,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
const Brush *brush,
|
||||
Object &ob);
|
||||
|
||||
bool mode_enabled(const Sculpt &sd, const Brush *br, eAutomasking_flag mode);
|
||||
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br);
|
||||
bool is_enabled(const Paint &paint, const Object &object, const Brush *br);
|
||||
|
||||
/**
|
||||
* Calculate all auto-masking influence on each vertex.
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ const Cache *active_cache_get(const SculptSession &ss)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool mode_enabled(const Sculpt &sd, const Brush *br, const eAutomasking_flag mode)
|
||||
static bool mode_enabled(const Paint &paint, const Brush *br, const eAutomasking_flag mode)
|
||||
{
|
||||
int automasking = sd.automasking_flags;
|
||||
int automasking = paint.mesh_automasking_settings->flags;
|
||||
|
||||
if (br) {
|
||||
automasking |= br->automasking_flags;
|
||||
|
|
@ -63,40 +63,40 @@ bool mode_enabled(const Sculpt &sd, const Brush *br, const eAutomasking_flag mod
|
|||
return eAutomasking_flag(automasking) & mode;
|
||||
}
|
||||
|
||||
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
|
||||
bool is_enabled(const Paint &paint, const Object &object, const Brush *br)
|
||||
{
|
||||
if (object.runtime->sculpt_session && br && dyntopo::stroke_is_dyntopo(object, *br)) {
|
||||
return false;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
return true;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
return true;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
return true;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
return true;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
|
||||
return true;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
||||
return true;
|
||||
}
|
||||
if (mode_enabled(sd, br, BRUSH_AUTOMASKING_CAVITY_ALL)) {
|
||||
if (mode_enabled(paint, br, BRUSH_AUTOMASKING_CAVITY_ALL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int calc_effective_bits(const Sculpt &sd, const Brush *brush)
|
||||
static int calc_effective_bits(const Paint &paint, const Brush *brush)
|
||||
{
|
||||
if (brush) {
|
||||
int flags = sd.automasking_flags | brush->automasking_flags;
|
||||
int flags = paint.mesh_automasking_settings->flags | brush->automasking_flags;
|
||||
|
||||
/* Check if we are using brush cavity settings. */
|
||||
if (brush->automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
|
||||
|
|
@ -104,15 +104,15 @@ static int calc_effective_bits(const Sculpt &sd, const Brush *brush)
|
|||
BRUSH_AUTOMASKING_CAVITY_NORMAL);
|
||||
flags |= brush->automasking_flags;
|
||||
}
|
||||
else if (sd.automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
|
||||
else if (paint.mesh_automasking_settings->flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
|
||||
flags &= ~(BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE |
|
||||
BRUSH_AUTOMASKING_CAVITY_NORMAL);
|
||||
flags |= sd.automasking_flags;
|
||||
flags |= paint.mesh_automasking_settings->flags;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
return sd.automasking_flags;
|
||||
return paint.mesh_automasking_settings->flags;
|
||||
}
|
||||
|
||||
static float normal_calc(const float3 &compare_normal,
|
||||
|
|
@ -162,18 +162,18 @@ static bool is_constrained_by_radius(const Brush *br)
|
|||
|
||||
/* Fetch the propogation_steps value, preferring the brush level value over the global sculpt tool
|
||||
* value. */
|
||||
static int boundary_propagation_steps(const Sculpt &sd, const Brush *brush)
|
||||
static int boundary_propagation_steps(const Paint &paint, const Brush *brush)
|
||||
{
|
||||
return brush && brush->automasking_flags &
|
||||
(BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) ?
|
||||
brush->automasking_boundary_edges_propagation_steps :
|
||||
sd.automasking_boundary_edges_propagation_steps;
|
||||
paint.mesh_automasking_settings->boundary_edges_propagation_steps;
|
||||
}
|
||||
|
||||
/* Determine if the given automasking settings require values to be precomputed and cached. */
|
||||
static bool needs_factors_cache(const Sculpt &sd, const Brush *brush)
|
||||
static bool needs_factors_cache(const Paint &paint, const Brush *brush)
|
||||
{
|
||||
const int automasking_flags = calc_effective_bits(sd, brush);
|
||||
const int automasking_flags = calc_effective_bits(paint, brush);
|
||||
|
||||
if (automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY && brush && is_constrained_by_radius(brush)) {
|
||||
return true;
|
||||
|
|
@ -182,7 +182,7 @@ static bool needs_factors_cache(const Sculpt &sd, const Brush *brush)
|
|||
if (automasking_flags &
|
||||
(BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS))
|
||||
{
|
||||
return boundary_propagation_steps(sd, brush) != 1;
|
||||
return boundary_propagation_steps(paint, brush) != 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1111,13 +1111,13 @@ void calc_vert_factors(const Depsgraph &depsgraph,
|
|||
}
|
||||
|
||||
static void fill_topology_automasking_factors_mesh(const Depsgraph &depsgraph,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
Object &ob,
|
||||
const Span<float3> vert_positions,
|
||||
MutableSpan<float> factors)
|
||||
{
|
||||
SculptSession &ss = *ob.runtime->sculpt_session;
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
const Brush *brush = BKE_paint_brush_for_read(&paint);
|
||||
const Mesh &mesh = *id_cast<const Mesh *>(ob.data);
|
||||
const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
|
||||
|
||||
|
|
@ -1148,14 +1148,14 @@ static void fill_topology_automasking_factors_mesh(const Depsgraph &depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
static void fill_topology_automasking_factors_grids(const Sculpt &sd,
|
||||
static void fill_topology_automasking_factors_grids(const Paint &paint,
|
||||
Object &ob,
|
||||
const SubdivCCG &subdiv_ccg,
|
||||
MutableSpan<float> factors)
|
||||
|
||||
{
|
||||
SculptSession &ss = *ob.runtime->sculpt_session;
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
const Brush *brush = BKE_paint_brush_for_read(&paint);
|
||||
|
||||
const float radius = ss.cache ? ss.cache->radius : std::numeric_limits<float>::max();
|
||||
const int active_vert = ss.active_vert_index();
|
||||
|
|
@ -1191,13 +1191,13 @@ static void fill_topology_automasking_factors_grids(const Sculpt &sd,
|
|||
}
|
||||
}
|
||||
|
||||
static void fill_topology_automasking_factors_bmesh(const Sculpt &sd,
|
||||
static void fill_topology_automasking_factors_bmesh(const Paint &paint,
|
||||
Object &ob,
|
||||
BMesh &bm,
|
||||
MutableSpan<float> factors)
|
||||
{
|
||||
SculptSession &ss = *ob.runtime->sculpt_session;
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
const Brush *brush = BKE_paint_brush_for_read(&paint);
|
||||
|
||||
const float radius = ss.cache ? ss.cache->radius : std::numeric_limits<float>::max();
|
||||
BMVert *active_vert = std::get<BMVert *>(ss.active_vert());
|
||||
|
|
@ -1228,7 +1228,7 @@ static void fill_topology_automasking_factors_bmesh(const Sculpt &sd,
|
|||
}
|
||||
|
||||
static void fill_topology_automasking_factors(const Depsgraph &depsgraph,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
Object &ob,
|
||||
MutableSpan<float> factors)
|
||||
{
|
||||
|
|
@ -1245,22 +1245,22 @@ static void fill_topology_automasking_factors(const Depsgraph &depsgraph,
|
|||
switch (bke::object::pbvh_get(ob)->type()) {
|
||||
case bke::pbvh::Type::Mesh:
|
||||
fill_topology_automasking_factors_mesh(
|
||||
depsgraph, sd, ob, bke::pbvh::vert_positions_eval(depsgraph, ob), factors);
|
||||
depsgraph, paint, ob, bke::pbvh::vert_positions_eval(depsgraph, ob), factors);
|
||||
break;
|
||||
case bke::pbvh::Type::Grids:
|
||||
fill_topology_automasking_factors_grids(sd, ob, *ss.subdiv_ccg, factors);
|
||||
fill_topology_automasking_factors_grids(paint, ob, *ss.subdiv_ccg, factors);
|
||||
break;
|
||||
case bke::pbvh::Type::BMesh:
|
||||
fill_topology_automasking_factors_bmesh(sd, ob, *ss.bm, factors);
|
||||
fill_topology_automasking_factors_bmesh(paint, ob, *ss.bm, factors);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_face_sets_masking(const Sculpt &sd, Object &ob, MutableSpan<float> factors)
|
||||
static void init_face_sets_masking(const Paint &paint, Object &ob, MutableSpan<float> factors)
|
||||
{
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
const Brush *brush = BKE_paint_brush_for_read(&paint);
|
||||
|
||||
if (!is_enabled(sd, ob, brush)) {
|
||||
if (!is_enabled(paint, ob, brush)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1553,10 +1553,10 @@ static void init_boundary_masking(Object &object,
|
|||
/* Updates the cached values, preferring brush settings over tool-level settings. */
|
||||
static void cache_settings_update(Cache &automasking,
|
||||
Object &object,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
const Brush *brush)
|
||||
{
|
||||
automasking.settings.flags = calc_effective_bits(sd, brush);
|
||||
automasking.settings.flags = calc_effective_bits(paint, brush);
|
||||
automasking.settings.initial_face_set = face_set::active_face_set_get(object);
|
||||
|
||||
if (brush && (brush->automasking_flags & BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
||||
|
|
@ -1564,8 +1564,9 @@ static void cache_settings_update(Cache &automasking,
|
|||
automasking.settings.view_normal_falloff = brush->automasking_view_normal_falloff;
|
||||
}
|
||||
else {
|
||||
automasking.settings.view_normal_limit = sd.automasking_view_normal_limit;
|
||||
automasking.settings.view_normal_falloff = sd.automasking_view_normal_falloff;
|
||||
automasking.settings.view_normal_limit = paint.mesh_automasking_settings->view_normal_limit;
|
||||
automasking.settings.view_normal_falloff =
|
||||
paint.mesh_automasking_settings->view_normal_falloff;
|
||||
}
|
||||
|
||||
if (brush && (brush->automasking_flags & BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
|
||||
|
|
@ -1573,8 +1574,9 @@ static void cache_settings_update(Cache &automasking,
|
|||
automasking.settings.start_normal_falloff = brush->automasking_start_normal_falloff;
|
||||
}
|
||||
else {
|
||||
automasking.settings.start_normal_limit = sd.automasking_start_normal_limit;
|
||||
automasking.settings.start_normal_falloff = sd.automasking_start_normal_falloff;
|
||||
automasking.settings.start_normal_limit = paint.mesh_automasking_settings->start_normal_limit;
|
||||
automasking.settings.start_normal_falloff =
|
||||
paint.mesh_automasking_settings->start_normal_falloff;
|
||||
}
|
||||
|
||||
if (brush && (brush->automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL)) {
|
||||
|
|
@ -1583,9 +1585,9 @@ static void cache_settings_update(Cache &automasking,
|
|||
automasking.settings.cavity_blur_steps = brush->automasking_cavity_blur_steps;
|
||||
}
|
||||
else {
|
||||
automasking.settings.cavity_curve = sd.automasking_cavity_curve;
|
||||
automasking.settings.cavity_factor = sd.automasking_cavity_factor;
|
||||
automasking.settings.cavity_blur_steps = sd.automasking_cavity_blur_steps;
|
||||
automasking.settings.cavity_curve = paint.mesh_automasking_settings->cavity_curve;
|
||||
automasking.settings.cavity_factor = paint.mesh_automasking_settings->cavity_factor;
|
||||
automasking.settings.cavity_blur_steps = paint.mesh_automasking_settings->cavity_blur_steps;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1665,21 +1667,21 @@ static void normal_occlusion_automasking_fill(const Depsgraph &depsgraph,
|
|||
}
|
||||
|
||||
std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
const Brush *brush,
|
||||
Object &ob)
|
||||
{
|
||||
SculptSession &ss = *ob.runtime->sculpt_session;
|
||||
|
||||
if (!is_enabled(sd, ob, brush)) {
|
||||
if (!is_enabled(paint, ob, brush)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Cache> automasking = std::make_unique<Cache>();
|
||||
cache_settings_update(*automasking, ob, sd, brush);
|
||||
cache_settings_update(*automasking, ob, paint, brush);
|
||||
boundary::ensure_boundary_info(ob);
|
||||
|
||||
int mode = calc_effective_bits(sd, brush);
|
||||
int mode = calc_effective_bits(paint, brush);
|
||||
|
||||
vert_random_access_ensure(ob);
|
||||
if (mode & BRUSH_AUTOMASKING_TOPOLOGY && ss.active_vert_index() != -1) {
|
||||
|
|
@ -1707,19 +1709,19 @@ std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
|
|||
}
|
||||
|
||||
if (mode & BRUSH_AUTOMASKING_CAVITY_ALL) {
|
||||
if (mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_USE_CURVE)) {
|
||||
if (mode_enabled(paint, brush, BRUSH_AUTOMASKING_CAVITY_USE_CURVE)) {
|
||||
if (brush) {
|
||||
BKE_curvemapping_init(brush->automasking_cavity_curve);
|
||||
}
|
||||
|
||||
BKE_curvemapping_init(sd.automasking_cavity_curve);
|
||||
BKE_curvemapping_init(paint.mesh_automasking_settings->cavity_curve);
|
||||
}
|
||||
automasking->cavity_factor = Array<float>(verts_num, -1.0f);
|
||||
}
|
||||
|
||||
/* Avoid precomputing data on the vertex level if the current auto-masking modes do not require
|
||||
* it to function. */
|
||||
if (!needs_factors_cache(sd, brush)) {
|
||||
if (!needs_factors_cache(paint, brush)) {
|
||||
return automasking;
|
||||
}
|
||||
|
||||
|
|
@ -1730,30 +1732,30 @@ std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
|
|||
MutableSpan<float> factors = automasking->factor;
|
||||
|
||||
/* Additive modes. */
|
||||
if (mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
if (mode_enabled(paint, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
vert_random_access_ensure(ob);
|
||||
|
||||
automasking->settings.topology_use_brush_limit = is_constrained_by_radius(brush);
|
||||
fill_topology_automasking_factors(depsgraph, sd, ob, factors);
|
||||
fill_topology_automasking_factors(depsgraph, paint, ob, factors);
|
||||
}
|
||||
|
||||
if (mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
if (mode_enabled(paint, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
vert_random_access_ensure(ob);
|
||||
init_face_sets_masking(sd, ob, factors);
|
||||
init_face_sets_masking(paint, ob, factors);
|
||||
}
|
||||
|
||||
const int steps = boundary_propagation_steps(sd, brush);
|
||||
if (mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
const int steps = boundary_propagation_steps(paint, brush);
|
||||
if (mode_enabled(paint, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
vert_random_access_ensure(ob);
|
||||
init_boundary_masking(ob, depsgraph, BoundaryAutomaskMode::Edges, steps, factors);
|
||||
}
|
||||
if (mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
if (mode_enabled(paint, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
vert_random_access_ensure(ob);
|
||||
init_boundary_masking(ob, depsgraph, BoundaryAutomaskMode::FaceSets, steps, factors);
|
||||
}
|
||||
|
||||
/* Subtractive modes. */
|
||||
int normal_bits = calc_effective_bits(sd, brush) &
|
||||
int normal_bits = calc_effective_bits(paint, brush) &
|
||||
(BRUSH_AUTOMASKING_VIEW_NORMAL | BRUSH_AUTOMASKING_VIEW_OCCLUSION);
|
||||
|
||||
if (normal_bits) {
|
||||
|
|
@ -1764,28 +1766,29 @@ std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
|
|||
return automasking;
|
||||
}
|
||||
|
||||
Cache &filter_cache_ensure(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
|
||||
Cache &filter_cache_ensure(const Depsgraph &depsgraph, const Paint &paint, Object &ob)
|
||||
{
|
||||
BLI_assert(is_enabled(sd, ob, nullptr));
|
||||
BLI_assert(is_enabled(paint, ob, nullptr));
|
||||
if (ob.runtime->sculpt_session->filter_cache->automasking) {
|
||||
return *ob.runtime->sculpt_session->filter_cache->automasking;
|
||||
}
|
||||
|
||||
ob.runtime->sculpt_session->filter_cache->automasking = cache_init(depsgraph, sd, nullptr, ob);
|
||||
ob.runtime->sculpt_session->filter_cache->automasking = cache_init(
|
||||
depsgraph, paint, nullptr, ob);
|
||||
return *ob.runtime->sculpt_session->filter_cache->automasking;
|
||||
}
|
||||
|
||||
Cache &stroke_cache_ensure(const Depsgraph &depsgraph,
|
||||
const Sculpt &sd,
|
||||
const Paint &paint,
|
||||
const Brush *brush,
|
||||
Object &ob)
|
||||
{
|
||||
BLI_assert(is_enabled(sd, ob, brush));
|
||||
BLI_assert(is_enabled(paint, ob, brush));
|
||||
if (ob.runtime->sculpt_session->cache->automasking) {
|
||||
return *ob.runtime->sculpt_session->cache->automasking;
|
||||
}
|
||||
|
||||
ob.runtime->sculpt_session->cache->automasking = cache_init(depsgraph, sd, brush, ob);
|
||||
ob.runtime->sculpt_session->cache->automasking = cache_init(depsgraph, paint, brush, ob);
|
||||
return *ob.runtime->sculpt_session->cache->automasking;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2327,7 +2327,7 @@ static wmOperatorStatus sculpt_cloth_filter_modal(bContext *C,
|
|||
|
||||
const IndexMask &node_mask = ss.filter_cache->node_mask;
|
||||
|
||||
if (auto_mask::is_enabled(sd, object, nullptr) && ss.filter_cache->automasking &&
|
||||
if (auto_mask::is_enabled(sd.paint, object, nullptr) && ss.filter_cache->automasking &&
|
||||
ss.filter_cache->automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL)
|
||||
{
|
||||
ss.filter_cache->automasking->calc_cavity_factor(*depsgraph, object, node_mask);
|
||||
|
|
@ -2461,8 +2461,8 @@ static wmOperatorStatus sculpt_cloth_filter_invoke(bContext *C,
|
|||
RNA_float_get(op->ptr, "area_normal_radius"),
|
||||
RNA_float_get(op->ptr, "strength"));
|
||||
|
||||
if (auto_mask::is_enabled(sd, ob, nullptr)) {
|
||||
auto_mask::filter_cache_ensure(*depsgraph, sd, ob);
|
||||
if (auto_mask::is_enabled(sd.paint, ob, nullptr)) {
|
||||
auto_mask::filter_cache_ensure(*depsgraph, sd.paint, ob);
|
||||
}
|
||||
|
||||
const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
|
||||
|
|
|
|||
|
|
@ -434,7 +434,7 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
|
|||
}
|
||||
|
||||
const IndexMask &node_mask = ss.filter_cache->node_mask;
|
||||
if (auto_mask::is_enabled(sd, ob, nullptr) && ss.filter_cache->automasking &&
|
||||
if (auto_mask::is_enabled(sd.paint, ob, nullptr) && ss.filter_cache->automasking &&
|
||||
ss.filter_cache->automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL)
|
||||
{
|
||||
ss.filter_cache->automasking->calc_cavity_factor(depsgraph, ob, node_mask);
|
||||
|
|
@ -547,7 +547,7 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
|||
RNA_int_get_array(op->ptr, "start_mouse", mval);
|
||||
float mval_fl[2] = {float(mval[0]), float(mval[1])};
|
||||
|
||||
const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
|
||||
const bool use_automasking = auto_mask::is_enabled(sd.paint, ob, nullptr);
|
||||
if (use_automasking) {
|
||||
if (v3d) {
|
||||
/* Update the active face set manually as the paint cursor is not enabled when using the Mesh
|
||||
|
|
@ -583,8 +583,8 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
|||
const SculptSession &ss = *ob.runtime->sculpt_session;
|
||||
filter::Cache *filter_cache = ss.filter_cache;
|
||||
filter_cache->active_face_set = face_set_none_id;
|
||||
if (auto_mask::is_enabled(sd, ob, nullptr)) {
|
||||
auto_mask::filter_cache_ensure(*depsgraph, sd, ob);
|
||||
if (auto_mask::is_enabled(sd.paint, ob, nullptr)) {
|
||||
auto_mask::filter_cache_ensure(*depsgraph, sd.paint, ob);
|
||||
}
|
||||
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
|
|
|
|||
|
|
@ -2236,7 +2236,7 @@ static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op, bool is_replay
|
|||
vert_random_access_ensure(ob);
|
||||
|
||||
const IndexMask &node_mask = ss.filter_cache->node_mask;
|
||||
if (auto_mask::is_enabled(sd, ob, nullptr) && ss.filter_cache->automasking &&
|
||||
if (auto_mask::is_enabled(sd.paint, ob, nullptr) && ss.filter_cache->automasking &&
|
||||
ss.filter_cache->automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL)
|
||||
{
|
||||
ss.filter_cache->automasking->calc_cavity_factor(depsgraph, ob, node_mask);
|
||||
|
|
@ -2501,7 +2501,7 @@ static wmOperatorStatus sculpt_mesh_filter_start(bContext *C, wmOperator *op)
|
|||
RNA_int_get_array(op->ptr, "start_mouse", mval);
|
||||
|
||||
const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
|
||||
const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
|
||||
const bool use_automasking = auto_mask::is_enabled(sd.paint, ob, nullptr);
|
||||
const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
|
||||
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, &ob, false);
|
||||
|
|
@ -2550,8 +2550,8 @@ static wmOperatorStatus sculpt_mesh_filter_start(bContext *C, wmOperator *op)
|
|||
|
||||
filter::Cache *filter_cache = ss.filter_cache;
|
||||
filter_cache->active_face_set = face_set_none_id;
|
||||
if (auto_mask::is_enabled(sd, ob, nullptr)) {
|
||||
auto_mask::filter_cache_ensure(*depsgraph, sd, ob);
|
||||
if (auto_mask::is_enabled(sd.paint, ob, nullptr)) {
|
||||
auto_mask::filter_cache_ensure(*depsgraph, sd.paint, ob);
|
||||
}
|
||||
|
||||
sculpt_filter_specific_init(*depsgraph, filter_type, op, ob);
|
||||
|
|
|
|||
|
|
@ -1104,6 +1104,7 @@ static wmOperatorStatus mask_from_cavity_exec(bContext *C, wmOperator *op)
|
|||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Object &ob = *CTX_data_active_object(C);
|
||||
const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
|
||||
const Paint &paint = sd.paint;
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
|
|
@ -1129,40 +1130,49 @@ static wmOperatorStatus mask_from_cavity_exec(bContext *C, wmOperator *op)
|
|||
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
|
||||
|
||||
/* Set up automasking settings. */
|
||||
Sculpt scene_copy = dna::shallow_copy(sd);
|
||||
Paint scene_copy = dna::shallow_copy(sd.paint);
|
||||
/* We don't do a deep copy of the automasking settings, we simply need a new one so that the
|
||||
* canonical pointer isn't overwritten. */
|
||||
MeshAutomaskingSettings automasking_settings;
|
||||
scene_copy.mesh_automasking_settings = &automasking_settings;
|
||||
|
||||
/* TODO: This pattern of recreating the scene / brush and using them as the "settings" is weak
|
||||
* and can cause hard to find bugs due to modifying actual data. This should be refactored to
|
||||
* take in a options struct */
|
||||
MaskSettingsSource src = MaskSettingsSource(RNA_enum_get(op->ptr, "settings_source"));
|
||||
switch (src) {
|
||||
case MaskSettingsSource::Operator:
|
||||
if (RNA_boolean_get(op->ptr, "invert")) {
|
||||
scene_copy.automasking_flags = BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
scene_copy.mesh_automasking_settings->flags = BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
}
|
||||
else {
|
||||
scene_copy.automasking_flags = BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
scene_copy.mesh_automasking_settings->flags = BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
}
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "use_curve")) {
|
||||
scene_copy.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
|
||||
scene_copy.mesh_automasking_settings->flags |= BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
|
||||
}
|
||||
|
||||
scene_copy.automasking_cavity_blur_steps = RNA_int_get(op->ptr, "blur_steps");
|
||||
scene_copy.automasking_cavity_factor = RNA_float_get(op->ptr, "factor");
|
||||
scene_copy.mesh_automasking_settings->cavity_blur_steps = RNA_int_get(op->ptr, "blur_steps");
|
||||
scene_copy.mesh_automasking_settings->cavity_factor = RNA_float_get(op->ptr, "factor");
|
||||
|
||||
scene_copy.automasking_cavity_curve = sd.automasking_cavity_curve_op;
|
||||
scene_copy.mesh_automasking_settings->cavity_curve =
|
||||
paint.mesh_automasking_settings->cavity_curve_op;
|
||||
break;
|
||||
case MaskSettingsSource::Brush:
|
||||
if (brush) {
|
||||
scene_copy.automasking_flags = brush->automasking_flags;
|
||||
scene_copy.automasking_cavity_factor = brush->automasking_cavity_factor;
|
||||
scene_copy.automasking_cavity_curve = brush->automasking_cavity_curve;
|
||||
scene_copy.automasking_cavity_blur_steps = brush->automasking_cavity_blur_steps;
|
||||
scene_copy.mesh_automasking_settings->flags = brush->automasking_flags;
|
||||
scene_copy.mesh_automasking_settings->cavity_factor = brush->automasking_cavity_factor;
|
||||
scene_copy.mesh_automasking_settings->cavity_curve = brush->automasking_cavity_curve;
|
||||
scene_copy.mesh_automasking_settings->cavity_blur_steps =
|
||||
brush->automasking_cavity_blur_steps;
|
||||
|
||||
/* Ensure only cavity masking is enabled. */
|
||||
scene_copy.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL |
|
||||
BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
|
||||
scene_copy.mesh_automasking_settings->flags &= BRUSH_AUTOMASKING_CAVITY_ALL |
|
||||
BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
|
||||
}
|
||||
else {
|
||||
scene_copy.automasking_flags = 0;
|
||||
scene_copy.mesh_automasking_settings->flags = 0;
|
||||
BKE_report(op->reports, RPT_WARNING, "No active brush");
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
|
|
@ -1171,14 +1181,14 @@ static wmOperatorStatus mask_from_cavity_exec(bContext *C, wmOperator *op)
|
|||
break;
|
||||
case MaskSettingsSource::Scene:
|
||||
/* Ensure only cavity masking is enabled. */
|
||||
scene_copy.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL |
|
||||
BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
|
||||
scene_copy.mesh_automasking_settings->flags &= BRUSH_AUTOMASKING_CAVITY_ALL |
|
||||
BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure cavity mask is actually enabled. */
|
||||
if (!(scene_copy.automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL)) {
|
||||
scene_copy.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
if (!(scene_copy.mesh_automasking_settings->flags & BRUSH_AUTOMASKING_CAVITY_ALL)) {
|
||||
scene_copy.mesh_automasking_settings->flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
}
|
||||
|
||||
/* Create copy of brush with cleared automasking settings. */
|
||||
|
|
@ -1187,7 +1197,7 @@ static wmOperatorStatus mask_from_cavity_exec(bContext *C, wmOperator *op)
|
|||
brush_copy.sculpt_brush_type = SCULPT_BRUSH_TYPE_SMOOTH;
|
||||
brush_copy.automasking_flags = 0;
|
||||
brush_copy.automasking_boundary_edges_propagation_steps = 1;
|
||||
brush_copy.automasking_cavity_curve = scene_copy.automasking_cavity_curve;
|
||||
brush_copy.automasking_cavity_curve = scene_copy.mesh_automasking_settings->cavity_curve;
|
||||
|
||||
std::unique_ptr<auto_mask::Cache> automasking = auto_mask::cache_init(
|
||||
*depsgraph, scene_copy, &brush_copy, ob);
|
||||
|
|
@ -1332,7 +1342,7 @@ static wmOperatorStatus mask_from_boundary_exec(bContext *C, wmOperator *op)
|
|||
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
|
||||
|
||||
/* Set up automasking settings. */
|
||||
Sculpt scene_copy = dna::shallow_copy(sd);
|
||||
Paint scene_copy = dna::shallow_copy(sd.paint);
|
||||
|
||||
MaskSettingsSource src = MaskSettingsSource(RNA_enum_get(op->ptr, "settings_source"));
|
||||
switch (src) {
|
||||
|
|
@ -1341,27 +1351,27 @@ static wmOperatorStatus mask_from_boundary_exec(bContext *C, wmOperator *op)
|
|||
RNA_enum_get(op->ptr, "boundary_mode"));
|
||||
switch (boundary_mode) {
|
||||
case MaskBoundaryMode::Mesh:
|
||||
scene_copy.automasking_flags = BRUSH_AUTOMASKING_BOUNDARY_EDGES;
|
||||
scene_copy.mesh_automasking_settings->flags = BRUSH_AUTOMASKING_BOUNDARY_EDGES;
|
||||
break;
|
||||
case MaskBoundaryMode::FaceSets:
|
||||
scene_copy.automasking_flags = BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS;
|
||||
scene_copy.mesh_automasking_settings->flags = BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS;
|
||||
break;
|
||||
}
|
||||
scene_copy.automasking_boundary_edges_propagation_steps = RNA_int_get(op->ptr,
|
||||
"propagation_steps");
|
||||
scene_copy.mesh_automasking_settings->boundary_edges_propagation_steps = RNA_int_get(
|
||||
op->ptr, "propagation_steps");
|
||||
break;
|
||||
}
|
||||
case MaskSettingsSource::Brush:
|
||||
if (brush) {
|
||||
scene_copy.automasking_flags = brush->automasking_flags;
|
||||
scene_copy.automasking_boundary_edges_propagation_steps =
|
||||
scene_copy.mesh_automasking_settings->flags = brush->automasking_flags;
|
||||
scene_copy.mesh_automasking_settings->boundary_edges_propagation_steps =
|
||||
brush->automasking_boundary_edges_propagation_steps;
|
||||
|
||||
scene_copy.automasking_flags &= BRUSH_AUTOMASKING_BOUNDARY_EDGES |
|
||||
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS;
|
||||
scene_copy.mesh_automasking_settings->flags &= BRUSH_AUTOMASKING_BOUNDARY_EDGES |
|
||||
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS;
|
||||
}
|
||||
else {
|
||||
scene_copy.automasking_flags = 0;
|
||||
scene_copy.mesh_automasking_settings->flags = 0;
|
||||
BKE_report(op->reports, RPT_WARNING, "No active brush");
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
|
|
@ -1369,8 +1379,8 @@ static wmOperatorStatus mask_from_boundary_exec(bContext *C, wmOperator *op)
|
|||
|
||||
break;
|
||||
case MaskSettingsSource::Scene:
|
||||
scene_copy.automasking_flags &= BRUSH_AUTOMASKING_BOUNDARY_EDGES |
|
||||
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS;
|
||||
scene_copy.mesh_automasking_settings->flags &= BRUSH_AUTOMASKING_BOUNDARY_EDGES |
|
||||
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1180,6 +1180,25 @@ enum ePaintCanvasSource {
|
|||
PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE = 2,
|
||||
};
|
||||
|
||||
struct MeshAutomaskingSettings {
|
||||
DNA_DEFINE_CXX_METHODS(MeshAutomaskingSettings)
|
||||
|
||||
int flags = 0;
|
||||
|
||||
int boundary_edges_propagation_steps = 1;
|
||||
int cavity_blur_steps = 0;
|
||||
float cavity_factor = 0.5f;
|
||||
|
||||
float start_normal_limit = 0.34906585f; /* 20 / 180 * pi. */
|
||||
float start_normal_falloff = 0.25f;
|
||||
float view_normal_limit = 1.570796; /* 0.5 * pi. */
|
||||
float view_normal_falloff = 0.25f;
|
||||
|
||||
struct CurveMapping *cavity_curve = nullptr;
|
||||
/** For use by operators. */
|
||||
struct CurveMapping *cavity_curve_op = nullptr;
|
||||
};
|
||||
|
||||
/** Paint Tool Base. */
|
||||
struct Paint {
|
||||
DNA_DEFINE_CXX_METHODS(Paint)
|
||||
|
|
@ -1224,6 +1243,7 @@ struct Paint {
|
|||
|
||||
float tile_offset[3] = {1.0f, 1.0f, 1.0f};
|
||||
struct UnifiedPaintSettings unified_paint_settings;
|
||||
struct MeshAutomaskingSettings *mesh_automasking_settings = nullptr;
|
||||
|
||||
bke::PaintRuntime *runtime = nullptr;
|
||||
};
|
||||
|
|
@ -1461,7 +1481,8 @@ struct Sculpt {
|
|||
/** Transform tool. */
|
||||
int transform_mode = 0;
|
||||
|
||||
int automasking_flags = 0;
|
||||
/** Deprecated. \see MeshAutomaskingSettings */
|
||||
DNA_DEPRECATED int automasking_flags = 0;
|
||||
|
||||
int radial_symm_legacy[3] = {};
|
||||
|
||||
|
|
@ -1479,18 +1500,19 @@ struct Sculpt {
|
|||
float constant_detail = 3.0f;
|
||||
float detail_percent = 25;
|
||||
|
||||
int automasking_boundary_edges_propagation_steps = 1;
|
||||
int automasking_cavity_blur_steps = 0;
|
||||
float automasking_cavity_factor = 0;
|
||||
/** Deprecated. \see MeshAutomaskingSettings */
|
||||
DNA_DEPRECATED int automasking_boundary_edges_propagation_steps = 1;
|
||||
DNA_DEPRECATED int automasking_cavity_blur_steps = 0;
|
||||
DNA_DEPRECATED float automasking_cavity_factor = 0;
|
||||
|
||||
float automasking_start_normal_limit = 0.34906585f; /* 20 / 180 * pi. */
|
||||
float automasking_start_normal_falloff = 0.25f;
|
||||
float automasking_view_normal_limit = 1.570796; /* 0.5 * pi. */
|
||||
float automasking_view_normal_falloff = 0.25f;
|
||||
DNA_DEPRECATED float automasking_start_normal_limit = 0.34906585f; /* 20 / 180 * pi. */
|
||||
DNA_DEPRECATED float automasking_start_normal_falloff = 0.25f;
|
||||
DNA_DEPRECATED float automasking_view_normal_limit = 1.570796; /* 0.5 * pi. */
|
||||
DNA_DEPRECATED float automasking_view_normal_falloff = 0.25f;
|
||||
|
||||
struct CurveMapping *automasking_cavity_curve = nullptr;
|
||||
DNA_DEPRECATED struct CurveMapping *automasking_cavity_curve = nullptr;
|
||||
/** For use by operators. */
|
||||
struct CurveMapping *automasking_cavity_curve_op = nullptr;
|
||||
DNA_DEPRECATED struct CurveMapping *automasking_cavity_curve_op = nullptr;
|
||||
struct Object *gravity_object = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -481,29 +481,55 @@ static std::optional<std::string> rna_GPencilSculptGuide_path(const PointerRNA *
|
|||
return "tool_settings.gpencil_sculpt.guide";
|
||||
}
|
||||
|
||||
static void rna_Sculpt_automasking_invert_cavity_set(PointerRNA *ptr, bool val)
|
||||
static const MeshAutomaskingSettings *rna_MeshAutomaskingSettings_address_get(const Paint *paint)
|
||||
{
|
||||
Sculpt *sd = static_cast<Sculpt *>(ptr->data);
|
||||
if (!paint) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return paint->mesh_automasking_settings;
|
||||
}
|
||||
|
||||
static std::optional<std::string> rna_MeshAutomaskingSettings_path(const PointerRNA *ptr)
|
||||
{
|
||||
const Scene *scene = reinterpret_cast<Scene *>(ptr->owner_id);
|
||||
const ToolSettings *tool_settings = scene ? scene->toolsettings : nullptr;
|
||||
if (tool_settings == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (rna_MeshAutomaskingSettings_address_get(reinterpret_cast<Paint *>(tool_settings->sculpt)) ==
|
||||
ptr->data)
|
||||
{
|
||||
return "tool_settings.sculpt.mesh_automasking_settings";
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static void rna_MeshAutomaskingSettings_invert_cavity_set(PointerRNA *ptr, bool val)
|
||||
{
|
||||
MeshAutomaskingSettings *automasking_settings = static_cast<MeshAutomaskingSettings *>(
|
||||
ptr->data);
|
||||
|
||||
if (val) {
|
||||
sd->automasking_flags &= ~BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
sd->automasking_flags |= BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
automasking_settings->flags &= ~BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
automasking_settings->flags |= BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
}
|
||||
else {
|
||||
sd->automasking_flags &= ~BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
automasking_settings->flags &= ~BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_Sculpt_automasking_cavity_set(PointerRNA *ptr, bool val)
|
||||
static void rna_MeshAutomaskingSettings_cavity_set(PointerRNA *ptr, bool val)
|
||||
{
|
||||
Sculpt *sd = static_cast<Sculpt *>(ptr->data);
|
||||
MeshAutomaskingSettings *automasking_settings = static_cast<MeshAutomaskingSettings *>(
|
||||
ptr->data);
|
||||
|
||||
if (val) {
|
||||
sd->automasking_flags &= ~BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
sd->automasking_flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
automasking_settings->flags &= ~BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
automasking_settings->flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
}
|
||||
else {
|
||||
sd->automasking_flags &= ~BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
automasking_settings->flags &= ~BRUSH_AUTOMASKING_CAVITY_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -764,6 +790,11 @@ static void rna_def_paint(BlenderRNA *brna)
|
|||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_struct_type(prop, "UnifiedPaintSettings");
|
||||
RNA_def_property_ui_text(prop, "Unified Paint Settings", nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "mesh_automasking_settings", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_struct_type(prop, "MeshAutomaskingSettings");
|
||||
RNA_def_property_ui_text(prop, "Mesh Automasking Settings", nullptr);
|
||||
}
|
||||
|
||||
static void rna_def_unified_paint_settings(BlenderRNA *brna)
|
||||
|
|
@ -970,6 +1001,101 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
|
||||
}
|
||||
|
||||
static void rna_def_mesh_automasking_settings(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "MeshAutomaskingSettings", nullptr);
|
||||
RNA_def_struct_path_func(srna, "rna_MeshAutomaskingSettings_path");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Automasking Settings", "Automasking settings for mesh painting & sculpting.");
|
||||
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
|
||||
|
||||
const EnumPropertyItem *entry = rna_enum_shared_automasking_flag_items;
|
||||
do {
|
||||
prop = RNA_def_property(srna, entry->identifier, PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flags", entry->value);
|
||||
RNA_def_property_ui_text(prop, entry->name, entry->description);
|
||||
|
||||
if (entry->value == BRUSH_AUTOMASKING_CAVITY_NORMAL) {
|
||||
RNA_def_property_boolean_funcs(prop, nullptr, "rna_MeshAutomaskingSettings_cavity_set");
|
||||
}
|
||||
else if (entry->value == BRUSH_AUTOMASKING_CAVITY_INVERTED) {
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, nullptr, "rna_MeshAutomaskingSettings_invert_cavity_set");
|
||||
}
|
||||
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
} while ((++entry)->identifier);
|
||||
|
||||
prop = RNA_def_property(srna, "boundary_edges_propagation_steps", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "boundary_edges_propagation_steps");
|
||||
RNA_def_property_range(prop, 1, AUTOMASKING_BOUNDARY_EDGES_MAX_PROPAGATION_STEPS);
|
||||
RNA_def_property_ui_range(prop, 1, AUTOMASKING_BOUNDARY_EDGES_MAX_PROPAGATION_STEPS, 1, -1);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Propagation Steps",
|
||||
"Distance where boundary edge automasking is going to protect vertices "
|
||||
"from the fully masked edge");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "cavity_factor");
|
||||
RNA_def_property_ui_text(prop, "Cavity Factor", "The contrast of the cavity mask");
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_range(prop, 0.0f, 5.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_blur_steps", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "cavity_blur_steps");
|
||||
RNA_def_property_ui_text(prop, "Blur Steps", "The number of times the cavity mask is blurred");
|
||||
RNA_def_property_int_default(prop, 0);
|
||||
RNA_def_property_range(prop, 0, 25);
|
||||
RNA_def_property_ui_range(prop, 0, 10, 1, 1);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_curve", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "cavity_curve");
|
||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||
RNA_def_property_ui_text(prop, "Cavity Curve", "Curve used for the sensitivity");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_curve_op", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "cavity_curve_op");
|
||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||
RNA_def_property_ui_text(prop, "Cavity Curve", "Curve used for the sensitivity");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "start_normal_limit", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "start_normal_limit");
|
||||
RNA_def_property_range(prop, 0.0001f, M_PI);
|
||||
RNA_def_property_ui_text(prop, "Area Normal Limit", "The range of angles that will be affected");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "start_normal_falloff", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "start_normal_falloff");
|
||||
RNA_def_property_range(prop, 0.0001f, 1.0f);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Area Normal Falloff", "Extend the angular range with a falloff gradient");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "view_normal_limit", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "view_normal_limit");
|
||||
RNA_def_property_range(prop, 0.0001f, M_PI);
|
||||
RNA_def_property_ui_text(prop, "View Normal Limit", "The range of angles that will be affected");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "view_normal_falloff", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "view_normal_falloff");
|
||||
RNA_def_property_range(prop, 0.0001f, 1.0f);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "View Normal Falloff", "Extend the angular range with a falloff gradient");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
}
|
||||
|
||||
static void rna_def_sculpt(BlenderRNA *brna)
|
||||
{
|
||||
static const EnumPropertyItem detail_refine_items[] = {
|
||||
|
|
@ -1088,89 +1214,6 @@ static void rna_def_sculpt(BlenderRNA *brna)
|
|||
"of Blender unit - higher value means smaller edge length)");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
const EnumPropertyItem *entry = rna_enum_shared_automasking_flag_items;
|
||||
do {
|
||||
prop = RNA_def_property(srna, entry->identifier, PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "automasking_flags", entry->value);
|
||||
RNA_def_property_ui_text(prop, entry->name, entry->description);
|
||||
|
||||
if (entry->value == BRUSH_AUTOMASKING_CAVITY_NORMAL) {
|
||||
RNA_def_property_boolean_funcs(prop, nullptr, "rna_Sculpt_automasking_cavity_set");
|
||||
}
|
||||
else if (entry->value == BRUSH_AUTOMASKING_CAVITY_INVERTED) {
|
||||
RNA_def_property_boolean_funcs(prop, nullptr, "rna_Sculpt_automasking_invert_cavity_set");
|
||||
}
|
||||
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
} while ((++entry)->identifier);
|
||||
|
||||
prop = RNA_def_property(
|
||||
srna, "automasking_boundary_edges_propagation_steps", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "automasking_boundary_edges_propagation_steps");
|
||||
RNA_def_property_range(prop, 1, AUTOMASKING_BOUNDARY_EDGES_MAX_PROPAGATION_STEPS);
|
||||
RNA_def_property_ui_range(prop, 1, AUTOMASKING_BOUNDARY_EDGES_MAX_PROPAGATION_STEPS, 1, -1);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Propagation Steps",
|
||||
"Distance where boundary edge automasking is going to protect vertices "
|
||||
"from the fully masked edge");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_cavity_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "automasking_cavity_factor");
|
||||
RNA_def_property_ui_text(prop, "Cavity Factor", "The contrast of the cavity mask");
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_range(prop, 0.0f, 5.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_cavity_blur_steps", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "automasking_cavity_blur_steps");
|
||||
RNA_def_property_ui_text(prop, "Blur Steps", "The number of times the cavity mask is blurred");
|
||||
RNA_def_property_int_default(prop, 0);
|
||||
RNA_def_property_range(prop, 0, 25);
|
||||
RNA_def_property_ui_range(prop, 0, 10, 1, 1);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_cavity_curve", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "automasking_cavity_curve");
|
||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||
RNA_def_property_ui_text(prop, "Cavity Curve", "Curve used for the sensitivity");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_cavity_curve_op", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "automasking_cavity_curve_op");
|
||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||
RNA_def_property_ui_text(prop, "Cavity Curve", "Curve used for the sensitivity");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_start_normal_limit", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "automasking_start_normal_limit");
|
||||
RNA_def_property_range(prop, 0.0001f, M_PI);
|
||||
RNA_def_property_ui_text(prop, "Area Normal Limit", "The range of angles that will be affected");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_start_normal_falloff", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "automasking_start_normal_falloff");
|
||||
RNA_def_property_range(prop, 0.0001f, 1.0f);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Area Normal Falloff", "Extend the angular range with a falloff gradient");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_view_normal_limit", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "automasking_view_normal_limit");
|
||||
RNA_def_property_range(prop, 0.0001f, M_PI);
|
||||
RNA_def_property_ui_text(prop, "View Normal Limit", "The range of angles that will be affected");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "automasking_view_normal_falloff", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "automasking_view_normal_falloff");
|
||||
RNA_def_property_range(prop, 0.0001f, 1.0f);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "View Normal Falloff", "Extend the angular range with a falloff gradient");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "symmetrize_direction", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_enum_symmetrize_direction_items);
|
||||
RNA_def_property_ui_text(prop, "Direction", "Source and destination for symmetrize operator");
|
||||
|
|
@ -1938,6 +1981,7 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
|
|||
rna_def_paint_curve(brna);
|
||||
rna_def_paint(brna);
|
||||
rna_def_unified_paint_settings(brna);
|
||||
rna_def_mesh_automasking_settings(brna);
|
||||
rna_def_sculpt(brna);
|
||||
rna_def_uv_sculpt(brna);
|
||||
rna_def_gp_paint(brna);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class BrushAutomaskTest(unittest.TestCase):
|
|||
def test_face_set_automasking_ignores_any_non_starting_face_set(self):
|
||||
# This test mesh has 3 face sets, 1 and 2 are used for the eyes, the rest of the monkey's head is 3
|
||||
ACTIVE_FACE_SET = 3
|
||||
bpy.data.scenes[0].tool_settings.sculpt.use_automasking_face_sets = True
|
||||
bpy.data.scenes[0].tool_settings.sculpt.mesh_automasking_settings.use_automasking_face_sets = True
|
||||
|
||||
initial_data = get_attribute_data(BackendType.MESH, AttributeType.POSITION)
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ class BrushAutomaskTest(unittest.TestCase):
|
|||
def test_topology_automasking_ignores_any_non_starting_island(self):
|
||||
# This test mesh has 3 island ids, 0 and 1 are used for the eyes, the rest of the monkey's head is 2
|
||||
ACTIVE_ISLAND_ID = 2
|
||||
bpy.data.scenes[0].tool_settings.sculpt.use_automasking_topology = True
|
||||
bpy.data.scenes[0].tool_settings.sculpt.mesh_automasking_settings.use_automasking_topology = True
|
||||
|
||||
initial_data = get_attribute_data(BackendType.MESH, AttributeType.POSITION)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue