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