Use link_count from children vocabulary and return the stored vocabulary if already...
[synfig.git] / synfig-core / src / synfig / valuenode_composite.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_composite.cpp
3 **      \brief Implementation of the "Composite" valuenode conversion.
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2008 Chris Moore
10 **      Copyright (c) 2009 Nikita Kitaev
11 **
12 **      This package is free software; you can redistribute it and/or
13 **      modify it under the terms of the GNU General Public License as
14 **      published by the Free Software Foundation; either version 2 of
15 **      the License, or (at your option) any later version.
16 **
17 **      This package is distributed in the hope that it will be useful,
18 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
19 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 **      General Public License for more details.
21 **      \endlegal
22 */
23 /* ========================================================================= */
24
25 /* === H E A D E R S ======================================================= */
26
27 #ifdef USING_PCH
28 #       include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #       include <config.h>
32 #endif
33
34 #include "valuenode_composite.h"
35 #include "valuenode_const.h"
36 #include <stdexcept>
37 #include "general.h"
38 #include "valuenode_radialcomposite.h"
39 #include "vector.h"
40 #include "color.h"
41 #include "segment.h"
42 #include "savecanvas.h"
43
44 #endif
45
46 /* === U S I N G =========================================================== */
47
48 using namespace std;
49 using namespace etl;
50 using namespace synfig;
51
52 /* === M A C R O S ========================================================= */
53
54 /* === G L O B A L S ======================================================= */
55
56 /* === P R O C E D U R E S ================================================= */
57
58 /* === M E T H O D S ======================================================= */
59
60 synfig::ValueNode_Composite::ValueNode_Composite(const ValueBase &value):
61         LinkableValueNode(value.get_type())
62 {
63         Vocab ret(get_children_vocab());
64         set_children_vocab(ret);
65         switch(get_type())
66         {
67                 case ValueBase::TYPE_VECTOR:
68                         set_link("x",ValueNode_Const::create(value.get(Vector())[0]));
69                         set_link("y",ValueNode_Const::create(value.get(Vector())[1]));
70                         break;
71                 case ValueBase::TYPE_COLOR:
72                         set_link("r",ValueNode_Const::create(value.get(Color()).get_r()));
73                         set_link("g",ValueNode_Const::create(value.get(Color()).get_g()));
74                         set_link("b",ValueNode_Const::create(value.get(Color()).get_b()));
75                         set_link("a",ValueNode_Const::create(value.get(Color()).get_a()));
76                         break;
77                 case ValueBase::TYPE_SEGMENT:
78                         set_link("p1",ValueNode_Const::create(value.get(Segment()).p1));
79                         set_link("t1",ValueNode_Const::create(value.get(Segment()).t1));
80                         set_link("p2",ValueNode_Const::create(value.get(Segment()).p2));
81                         set_link("t2",ValueNode_Const::create(value.get(Segment()).t2));
82                         break;
83                 case ValueBase::TYPE_BLINEPOINT:
84                 {
85                         BLinePoint bline_point(value);
86                         set_link("point",ValueNode_Const::create(bline_point.get_vertex()));
87                         set_link("width",ValueNode_Const::create(bline_point.get_width()));
88                         set_link("origin",ValueNode_Const::create(bline_point.get_origin()));
89                         set_link("split",ValueNode_Const::create(bline_point.get_split_tangent_flag()));
90                         set_link("t1",ValueNode_RadialComposite::create(bline_point.get_tangent1()));
91                         set_link("t2",ValueNode_RadialComposite::create(bline_point.get_tangent2()));
92                         break;
93                 }
94                 default:
95                         assert(0);
96                         throw Exception::BadType(ValueBase::type_local_name(get_type()));
97         }
98 }
99
100 ValueNode_Composite::~ValueNode_Composite()
101 {
102         unlink_all();
103 }
104
105 ValueNode_Composite*
106 ValueNode_Composite::create(const ValueBase &value)
107 {
108         return new ValueNode_Composite(value);
109 }
110
111 LinkableValueNode*
112 ValueNode_Composite::create_new()const
113 {
114         return new ValueNode_Composite(ValueBase(get_type()));
115 }
116
117 ValueBase
118 synfig::ValueNode_Composite::operator()(Time t)const
119 {
120         if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
121                 printf("%s:%d operator()\n", __FILE__, __LINE__);
122
123         switch(get_type())
124         {
125                 case ValueBase::TYPE_VECTOR:
126                 {
127                         Vector vect;
128                         assert(components[0] && components[1]);
129                         vect[0]=(*components[0])(t).get(Vector::value_type());
130                         vect[1]=(*components[1])(t).get(Vector::value_type());
131                         return vect;
132                 }
133                 case ValueBase::TYPE_COLOR:
134                 {
135                         Color color;
136                         assert(components[0] && components[1] && components[2] && components[3]);
137                         color.set_r((*components[0])(t).get(Vector::value_type()));
138                         color.set_g((*components[1])(t).get(Vector::value_type()));
139                         color.set_b((*components[2])(t).get(Vector::value_type()));
140                         color.set_a((*components[3])(t).get(Vector::value_type()));
141                         return color;
142                 }
143                 case ValueBase::TYPE_SEGMENT:
144                 {
145                         Segment seg;
146                         assert(components[0] && components[1] && components[2] && components[3]);
147                         seg.p1=(*components[0])(t).get(Point());
148                         seg.t1=(*components[1])(t).get(Vector());
149                         seg.p2=(*components[2])(t).get(Point());
150                         seg.t2=(*components[3])(t).get(Vector());
151                         return seg;
152                 }
153                 case ValueBase::TYPE_BLINEPOINT:
154                 {
155                         BLinePoint ret;
156                         assert(components[0] && components[1] && components[2] && components[3] && components[4] && components[5]);
157                         ret.set_vertex((*components[0])(t).get(Point()));
158                         ret.set_width((*components[1])(t).get(Real()));
159                         ret.set_origin((*components[2])(t).get(Real()));
160                         ret.set_split_tangent_flag((*components[3])(t).get(bool()));
161                         ret.set_tangent1((*components[4])(t).get(Vector()));
162                         if(ret.get_split_tangent_flag())
163                                 ret.set_tangent2((*components[5])(t).get(Vector()));
164                         return ret;
165                 }
166                 default:
167                         synfig::error(string("ValueNode_Composite::operator():")+_("Bad type for composite"));
168                         assert(components[0]);
169                         return (*components[0])(t);
170         }
171 }
172
173 int
174 ValueNode_Composite::link_count()const
175 {
176         switch(get_type())
177         {
178         case ValueBase::TYPE_VECTOR:
179                 return 2;
180         case ValueBase::TYPE_COLOR:
181                 return 4;
182         case ValueBase::TYPE_SEGMENT:
183                 return 4;
184         case ValueBase::TYPE_BLINEPOINT:
185                 return 6;
186         default:
187                 synfig::warning(string("ValueNode_Composite::component_count():")+_("Bad type for composite"));
188                 return 1;
189         }
190 }
191
192 bool
193 ValueNode_Composite::set_link_vfunc(int i,ValueNode::Handle x)
194 {
195         assert(i>=0 && i<link_count());
196
197         if(PlaceholderValueNode::Handle::cast_dynamic(x))
198         {
199                 components[i]=x;
200                 return true;
201         }
202
203         switch(get_type())
204         {
205                 case ValueBase::TYPE_VECTOR:
206                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
207                         {
208                                 components[i]=x;
209                                 return true;
210                         }
211                         break;
212
213                 case ValueBase::TYPE_COLOR:
214                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
215                         {
216                                 components[i]=x;
217                                 return true;
218                         }
219                         break;
220
221                 case ValueBase::TYPE_SEGMENT:
222                         if(x->get_type()==ValueBase(Point()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
223                         {
224                                 components[i]=x;
225                                 return true;
226                         }
227                         break;
228
229                 case ValueBase::TYPE_BLINEPOINT:
230                         if((i==0 || i==4 || i==5) && x->get_type()==ValueBase(Point()).get_type())
231                         {
232                                 components[i]=x;
233                                 return true;
234                         }
235                         if((i==1 || i==2) && x->get_type()==ValueBase(Real()).get_type())
236                         {
237                                 components[i]=x;
238                                 return true;
239                         }
240                         if(i==3 && x->get_type()==ValueBase(bool()).get_type())
241                         {
242                                 components[i]=x;
243                                 return true;
244                         }
245                         break;
246
247                 default:
248                         break;
249         }
250         return false;
251 }
252
253 ValueNode::LooseHandle
254 ValueNode_Composite::get_link_vfunc(int i)const
255 {
256         assert(i>=0 && i<link_count());
257
258         return components[i];
259 }
260
261 String
262 ValueNode_Composite::link_local_name(int i)const
263 {
264         assert(i>=0 && i<link_count());
265
266         switch(get_type())
267         {
268                 case ValueBase::TYPE_VECTOR:
269                         return strprintf("%c-Axis",'X'+i);
270
271                 case ValueBase::TYPE_COLOR:
272                         if(i==0)
273                                 return _("Red");
274                         else if(i==1)
275                                 return _("Green");
276                         else if(i==2)
277                                 return _("Blue");
278                         else if(i==3)
279                                 return _("Alpha");
280
281                 case ValueBase::TYPE_SEGMENT:
282                         if(i==0)
283                                 return _("Vertex 1");
284                         else if(i==1)
285                                 return _("Tangent 1");
286                         else if(i==2)
287                                 return _("Vertex 2");
288                         else if(i==3)
289                                 return _("Tangent 2");
290
291                 case ValueBase::TYPE_BLINEPOINT:
292                         if(i==0)
293                                 return _("Vertex");
294                         else if(i==1)
295                                 return _("Width");
296                         else if(i==2)
297                                 return _("Origin");
298                         else if(i==3)
299                                 return _("Split Tangents");
300                         else if(i==4)
301                                 return _("Tangent 1");
302                         else if(i==5)
303                                 return _("Tangent 2");
304
305                 default:
306                         assert(0);
307                         // notice that Composite counts from 1 and Radial Composite counts
308                         // from 0!  we need to keep it like that to correctly load old
309                         // animations, but let's not save "c%d" format link names in future
310                         return etl::strprintf(_("C%d"),i+1);
311         }
312 }
313
314
315 String
316 ValueNode_Composite::link_name(int i)const
317 {
318         assert(i>=0 && i<link_count());
319
320         if (get_file_version() < RELEASE_VERSION_0_61_08)
321                 return strprintf("c%d",i+1);
322
323         switch(get_type())
324         {
325         case ValueBase::TYPE_COLOR:
326                 switch(i)
327                 {
328                 case 0: return "red";
329                 case 1: return "green";
330                 case 2: return "blue";
331                 case 3: return "alpha";
332                 }
333                 break;
334         case ValueBase::TYPE_SEGMENT:
335                 switch(i)
336                 {
337                 case 0: return "p1";
338                 case 1: return "t1";
339                 case 2: return "p2";
340                 case 3: return "t2";
341                 }
342                 break;
343         case ValueBase::TYPE_VECTOR:
344                 switch(i)
345                 {
346                 case 0: return "x";
347                 case 1: return "y";
348                 }
349                 break;
350         case ValueBase::TYPE_BLINEPOINT:
351                 switch(i)
352                 {
353                 case 0: return "point";
354                 case 1: return "width";
355                 case 2: return "origin";
356                 case 3: return "split";
357                 case 4: return "t1";
358                 case 5: return "t2";
359                 }
360                 break;
361         default:
362                 break;
363         }
364
365         assert(0);
366         // notice that Composite counts from 1 and Radial Composite counts
367         // from 0!  we need to keep it like that to correctly load old
368         // animations, but let's not save "c%d" format link names in future
369         return strprintf("c%d",i+1);
370 }
371
372 int
373 ValueNode_Composite::get_link_index_from_name(const String &name)const
374 {
375         if(name.empty())
376                 throw Exception::BadLinkName(name);
377
378         if(name[0]=='c' && name.size() == 2 && name[1]-'1' >= 0 && name[1]-'1' < link_count())
379                 return name[1]-'1';
380
381         switch(get_type())
382         {
383         case ValueBase::TYPE_COLOR:
384                 if(name[0]=='r')
385                         return 0;
386                 if(name[0]=='g')
387                         return 1;
388                 if(name[0]=='b')
389                         return 2;
390                 if(name[0]=='a')
391                         return 3;
392         case ValueBase::TYPE_SEGMENT:
393                 if(name=="p1")
394                         return 0;
395                 if(name=="t1")
396                         return 1;
397                 if(name=="p2")
398                         return 2;
399                 if(name=="t2")
400                         return 3;
401         case ValueBase::TYPE_VECTOR:
402                 if(name[0]=='x')
403                         return 0;
404                 if(name[0]=='y')
405                         return 1;
406                 if(name[0]=='z')                // \todo "z"?  really?
407                         return 2;
408         case ValueBase::TYPE_BLINEPOINT:
409                 if(name[0]=='p' || name=="v1" || name=="p1")
410                         return 0;
411                 if(name=="w" || name=="width")
412                         return 1;
413                 if(name=="o" || name=="origin")
414                         return 2;
415                 if(name=="split")
416                         return 3;
417                 if(name=="t1")
418                         return 4;
419                 if(name=="t2")
420                         return 5;
421         default:
422                 break;
423         }
424
425         throw Exception::BadLinkName(name);
426 }
427
428 String
429 ValueNode_Composite::get_name()const
430 {
431         return "composite";
432 }
433
434 String
435 ValueNode_Composite::get_local_name()const
436 {
437         return _("Composite");
438 }
439
440 bool
441 ValueNode_Composite::check_type(ValueBase::Type type)
442 {
443         return
444                 type==ValueBase::TYPE_SEGMENT ||
445                 type==ValueBase::TYPE_VECTOR ||
446                 type==ValueBase::TYPE_COLOR ||
447                 type==ValueBase::TYPE_BLINEPOINT;
448 }
449
450 LinkableValueNode::Vocab
451 ValueNode_Composite::get_children_vocab_vfunc()const
452 {
453         if(children_vocab.size())
454                 return children_vocab;
455
456         LinkableValueNode::Vocab ret;
457
458         switch(get_type())
459         {
460         case ValueBase::TYPE_COLOR:
461                 ret.push_back(ParamDesc(ValueBase(),"red")
462                         .set_local_name(_("Red"))
463                         .set_description(_("The red component of the color"))
464                 );
465                 ret.push_back(ParamDesc(ValueBase(),"green")
466                         .set_local_name(_("Green"))
467                         .set_description(_("The green component of the color"))
468                 );
469                 ret.push_back(ParamDesc(ValueBase(),"blue")
470                         .set_local_name(_("Blue"))
471                         .set_description(_("The blue component of the color"))
472                 );
473                 ret.push_back(ParamDesc(ValueBase(),"alpha")
474                         .set_local_name(_("Alpha"))
475                         .set_description(_("The alpha of the color"))
476                 );
477                 return ret;
478         case ValueBase::TYPE_SEGMENT:
479                 ret.push_back(ParamDesc(ValueBase(),"p1")
480                         .set_local_name(_("Vertex 1"))
481                         .set_description(_("The first vertex of the segment"))
482                 );
483                 ret.push_back(ParamDesc(ValueBase(),"t1")
484                         .set_local_name(_("Tangent 1"))
485                         .set_description(_("The first tangent of the segment"))
486                 );
487                 ret.push_back(ParamDesc(ValueBase(),"p2")
488                         .set_local_name(_("Vertex 2"))
489                         .set_description(_("The second vertex of the segment"))
490                 );
491                 ret.push_back(ParamDesc(ValueBase(),"t2")
492                         .set_local_name(_("Tangent 2"))
493                         .set_description(_("The second tangent of the segment"))
494                 );
495                 return ret;
496         case ValueBase::TYPE_VECTOR:
497                 ret.push_back(ParamDesc(ValueBase(),"x")
498                         .set_local_name(_("X-Axis"))
499                         .set_description(_("The X-Axis component of the vector"))
500                 );
501                 ret.push_back(ParamDesc(ValueBase(),"y")
502                         .set_local_name(_("Y-Axis"))
503                         .set_description(_("The Y-Axis component of the vector"))
504                 );
505                 return ret;
506         case ValueBase::TYPE_BLINEPOINT:
507                 ret.push_back(ParamDesc(ValueBase(),"point")
508                         .set_local_name(_("Vertex"))
509                         .set_description(_("The vertex of the BLine Point"))
510                 );
511                 ret.push_back(ParamDesc(ValueBase(),"width")
512                         .set_local_name(_("Width"))
513                         .set_description(_("The width of the BLine Point"))
514                 );
515                 ret.push_back(ParamDesc(ValueBase(),"origin")
516                         .set_local_name(_("Origin"))
517                         .set_description(_("Defines the Off and On position relative to neighbours"))
518                 );
519                 ret.push_back(ParamDesc(ValueBase(),"split")
520                         .set_local_name(_("Split"))
521                         .set_description(_("When checked, tangents are independent"))
522                 );
523                 ret.push_back(ParamDesc(ValueBase(),"t1")
524                         .set_local_name(_("Tangent 1"))
525                         .set_description(_("The first tangent of the BLine Point"))
526                 );
527                 ret.push_back(ParamDesc(ValueBase(),"t2")
528                         .set_local_name(_("Tangent 2"))
529                         .set_description(_("The second tangent of the BLine Point"))
530                 );
531                 return ret;
532         default:
533                 break;
534         }
535
536         return ret;
537 }