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