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