From befc0827362da04cfff41e057e789159ab5bb0b5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 29 Nov 2019 15:48:32 +0100 Subject: Fix T71908: Animated properties are lost after frame-post handler The issue was caused by special handling of animation update after manual edits in frame_post handler: to avid loss of manual edits done on top of animated property. This was done as a separate pass for non-animation update after frame_post did modifications. This caused some other side-effect: non-modified animated property was re-setting to the value which is used in the viewport. Idea of this solution is simple: preserve values which came from animation update through copy-on-write process. The actual process of this is a bit involved: need to decode RNA path and do it twice since f-curve might point to a sub-data which pointer will change. Since this is only done for non-active depsgraph (aka depsgraph used for render pipeline) this is probably fine since all this extra overhead is just a fraction of overall render process. Differential Revision: https://developer.blender.org/D6330 --- source/blender/depsgraph/CMakeLists.txt | 2 + .../intern/eval/deg_eval_runtime_backup.cc | 7 +- .../intern/eval/deg_eval_runtime_backup.h | 2 + .../eval/deg_eval_runtime_backup_animation.cc | 139 +++++++++++++++++++++ .../eval/deg_eval_runtime_backup_animation.h | 64 ++++++++++ 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h (limited to 'source/blender/depsgraph') diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 4abeec19645..7f3c7d5043f 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -59,6 +59,7 @@ set(SRC intern/eval/deg_eval_copy_on_write.cc intern/eval/deg_eval_flush.cc intern/eval/deg_eval_runtime_backup.cc + intern/eval/deg_eval_runtime_backup_animation.cc intern/eval/deg_eval_runtime_backup_modifier.cc intern/eval/deg_eval_runtime_backup_movieclip.cc intern/eval/deg_eval_runtime_backup_object.cc @@ -108,6 +109,7 @@ set(SRC intern/eval/deg_eval_copy_on_write.h intern/eval/deg_eval_flush.h intern/eval/deg_eval_runtime_backup.h + intern/eval/deg_eval_runtime_backup_animation.h intern/eval/deg_eval_runtime_backup_modifier.h intern/eval/deg_eval_runtime_backup_movieclip.h intern/eval/deg_eval_runtime_backup_object.h diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc index 88390ab412f..4da5ca77fb8 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -32,7 +32,8 @@ namespace DEG { RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) - : scene_backup(depsgraph), + : animation_backup(depsgraph), + scene_backup(depsgraph), sound_backup(depsgraph), object_backup(depsgraph), drawdata_ptr(NULL), @@ -47,6 +48,8 @@ void RuntimeBackup::init_from_id(ID *id) return; } + animation_backup.init_from_id(id); + const ID_Type id_type = GS(id->name); switch (id_type) { case ID_OB: @@ -76,6 +79,8 @@ void RuntimeBackup::init_from_id(ID *id) void RuntimeBackup::restore_to_id(ID *id) { + animation_backup.restore_to_id(id); + const ID_Type id_type = GS(id->name); switch (id_type) { case ID_OB: diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h index 31ae3164e37..892cc88002f 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -25,6 +25,7 @@ #include "DNA_ID.h" +#include "intern/eval/deg_eval_runtime_backup_animation.h" #include "intern/eval/deg_eval_runtime_backup_movieclip.h" #include "intern/eval/deg_eval_runtime_backup_object.h" #include "intern/eval/deg_eval_runtime_backup_scene.h" @@ -44,6 +45,7 @@ class RuntimeBackup { /* Restore fields to the given ID. */ void restore_to_id(ID *id); + AnimationBackup animation_backup; SceneBackup scene_backup; SoundBackup sound_backup; ObjectRuntimeBackup object_backup; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc new file mode 100644 index 00000000000..0a6f0641fcf --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc @@ -0,0 +1,139 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_animation.h" + +#include "DNA_anim_types.h" + +#include "BKE_animsys.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#include "intern/depsgraph.h" + +namespace DEG { + +namespace { + +struct AnimatedPropertyStoreCalbackData { + AnimationBackup *backup; + + /* ID which needs to be stored. + * Is used to check possibly nested IDs which f-curves are pointing to. */ + ID *id; + + PointerRNA id_pointer_rna; +}; + +void animated_property_store_cb(ID *id, FCurve *fcurve, void *data_v) +{ + AnimatedPropertyStoreCalbackData *data = reinterpret_cast( + data_v); + if (fcurve->rna_path == NULL || fcurve->rna_path[0] == '\0') { + return; + } + if (id != data->id) { + return; + } + + /* Resolve path to the property. */ + PathResolvedRNA resolved_rna; + if (!RNA_path_resolve_property_full(&data->id_pointer_rna, + fcurve->rna_path, + &resolved_rna.ptr, + &resolved_rna.prop, + &resolved_rna.prop_index)) { + return; + } + + /* Read property value. */ + float value; + if (!BKE_animsys_read_rna_setting(&resolved_rna, &value)) { + return; + } + + data->backup->values_backup.emplace_back(fcurve->rna_path, value); +} + +} // namespace + +AnimationValueBackup::AnimationValueBackup() +{ +} + +AnimationValueBackup::AnimationValueBackup(const string &rna_path, float value) + : rna_path(rna_path), value(value) +{ +} + +AnimationValueBackup::~AnimationValueBackup() +{ +} + +AnimationBackup::AnimationBackup(const Depsgraph *depsgraph) +{ + meed_value_backup = !depsgraph->is_active; + reset(); +} + +void AnimationBackup::reset() +{ +} + +void AnimationBackup::init_from_id(ID *id) +{ + AnimatedPropertyStoreCalbackData data; + data.backup = this; + data.id = id; + RNA_id_pointer_create(id, &data.id_pointer_rna); + BKE_fcurves_id_cb(id, animated_property_store_cb, &data); +} + +void AnimationBackup::restore_to_id(ID *id) +{ + PointerRNA id_pointer_rna; + RNA_id_pointer_create(id, &id_pointer_rna); + for (const AnimationValueBackup &value_backup : values_backup) { + /* Resolve path to the property. + * + * NOTE: Do it again (after storing), since the sub-data [ointers might be + * changed after copy-on-write. + */ + PathResolvedRNA resolved_rna; + if (!RNA_path_resolve_property_full(&id_pointer_rna, + value_backup.rna_path.c_str(), + &resolved_rna.ptr, + &resolved_rna.prop, + &resolved_rna.prop_index)) { + return; + } + + /* Write property value. */ + if (!BKE_animsys_write_rna_setting(&resolved_rna, value_backup.value)) { + return; + } + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h new file mode 100644 index 00000000000..8c111107f36 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "BKE_modifier.h" + +#include "intern/depsgraph_type.h" + +namespace DEG { + +struct Depsgraph; + +class AnimationValueBackup { + public: + AnimationValueBackup(); + AnimationValueBackup(const string &rna_path, float value); + ~AnimationValueBackup(); + + AnimationValueBackup(const AnimationValueBackup &other) = default; + AnimationValueBackup(AnimationValueBackup &&other) noexcept = default; + + AnimationValueBackup &operator=(const AnimationValueBackup &other) = default; + AnimationValueBackup &operator=(AnimationValueBackup &&other) = default; + + string rna_path; + float value; +}; + +/* Backup of animated properties values. */ +class AnimationBackup { + public: + AnimationBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_id(ID *id); + void restore_to_id(ID *id); + + bool meed_value_backup; + vector values_backup; +}; + +} // namespace DEG -- cgit v1.2.3