Implement backup/restore for animated values

This commit is contained in:
Pedro J. Estébanez 2017-11-01 21:32:39 +01:00
parent 3f31925b18
commit ff03a0bc7b
2 changed files with 92 additions and 7 deletions

View file

@ -228,7 +228,11 @@ void AnimationPlayer::_notification(int p_what) {
}
}
void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
// Already cached?
if (p_anim->node_cache.size() == p_anim->animation->get_track_count())
return;
Node *parent = get_node(root);
@ -336,11 +340,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete) {
if (p_anim->node_cache.size() != p_anim->animation->get_track_count()) {
// animation hasn't been "node-cached"
_generate_node_caches(p_anim);
}
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
Animation *a = p_anim->animation.operator->();
@ -1205,6 +1205,70 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i
Node::get_argument_options(p_function, p_idx, r_options);
}
#ifdef TOOLS_ENABLED
AnimatedValuesBackup AnimationPlayer::backup_animated_values() {
if (!playback.current.from)
return AnimatedValuesBackup();
_ensure_node_caches(playback.current.from);
AnimatedValuesBackup backup;
for (int i = 0; i < playback.current.from->node_cache.size(); i++) {
TrackNodeCache *nc = playback.current.from->node_cache[i];
if (!nc)
continue;
if (nc->skeleton) {
if (nc->bone_idx == -1)
continue;
AnimatedValuesBackup::Entry entry;
entry.object = nc->skeleton;
entry.bone_idx = nc->bone_idx;
entry.value = nc->skeleton->get_bone_pose(nc->bone_idx);
backup.entries.push_back(entry);
} else {
if (nc->spatial) {
AnimatedValuesBackup::Entry entry;
entry.object = nc->spatial;
entry.subpath.push_back("transform");
entry.value = nc->spatial->get_transform();
entry.bone_idx = -1;
backup.entries.push_back(entry);
} else {
for (Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.front(); E; E = E->next()) {
AnimatedValuesBackup::Entry entry;
entry.object = E->value().object;
entry.subpath = E->value().subpath;
bool valid;
entry.value = E->value().object->get_indexed(E->value().subpath, &valid);
entry.bone_idx = -1;
if (valid)
backup.entries.push_back(entry);
}
}
}
}
return backup;
}
void AnimationPlayer::restore_animated_values(const AnimatedValuesBackup &p_backup) {
for (int i = 0; i < p_backup.entries.size(); i++) {
const AnimatedValuesBackup::Entry *entry = &p_backup.entries[i];
if (entry->bone_idx == -1) {
entry->object->set_indexed(entry->subpath, entry->value);
} else {
Object::cast_to<Skeleton>(entry->object)->set_bone_pose(entry->bone_idx, entry->value);
}
}
}
#endif
void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("_node_removed"), &AnimationPlayer::_node_removed);

View file

@ -38,6 +38,21 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
#ifdef TOOLS_ENABLED
// To save/restore animated values
class AnimatedValuesBackup {
struct Entry {
Object *object;
Vector<StringName> subpath; // Unused if bone
int bone_idx; // -1 if not a bone
Variant value;
};
Vector<Entry> entries;
friend class AnimationPlayer;
};
#endif
class AnimationPlayer : public Node {
GDCLASS(AnimationPlayer, Node);
OBJ_CATEGORY("Animation Nodes");
@ -198,7 +213,7 @@ private:
void _animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete = true);
void _generate_node_caches(AnimationData *p_anim);
void _ensure_node_caches(AnimationData *p_anim);
void _animation_process_data(PlaybackData &cd, float p_delta, float p_blend);
void _animation_process2(float p_delta);
void _animation_update_transforms();
@ -291,6 +306,12 @@ public:
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
#ifdef TOOLS_ENABLED
// These may be interesting for games, but are too dangerous for general use
AnimatedValuesBackup backup_animated_values();
void restore_animated_values(const AnimatedValuesBackup &p_backup);
#endif
AnimationPlayer();
~AnimationPlayer();
};