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
This commit is contained in:
Sergey Sharybin 2019-11-29 15:48:32 +01:00
parent c3d6929e4f
commit befc082736
Notes: blender-bot 2023-02-14 08:08:56 +01:00
Referenced by issue #73077, Blender exits incorrectly when editing any keyframe
Referenced by issue #73029, 2.83: Unable to move, grab, or duplicate keyframes in any editor without a Crash
Referenced by issue #73029, 2.83: Unable to move, grab, or duplicate keyframes in any editor without a Crash
Referenced by issue #71908, Keyframed parameters are not preserved when frame_change_post handler is used
5 changed files with 213 additions and 1 deletions

View File

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

View File

@ -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:

View File

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

View File

@ -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<AnimatedPropertyStoreCalbackData *>(
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

View File

@ -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<AnimationValueBackup> values_backup;
};
} // namespace DEG