24 namespace image {
class locator; }
25 using namespace std::chrono_literals;
27 template<
typename T,
typename D>
31 using data_t = std::vector<std::pair<D, std::chrono::milliseconds>>;
38 virtual const T
get_current_element(
const std::chrono::milliseconds& current_time, T default_val)
const = 0;
42 return data_.size() <= 1;
47 std::chrono::milliseconds total{0};
48 for(
const auto& entry : data_) {
49 total += entry.second;
81 progressive_pair(
const std::string& input =
"",
const std::chrono::milliseconds& duration = std::chrono::milliseconds{0})
88 const std::vector<std::string> comma_split =
utils::split(input,
',', split_flag);
89 const auto time_chunk = std::max(1ms, duration / std::max<int>(comma_split.size(), 1));
91 for(
const auto& entry : comma_split) {
92 std::vector<std::string> colon_split =
utils::split(entry,
':', split_flag);
96 time = (colon_split.size() > 1) ? std::chrono::milliseconds{std::stoi(colon_split[1])} : time_chunk;
97 }
catch(
const std::invalid_argument&) {
102 std::vector<std::string> range =
utils::split(colon_split[0],
'~',split_flag);
103 T range0 = lexical_cast<T>(range[0]);
104 T range1 = (range.size() > 1) ? lexical_cast<T>(range[1]) : range0;
106 base_data.push_back({{range0, range1}, time});
111 virtual const T
get_current_element(
const std::chrono::milliseconds& current_time, T default_val = T())
const override
114 const std::chrono::milliseconds& base_duration = progressive_pair_base_type::duration();
116 if(base_data.empty()) {
122 const std::chrono::milliseconds searched_time = std::clamp(current_time, 0ms, base_duration);
124 while(time < searched_time &&
i < base_data.size()) {
125 time += base_data[
i].second;
131 time -= base_data[
i].second;
134 const auto [first, second] = base_data[
i].first;
135 using fractional_milliseconds = std::chrono::duration<double, std::milli>;
138 fractional_milliseconds{searched_time - time} /
139 fractional_milliseconds{base_data[
i].second}
140 ) * (second - first) + first);
146 return base_data.empty() || (base_data.size() == 1 && base_data[0].first.first == base_data[0].first.second);
157 progressive_single(
const std::string& input =
"",
const std::chrono::milliseconds& duration = std::chrono::milliseconds{0})
163 auto time_chunk = std::max(duration, 1ms);
165 if(duration > 1ms && !first_pass.empty()) {
167 auto total_specified_time = 0ms;
169 for(
const std::string& fp_string : first_pass) {
170 std::vector<std::string> second_pass =
utils::split(fp_string,
':');
171 if(second_pass.size() > 1) {
173 total_specified_time += std::chrono::milliseconds{std::stoi(second_pass[1])};
174 }
catch(
const std::invalid_argument&) {
182 std::chrono::milliseconds new_time_chunk{(duration - total_specified_time) / first_pass.size()};
183 time_chunk = std::max(new_time_chunk, 1ms);
186 for(
const std::string& fp_string : first_pass) {
187 std::vector<std::string> second_pass =
utils::split(fp_string,
':');
188 if(second_pass.size() > 1) {
190 std::chrono::milliseconds time{std::stoi(second_pass[1])};
191 base_data.emplace_back(std::move(second_pass[0]), time);
192 }
catch(
const std::invalid_argument&) {
196 base_data.emplace_back(std::move(second_pass[0]), time_chunk);
201 virtual const T
get_current_element(
const std::chrono::milliseconds& current_time, T default_val = T())
const override
205 if(base_data.empty()) {
212 while(time < current_time &&
i < base_data.size()) {
213 time += base_data[
i].second;
224 return base_data[
i].first;
const data_t & data() const
virtual ~progressive_base()
std::vector< std::pair< D, std::chrono::milliseconds > > data_t
progressive_base(const std::string &input)
virtual const T get_current_element(const std::chrono::milliseconds ¤t_time, T default_val) const =0
std::string get_original() const
virtual bool does_not_change() const
std::chrono::milliseconds duration() const
progressive_pair(const std::string &input="", const std::chrono::milliseconds &duration=std::chrono::milliseconds{0})
virtual const T get_current_element(const std::chrono::milliseconds ¤t_time, T default_val=T()) const override
bool does_not_change() const override
progressive_single(const std::string &input="", const std::chrono::milliseconds &duration=std::chrono::milliseconds{0})
virtual const T get_current_element(const std::chrono::milliseconds ¤t_time, T default_val=T()) const override
New lexcical_cast header.
Functions to load and save images from/to disk.
std::vector< std::string > square_parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Similar to parenthetical_split, but also expands embedded square brackets.
std::vector< std::string > split(const config_attribute_value &val)
Thrown when a lexical_cast fails.