Pose channel: Add session UUID
Allows to identify pose channels more reliably than by the pointer.
This commit is contained in:
@@ -129,6 +129,8 @@ void BKE_pose_channel_free(struct bPoseChannel *pchan);
|
||||
void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user);
|
||||
|
||||
void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime);
|
||||
void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime);
|
||||
|
||||
void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime);
|
||||
|
||||
void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime);
|
||||
@@ -153,12 +155,15 @@ void BKE_pose_copy_data_ex(struct bPose **dst,
|
||||
const bool copy_constraints);
|
||||
void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints);
|
||||
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
|
||||
void BKE_pose_channel_session_uuid_generate(struct bPoseChannel *pchan);
|
||||
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
|
||||
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
|
||||
struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob);
|
||||
struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name);
|
||||
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name);
|
||||
|
||||
void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose);
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool BKE_pose_channels_is_valid(const struct bPose *pose);
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_session_uuid.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
@@ -482,6 +483,11 @@ void action_groups_clear_tempflags(bAction *act)
|
||||
|
||||
/* *************** Pose channels *************** */
|
||||
|
||||
void BKE_pose_channel_session_uuid_generate(bPoseChannel *pchan)
|
||||
{
|
||||
pchan->runtime.session_uuid = BLI_session_uuid_generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the pose channel of the given name
|
||||
* from this pose.
|
||||
@@ -524,6 +530,8 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
|
||||
/* If not, create it and add it */
|
||||
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
|
||||
|
||||
BKE_pose_channel_session_uuid_generate(chan);
|
||||
|
||||
BLI_strncpy(chan->name, name, sizeof(chan->name));
|
||||
|
||||
chan->custom_scale = 1.0f;
|
||||
@@ -698,6 +706,10 @@ void BKE_pose_copy_data_ex(bPose **dst,
|
||||
id_us_plus((ID *)pchan->custom);
|
||||
}
|
||||
|
||||
if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
|
||||
BKE_pose_channel_session_uuid_generate(pchan);
|
||||
}
|
||||
|
||||
/* warning, O(n2) here, if done without the hash, but these are rarely used features. */
|
||||
if (pchan->custom_tx) {
|
||||
pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
|
||||
@@ -726,7 +738,7 @@ void BKE_pose_copy_data_ex(bPose **dst,
|
||||
pchan->draw_data = NULL; /* Drawing cache, no need to copy. */
|
||||
|
||||
/* Runtime data, no need to copy. */
|
||||
memset(&pchan->runtime, 0, sizeof(pchan->runtime));
|
||||
BKE_pose_channel_runtime_reset_on_copy(&pchan->runtime);
|
||||
}
|
||||
|
||||
/* for now, duplicate Bone Groups too when doing this */
|
||||
@@ -956,6 +968,14 @@ void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime)
|
||||
memset(runtime, 0, sizeof(*runtime));
|
||||
}
|
||||
|
||||
/* Reset all non-persistent fields. */
|
||||
void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime)
|
||||
{
|
||||
const SessionUUID uuid = runtime->session_uuid;
|
||||
memset(runtime, 0, sizeof(*runtime));
|
||||
runtime->session_uuid = uuid;
|
||||
}
|
||||
|
||||
/** Deallocates runtime cache of a pose channel */
|
||||
void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime)
|
||||
{
|
||||
@@ -1692,3 +1712,30 @@ void what_does_obaction(Object *ob,
|
||||
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pose_check_uuids_unique_and_report(const bPose *pose)
|
||||
{
|
||||
if (pose == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct GSet *used_uuids = BLI_gset_new(
|
||||
BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "sequencer used uuids");
|
||||
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
|
||||
const SessionUUID *session_uuid = &pchan->runtime.session_uuid;
|
||||
if (!BLI_session_uuid_is_generated(session_uuid)) {
|
||||
printf("Pose channel %s does not have UUID generated.\n", pchan->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) {
|
||||
printf("Pose channel %s has duplicate UUID generated.\n", pchan->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_gset_insert(used_uuids, (void *)session_uuid);
|
||||
}
|
||||
|
||||
BLI_gset_free(used_uuids, NULL);
|
||||
}
|
||||
|
||||
@@ -2205,7 +2205,7 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
|
||||
pchan->mpath = NULL;
|
||||
|
||||
/* Reset runtime data, we don't want to share that with the proxy. */
|
||||
BKE_pose_channel_runtime_reset(&pchanw.runtime);
|
||||
BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime);
|
||||
|
||||
/* this is freed so copy a copy, else undo crashes */
|
||||
if (pchanw.prop) {
|
||||
|
||||
@@ -5145,6 +5145,9 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose)
|
||||
pose->chan_array = NULL;
|
||||
|
||||
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||
BKE_pose_channel_runtime_reset(&pchan->runtime);
|
||||
BKE_pose_channel_session_uuid_generate(pchan);
|
||||
|
||||
pchan->bone = NULL;
|
||||
BLO_read_data_address(reader, &pchan->parent);
|
||||
BLO_read_data_address(reader, &pchan->child);
|
||||
@@ -5170,7 +5173,6 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose)
|
||||
CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
|
||||
|
||||
pchan->draw_data = NULL;
|
||||
BKE_pose_channel_runtime_reset(&pchan->runtime);
|
||||
}
|
||||
pose->ikdata = NULL;
|
||||
if (pose->ikparam != NULL) {
|
||||
|
||||
@@ -283,6 +283,14 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid)
|
||||
{
|
||||
const ID *id_for_copy = id;
|
||||
|
||||
if (G.debug & G_DEBUG_DEPSGRAPH_UUID) {
|
||||
const ID_Type id_type = GS(id_for_copy->name);
|
||||
if (id_type == ID_OB) {
|
||||
const Object *object = reinterpret_cast<const Object *>(id_for_copy);
|
||||
BKE_pose_check_uuids_unique_and_report(object->pose);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NESTED_ID_NASTY_WORKAROUND
|
||||
NestedIDHackTempStorage id_hack_storage;
|
||||
id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
|
||||
|
||||
@@ -384,6 +384,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
|
||||
BLI_remlink(curarm->edbo, curbone);
|
||||
BLI_addtail(arm->edbo, curbone);
|
||||
|
||||
/* Pose channel is moved from one storage to another, its UUID is still unique. */
|
||||
BLI_remlink(&opose->chanbase, pchan);
|
||||
BLI_addtail(&pose->chanbase, pchan);
|
||||
BKE_pose_channels_hash_free(opose);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_session_uuid_types.h"
|
||||
#include "DNA_userdef_types.h" /* ThemeWireColor */
|
||||
#include "DNA_vec_types.h"
|
||||
#include "DNA_view2d_types.h"
|
||||
@@ -188,6 +189,8 @@ struct DualQuat;
|
||||
struct Mat4;
|
||||
|
||||
typedef struct bPoseChannel_Runtime {
|
||||
SessionUUID session_uuid;
|
||||
|
||||
/* Cached dual quaternion for deformation. */
|
||||
struct DualQuat deform_dual_quat;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user