Add new convert type 'Time Loop' to allow individual parameters to be time looped...
[synfig.git] / synfig-core / trunk / src / synfig / valuenode.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode.cpp
3 **      \brief Implementation of the "Placeholder" valuenode conversion.
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
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 /* === H E A D E R S ======================================================= */
25
26 #define SYNFIG_NO_ANGLE
27
28 //#define HAS_HASH_MAP 1
29
30 #ifdef USING_PCH
31 #       include "pch.h"
32 #else
33 #ifdef HAVE_CONFIG_H
34 #       include <config.h>
35 #endif
36
37 #include "valuenode.h"
38 #include "general.h"
39 #include "canvas.h"
40
41 #include "valuenode_const.h"
42 #include "valuenode_linear.h"
43 #include "valuenode_composite.h"
44 #include "valuenode_reference.h"
45 #include "valuenode_scale.h"
46 #include "valuenode_blinecalctangent.h"
47 #include "valuenode_blinecalcvertex.h"
48 #include "valuenode_blinereversetangent.h"
49 #include "valuenode_segcalctangent.h"
50 #include "valuenode_segcalcvertex.h"
51 #include "valuenode_repeat_gradient.h"
52 #include "valuenode_stripes.h"
53 #include "valuenode_range.h"
54 #include "valuenode_add.h"
55 #include "valuenode_subtract.h"
56 #include "valuenode_timedswap.h"
57 #include "valuenode_twotone.h"
58 #include "valuenode_bline.h"
59 #include "valuenode_dynamiclist.h"
60 #include "valuenode_radialcomposite.h"
61 #include "valuenode_gradientrotate.h"
62 #include "valuenode_sine.h"
63 #include "valuenode_cos.h"
64 #include "valuenode_atan2.h"
65 #include "valuenode_exp.h"
66 #include "valuenode_switch.h"
67 #include "valuenode_timeloop.h"
68
69 #include "layer.h"
70
71 #endif
72
73 /* === U S I N G =========================================================== */
74
75 using namespace std;
76 using namespace etl;
77 using namespace synfig;
78
79 /* === M A C R O S ========================================================= */
80
81 /* === G L O B A L S ======================================================= */
82
83 static int value_node_count(0);
84
85 static LinkableValueNode::Book *book_;
86
87
88 ValueNode::LooseHandle
89 synfig::find_value_node(const GUID& guid)
90 {
91         return guid_cast<ValueNode>(guid);
92 }
93
94 /* === P R O C E D U R E S ================================================= */
95
96 /* === M E T H O D S ======================================================= */
97
98 bool
99 ValueNode::subsys_init()
100 {
101         book_=new LinkableValueNode::Book();
102
103 #define ADD_VALUENODE(class,name,local)                                                                                                                 \
104         (*book_)[name].factory=reinterpret_cast<LinkableValueNode::Factory>(&class::create);            \
105         (*book_)[name].check_type=&class::check_type;                                                                                           \
106         (*book_)[name].local_name=local
107
108 #define ADD_VALUENODE2(class,name,local)                                                                                                                \
109         (*book_)[name].factory=reinterpret_cast<LinkableValueNode::Factory>(&class::create_from);       \
110         (*book_)[name].check_type=&class::check_type;                                                                                           \
111         (*book_)[name].local_name=local
112
113         ADD_VALUENODE(ValueNode_Linear,                 "linear",                       _("Linear")                             );
114         ADD_VALUENODE(ValueNode_Composite,              "composite",            _("Composite")                  );
115         ADD_VALUENODE(ValueNode_RadialComposite,"radial_composite",     _("Radial Composite")   );
116         ADD_VALUENODE(ValueNode_Reference,              "reference",            _("Reference")                  );
117         ADD_VALUENODE(ValueNode_Repeat_Gradient,"repeat_gradient",      _("Repeat Gradient")    );
118         ADD_VALUENODE(ValueNode_Scale,                  "scale",                        _("Scale")                              );
119         ADD_VALUENODE(ValueNode_BLineCalcTangent,"blinecalctangent",_("BLine Tangent")          );
120         ADD_VALUENODE(ValueNode_BLineCalcVertex,"blinecalcvertex",      _("BLine Vertex")               );
121         ADD_VALUENODE(ValueNode_BLineRevTangent,"blinerevtangent",      _("Reverse Tangent")    );
122         ADD_VALUENODE(ValueNode_SegCalcTangent, "segcalctangent",       _("Segment Tangent")    );
123         ADD_VALUENODE(ValueNode_SegCalcVertex,  "segcalcvertex",        _("Segment Vertex")             );
124         ADD_VALUENODE(ValueNode_Stripes,                "stripes",                      _("Stripes")                    );
125         ADD_VALUENODE(ValueNode_Range,                  "range",                        _("Range")                              );
126         ADD_VALUENODE(ValueNode_Add,                    "add",                          _("Add")                                );
127         ADD_VALUENODE(ValueNode_Subtract,               "subtract",                     _("Subtract")                   );
128         ADD_VALUENODE(ValueNode_TimedSwap,              "timed_swap",           _("Timed Swap")                 );
129         ADD_VALUENODE(ValueNode_TwoTone,                "twotone",                      _("Two-Tone")                   );
130         ADD_VALUENODE(ValueNode_BLine,                  "bline",                        _("BLine")                              );
131         ADD_VALUENODE2(ValueNode_DynamicList,   "dynamic_list",         _("Dynamic List")               );
132         ADD_VALUENODE(ValueNode_GradientRotate, "gradient_rotate",      _("Gradient Rotate")    );
133         ADD_VALUENODE(ValueNode_Sine,                   "sine",                         _("Sine")                               );
134         ADD_VALUENODE(ValueNode_Cos,                    "cos",                          _("Cos")                                );
135         ADD_VALUENODE(ValueNode_Atan2,                  "atan2",                        _("aTan2")                              );
136         ADD_VALUENODE(ValueNode_Exp,                    "exp",                          _("Exponential")                );
137         ADD_VALUENODE(ValueNode_Switch,                 "switch",                       _("Switch")                             );
138         ADD_VALUENODE(ValueNode_TimeLoop,               "timeloop",                     _("Time Loop")                  );
139
140 #undef ADD_VALUENODE
141 #undef ADD_VALUENODE2
142
143         return true;
144 }
145
146 bool
147 ValueNode::subsys_stop()
148 {
149         delete book_;
150 /*      if(global_value_node_map.size() || value_node_count)
151         {
152                 if(value_node_count)
153                         synfig::error("%d ValueNodes haven't been destroyed yet!",value_node_count);
154
155                 if(global_value_node_map.size()!=value_node_count)
156                         synfig::error("value node count mismatch! map.size()!=value_node_count (%d!=%d)",global_value_node_map.size(),value_node_count);
157
158                 GlobalValueNodeMap::iterator iter;
159                 for(iter=global_value_node_map.begin();iter!=global_value_node_map.end();++iter)
160                 {
161                         if(!iter->second->is_exported())
162                                 synfig::info("%s: count:%d name:%s type:%s",
163                                         iter->first.get_string().c_str(),
164                                         iter->second->count(),
165                                         iter->second->get_name().c_str(),
166                                         ValueBase::type_name(iter->second->get_type()).c_str()
167                                 );
168                         else
169                                 synfig::info("%s: id:%s count:%d name:%s type:%s",
170                                         iter->first.get_string().c_str(),
171                                         iter->second->get_id().c_str(),
172                                         iter->second->count(),
173                                         iter->second->get_name().c_str(),
174                                         ValueBase::type_name(iter->second->get_type()).c_str()
175                                 );
176                 }
177         }
178 */
179         return true;
180 }
181
182 ValueNode::ValueNode(ValueBase::Type type):type(type)
183 {
184         value_node_count++;
185 }
186
187 LinkableValueNode::Book&
188 LinkableValueNode::book()
189 {
190         return *book_;
191 }
192
193 LinkableValueNode::Handle
194 LinkableValueNode::create(const String &name, const ValueBase& x)
195 {
196         if(!book().count(name))
197                 return 0;
198         return book()[name].factory(x);
199 }
200
201 bool
202 LinkableValueNode::check_type(const String &name, ValueBase::Type x)
203 {
204         if(!book().count(name) || !book()[name].check_type)
205                 return false;
206         return book()[name].check_type(x);
207 }
208
209 bool
210 LinkableValueNode::set_link(int i,ValueNode::Handle x)
211 {
212         ValueNode::Handle previous(get_link(i));
213
214         if(set_link_vfunc(i,x))
215         {
216                 if(previous)
217                         remove_child(previous.get());
218                 add_child(x.get());
219
220                 if(!x->is_exported() && get_parent_canvas())
221                 {
222                         x->set_parent_canvas(get_parent_canvas());
223                 }
224                 changed();
225                 return true;
226         }
227         return false;
228 }
229
230 ValueNode::LooseHandle
231 LinkableValueNode::get_link(int i)const
232 {
233         return get_link_vfunc(i);
234 }
235
236 void
237 LinkableValueNode::unlink_all()
238 {
239         for(int i=0;i<link_count();i++)
240         {
241                 ValueNode::LooseHandle value_node(get_link(i));
242                 if(value_node)
243                         value_node->parent_set.erase(this);
244         }
245 }
246
247 ValueNode::~ValueNode()
248 {
249         value_node_count--;
250
251         begin_delete();
252
253         //DEBUGPOINT();
254 }
255
256 void
257 ValueNode::on_changed()
258 {
259         etl::loose_handle<Canvas> parent_canvas = get_parent_canvas();
260         if(parent_canvas)
261                 do                                              // signal to all the ancestor canvases
262                         parent_canvas->signal_value_node_changed()(this);
263                 while (parent_canvas = parent_canvas->parent());
264         else if(get_root_canvas())
265                 get_root_canvas()->signal_value_node_changed()(this);
266
267         Node::on_changed();
268 }
269
270 int
271 ValueNode::replace(etl::handle<ValueNode> x)
272 {
273         if(x.get()==this)
274                 return 0;
275
276         while(parent_set.size())
277         {
278                 (*parent_set.begin())->add_child(x.get());
279                 (*parent_set.begin())->remove_child(this);
280                 //x->parent_set.insert(*parent_set.begin());
281                 //parent_set.erase(parent_set.begin());
282         }
283         int r(RHandle(this).replace(x));
284         x->changed();
285         return r;
286 }
287
288 void
289 ValueNode::set_id(const String &x)
290 {
291         if(name!=x)
292         {
293                 name=x;
294                 signal_id_changed_();
295         }
296 }
297
298 ValueNodeList::ValueNodeList():
299         placeholder_count_(0)
300 {
301 }
302
303 bool
304 ValueNodeList::count(const String &id)const
305 {
306         const_iterator iter;
307
308         if(id.empty())
309                 return false;
310
311         for(iter=begin();iter!=end() && id!=(*iter)->get_id();++iter);
312
313         if(iter==end())
314                 return false;
315
316         return true;
317 }
318
319 ValueNode::Handle
320 ValueNodeList::find(const String &id)
321 {
322         iterator iter;
323
324         if(id.empty())
325                 throw Exception::IDNotFound("Empty ID");
326
327         for(iter=begin();iter!=end() && id!=(*iter)->get_id();++iter);
328
329         if(iter==end())
330                 throw Exception::IDNotFound("ValueNode in ValueNodeList: "+id);
331
332         return *iter;
333 }
334
335 ValueNode::ConstHandle
336 ValueNodeList::find(const String &id)const
337 {
338         const_iterator iter;
339
340         if(id.empty())
341                 throw Exception::IDNotFound("Empty ID");
342
343         for(iter=begin();iter!=end() && id!=(*iter)->get_id();++iter);
344
345         if(iter==end())
346                 throw Exception::IDNotFound("ValueNode in ValueNodeList: "+id);
347
348         return *iter;
349 }
350
351 ValueNode::Handle
352 ValueNodeList::surefind(const String &id)
353 {
354         if(id.empty())
355                 throw Exception::IDNotFound("Empty ID");
356
357         ValueNode::Handle value_node;
358
359         try
360         {
361                 value_node=find(id);
362         }
363         catch(Exception::IDNotFound)
364         {
365                 value_node=PlaceholderValueNode::create();
366                 value_node->set_id(id);
367                 push_back(value_node);
368                 placeholder_count_++;
369         }
370
371         return value_node;
372 }
373
374 bool
375 ValueNodeList::erase(ValueNode::Handle value_node)
376 {
377         assert(value_node);
378
379         iterator iter;
380
381         for(iter=begin();iter!=end();++iter)
382                 if(value_node.get()==iter->get())
383                 {
384                         std::list<ValueNode::RHandle>::erase(iter);
385                         if(PlaceholderValueNode::Handle::cast_dynamic(value_node))
386                                 placeholder_count_--;
387                         return true;
388                 }
389         return false;
390 }
391
392 bool
393 ValueNodeList::add(ValueNode::Handle value_node)
394 {
395         if(!value_node)
396                 return false;
397         if(value_node->get_id().empty())
398                 return false;
399
400         try
401         {
402                 ValueNode::RHandle other_value_node=find(value_node->get_id());
403                 if(PlaceholderValueNode::Handle::cast_dynamic(other_value_node))
404                 {
405                         other_value_node->replace(value_node);
406                         placeholder_count_--;
407                         return true;
408                 }
409
410                 return false;
411         }
412         catch(Exception::IDNotFound)
413         {
414                 push_back(value_node);
415                 return true;
416         }
417
418         return false;
419 }
420
421 void
422 ValueNodeList::audit()
423 {
424         iterator iter,next;
425
426         for(next=begin(),iter=next++;iter!=end();iter=next++)
427                 if(iter->count()==1)
428                         std::list<ValueNode::RHandle>::erase(iter);
429 }
430
431
432 String
433 PlaceholderValueNode::get_name()const
434 {
435         return "placeholder";
436 }
437
438 String
439 PlaceholderValueNode::get_local_name()const
440 {
441         return _("Placeholder");
442 }
443
444 ValueNode*
445 PlaceholderValueNode::clone(const GUID& deriv_guid)const
446 {
447         ValueNode* ret(new PlaceholderValueNode());
448         ret->set_guid(get_guid()^deriv_guid);
449         return ret;
450 }
451
452 PlaceholderValueNode::Handle
453 PlaceholderValueNode::create(ValueBase::Type type)
454 {
455         return new PlaceholderValueNode(type);
456 }
457
458 ValueBase
459 PlaceholderValueNode::operator()(Time /*t*/)const
460 {
461         assert(0);
462         return ValueBase();
463 }
464
465 PlaceholderValueNode::PlaceholderValueNode(ValueBase::Type type):
466         ValueNode(type)
467 {
468 }
469
470 ValueNode*
471 LinkableValueNode::clone(const GUID& deriv_guid)const
472 {
473         // printf("%s:%d clone()\n", __FILE__, __LINE__);
474         { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)
475                                                                                                                                   {
476                                                                                                                                           printf("VALUENODE FOUND VALUENODE\n");
477                                                                                                                                           return x;
478                                                                                                                                   }}
479
480         int i;
481         LinkableValueNode *ret=create_new();
482         ret->set_guid(get_guid()^deriv_guid);
483
484         for(i=0;i<link_count();i++)
485         {
486                 ValueNode::Handle link=get_link_vfunc(i);
487                 if(!link->is_exported())
488                 {
489                         ValueNode::LooseHandle value_node(find_value_node(link->get_guid()^deriv_guid));
490                         if(!value_node)
491                                 value_node=link->clone(deriv_guid);
492                         ret->set_link(i,value_node);
493                 }
494                 else
495                         ret->set_link(i,link);
496         }
497
498         return ret;
499 }
500
501 String
502 ValueNode::get_relative_id(etl::loose_handle<const Canvas> x)const
503 {
504         assert(is_exported());
505         assert(canvas_);
506
507         if(x.get()==canvas_.get())
508                 return get_id();
509
510         return canvas_->_get_relative_id(x)+':'+get_id();
511 }
512
513 void
514 ValueNode::set_parent_canvas(etl::loose_handle<Canvas> x)
515 {
516         canvas_=x; if(x) root_canvas_=x->get_root();
517 }
518
519 void
520 ValueNode::set_root_canvas(etl::loose_handle<Canvas> x)
521 {
522         root_canvas_=x->get_root();
523 }
524
525 void LinkableValueNode::get_times_vfunc(Node::time_set &set) const
526 {
527         ValueNode::LooseHandle  h;
528
529         int size = link_count();
530
531         //just add it to the set...
532         for(int i=0; i < size; ++i)
533         {
534                 h = get_link(i);
535
536                 if(h)
537                 {
538                         const Node::time_set &tset = h->get_times();
539                         set.insert(tset.begin(),tset.end());
540                 }
541         }
542 }