e73afd97d31c07f51cc463d9a4879cf0e59d39bf
[synfig.git] /
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_dynamiclist.h
3 **      \brief Header file for implementation of the "Dynamic List" valuenode conversion.
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === S T A R T =========================================================== */
24
25 #ifndef __SYNFIG_VALUENODE_DYNAMICLIST_H
26 #define __SYNFIG_VALUENODE_DYNAMICLIST_H
27
28 /* === H E A D E R S ======================================================= */
29
30 #include <vector>
31 #include <list>
32
33 #include "valuenode.h"
34 #include "time.h"
35 #include "uniqueid.h"
36 #include "activepoint.h"
37
38 /* === M A C R O S ========================================================= */
39
40 /* === C L A S S E S & S T R U C T S ======================================= */
41
42 namespace synfig {
43 class ValueNode_BLine;
44 class Canvas;
45
46 /*! \class ValueNode_DynamicList
47 **      \brief Animated List ValueNode
48 **
49 **      This ValueNode was originally set up to have a list
50 **      of ValueNodes and their associated "on" and "off" points.
51 **      ie: Any time that was directly after an "on" point,
52 **      the item would be "on", and any time that was directly
53 **      after an "off" point would be "off". This is pretty intuitive.
54 **      However, it does have its problems.
55 **
56 **      The problems arise when we introduce the concept of a
57 **      Keyframe. Keyframes can be manipulated via the Synfig
58 **      Application Library. They allow the user to quickly
59 **      and "automagically" rearrange an animation by moving
60 **      the associated keyframes. With the old way that the
61 **      "on" and "off" points were handled, this task became
62 **      overly complicated.
63 **
64 **      What is required is a "symmetric" system of describing
65 **      "on" and "off" points. Instead of the point representing
66 **      the state of the item after that point in time, we have
67 **      the point represent <i>only that frame</i>. The state
68 **      of the item is calculated by looking at the points
69 **      around it: If either (or both) points are "on", then the
70 **      current state is "on". Otherwise, the point is "off"
71 **
72 **      This may be a bit confusing at first, but it is required
73 **      if we want the keyframe mechanism to "just work".
74 */
75 class ValueNode_DynamicList : public LinkableValueNode
76 {
77 public:
78
79         /*! \class ListEntry
80         **      \brief Contains a potential list item, and associated timing information
81         **
82         **      This structure contains a RHandle to a ValueNode,
83         **      as well as the associated on/off timing information
84         **      which determines when this item is included in the list.
85         **
86         **      The timing information is stored in the member <tt>timing_info</tt>.
87         */
88         struct ListEntry : public UniqueID
89         {
90                 friend class ValueNode_DynamicList;
91                 friend class ValueNode_BLine;
92         public:
93                 typedef synfig::Activepoint Activepoint;
94
95                 typedef std::list<Activepoint> ActivepointList;
96
97                 typedef std::pair<ActivepointList::iterator,bool>               findresult;
98                 typedef std::pair<ActivepointList::const_iterator,bool> const_findresult;
99
100
101         private:
102                 mutable Node::time_set  times;
103         public:
104                 ValueNode::RHandle value_node;
105
106                 ActivepointList timing_info;
107
108         private:
109                 int index;
110                 etl::loose_handle<ValueNode> parent_;
111                 void set_parent_value_node(const etl::loose_handle<ValueNode> &x) { parent_=x; }
112
113         public:
114
115                 int get_index()const { return index; }
116
117
118                 bool status_at_time(const Time &x)const;
119
120                 float amount_at_time(const Time &x, bool *rising=0)const;
121
122                 ActivepointList::iterator add(Time time, bool status, int priority=0);
123                 ActivepointList::iterator add(const Activepoint &x);
124
125                 findresult find_uid(const UniqueID& x);
126                 const_findresult find_uid(const UniqueID& x)const;
127
128                 findresult find_time(const Time& x);
129                 const_findresult find_time(const Time& x)const;
130
131                 ActivepointList::iterator find(const UniqueID& x);
132                 ActivepointList::const_iterator find(const UniqueID& x)const;
133                 ActivepointList::iterator find(const Time& x);
134                 ActivepointList::const_iterator find(const Time& x)const;
135                 ActivepointList::iterator find_prev(const Time& x);
136                 ActivepointList::const_iterator find_prev(const Time& x)const;
137                 ActivepointList::iterator find_next(const Time& x);
138                 ActivepointList::const_iterator find_next(const Time& x)const;
139
140                 Activepoint new_activepoint_at_time(const Time& x)const;
141
142                 ActivepointList::iterator add(Time time)
143                         { return add(time, status_at_time(time)); }
144
145                 void erase(const UniqueID& x);
146
147                 int find(const Time& begin,const Time& end,std::vector<Activepoint*>& list);
148
149                 const synfig::Node::time_set    &get_times() const;
150
151                 const etl::loose_handle<ValueNode> &get_parent_value_node()const { return parent_; }
152
153                 ListEntry();
154                 ListEntry(const ValueNode::Handle &value_node);
155                 ListEntry(const ValueNode::Handle &value_node,Time begin, Time end);
156         }; // END of struct ValueNode_DynamicList::ListEntry
157
158         typedef etl::handle<ValueNode_DynamicList> Handle;
159         typedef etl::handle<const ValueNode_DynamicList> ConstHandle;
160
161 protected:
162         ValueNode_DynamicList(ValueBase::Type container_type=ValueBase::TYPE_NIL);
163
164         ValueBase::Type container_type;
165
166         bool loop_;
167
168
169 public:
170         std::vector<ListEntry> list;
171
172 public:
173
174         void add(const ValueNode::Handle &value_node, int index=-1);
175         void add(const ListEntry &value_node, int index=-1);
176         void erase(const ValueNode::Handle &value_node);
177         void reindex();
178
179         int find_next_valid_entry(int x, Time t)const;
180         int find_prev_valid_entry(int x, Time t)const;
181
182         virtual ValueNode::LooseHandle get_link_vfunc(int i)const;
183
184         virtual int link_count()const;
185
186         virtual String link_name(int i)const;
187
188         virtual ValueBase operator()(Time t)const;
189
190         virtual ~ValueNode_DynamicList();
191
192         virtual String link_local_name(int i)const;
193         virtual int get_link_index_from_name(const String &name)const;
194
195         virtual String get_name()const;
196         virtual String get_local_name()const;
197
198         bool get_loop()const { return loop_; }
199         void set_loop(bool x) { loop_=x; }
200
201         void set_member_canvas(etl::loose_handle<Canvas>);
202
203         ValueBase::Type get_contained_type()const;
204
205
206         template <typename iterator> static Handle
207         create(iterator begin, iterator end)
208         {
209                 Handle ret=create((*begin)->get_type());
210                 for(;begin!=end;++begin)
211                         ret->add(ListEntry(*begin));
212                 return ret;
213         }
214
215         void insert_time(const Time& location, const Time& delta);
216         //void manipulate_time(const Time& old_begin,const Time& old_end,const Time& new_begin,const Time& new_end);
217
218         virtual ValueNode* clone(const GUID& deriv_guid=GUID())const;
219
220         virtual ListEntry create_list_entry(int index, Time time=0, Real origin=0.5);
221
222 protected:
223
224         virtual bool set_link_vfunc(int i,ValueNode::Handle x);
225         LinkableValueNode* create_new()const;
226
227         virtual void get_times_vfunc(Node::time_set &set) const;
228
229 public:
230         /*! \note The construction parameter (\a id) is the type that the list
231         **      contains, rather than the type that it will yield
232         **      (which is ValueBase::TYPE_LIST)
233         */
234         static Handle create(ValueBase::Type id=ValueBase::TYPE_NIL);
235         using synfig::LinkableValueNode::get_link_vfunc;
236         using synfig::LinkableValueNode::set_link_vfunc;
237         static bool check_type(ValueBase::Type type);
238         static ValueNode_DynamicList* create_from(const ValueBase &x=ValueBase::TYPE_GRADIENT);
239 }; // END of class ValueNode_DynamicList
240
241 typedef ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
242 typedef ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
243
244 }; // END of namespace synfig
245
246 /* === E N D =============================================================== */
247
248 #endif