Weight Paint: 'Sample' now supports multi-paint
Since the coloring uses sum or average of the weights of all selected groups, the weight pick tool should also use that instead of reading the weight of the single active group that you can't see.
This commit is contained in:
@@ -68,6 +68,10 @@ void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *s
|
||||
float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup);
|
||||
float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup);
|
||||
|
||||
float BKE_defvert_multipaint_collective_weight(
|
||||
const struct MDeformVert *dv, int defbase_tot,
|
||||
const bool *defbase_sel, int defbase_tot_sel, bool do_autonormalize);
|
||||
|
||||
void defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src);
|
||||
void defvert_copy_subset(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src,
|
||||
const bool *vgroup_subset, const int vgroup_tot);
|
||||
|
||||
@@ -1373,30 +1373,13 @@ static void calc_weightpaint_vert_color(
|
||||
|
||||
if ((defbase_sel_tot > 1) && (draw_flag & CALC_WP_MULTIPAINT)) {
|
||||
/* Multi-Paint feature */
|
||||
bool was_a_nonzero = false;
|
||||
unsigned int i;
|
||||
|
||||
const MDeformWeight *dw = dv->dw;
|
||||
for (i = dv->totweight; i != 0; i--, dw++) {
|
||||
/* in multipaint, get the average if auto normalize is inactive
|
||||
* get the sum if it is active */
|
||||
if (dw->def_nr < defbase_tot) {
|
||||
if (defbase_sel[dw->def_nr]) {
|
||||
if (dw->weight) {
|
||||
input += dw->weight;
|
||||
was_a_nonzero = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input = BKE_defvert_multipaint_collective_weight(
|
||||
dv, defbase_tot, defbase_sel, defbase_sel_tot, (draw_flag & CALC_WP_AUTO_NORMALIZE) != 0);
|
||||
|
||||
/* make it black if the selected groups have no weight on a vertex */
|
||||
if (was_a_nonzero == false) {
|
||||
if (input == 0.0f) {
|
||||
show_alert_color = true;
|
||||
}
|
||||
else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == false) {
|
||||
input /= defbase_sel_tot; /* get the average */
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* default, non tricky behavior */
|
||||
|
||||
@@ -919,6 +919,40 @@ bool defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \return The representative weight of a multipaint group, used for
|
||||
* viewport colors and actual painting.
|
||||
*
|
||||
* Result equal to sum of weights with auto normalize, and average otherwise.
|
||||
* Value is not clamped, since painting relies on multiplication being always
|
||||
* commutative with the collective weight function.
|
||||
*/
|
||||
float BKE_defvert_multipaint_collective_weight(
|
||||
const struct MDeformVert *dv, int defbase_tot,
|
||||
const bool *defbase_sel, int defbase_tot_sel, bool do_autonormalize)
|
||||
{
|
||||
int i;
|
||||
float total = 0.0f;
|
||||
const MDeformWeight *dw = dv->dw;
|
||||
|
||||
for (i = dv->totweight; i != 0; i--, dw++) {
|
||||
/* in multipaint, get the average if auto normalize is inactive
|
||||
* get the sum if it is active */
|
||||
if (dw->def_nr < defbase_tot) {
|
||||
if (defbase_sel[dw->def_nr]) {
|
||||
total += dw->weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_autonormalize == false) {
|
||||
total /= defbase_tot_sel;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Defvert Array functions */
|
||||
|
||||
|
||||
@@ -1014,6 +1014,24 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
||||
Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
|
||||
const int vgroup_active = vc.obact->actdef - 1;
|
||||
float vgroup_weight = defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
|
||||
|
||||
/* use combined weight in multipaint mode, since that's what is displayed to the user in the colors */
|
||||
if (ts->multipaint) {
|
||||
int defbase_tot_sel;
|
||||
const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
|
||||
bool *defbase_sel = BKE_object_defgroup_selected_get(vc.obact, defbase_tot, &defbase_tot_sel);
|
||||
|
||||
if (defbase_tot_sel > 1) {
|
||||
vgroup_weight = BKE_defvert_multipaint_collective_weight(
|
||||
&me->dvert[v_idx_best], defbase_tot, defbase_sel, defbase_tot_sel, ts->auto_normalize);
|
||||
|
||||
/* if autonormalize is enabled, but weights are not normalized, the value can exceed 1 */
|
||||
CLAMP(vgroup_weight, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
MEM_freeN(defbase_sel);
|
||||
}
|
||||
|
||||
BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user