1// Aseprite Document Library
2// Copyright (c) 2022 Igara Studio S.A.
3// Copyright (c) 2017 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifndef DOC_KEYFRAMES_H_INCLUDED
9#define DOC_KEYFRAMES_H_INCLUDED
10#pragma once
11
12#include "doc/frame.h"
13
14#include <memory>
15#include <vector>
16
17namespace doc {
18
19 template<typename T>
20 class Keyframes {
21 public:
22 class Key {
23 public:
24 Key(const frame_t frame,
25 std::unique_ptr<T>&& value)
26 : m_frame(frame)
27 , m_value(std::move(value)) { }
28 Key(const Key& o)
29 : m_frame(o.m_frame)
30 , m_value(o.m_value ? new T(*o.m_value): nullptr) { }
31 Key(Key&& o) = default;
32 Key& operator=(Key&& o) = default;
33 frame_t frame() const { return m_frame; }
34 T* value() const { return m_value.get(); }
35 void setFrame(const frame_t frame) { m_frame = frame; }
36 void setValue(std::unique_ptr<T>&& value) { m_value = std::move(value); }
37 private:
38 frame_t m_frame = 0;
39 std::unique_ptr<T> m_value = nullptr;
40 };
41
42 typedef std::vector<Key> List;
43 typedef typename List::iterator iterator;
44 typedef typename List::const_iterator const_iterator;
45
46 class Range {
47 public:
48 class RangeIterator {
49 public:
50 RangeIterator(const iterator& it,
51 const iterator& end, const frame_t frame)
52 : m_it(it), m_end(end), m_frame(frame) {
53 if (it != end) {
54 m_next = it;
55 ++m_next;
56 }
57 else
58 m_next = end;
59 }
60 RangeIterator& operator++() {
61 ++m_frame;
62 if (m_next != m_end &&
63 m_next->frame() == m_frame) {
64 m_it = m_next;
65 ++m_next;
66 }
67 return *this;
68 }
69 bool operator!=(const RangeIterator& other) {
70 return (m_frame != other.m_frame+1);
71 }
72 T* operator*() {
73 if (m_it != m_end)
74 return m_it->value();
75 else
76 return nullptr;
77 }
78 T* operator->() {
79 if (m_it != m_end)
80 return m_it->value();
81 else
82 return nullptr;
83 }
84 private:
85 iterator m_it, m_next;
86 const iterator m_end;
87 frame_t m_frame;
88 };
89 Range(const iterator& fromIt,
90 const iterator& endIt,
91 const frame_t from,
92 const frame_t to)
93 : m_fromIt(fromIt), m_endIt(endIt)
94 , m_from(from), m_to(to) {
95 }
96 RangeIterator begin() const {
97 return RangeIterator(m_fromIt, m_endIt, m_from);
98 }
99 RangeIterator end() const {
100 return RangeIterator(m_fromIt, m_endIt, m_to);
101 }
102 bool empty() const {
103 return (m_fromIt == m_endIt ||
104 m_to < m_fromIt->frame());
105 }
106 size_t countKeys() const {
107 size_t count = 0;
108 auto it = m_fromIt;
109 for (; it!=m_endIt; ++it) {
110 if (it->frame() > m_to)
111 break;
112 ++count;
113 }
114 return count;
115 }
116 private:
117 const iterator m_fromIt, m_endIt;
118 const frame_t m_from, m_to;
119 };
120
121 Keyframes() { }
122
123 Keyframes(const Keyframes& other) {
124 for (const auto& key : other.m_keys)
125 m_keys.push_back(Key(key.frame(), std::make_unique<T>(*key.value())));
126 }
127
128 void insert(const frame_t frame, std::unique_ptr<T>&& value) {
129 auto it = getIterator(frame);
130 if (it == end())
131 m_keys.push_back(Key(frame, std::move(value)));
132 else if (it->frame() == frame)
133 it->setValue(std::move(value));
134 else {
135 // We must insert keys in order. So if "frame" is less than
136 // the "it" frame, insert() will insert the new key before the
137 // iterator just as we want. In other case we have to use the
138 // next iterator (++it).
139 if (frame > it->frame())
140 ++it;
141 m_keys.insert(it, Key(frame, std::move(value)));
142 }
143 }
144
145 void remove(const frame_t frame) {
146 auto it = getIterator(frame);
147 if (it != end())
148 m_keys.erase(it);
149 }
150
151 T* operator[](const frame_t frame) {
152 auto it = getIterator(frame);
153 if (it != end() &&
154 it->value() &&
155 frame >= it->frame())
156 return it->value();
157 else
158 return nullptr;
159 }
160
161 iterator begin() { return m_keys.begin(); }
162 iterator end() { return m_keys.end(); }
163 const_iterator begin() const { return m_keys.begin(); }
164 const_iterator end() const { return m_keys.end(); }
165
166 std::size_t size() const { return m_keys.size(); }
167 bool empty() const { return m_keys.empty(); }
168
169 iterator getIterator(const frame_t frame) {
170 auto
171 it = m_keys.begin(),
172 end = m_keys.end();
173 auto next = it;
174 for (; it != end; it=next) {
175 ++next;
176 if (((frame >= it->frame()) &&
177 (next == end || frame < next->frame())) ||
178 (frame < it->frame())) {
179 return it;
180 }
181 }
182 return end;
183 }
184
185 frame_t fromFrame() const {
186 if (!m_keys.empty())
187 return m_keys.front().frame();
188 else
189 return -1;
190 }
191
192 frame_t toFrame() const {
193 if (!m_keys.empty())
194 return m_keys.back().frame();
195 else
196 return -1;
197 }
198
199 Range range(const frame_t from,
200 const frame_t to) {
201 return Range(getIterator(from), end(), from, to);
202 }
203
204 private:
205 List m_keys;
206 };
207
208} // namespace doc
209
210#endif
211