improved intelligent keyframe cache invalidation
Some minor code cleanups and also implementing invalidation when removing or moving a keyframe.
This commit is contained in:
+61
-35
@@ -201,18 +201,23 @@ void NodeInput::insert_keyframe(NodeKeyframePtr key)
|
||||
connect(key.get(), &NodeKeyframe::ValueChanged, this, &NodeInput::KeyframeValueChanged);
|
||||
|
||||
emit KeyframeAdded(key);
|
||||
|
||||
emit_range_affected_by_keyframe(key.get());
|
||||
}
|
||||
|
||||
void NodeInput::remove_keyframe(NodeKeyframePtr key)
|
||||
{
|
||||
Q_ASSERT(is_keyframable() && keyframes_.size() > 1);
|
||||
|
||||
TimeRange time_affected = get_range_affected_by_keyframe(key.get());
|
||||
|
||||
disconnect(key.get(), &NodeKeyframe::TimeChanged, this, &NodeInput::KeyframeTimeChanged);
|
||||
disconnect(key.get(), &NodeKeyframe::ValueChanged, this, &NodeInput::KeyframeValueChanged);
|
||||
|
||||
keyframes_.removeOne(key);
|
||||
|
||||
emit KeyframeRemoved(key);
|
||||
emit_time_range(time_affected);
|
||||
}
|
||||
|
||||
void NodeInput::KeyframeTimeChanged()
|
||||
@@ -222,54 +227,30 @@ void NodeInput::KeyframeTimeChanged()
|
||||
|
||||
Q_ASSERT(keyframe_index > -1);
|
||||
|
||||
TimeRange original_range = get_range_around_index(keyframe_index);
|
||||
|
||||
if ((keyframe_index > 0 && keyframes_.at(keyframe_index - 1)->time() > key->time())
|
||||
|| (keyframe_index < keyframes_.size() - 1 && keyframes_.at(keyframe_index + 1)->time() < key->time())) {
|
||||
// This keyframe needs resorting, store it and remove it from the list
|
||||
NodeKeyframePtr key_shared_ptr = keyframes_.at(keyframe_index);
|
||||
|
||||
keyframes_.removeAt(keyframe_index);
|
||||
|
||||
// Automatically insertion sort
|
||||
insert_keyframe_internal(key_shared_ptr);
|
||||
|
||||
// Invalidate new area that the keyframe has been moved to
|
||||
emit_range_affected_by_keyframe(key_shared_ptr.get());
|
||||
}
|
||||
|
||||
// Invalidate entire area surrounding the keyframe (either where it currently is, or where it used to be before it
|
||||
// was resorted in the if block above)
|
||||
emit_time_range(original_range);
|
||||
}
|
||||
|
||||
void NodeInput::KeyframeValueChanged()
|
||||
{
|
||||
NodeKeyframe* key = static_cast<NodeKeyframe*>(sender());
|
||||
int keyframe_index = FindIndexOfKeyframeFromRawPtr(key);
|
||||
|
||||
rational range_begin = RATIONAL_MIN;
|
||||
rational range_end = RATIONAL_MAX;
|
||||
|
||||
if (keyframes_.size() > 1) {
|
||||
if (keyframe_index == 0) {
|
||||
// This is the earliest keyframe, all we need to do is invalidate the earliest point up until the next keyframe
|
||||
range_end = keyframes_.at(1)->time();
|
||||
} else {
|
||||
// Range is somewhere in the middle or towards the end
|
||||
|
||||
// Check previous keyframe
|
||||
NodeKeyframePtr previous_key = keyframes_.at(keyframe_index - 1);
|
||||
if (previous_key->type() == NodeKeyframe::kHold) {
|
||||
// If the PREVIOUS keyframe is a hold, it won't be affected by this
|
||||
range_begin = key->time();
|
||||
} else {
|
||||
// Otherwise, the frames between the previous and this keyframe will be affected too
|
||||
range_begin = previous_key->time();
|
||||
}
|
||||
|
||||
// Check if this keyframe is the last keyframe
|
||||
if (keyframe_index == keyframes_.size() - 1) {
|
||||
// If so, we'll invalidate until the latest point
|
||||
range_end = RATIONAL_MAX;
|
||||
} else {
|
||||
// Otherwise, we only need to invalidate up until the next keyframe
|
||||
range_end = keyframes_.at(keyframe_index + 1)->time();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit ValueChanged(range_begin, range_end);
|
||||
emit_range_affected_by_keyframe(static_cast<NodeKeyframe*>(sender()));
|
||||
}
|
||||
|
||||
int NodeInput::FindIndexOfKeyframeFromRawPtr(NodeKeyframe *raw_ptr) const
|
||||
@@ -305,6 +286,51 @@ bool NodeInput::is_using_standard_value() const
|
||||
return (!is_keyframing() || keyframes_.isEmpty());
|
||||
}
|
||||
|
||||
TimeRange NodeInput::get_range_affected_by_keyframe(NodeKeyframe *key) const
|
||||
{
|
||||
int keyframe_index = FindIndexOfKeyframeFromRawPtr(key);
|
||||
|
||||
TimeRange range = get_range_around_index(keyframe_index);
|
||||
|
||||
// If a previous key exists and it's a hold, we don't need to invalidate those frames
|
||||
if (keyframes().size() > 1
|
||||
&& keyframe_index > 0
|
||||
&& keyframes_.at(keyframe_index - 1)->type() == NodeKeyframe::kHold) {
|
||||
range.set_in(key->time());
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
TimeRange NodeInput::get_range_around_index(int index) const
|
||||
{
|
||||
rational range_begin = RATIONAL_MIN;
|
||||
rational range_end = RATIONAL_MAX;
|
||||
|
||||
if (keyframes_.size() > 1) {
|
||||
if (index > 0) {
|
||||
// If this is not the first key, we'll need to limit it to the key just before
|
||||
range_begin = keyframes_.at(index - 1)->time();
|
||||
}
|
||||
if (index < keyframes_.size() - 1) {
|
||||
// If this is not the last key, we'll need to limit it to the key just after
|
||||
range_end = keyframes_.at(index + 1)->time();
|
||||
}
|
||||
}
|
||||
|
||||
return TimeRange(range_begin, range_end);
|
||||
}
|
||||
|
||||
void NodeInput::emit_time_range(const TimeRange &range)
|
||||
{
|
||||
emit ValueChanged(range.in(), range.out());
|
||||
}
|
||||
|
||||
void NodeInput::emit_range_affected_by_keyframe(NodeKeyframe *key)
|
||||
{
|
||||
emit_time_range(get_range_affected_by_keyframe(key));
|
||||
}
|
||||
|
||||
bool NodeInput::has_keyframe_at_time(const rational &time) const
|
||||
{
|
||||
// If we aren't keyframing, there definitely isn't a keyframe at a given time
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifndef NODEINPUT_H
|
||||
#define NODEINPUT_H
|
||||
|
||||
#include "common/timerange.h"
|
||||
#include "keyframe.h"
|
||||
#include "param.h"
|
||||
|
||||
@@ -194,6 +195,26 @@ private:
|
||||
*/
|
||||
bool is_using_standard_value() const;
|
||||
|
||||
/**
|
||||
* @brief Intelligently determine how what time range is affected by a keyframe
|
||||
*/
|
||||
TimeRange get_range_affected_by_keyframe(NodeKeyframe *key) const;
|
||||
|
||||
/**
|
||||
* @brief Gets a time range between the previous and next keyframes of index
|
||||
*/
|
||||
TimeRange get_range_around_index(int index) const;
|
||||
|
||||
/**
|
||||
* @brief Convenience function - equivalent to calling `emit ValueChanged(range.in(), range.out())`
|
||||
*/
|
||||
void emit_time_range(const TimeRange& range);
|
||||
|
||||
/**
|
||||
* @brief Convenience function - equivalent to calling `emit_time_range(get_range_affected_by_keyframe(key))`
|
||||
*/
|
||||
void emit_range_affected_by_keyframe(NodeKeyframe* key);
|
||||
|
||||
/**
|
||||
* @brief Internal list of accepted data types
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user