UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 72 additions and 19 deletions
Showing only changes of commit 24b9d2b8ca - Show all commits

View File

@ -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
* \{ */

View File

@ -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;
}

View File

@ -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);
}
/** \} */

View File

@ -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);
}
/** \} */

View File

@ -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. */