Paint: Migrate radial_symmetry from Scene to Mesh
This commit introduces the `radial_symmetry` property on the `Mesh` datablock and simultaneously removes the `radial_symm` property in Sculpt, Vertex Paint, and Weight Paint. This allows users to have these symmetry values defined on a per-object basis instead of needing to reconfigure it for each mesh. Current values stored on the `ToolSettings` on a per-scene basis are not copied to each mesh in a scene. This is done to avoid introducing potentially inaccurate data to a large number of meshes at the cost of some minor backwards incompatibility. Part of #108107 Pull Request: https://projects.blender.org/blender/blender/pulls/141108
This commit is contained in:
@@ -95,6 +95,8 @@ class View3DPanel:
|
||||
|
||||
# Used by vertex & weight paint
|
||||
def draw_vpaint_symmetry(layout, vpaint, obj):
|
||||
mesh = obj.data
|
||||
|
||||
col = layout.column()
|
||||
row = col.row(heading="Mirror", align=True)
|
||||
row.prop(obj, "use_mesh_mirror_x", text="X", toggle=True)
|
||||
@@ -103,7 +105,7 @@ def draw_vpaint_symmetry(layout, vpaint, obj):
|
||||
|
||||
col = layout.column()
|
||||
col.active = not obj.data.use_mirror_vertex_groups
|
||||
col.prop(vpaint, "radial_symmetry", text="Radial")
|
||||
col.prop(mesh, "radial_symmetry", text="Radial")
|
||||
|
||||
|
||||
# ********** default tools for object mode ****************
|
||||
@@ -1147,7 +1149,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
|
||||
row.prop(sculpt, "tile_z", text="Z", toggle=True)
|
||||
|
||||
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
|
||||
layout.prop(sculpt, "radial_symmetry", text="Radial")
|
||||
layout.prop(mesh, "radial_symmetry", text="Radial")
|
||||
layout.prop(sculpt, "tile_offset", text="Tile Offset")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 31
|
||||
#define BLENDER_FILE_SUBVERSION 32
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -1253,6 +1253,14 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 32)) {
|
||||
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
|
||||
mesh->radial_symmetry[0] = 1;
|
||||
mesh->radial_symmetry[1] = 1;
|
||||
mesh->radial_symmetry[2] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
|
||||
@@ -1150,6 +1150,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
|
||||
const Object &ob,
|
||||
const float radius)
|
||||
{
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob.data);
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
float3 location;
|
||||
float symm_rot_mat[4][4];
|
||||
@@ -1166,8 +1167,8 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
|
||||
|
||||
/* Radial Symmetry. */
|
||||
for (char raxis = 0; raxis < 3; raxis++) {
|
||||
for (int r = 1; r < sd.radial_symm[raxis]; r++) {
|
||||
float angle = 2 * M_PI * r / sd.radial_symm[int(raxis)];
|
||||
for (int r = 1; r < mesh->radial_symmetry[raxis]; r++) {
|
||||
float angle = 2 * M_PI * r / mesh->radial_symmetry[int(raxis)];
|
||||
location = symmetry_flip(true_location, ePaintSymmetryFlags(i));
|
||||
unit_m4(symm_rot_mat);
|
||||
rotate_m4(symm_rot_mat, raxis + 'X', angle);
|
||||
|
||||
@@ -1977,8 +1977,8 @@ static void vpaint_do_radial_symmetry(bContext *C,
|
||||
const ePaintSymmetryFlags symm,
|
||||
const int axis)
|
||||
{
|
||||
for (int i = 1; i < vp.radial_symm[axis - 'X']; i++) {
|
||||
const float angle = (2.0 * M_PI) * i / vp.radial_symm[axis - 'X'];
|
||||
for (int i = 1; i < mesh.radial_symmetry[axis - 'X']; i++) {
|
||||
const float angle = (2.0 * M_PI) * i / mesh.radial_symmetry[axis - 'X'];
|
||||
vpaint_do_paint(C, vp, vpd, ob, mesh, brush, symm, axis, i, angle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1719,8 +1719,8 @@ static void wpaint_do_radial_symmetry(bContext *C,
|
||||
const ePaintSymmetryFlags symm,
|
||||
const int axis)
|
||||
{
|
||||
for (int i = 1; i < wp.radial_symm[axis - 'X']; i++) {
|
||||
const float angle = (2.0 * M_PI) * i / wp.radial_symm[axis - 'X'];
|
||||
for (int i = 1; i < mesh.radial_symmetry[axis - 'X']; i++) {
|
||||
const float angle = (2.0 * M_PI) * i / mesh.radial_symmetry[axis - 'X'];
|
||||
wpaint_do_paint(C, ob, wp, wpd, wpi, mesh, brush, symm, axis, i, angle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1212,15 +1212,15 @@ static float calc_overlap(const blender::ed::sculpt_paint::StrokeCache &cache,
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static float calc_radial_symmetry_feather(const Sculpt &sd,
|
||||
static float calc_radial_symmetry_feather(const Mesh &mesh,
|
||||
const blender::ed::sculpt_paint::StrokeCache &cache,
|
||||
const ePaintSymmetryFlags symm,
|
||||
const char axis)
|
||||
{
|
||||
float overlap = 0.0f;
|
||||
|
||||
for (int i = 1; i < sd.radial_symm[axis - 'X']; i++) {
|
||||
const float angle = 2.0f * M_PI * i / sd.radial_symm[axis - 'X'];
|
||||
for (int i = 1; i < mesh.radial_symmetry[axis - 'X']; i++) {
|
||||
const float angle = 2.0f * M_PI * i / mesh.radial_symmetry[axis - 'X'];
|
||||
overlap += calc_overlap(cache, symm, axis, angle);
|
||||
}
|
||||
|
||||
@@ -1228,6 +1228,7 @@ static float calc_radial_symmetry_feather(const Sculpt &sd,
|
||||
}
|
||||
|
||||
static float calc_symmetry_feather(const Sculpt &sd,
|
||||
const Mesh &mesh,
|
||||
const blender::ed::sculpt_paint::StrokeCache &cache)
|
||||
{
|
||||
if (!(sd.paint.symmetry_flags & PAINT_SYMMETRY_FEATHER)) {
|
||||
@@ -1244,9 +1245,9 @@ static float calc_symmetry_feather(const Sculpt &sd,
|
||||
|
||||
overlap += calc_overlap(cache, ePaintSymmetryFlags(i), 0, 0);
|
||||
|
||||
overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'X');
|
||||
overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'Y');
|
||||
overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'Z');
|
||||
overlap += calc_radial_symmetry_feather(mesh, cache, ePaintSymmetryFlags(i), 'X');
|
||||
overlap += calc_radial_symmetry_feather(mesh, cache, ePaintSymmetryFlags(i), 'Y');
|
||||
overlap += calc_radial_symmetry_feather(mesh, cache, ePaintSymmetryFlags(i), 'Z');
|
||||
}
|
||||
return 1.0f / overlap;
|
||||
}
|
||||
@@ -3576,9 +3577,10 @@ static void do_radial_symmetry(const Depsgraph &depsgraph,
|
||||
const float /*feather*/)
|
||||
{
|
||||
SculptSession &ss = *ob.sculpt;
|
||||
const Mesh &mesh = *static_cast<Mesh *>(ob.data);
|
||||
|
||||
for (int i = 1; i < sd.radial_symm[axis - 'X']; i++) {
|
||||
const float angle = 2.0f * M_PI * i / sd.radial_symm[axis - 'X'];
|
||||
for (int i = 1; i < mesh.radial_symmetry[axis - 'X']; i++) {
|
||||
const float angle = 2.0f * M_PI * i / mesh.radial_symmetry[axis - 'X'];
|
||||
ss.cache->radial_symmetry_pass = i;
|
||||
SCULPT_cache_calc_brushdata_symm(*ss.cache, symm, axis, angle);
|
||||
do_tiled(depsgraph, scene, sd, ob, brush, ups, paint_mode_settings, action);
|
||||
@@ -3609,11 +3611,12 @@ static void do_symmetrical_brush_actions(const Depsgraph &depsgraph,
|
||||
PaintModeSettings &paint_mode_settings)
|
||||
{
|
||||
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
|
||||
const Mesh &mesh = *static_cast<Mesh *>(ob.data);
|
||||
SculptSession &ss = *ob.sculpt;
|
||||
StrokeCache &cache = *ss.cache;
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
|
||||
float feather = calc_symmetry_feather(sd, *ss.cache);
|
||||
float feather = calc_symmetry_feather(sd, mesh, *ss.cache);
|
||||
|
||||
cache.bstrength = brush_strength(sd, cache, feather, ups, paint_mode_settings);
|
||||
cache.symmetry = symm;
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
.face_sets_color_seed = 0, \
|
||||
.face_sets_color_default = 1, \
|
||||
.flag = ME_REMESH_REPROJECT_VOLUME | ME_REMESH_REPROJECT_ATTRIBUTES, \
|
||||
.editflag = ME_EDIT_MIRROR_VERTEX_GROUPS \
|
||||
.editflag = ME_EDIT_MIRROR_VERTEX_GROUPS, \
|
||||
.radial_symmetry = {1, 1, 1} \
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -241,7 +241,8 @@ typedef struct Mesh {
|
||||
/* Deprecated size of #fdata. */
|
||||
int totface_legacy;
|
||||
|
||||
char _pad1[4];
|
||||
char _pad1;
|
||||
int8_t radial_symmetry[3];
|
||||
|
||||
/**
|
||||
* Data that isn't saved in files, including caches of derived data, temporary data to improve
|
||||
|
||||
@@ -1340,7 +1340,7 @@ typedef struct Sculpt {
|
||||
|
||||
// /* Control tablet input. */
|
||||
// char tablet_size, tablet_strength; XXX not used?
|
||||
int radial_symm[3];
|
||||
int radial_symm[3] DNA_DEPRECATED;
|
||||
|
||||
/** Maximum edge length for dynamic topology sculpting (in pixels). */
|
||||
float detail_size;
|
||||
@@ -1428,7 +1428,7 @@ typedef struct VPaint {
|
||||
char flag;
|
||||
char _pad[3];
|
||||
/** For mirrored painting. */
|
||||
int radial_symm[3];
|
||||
int radial_symm[3] DNA_DEPRECATED;
|
||||
} VPaint;
|
||||
|
||||
/** #VPaint::flag */
|
||||
|
||||
@@ -3302,6 +3302,15 @@ static void rna_def_mesh(BlenderRNA *brna)
|
||||
"Mirror the left/right vertex groups when painting. The symmetry axis "
|
||||
"is determined by the symmetry settings.");
|
||||
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
|
||||
|
||||
prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "radial_symmetry");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_int_default(prop, 1);
|
||||
RNA_def_property_range(prop, 1, 64);
|
||||
RNA_def_property_ui_range(prop, 1, 32, 1, 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Radial Symmetry Count", "Number of mirrored regions around a central axis");
|
||||
/* End Symmetry */
|
||||
|
||||
RNA_define_verify_sdna(false);
|
||||
|
||||
@@ -1006,14 +1006,6 @@ static void rna_def_sculpt(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(srna, "Sculpt", "");
|
||||
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
|
||||
|
||||
prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "radial_symm");
|
||||
RNA_def_property_int_default(prop, 1);
|
||||
RNA_def_property_range(prop, 1, 64);
|
||||
RNA_def_property_ui_range(prop, 0, 32, 1, 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Radial Symmetry Count X Axis", "Number of times to copy strokes across the surface");
|
||||
|
||||
prop = RNA_def_property(srna, "lock_x", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flags", SCULPT_LOCK_X);
|
||||
RNA_def_property_ui_text(prop, "Lock X", "Disallow changes to the X axis of vertices");
|
||||
@@ -1312,15 +1304,6 @@ static void rna_def_vertex_paint(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", VP_FLAG_VGROUP_RESTRICT);
|
||||
RNA_def_property_ui_text(prop, "Restrict", "Restrict painting to vertices in the group");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
/* Mirroring */
|
||||
prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "radial_symm");
|
||||
RNA_def_property_int_default(prop, 1);
|
||||
RNA_def_property_range(prop, 1, 64);
|
||||
RNA_def_property_ui_range(prop, 1, 32, 1, 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Radial Symmetry Count X Axis", "Number of times to copy strokes across the surface");
|
||||
}
|
||||
|
||||
static void rna_def_paint_mode(BlenderRNA *brna)
|
||||
|
||||
Reference in New Issue
Block a user