Class Channel
Defined in File channel.hpp
Class Documentation
-
class Channel
A named, time-ordered sequence of keyframes that can be evaluated as a curve.
A Channel owns its keyframes, keeps them sorted by time, and applies the appropriate handle constraints as they are added or edited. Evaluating the channel at a given time interpolates between the surrounding keyframes according to each keyframe’s Function; times outside the keyframe range are resolved using the channel’s Extend settings.
Channels are created and owned by an Animation (the constructor is not public) via Animation::create_channel, which assigns each channel a unique, immutable Id. Channels are non-copyable; use Animation::copy_channel to duplicate one.
Public Functions
-
inline const std::string &name() const
The channel’s name.
-
inline void set_name(const std::string &name)
Renames the channel.
-
const Keyframe &create_keyframe(double time, double value, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Smooth)
Creates a keyframe at a time and value and inserts it in time order.
If a keyframe already exists within ~1/200s of
timeit is replaced rather than duplicated. The handles are computed fromhandle_mode.- Returns:
A reference to the stored keyframe.
-
const Keyframe &create_keyframe(const Point &position, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Smooth)
Creates a keyframe from a position point.
-
const Keyframe &create_keyframe(double time, double value, const Point &in_handle, const Point &out_handle, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Aligned)
Creates a keyframe with explicit in/out handles (defaults to HandleMode::Aligned).
-
const Keyframe &create_keyframe(const Point &position, const Point &in_handle, const Point &out_handle, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Aligned)
Creates a keyframe from a position point with explicit in/out handles.
-
const Keyframe &create_keyframe(const Keyframe &reference_keyframe)
Creates a keyframe by copying an existing one (replacing any keyframe at the same time).
-
const Keyframe &emplace_keyframe(Keyframe &&keyframe)
Inserts a keyframe by move, in time order.
See also
-
bool has_keyframe(double time) const
True if a keyframe exists at (approximately)
time.
-
void delete_keyframe(size_t index)
Removes the keyframe at
index.- Throws:
std::out_of_range – if
indexis out of range.
-
const Keyframe &keyframe(size_t index) const
Returns the keyframe at
index.- Throws:
std::out_of_range – if
indexis out of range.
-
inline const Keyframe &operator[](size_t index) const
Indexed access, equivalent to keyframe(index).
- Throws:
std::out_of_range – if out of range.
-
const Keyframe &prev_keyframe(double time) const
Returns the last keyframe strictly before
time.- Throws:
std::out_of_range – if the channel is empty or no earlier keyframe exists.
-
const Keyframe &next_keyframe(double time) const
Returns the first keyframe strictly after
time.- Throws:
std::out_of_range – if the channel is empty or no later keyframe exists.
-
const Keyframe &closest_keyframe(double time) const
Returns the keyframe nearest
time.- Throws:
std::out_of_range – if the channel is empty.
-
const std::vector<Keyframe> &keyframes() const
Direct read access to the time-ordered keyframe vector.
-
inline size_t size() const
Number of keyframes.
-
inline bool empty() const
True if the channel has no keyframes.
-
void update_keyframe(size_t index, const Keyframe &keyframe)
Replaces the keyframe at
index, re-sorting and re-applying constraints.- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_time(size_t index, double time)
Sets the time of keyframe
index, clamped between its neighbours.- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_value(size_t index, double value)
Sets the value of keyframe
index.- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_position(size_t index, const Point &position)
Sets the position of keyframe
index(time clamped between neighbours).- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_position(size_t index, double time, double value)
Sets the position of keyframe
indexfrom a time and value.- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_in_handle(size_t index, const Point &in_handle)
Sets the in-handle of keyframe
index(re-applying handle constraints).- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_out_handle(size_t index, const Point &out_handle)
Sets the out-handle of keyframe
index(re-applying handle constraints).- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_function(size_t index, Function function)
Sets the interpolation function of keyframe
index.- Throws:
std::out_of_range – if out of range.
-
void set_keyframe_handle_mode(size_t index, HandleMode handle_mode)
Sets the handle mode of keyframe
index.- Throws:
std::out_of_range – if out of range.
-
double evaluate(double time, double *prev_t = nullptr) const
Evaluates the channel’s value at
time.Interpolates between the surrounding keyframes; times outside the keyframe range follow the channel’s Extend settings. An empty channel returns 0.
- Parameters:
time – The time to evaluate at.
prev_t – Optional Bézier solver seed (a previous parameter in [0,1]) used only as a convergence hint; it is not modified.
- Returns:
The interpolated value.
-
std::vector<double> evaluate_range(double start_time, double end_time, int num_samples, RangeEnd range_end = RangeEnd::Exclusive) const
Evaluates
num_samplesevenly spaced values fromstart_timetoend_time.By default the range is half-open, as in evaluate_range_by_rate(): sample
iis atstart_time + i * (end_time - start_time) / num_samples, so the last sample is one step short ofend_timeandend_timeitself is not sampled. Sampling 0 to 4 with 5 samples gives 0.0, 0.8, 1.6, 2.4 and 3.2.Pass RangeEnd::Inclusive to divide the span by one less and land the last sample on
end_time, giving 0.0, 1.0, 2.0, 3.0 and 4.0 for the same call. That is what plotting a curve or building a lookup table wants, where a sample is a point rather than the interval that follows it.Exactly
num_samplesvalues are returned, including whenstart_timeandend_timeare equal, in which case they are all the value at that time.- Parameters:
range_end – Whether
end_timeis sampled; half-open by default.- Throws:
std::invalid_argument – if
num_samplesis negative, or ifstart_timeis afterend_time.- Returns:
A vector of
num_samplesvalues; empty ifnum_samplesis 0.
-
std::vector<double> evaluate_range_by_rate(double start_time, double end_time, double sample_rate, RangeEnd range_end = RangeEnd::Exclusive) const
Evaluates values from
start_timetoend_timeat a fixed sample rate.Sample
iis atstart_time + i / sample_rate, so the spacing is exactly one sample period no matter what the range is.By default the range is half-open and
end_timeis not sampled, so a span of n periods gives n samples: 4 seconds at 30 Hz yields 120 values, the last at 3.9667, not 121 ending on 4.0. Pass RangeEnd::Inclusive for the closing sample, giving 121.The two differ only when the span is a whole number of periods, since that is the only case where a sample lands on
end_time. A span that is not is rounded up either way, so the whole range is covered.- Parameters:
start_time – First time to sample.
end_time – Upper bound of the range, sampled only if
range_endis RangeEnd::Inclusive.sample_rate – Samples per unit time; must be positive.
range_end – Whether
end_timeis sampled; half-open by default.
- Throws:
std::invalid_argument – if
sample_rateis not positive, or ifstart_timeis afterend_time.- Returns:
A vector of num_samples() values, or a single value if
start_timeandend_timeare equal.
-
double start_time() const
Time of the first keyframe (0 if empty).
-
double end_time() const
Time of the last keyframe (0 if empty).
-
double length() const
Duration spanned by the keyframes (end_time() - start_time()).
-
void copy_keyframes_from(const Channel &source)
Replaces this channel’s keyframes with a copy of
source'skeyframes.Used by Animation::copy_channel; the channel’s own name and id are left unchanged.
Protected Functions
-
Channel() = delete
-
inline const std::string &name() const