Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2019-04-18 21:19:57 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2019-04-18 21:32:17 +0300
commit7ec6bca92fd0ee4a3b1dcdf90fdba1f9d0aec11a (patch)
treeaaf24d40b196131cf62bfaa1ff3340e7c17e6bf5
parent64bcdd65bf0727c5e39ac2b3f32bf897bfbf07a1 (diff)
Fix T63332: backup and restore bPoseChannel_Runtime data during COW.
-rw-r--r--source/blender/blenkernel/BKE_action.h6
-rw-r--r--source/blender/blenkernel/intern/action.c20
-rw-r--r--source/blender/blenkernel/intern/armature.c6
-rw-r--r--source/blender/blenkernel/intern/armature_update.c4
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc42
6 files changed, 67 insertions, 13 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 08237be0a21..69f3070fcba 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index a3b7df6b020..885ddc5b9c2 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -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);
}
-/** Deallocates runtime cache of a pose channel's B-Bone shape. */
-void BKE_pose_channel_free_bbone_cache(bPoseChannel *pchan)
+/** Clears the runtime cache of a pose channel without free. */
+void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime)
{
- bPoseChannel_Runtime *runtime = &pchan->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_Runtime *runtime)
+{
runtime->bbone_segments = 0;
MEM_SAFE_FREE(runtime->bbone_rest_mats);
MEM_SAFE_FREE(runtime->bbone_pose_mats);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 69721651a45..91c760223aa 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index e6e9b561e78..bf33b1c7c50 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -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);
}
}
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 6acf0a76fa9..6e3c459ddda 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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) {
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 01b712fcd87..d134bc1ee2e 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -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)