Merge branch 'master' into sculpt-dev

This commit is contained in:
Pablo Dobarro 2020-12-21 21:17:51 +01:00
commit 6034a5bd5b
6 changed files with 204 additions and 157 deletions

View File

@ -1421,125 +1421,147 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval,
/* ---------------------- */
/* accumulate the old and new values of a channel according to mode and influence */
static float nla_blend_value(int blendmode, float old_value, float value, float inf)
/* Blend the lower nla stack value and upper strip value of a channel according to mode and
* influence. */
static float nla_blend_value(const int blendmode,
const float lower_value,
const float strip_value,
const float influence)
{
/* Optimization: no need to try applying if there is no influence. */
if (IS_EQF(inf, 0.0f)) {
return old_value;
if (IS_EQF(influence, 0.0f)) {
return lower_value;
}
/* perform blending */
/* Perform blending. */
switch (blendmode) {
case NLASTRIP_MODE_ADD:
/* simply add the scaled value on to the stack */
return old_value + (value * inf);
/* Simply add the scaled value on to the stack. */
return lower_value + (strip_value * influence);
case NLASTRIP_MODE_SUBTRACT:
/* simply subtract the scaled value from the stack */
return old_value - (value * inf);
/* Simply subtract the scaled value from the stack. */
return lower_value - (strip_value * influence);
case NLASTRIP_MODE_MULTIPLY:
/* multiply the scaled value with the stack */
/* Formula Used:
* result = fac * (a * b) + (1 - fac) * a
*/
return inf * (old_value * value) + (1 - inf) * old_value;
/* Multiply the scaled value with the stack. */
return influence * (lower_value * strip_value) + (1 - influence) * lower_value;
case NLASTRIP_MODE_COMBINE:
BLI_assert(!"combine mode");
ATTR_FALLTHROUGH;
case NLASTRIP_MODE_REPLACE:
default
: /* TODO: do we really want to blend by default? it seems more uses might prefer add... */
/* do linear interpolation
* - the influence of the accumulated data (elsewhere, that is called dstweight)
* is 1 - influence, since the strip's influence is srcweight
default:
/* TODO: Do we really want to blend by default? it seems more uses might prefer add... */
/* Do linear interpolation. The influence of the accumulated data (elsewhere, that is called
* dstweight) is 1 - influence, since the strip's influence is srcweight.
*/
return old_value * (1.0f - inf) + (value * inf);
return lower_value * (1.0f - influence) + (strip_value * influence);
}
}
/* accumulate the old and new values of a channel according to mode and influence */
static float nla_combine_value(
int mix_mode, float base_value, float old_value, float value, float inf)
/* Blend the lower nla stack value and upper strip value of a channel according to mode and
* influence. */
static float nla_combine_value(const int mix_mode,
float base_value,
const float lower_value,
const float strip_value,
const float influence)
{
/* Optimization: no need to try applying if there is no influence. */
if (IS_EQF(inf, 0.0f)) {
return old_value;
/* Optimization: No need to try applying if there is no influence. */
if (IS_EQF(influence, 0.0f)) {
return lower_value;
}
/* perform blending */
/* Perform blending */
switch (mix_mode) {
case NEC_MIX_ADD:
case NEC_MIX_AXIS_ANGLE:
return old_value + (value - base_value) * inf;
return lower_value + (strip_value - base_value) * influence;
case NEC_MIX_MULTIPLY:
if (IS_EQF(base_value, 0.0f)) {
base_value = 1.0f;
}
return old_value * powf(value / base_value, inf);
return lower_value * powf(strip_value / base_value, influence);
case NEC_MIX_QUATERNION:
default:
BLI_assert(!"invalid mix mode");
return old_value;
return lower_value;
}
}
/* compute the value that would blend to the desired target value using nla_blend_value */
static bool nla_invert_blend_value(
int blend_mode, float old_value, float target_value, float influence, float *r_value)
/** \returns true if solution exists and output is written to. */
static bool nla_blend_get_inverted_strip_value(const int blendmode,
const float lower_value,
const float blended_value,
const float influence,
float *r_strip_value)
{
/** No solution if strip had 0 influence. */
if (IS_EQF(influence, 0.0f)) {
return false;
}
switch (blend_mode) {
switch (blendmode) {
case NLASTRIP_MODE_ADD:
*r_value = (target_value - old_value) / influence;
*r_strip_value = (blended_value - lower_value) / influence;
return true;
case NLASTRIP_MODE_SUBTRACT:
*r_value = (old_value - target_value) / influence;
*r_strip_value = (lower_value - blended_value) / influence;
return true;
case NLASTRIP_MODE_MULTIPLY:
if (IS_EQF(old_value, 0.0f)) {
if (IS_EQF(lower_value, 0.0f)) {
/* Resolve 0/0 to 1. */
if (IS_EQF(target_value, 0.0f)) {
*r_value = 1.0f;
if (IS_EQF(blended_value, 0.0f)) {
*r_strip_value = 1.0f;
return true;
}
/* Division by zero. */
return false;
}
else {
*r_value = (target_value - old_value) / influence / old_value + 1.0f;
return true;
}
/** Math:
*
* blended_value = inf * (lower_value * strip_value) + (1 - inf) * lower_value
* blended_value - (1 - inf) * lower_value = inf * (lower_value * strip_value)
* (blended_value - (1 - inf) * lower_value) / (inf * lower_value) = strip_value
* (blended_value - lower_value + inf * lower_value) / (inf * lower_value) = strip_value
* ((blended_value - lower_value) / (inf * lower_value)) + 1 = strip_value
*
* strip_value = ((blended_value - lower_value) / (inf * lower_value)) + 1
*/
*r_strip_value = ((blended_value - lower_value) / (influence * lower_value)) + 1.0f;
return true;
case NLASTRIP_MODE_COMBINE:
BLI_assert(!"combine mode");
ATTR_FALLTHROUGH;
case NLASTRIP_MODE_REPLACE:
default:
*r_value = (target_value - old_value) / influence + old_value;
/** Math:
*
* blended_value = lower_value * (1.0f - inf) + (strip_value * inf)
* blended_value - lower_value * (1.0f - inf) = (strip_value * inf)
* (blended_value - lower_value * (1.0f - inf)) / inf = strip_value
*
* strip_value = (blended_value - lower_value * (1.0f - inf)) / inf
*/
*r_strip_value = (blended_value - lower_value * (1.0f - influence)) / influence;
return true;
}
}
/* compute the value that would blend to the desired target value using nla_combine_value */
static bool nla_invert_combine_value(int mix_mode,
float base_value,
float old_value,
float target_value,
float influence,
float *r_value)
/** \returns true if solution exists and output is written to. */
static bool nla_combine_get_inverted_strip_value(const int mix_mode,
float base_value,
const float lower_value,
const float blended_value,
const float influence,
float *r_strip_value)
{
/* No solution if strip had no influence. */
if (IS_EQF(influence, 0.0f)) {
@ -1549,65 +1571,72 @@ static bool nla_invert_combine_value(int mix_mode,
switch (mix_mode) {
case NEC_MIX_ADD:
case NEC_MIX_AXIS_ANGLE:
*r_value = base_value + (target_value - old_value) / influence;
*r_strip_value = base_value + (blended_value - lower_value) / influence;
return true;
case NEC_MIX_MULTIPLY:
if (IS_EQF(base_value, 0.0f)) {
base_value = 1.0f;
}
if (IS_EQF(old_value, 0.0f)) {
/* Divison by zero. */
if (IS_EQF(lower_value, 0.0f)) {
/* Resolve 0/0 to 1. */
if (IS_EQF(target_value, 0.0f)) {
*r_value = base_value;
if (IS_EQF(blended_value, 0.0f)) {
*r_strip_value = base_value;
return true;
}
/* Division by zero. */
return false;
}
*r_value = base_value * powf(target_value / old_value, 1.0f / influence);
*r_strip_value = base_value * powf(blended_value / lower_value, 1.0f / influence);
return true;
case NEC_MIX_QUATERNION:
default:
BLI_assert(!"invalid mix mode");
return false;
}
}
/* accumulate quaternion channels for Combine mode according to influence */
static void nla_combine_quaternion(const float old_values[4],
const float values[4],
float influence,
float result[4])
/** Accumulate quaternion channels for Combine mode according to influence.
* \returns blended_value = lower_values @ strip_values^infl
*/
static void nla_combine_quaternion(const float lower_values[4],
const float strip_values[4],
const float influence,
float r_blended_value[4])
{
float tmp_old[4], tmp_new[4];
float tmp_lower[4], tmp_strip_values[4];
normalize_qt_qt(tmp_old, old_values);
normalize_qt_qt(tmp_new, values);
normalize_qt_qt(tmp_lower, lower_values);
normalize_qt_qt(tmp_strip_values, strip_values);
pow_qt_fl_normalized(tmp_new, influence);
mul_qt_qtqt(result, tmp_old, tmp_new);
pow_qt_fl_normalized(tmp_strip_values, influence);
mul_qt_qtqt(r_blended_value, tmp_lower, tmp_strip_values);
}
/* invert accumulation of quaternion channels for Combine mode according to influence */
static bool nla_invert_combine_quaternion(const float old_values[4],
const float values[4],
float influence,
float result[4])
/** \returns true if solution exists and output written to. */
static bool nla_combine_quaternion_get_inverted_strip_values(const float lower_values[4],
const float blended_values[4],
const float influence,
float r_strip_values[4])
{
/* blended_value = lower_values @ r_strip_values^infl
* inv(lower_values) @ blended_value = r_strip_values^infl
* (inv(lower_values) @ blended_value) ^ (1/inf) = r_strip_values
*
* Returns: r_strip_values = (inv(lower_values) @ blended_value) ^ (1/inf) */
if (IS_EQF(influence, 0.0f)) {
return false;
}
float tmp_old[4], tmp_new[4];
float tmp_lower[4], tmp_blended[4];
normalize_qt_qt(tmp_old, old_values);
normalize_qt_qt(tmp_new, values);
invert_qt_normalized(tmp_old);
normalize_qt_qt(tmp_lower, lower_values);
normalize_qt_qt(tmp_blended, blended_values);
invert_qt_normalized(tmp_lower);
mul_qt_qtqt(result, tmp_old, tmp_new);
pow_qt_fl_normalized(result, 1.0f / influence);
mul_qt_qtqt(r_strip_values, tmp_lower, tmp_blended);
pow_qt_fl_normalized(r_strip_values, 1.0f / influence);
return true;
}
@ -2442,8 +2471,9 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
ctx = MEM_callocN(sizeof(*ctx), "NlaKeyframingContext");
ctx->adt = adt;
nlaeval_init(&ctx->nla_channels);
animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, anim_eval_context, flush_to_original, ctx);
nlaeval_init(&ctx->lower_eval_data);
animsys_evaluate_nla(
&ctx->lower_eval_data, ptr, adt, anim_eval_context, flush_to_original, ctx);
BLI_assert(ELEM(ctx->strip.act, NULL, adt->action));
BLI_addtail(cache, ctx);
@ -2504,44 +2534,51 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
.ptr = *prop_ptr,
.prop = prop,
};
NlaEvalData *nlaeval = &context->nla_channels;
NlaEvalChannel *nec = nlaevalchan_verify_key(nlaeval, NULL, &key);
/**
* Remove lower NLA stack effects.
*
* Using the tweak strip's blended result and the lower snapshot value, we can solve for the
* tweak strip value it must evaluate to.
*/
NlaEvalData *const lower_eval_data = &context->lower_eval_data;
NlaEvalChannel *const lower_nec = nlaevalchan_verify_key(lower_eval_data, NULL, &key);
if (nec->base_snapshot.length != count) {
if ((lower_nec->base_snapshot.length != count)) {
BLI_assert(!"invalid value count");
return false;
}
/* Invert the blending operation to compute the desired key values. */
NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_find_channel(&nlaeval->eval_snapshot,
nec);
/* Invert the blending operation to compute the desired strip values. */
NlaEvalChannelSnapshot *const lower_nec_snapshot = nlaeval_snapshot_find_channel(
&lower_eval_data->eval_snapshot, lower_nec);
float *old_values = nec_snapshot->values;
float *lower_values = lower_nec_snapshot->values;
if (blend_mode == NLASTRIP_MODE_COMBINE) {
/* Quaternion combine handles all sub-channels as a unit. */
if (nec->mix_mode == NEC_MIX_QUATERNION) {
if (lower_nec->mix_mode == NEC_MIX_QUATERNION) {
if (r_force_all == NULL) {
return false;
}
*r_force_all = true;
if (!nla_invert_combine_quaternion(old_values, values, influence, values)) {
if (!nla_combine_quaternion_get_inverted_strip_values(
lower_values, values, influence, values)) {
return false;
}
}
else {
float *base_values = nec->base_snapshot.values;
float *base_values = lower_nec->base_snapshot.values;
for (int i = 0; i < count; i++) {
if (ELEM(index, i, -1)) {
if (!nla_invert_combine_value(nec->mix_mode,
base_values[i],
old_values[i],
values[i],
influence,
&values[i])) {
if (!nla_combine_get_inverted_strip_value(lower_nec->mix_mode,
base_values[i],
lower_values[i],
values[i],
influence,
&values[i])) {
return false;
}
}
@ -2551,7 +2588,8 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
else {
for (int i = 0; i < count; i++) {
if (ELEM(index, i, -1)) {
if (!nla_invert_blend_value(blend_mode, old_values[i], values[i], influence, &values[i])) {
if (!nla_blend_get_inverted_strip_value(
blend_mode, lower_values[i], values[i], influence, &values[i])) {
return false;
}
}
@ -2568,7 +2606,7 @@ void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache)
{
LISTBASE_FOREACH (NlaKeyframingContext *, ctx, cache) {
MEM_SAFE_FREE(ctx->eval_strip);
nlaeval_free(&ctx->nla_channels);
nlaeval_free(&ctx->lower_eval_data);
}
BLI_freelistN(cache);

View File

@ -4797,6 +4797,13 @@ static bool constructive_modifier_is_deform_modified(ModifierData *md)
*/
return true;
}
if (md->type == eModifierType_Nodes) {
/* Not ideal for performance to always assume this is animated,
* but hard to detect in general. The better long term solution is likely
* to replace BKE_object_is_deform_modified by a test if the object was
* modified by the depsgraph when changing frames. */
return true;
}
return false;
}

View File

@ -156,8 +156,8 @@ typedef struct NlaKeyframingContext {
NlaStrip strip;
NlaEvalStrip *eval_strip;
/* Evaluated NLA stack below the current strip. */
NlaEvalData nla_channels;
/* Evaluated NLA stack below the tweak strip. */
NlaEvalData lower_eval_data;
} NlaKeyframingContext;
/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */

View File

@ -397,7 +397,7 @@ static void drw_mesh_weight_state_extract(Object *ob,
wstate->flags |= DRW_MESH_WEIGHT_STATE_MULTIPAINT |
(ts->auto_normalize ? DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE : 0);
if (me->symmetry & ME_SYMMETRY_X) {
if (me->editflag & ME_EDIT_VERTEX_GROUPS_X_SYMMETRY) {
BKE_object_defgroup_mirror_selection(ob,
wstate->defgroup_len,
wstate->defgroup_sel,

View File

@ -4771,73 +4771,75 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
}
}
if (wt) {
// rcti disablerect = *rect; /* rect gets clipped smaller for text */
if (wt == NULL) {
return;
}
const int roundboxalign = widget_roundbox_set(but, rect);
// rcti disablerect = *rect; /* rect gets clipped smaller for text */
/* Mask out flags re-used for local state. */
int state = but->flag & ~UI_STATE_FLAGS_ALL;
const int drawflag = but->drawflag;
const int roundboxalign = widget_roundbox_set(but, rect);
if (state & UI_SELECT_DRAW) {
state |= UI_SELECT;
/* Mask out flags re-used for local state. */
int state = but->flag & ~UI_STATE_FLAGS_ALL;
const int drawflag = but->drawflag;
if (state & UI_SELECT_DRAW) {
state |= UI_SELECT;
}
if ((but->editstr) ||
(UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but))) {
state |= UI_STATE_TEXT_INPUT;
}
if (but->hold_func) {
state |= UI_STATE_HOLD_ACTION;
}
if (state & UI_ACTIVE) {
if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
state |= UI_STATE_ACTIVE_LEFT;
}
if ((but->editstr) ||
(UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but))) {
state |= UI_STATE_TEXT_INPUT;
else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
state |= UI_STATE_ACTIVE_RIGHT;
}
}
if (but->hold_func) {
state |= UI_STATE_HOLD_ACTION;
bool use_alpha_blend = false;
if (but->emboss != UI_EMBOSS_PULLDOWN) {
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
use_alpha_blend = true;
ui_widget_color_disabled(wt, state);
}
}
if (state & UI_ACTIVE) {
if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
state |= UI_STATE_ACTIVE_LEFT;
}
else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
state |= UI_STATE_ACTIVE_RIGHT;
}
}
bool use_alpha_blend = false;
if (but->emboss != UI_EMBOSS_PULLDOWN) {
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
use_alpha_blend = true;
ui_widget_color_disabled(wt, state);
}
}
if (drawflag & UI_BUT_TEXT_RIGHT) {
state |= UI_STATE_TEXT_BEFORE_WIDGET;
}
if (drawflag & UI_BUT_TEXT_RIGHT) {
state |= UI_STATE_TEXT_BEFORE_WIDGET;
}
#ifdef USE_UI_POPOVER_ONCE
if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
state |= UI_BUT_ACTIVE_DEFAULT;
}
if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
state |= UI_BUT_ACTIVE_DEFAULT;
}
}
#endif
wt->state(wt, state, drawflag, but->emboss);
if (wt->custom) {
wt->custom(but, &wt->wcol, rect, state, roundboxalign);
}
else if (wt->draw) {
wt->draw(&wt->wcol, rect, state, roundboxalign);
}
wt->state(wt, state, drawflag, but->emboss);
if (wt->custom) {
wt->custom(but, &wt->wcol, rect, state, roundboxalign);
}
else if (wt->draw) {
wt->draw(&wt->wcol, rect, state, roundboxalign);
}
if (use_alpha_blend) {
GPU_blend(GPU_BLEND_ALPHA);
}
if (use_alpha_blend) {
GPU_blend(GPU_BLEND_ALPHA);
}
wt->text(fstyle, &wt->wcol, but, rect);
if (use_alpha_blend) {
GPU_blend(GPU_BLEND_NONE);
}
wt->text(fstyle, &wt->wcol, but, rect);
if (use_alpha_blend) {
GPU_blend(GPU_BLEND_NONE);
}
}

View File

@ -1751,7 +1751,7 @@ static bool *vgroup_selected_get(Object *ob)
/* Mirror the selection if X Mirror is enabled. */
Mesh *me = BKE_mesh_from_object(ob);
if (me && (me->symmetry & ME_SYMMETRY_X) != 0) {
if (me && (me->editflag & ME_EDIT_VERTEX_GROUPS_X_SYMMETRY) != 0) {
BKE_object_defgroup_mirror_selection(ob, defbase_tot, mask, mask, &sel_count);
}
}