UI: Asset Shelf (Experimental Feature) #104831
|
@ -182,6 +182,12 @@ bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index);
|
|||
*/
|
||||
bool BKE_keyblock_is_basis(const struct Key *key, int index);
|
||||
|
||||
/**
|
||||
* Returns a newly allocated array containing true for every key that has this one as basis.
|
||||
* If none are found, returns null.
|
||||
*/
|
||||
bool *BKE_keyblock_get_dependent_keys(const struct Key *key, int index);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Key-Block Data Access
|
||||
* \{ */
|
||||
|
|
|
@ -2598,3 +2598,46 @@ bool BKE_keyblock_is_basis(const Key *key, const int index)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool *BKE_keyblock_get_dependent_keys(const Key *key, const int index)
|
||||
{
|
||||
if (key->type != KEY_RELATIVE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int count = BLI_listbase_count(&key->block);
|
||||
|
||||
if (index < 0 || index >= count) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Seed the table with the specified key. */
|
||||
bool *marked = static_cast<bool *>(MEM_callocN(sizeof(bool) * count, __func__));
|
||||
|
||||
marked[index] = true;
|
||||
|
||||
/* Iterative breadth-first search through the key list. This method minimizes
|
||||
* the number of scans through the list and is failsafe vs reference cycles. */
|
||||
bool updated, found = false;
|
||||
int i;
|
||||
|
||||
do {
|
||||
updated = false;
|
||||
|
||||
LISTBASE_FOREACH_INDEX (const KeyBlock *, kb, &key->block, i) {
|
||||
if (!marked[i] && kb->relative >= 0 && kb->relative < count && marked[kb->relative]) {
|
||||
marked[i] = true;
|
||||
updated = found = true;
|
||||
}
|
||||
}
|
||||
} while (updated);
|
||||
|
||||
if (!found) {
|
||||
MEM_freeN(marked);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* After the search is complete, exclude the original key. */
|
||||
marked[index] = false;
|
||||
return marked;
|
||||
}
|
||||
|
|
|
@ -795,6 +795,7 @@ static void bm_to_mesh_shape(BMesh *bm,
|
|||
BMIter iter;
|
||||
BMVert *eve;
|
||||
float(*ofs)[3] = nullptr;
|
||||
bool *dependent = nullptr;
|
||||
|
||||
/* Editing the basis key updates others. */
|
||||
if ((key->type == KEY_RELATIVE) &&
|
||||
|
@ -803,7 +804,7 @@ static void bm_to_mesh_shape(BMesh *bm,
|
|||
/* Original key-indices are only used to check the vertex existed when entering edit-mode. */
|
||||
(cd_shape_keyindex_offset != -1) &&
|
||||
/* Offsets are only needed if the current shape is a basis for others. */
|
||||
BKE_keyblock_is_basis(key, bm->shapenr - 1))
|
||||
(dependent = BKE_keyblock_get_dependent_keys(key, bm->shapenr - 1)) != nullptr)
|
||||
{
|
||||
|
||||
BLI_assert(actkey != nullptr); /* Assured by `actkey_has_layer` check. */
|
||||
|
@ -830,6 +831,8 @@ static void bm_to_mesh_shape(BMesh *bm,
|
|||
* ones, creating a mess when doing e.g. subdivide + translate. */
|
||||
MEM_freeN(ofs);
|
||||
ofs = nullptr;
|
||||
MEM_freeN(dependent);
|
||||
dependent = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -856,7 +859,8 @@ static void bm_to_mesh_shape(BMesh *bm,
|
|||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (KeyBlock *, currkey, &key->block) {
|
||||
int currkey_i;
|
||||
LISTBASE_FOREACH_INDEX (KeyBlock *, currkey, &key->block, currkey_i) {
|
||||
int keyi;
|
||||
float(*currkey_data)[3];
|
||||
|
||||
|
@ -867,8 +871,7 @@ static void bm_to_mesh_shape(BMesh *bm,
|
|||
|
||||
/* Common case, the layer data is available, use it where possible. */
|
||||
if (cd_shape_offset != -1) {
|
||||
const bool apply_offset = (ofs != nullptr) && (currkey != actkey) &&
|
||||
(bm->shapenr - 1 == currkey->relative);
|
||||
const bool apply_offset = (ofs != nullptr) && (currkey != actkey) && dependent[currkey_i];
|
||||
|
||||
if (currkey->data && (currkey->totelem == bm->totvert)) {
|
||||
/* Use memory in-place. */
|
||||
|
@ -956,9 +959,8 @@ static void bm_to_mesh_shape(BMesh *bm,
|
|||
}
|
||||
}
|
||||
|
||||
if (ofs) {
|
||||
MEM_freeN(ofs);
|
||||
}
|
||||
MEM_SAFE_FREE(ofs);
|
||||
MEM_SAFE_FREE(dependent);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -631,7 +631,7 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
|
|||
return;
|
||||
}
|
||||
|
||||
int a, i;
|
||||
int a, i, currkey_i;
|
||||
EditNurb *editnurb = cu->editnurb;
|
||||
KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
|
||||
BezTriple *bezt, *oldbezt;
|
||||
|
@ -640,11 +640,14 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
|
|||
int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs);
|
||||
|
||||
float(*ofs)[3] = NULL;
|
||||
bool *dependent = NULL;
|
||||
float *oldkey, *newkey, *ofp;
|
||||
|
||||
/* editing the base key should update others */
|
||||
if (cu->key->type == KEY_RELATIVE) {
|
||||
if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */
|
||||
dependent = BKE_keyblock_get_dependent_keys(cu->key, editnurb->shapenr - 1);
|
||||
|
||||
if (dependent) { /* active key is a base */
|
||||
int totvec = 0;
|
||||
|
||||
/* Calculate needed memory to store offset */
|
||||
|
@ -702,9 +705,8 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
|
|||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (KeyBlock *, currkey, &cu->key->block) {
|
||||
const bool apply_offset = (ofs && (currkey != actkey) &&
|
||||
(editnurb->shapenr - 1 == currkey->relative));
|
||||
LISTBASE_FOREACH_INDEX (KeyBlock *, currkey, &cu->key->block, currkey_i) {
|
||||
const bool apply_offset = (ofs && (currkey != actkey) && dependent[currkey_i]);
|
||||
|
||||
float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
|
||||
ofp = oldkey = currkey->data;
|
||||
|
@ -866,9 +868,8 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
|
|||
currkey->data = newkey;
|
||||
}
|
||||
|
||||
if (ofs) {
|
||||
MEM_freeN(ofs);
|
||||
}
|
||||
MEM_SAFE_FREE(ofs);
|
||||
MEM_SAFE_FREE(dependent);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -3406,11 +3406,11 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
|
|||
{
|
||||
Mesh *me = (Mesh *)ob->data;
|
||||
float(*ofs)[3] = nullptr;
|
||||
int a;
|
||||
int a, currkey_i;
|
||||
const int kb_act_idx = ob->shapenr - 1;
|
||||
|
||||
/* For relative keys editing of base should update other keys. */
|
||||
if (BKE_keyblock_is_basis(me->key, kb_act_idx)) {
|
||||
if (bool *dependent = BKE_keyblock_get_dependent_keys(me->key, kb_act_idx)) {
|
||||
ofs = BKE_keyblock_convert_to_vertcos(ob, kb);
|
||||
|
||||
/* Calculate key coord offsets (from previous location). */
|
||||
|
@ -3419,13 +3419,14 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
|
|||
}
|
||||
|
||||
/* Apply offsets on other keys. */
|
||||
LISTBASE_FOREACH (KeyBlock *, currkey, &me->key->block) {
|
||||
if ((currkey != kb) && (currkey->relative == kb_act_idx)) {
|
||||
LISTBASE_FOREACH_INDEX (KeyBlock *, currkey, &me->key->block, currkey_i) {
|
||||
if ((currkey != kb) && dependent[currkey_i]) {
|
||||
BKE_keyblock_update_from_offset(ob, currkey, ofs);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(ofs);
|
||||
MEM_freeN(dependent);
|
||||
}
|
||||
|
||||
/* Modifying of basis key should update mesh. */
|
||||
|
|
Loading…
Reference in New Issue