Fix T63332: backup and restore bPoseChannel_Runtime data during COW.
This commit is contained in:
@@ -35,6 +35,7 @@ struct bActionGroup;
|
||||
struct bItasc;
|
||||
struct bPose;
|
||||
struct bPoseChannel;
|
||||
struct bPoseChannel_Runtime;
|
||||
|
||||
/* Kernel prototypes */
|
||||
#ifdef __cplusplus
|
||||
@@ -132,7 +133,10 @@ void action_groups_clear_tempflags(struct bAction *act);
|
||||
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_free_bbone_cache(struct bPoseChannel *pchan);
|
||||
void BKE_pose_channel_runtime_reset(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);
|
||||
|
||||
void BKE_pose_channels_free(struct bPose *pose);
|
||||
void BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_user);
|
||||
|
||||
@@ -793,15 +793,25 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
|
||||
/* Cached data, for new draw manager rendering code. */
|
||||
MEM_SAFE_FREE(pchan->draw_data);
|
||||
|
||||
/* Cached B-Bone shape data. */
|
||||
BKE_pose_channel_free_bbone_cache(pchan);
|
||||
/* Cached B-Bone shape and other data. */
|
||||
BKE_pose_channel_runtime_free(&pchan->runtime);
|
||||
}
|
||||
|
||||
/** Clears the runtime cache of a pose channel without free. */
|
||||
void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime)
|
||||
{
|
||||
memset(runtime, 0, sizeof(*runtime));
|
||||
}
|
||||
|
||||
/** Deallocates runtime cache of a pose channel */
|
||||
void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime)
|
||||
{
|
||||
BKE_pose_channel_free_bbone_cache(runtime);
|
||||
}
|
||||
|
||||
/** Deallocates runtime cache of a pose channel's B-Bone shape. */
|
||||
void BKE_pose_channel_free_bbone_cache(bPoseChannel *pchan)
|
||||
void BKE_pose_channel_free_bbone_cache(bPoseChannel_Runtime *runtime)
|
||||
{
|
||||
bPoseChannel_Runtime *runtime = &pchan->runtime;
|
||||
|
||||
runtime->bbone_segments = 0;
|
||||
MEM_SAFE_FREE(runtime->bbone_rest_mats);
|
||||
MEM_SAFE_FREE(runtime->bbone_pose_mats);
|
||||
|
||||
@@ -948,9 +948,7 @@ static void allocate_bbone_cache(bPoseChannel *pchan, int segments)
|
||||
bPoseChannel_Runtime *runtime = &pchan->runtime;
|
||||
|
||||
if (runtime->bbone_segments != segments) {
|
||||
if (runtime->bbone_segments != 0) {
|
||||
BKE_pose_channel_free_bbone_cache(pchan);
|
||||
}
|
||||
BKE_pose_channel_free_bbone_cache(runtime);
|
||||
|
||||
runtime->bbone_segments = segments;
|
||||
runtime->bbone_rest_mats = MEM_malloc_arrayN(
|
||||
@@ -1020,7 +1018,7 @@ void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pcha
|
||||
int segments = runtime_from->bbone_segments;
|
||||
|
||||
if (segments <= 1) {
|
||||
BKE_pose_channel_free_bbone_cache(pchan);
|
||||
BKE_pose_channel_free_bbone_cache(&pchan->runtime);
|
||||
}
|
||||
else {
|
||||
allocate_bbone_cache(pchan, segments);
|
||||
|
||||
@@ -613,7 +613,7 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec
|
||||
|
||||
/* Free B-Bone shape data cache if it's not a B-Bone. */
|
||||
if (pchan->bone == NULL || pchan->bone->segments <= 1) {
|
||||
BKE_pose_channel_free_bbone_cache(pchan);
|
||||
BKE_pose_channel_free_bbone_cache(&pchan->runtime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,7 +723,7 @@ void BKE_pose_bone_done(struct Depsgraph *depsgraph, struct Object *object, int
|
||||
copy_m4_m4(pchan_orig->constinv, pchan->constinv);
|
||||
BKE_pose_where_is_bone_tail(pchan_orig);
|
||||
if (pchan->bone == NULL || pchan->bone->segments <= 1) {
|
||||
BKE_pose_channel_free_bbone_cache(pchan_orig);
|
||||
BKE_pose_channel_free_bbone_cache(&pchan_orig->runtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5502,7 +5502,7 @@ static void direct_link_pose(FileData *fd, bPose *pose)
|
||||
CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
|
||||
|
||||
pchan->draw_data = NULL;
|
||||
memset(&pchan->runtime, 0, sizeof(pchan->runtime));
|
||||
BKE_pose_channel_runtime_reset(&pchan->runtime);
|
||||
}
|
||||
pose->ikdata = NULL;
|
||||
if (pose->ikparam != NULL) {
|
||||
|
||||
@@ -841,6 +841,9 @@ class ModifierDataBackupID {
|
||||
/* Storage for backed up runtime modifier data. */
|
||||
typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup;
|
||||
|
||||
/* Storage for backed up pose channel runtime data. */
|
||||
typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup;
|
||||
|
||||
struct ObjectRuntimeBackup {
|
||||
ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0)
|
||||
{
|
||||
@@ -853,16 +856,19 @@ struct ObjectRuntimeBackup {
|
||||
* pointers. */
|
||||
void init_from_object(Object *object);
|
||||
void backup_modifier_runtime_data(Object *object);
|
||||
void backup_pose_channel_runtime_data(Object *object);
|
||||
|
||||
/* Restore all fields to the given object. */
|
||||
void restore_to_object(Object *object);
|
||||
/* NOTE: Will free all runtime data which has not been restored. */
|
||||
void restore_modifier_runtime_data(Object *object);
|
||||
void restore_pose_channel_runtime_data(Object *object);
|
||||
|
||||
Object_Runtime runtime;
|
||||
short base_flag;
|
||||
unsigned short base_local_view_bits;
|
||||
ModifierRuntimeDataBackup modifier_runtime_data;
|
||||
PoseChannelRuntimeDataBackup pose_channel_runtime_data;
|
||||
};
|
||||
|
||||
void ObjectRuntimeBackup::init_from_object(Object *object)
|
||||
@@ -884,6 +890,8 @@ void ObjectRuntimeBackup::init_from_object(Object *object)
|
||||
base_local_view_bits = object->base_local_view_bits;
|
||||
/* Backup tuntime data of all modifiers. */
|
||||
backup_modifier_runtime_data(object);
|
||||
/* Backup runtime data of all pose channels. */
|
||||
backup_pose_channel_runtime_data(object);
|
||||
}
|
||||
|
||||
inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data)
|
||||
@@ -905,6 +913,19 @@ void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object)
|
||||
{
|
||||
if (object->pose != NULL) {
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
|
||||
/* This is NULL in Edit mode. */
|
||||
if (pchan->orig_pchan != NULL) {
|
||||
pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime;
|
||||
BKE_pose_channel_runtime_reset(&pchan->runtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRuntimeBackup::restore_to_object(Object *object)
|
||||
{
|
||||
Mesh *mesh_orig = object->runtime.mesh_orig;
|
||||
@@ -941,6 +962,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
|
||||
/* Restore modifier's runtime data.
|
||||
* NOTE: Data of unused modifiers will be freed there. */
|
||||
restore_modifier_runtime_data(object);
|
||||
restore_pose_channel_runtime_data(object);
|
||||
}
|
||||
|
||||
void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
|
||||
@@ -967,6 +989,26 @@ void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object)
|
||||
{
|
||||
if (object->pose != NULL) {
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
|
||||
/* This is NULL in Edit mode. */
|
||||
if (pchan->orig_pchan != NULL) {
|
||||
PoseChannelRuntimeDataBackup::iterator runtime_data_iterator =
|
||||
pose_channel_runtime_data.find(pchan->orig_pchan);
|
||||
if (runtime_data_iterator != pose_channel_runtime_data.end()) {
|
||||
pchan->runtime = runtime_data_iterator->second;
|
||||
pose_channel_runtime_data.erase(runtime_data_iterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) {
|
||||
BKE_pose_channel_runtime_free(&value.second);
|
||||
}
|
||||
}
|
||||
|
||||
class RuntimeBackup {
|
||||
public:
|
||||
RuntimeBackup() : drawdata_ptr(NULL)
|
||||
|
||||
Reference in New Issue
Block a user