1981a82c60ec11ff6115fb77261ab961b8d83bf8
[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         switch(get_type())
64         {
65                 case ValueBase::TYPE_VECTOR:
66                         set_link("x",ValueNode_Const::create(value.get(Vector())[0]));
67                         set_link("y",ValueNode_Const::create(value.get(Vector())[1]));
68                         break;
69                 case ValueBase::TYPE_COLOR:
70                         set_link("r",ValueNode_Const::create(value.get(Color()).get_r()));
71                         set_link("g",ValueNode_Const::create(value.get(Color()).get_g()));
72                         set_link("b",ValueNode_Const::create(value.get(Color()).get_b()));
73                         set_link("a",ValueNode_Const::create(value.get(Color()).get_a()));
74                         break;
75                 case ValueBase::TYPE_SEGMENT:
76                         set_link("p1",ValueNode_Const::create(value.get(Segment()).p1));
77                         set_link("t1",ValueNode_Const::create(value.get(Segment()).t1));
78                         set_link("p2",ValueNode_Const::create(value.get(Segment()).p2));
79                         set_link("t2",ValueNode_Const::create(value.get(Segment()).t2));
80                         break;
81                 case ValueBase::TYPE_BLINEPOINT:
82                 {
83                         BLinePoint bline_point(value);
84                         set_link("point",ValueNode_Const::create(bline_point.get_vertex()));
85                         set_link("width",ValueNode_Const::create(bline_point.get_width()));
86                         set_link("origin",ValueNode_Const::create(bline_point.get_origin()));
87                         set_link("split",ValueNode_Const::create(bline_point.get_split_tangent_flag()));
88                         set_link("t1",ValueNode_RadialComposite::create(bline_point.get_tangent1()));
89                         set_link("t2",ValueNode_RadialComposite::create(bline_point.get_tangent2()));
90                         break;
91                 }
92                 default:
93                         assert(0);
94                         throw Exception::BadType(ValueBase::type_local_name(get_type()));
95         }
96 }
97
98 ValueNode_Composite::~ValueNode_Composite()
99 {
100         unlink_all();
101 }
102
103 ValueNode_Composite*
104 ValueNode_Composite::create(const ValueBase &value)
105 {
106         return new ValueNode_Composite(value);
107 }
108
109 LinkableValueNode*
110 ValueNode_Composite::create_new()const
111 {
112         return new ValueNode_Composite(ValueBase(get_type()));
113 }
114
115 ValueBase
116 synfig::ValueNode_Composite::operator()(Time t)const
117 {
118         if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
119                 printf("%s:%d operator()\n", __FILE__, __LINE__);
120
121         switch(get_type())
122         {
123                 case ValueBase::TYPE_VECTOR:
124                 {
125                         Vector vect;
126                         assert(components[0] && components[1]);
127                         vect[0]=(*components[0])(t).get(Vector::value_type());
128                         vect[1]=(*components[1])(t).get(Vector::value_type());
129                         return vect;
130                 }
131                 case ValueBase::TYPE_COLOR:
132                 {
133                         Color color;
134                         assert(components[0] && components[1] && components[2] && components[3]);
135                         color.set_r((*components[0])(t).get(Vector::value_type()));
136                         color.set_g((*components[1])(t).get(Vector::value_type()));
137                         color.set_b((*components[2])(t).get(Vector::value_type()));
138                         color.set_a((*components[3])(t).get(Vector::value_type()));
139                         return color;
140                 }
141                 case ValueBase::TYPE_SEGMENT:
142                 {
143                         Segment seg;
144                         assert(components[0] && components[1] && components[2] && components[3]);
145                         seg.p1=(*components[0])(t).get(Point());
146                         seg.t1=(*components[1])(t).get(Vector());
147                         seg.p2=(*components[2])(t).get(Point());
148                         seg.t2=(*components[3])(t).get(Vector());
149                         return seg;
150                 }
151                 case ValueBase::TYPE_BLINEPOINT:
152                 {
153                         BLinePoint ret;
154                         assert(components[0] && components[1] && components[2] && components[3] && components[4] && components[5]);
155                         ret.set_vertex((*components[0])(t).get(Point()));
156                         ret.set_width((*components[1])(t).get(Real()));
157                         ret.set_origin((*components[2])(t).get(Real()));
158                         ret.set_split_tangent_flag((*components[3])(t).get(bool()));
159                         ret.set_tangent1((*components[4])(t).get(Vector()));
160                         if(ret.get_split_tangent_flag())
161                                 ret.set_tangent2((*components[5])(t).get(Vector()));
162                         return ret;
163                 }
164                 default:
165                         synfig::error(string("ValueNode_Composite::operator():")+_("Bad type for composite"));
166                         assert(components[0]);
167                         return (*components[0])(t);
168         }
169 }
170
171 int
172 ValueNode_Composite::link_count()const
173 {
174         switch(get_type())
175         {
176         case ValueBase::TYPE_VECTOR:
177                 return 2;
178         case ValueBase::TYPE_COLOR:
179                 return 4;
180         case ValueBase::TYPE_SEGMENT:
181                 return 4;
182         case ValueBase::TYPE_BLINEPOINT:
183                 return 6;
184         default:
185                 synfig::warning(string("ValueNode_Composite::component_count():")+_("Bad type for composite"));
186                 return 1;
187         }
188 }
189
190 bool
191 ValueNode_Composite::set_link_vfunc(int i,ValueNode::Handle x)
192 {
193         assert(i>=0 && i<link_count());
194
195         if(PlaceholderValueNode::Handle::cast_dynamic(x))
196         {
197                 components[i]=x;
198                 return true;
199         }
200
201         switch(get_type())
202         {
203                 case ValueBase::TYPE_VECTOR:
204                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
205                         {
206                                 components[i]=x;
207                                 return true;
208                         }
209                         break;
210
211                 case ValueBase::TYPE_COLOR:
212                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
213                         {
214                                 components[i]=x;
215                                 return true;
216                         }
217                         break;
218
219                 case ValueBase::TYPE_SEGMENT:
220                         if(x->get_type()==ValueBase(Point()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
221                         {
222                                 components[i]=x;
223                                 return true;
224                         }
225                         break;
226
227                 case ValueBase::TYPE_BLINEPOINT:
228                         if((i==0 || i==4 || i==5) && x->get_type()==ValueBase(Point()).get_type())
229                         {
230                                 components[i]=x;
231                                 return true;
232                         }
233                         if((i==1 || i==2) && x->get_type()==ValueBase(Real()).get_type())
234                         {
235                                 components[i]=x;
236                                 return true;
237                         }
238                         if(i==3 && x->get_type()==ValueBase(bool()).get_type())
239                         {
240                                 components[i]=x;
241                                 return true;
242                         }
243                         break;
244
245                 default:
246                         break;
247         }
248         return false;
249 }
250
251 ValueNode::LooseHandle
252 ValueNode_Composite::get_link_vfunc(int i)const
253 {
254         assert(i>=0 && i<link_count());
255
256         return components[i];
257 }
258
259 String
260 ValueNode_Composite::link_local_name(int i)const
261 {
262         assert(i>=0 && i<link_count());
263
264         switch(get_type())
265         {
266                 case ValueBase::TYPE_VECTOR:
267                         return strprintf("%c-Axis",'X'+i);
268
269                 case ValueBase::TYPE_COLOR:
270                         if(i==0)
271                                 return _("Red");
272                         else if(i==1)
273                                 return _("Green");
274                         else if(i==2)
275                                 return _("Blue");
276                         else if(i==3)
277                                 return _("Alpha");
278
279                 case ValueBase::TYPE_SEGMENT:
280                         if(i==0)
281                                 return _("Vertex 1");
282                         else if(i==1)
283                                 return _("Tangent 1");
284                         else if(i==2)
285                                 return _("Vertex 2");
286                         else if(i==3)
287                                 return _("Tangent 2");
288
289                 case ValueBase::TYPE_BLINEPOINT:
290                         if(i==0)
291                                 return _("Vertex");
292                         else if(i==1)
293                                 return _("Width");
294                         else if(i==2)
295                                 return _("Origin");
296                         else if(i==3)
297                                 return _("Split Tangents");
298                         else if(i==4)
299                                 return _("Tangent 1");
300                         else if(i==5)
301                                 return _("Tangent 2");
302
303                 default:
304                         assert(0);
305                         // notice that Composite counts from 1 and Radial Composite counts
306                         // from 0!  we need to keep it like that to correctly load old
307                         // animations, but let's not save "c%d" format link names in future
308                         return etl::strprintf(_("C%d"),i+1);
309         }
310 }
311
312
313 String
314 ValueNode_Composite::link_name(int i)const
315 {
316         assert(i>=0 && i<link_count());
317
318         if (get_file_version() < RELEASE_VERSION_0_61_08)
319                 return strprintf("c%d",i+1);
320
321         switch(get_type())
322         {
323         case ValueBase::TYPE_COLOR:
324                 switch(i)
325                 {
326                 case 0: return "red";
327                 case 1: return "green";
328                 case 2: return "blue";
329                 case 3: return "alpha";
330                 }
331                 break;
332         case ValueBase::TYPE_SEGMENT:
333                 switch(i)
334                 {
335                 case 0: return "p1";
336                 case 1: return "t1";
337                 case 2: return "p2";
338                 case 3: return "t2";
339                 }
340                 break;
341         case ValueBase::TYPE_VECTOR:
342                 switch(i)
343                 {
344                 case 0: return "x";
345                 case 1: return "y";
346                 }
347                 break;
348         case ValueBase::TYPE_BLINEPOINT:
349                 switch(i)
350                 {
351                 case 0: return "point";
352                 case 1: return "width";
353                 case 2: return "origin";
354                 case 3: return "split";
355                 case 4: return "t1";
356                 case 5: return "t2";
357                 }
358                 break;
359         default:
360                 break;
361         }
362
363         assert(0);
364         // notice that Composite counts from 1 and Radial Composite counts
365         // from 0!  we need to keep it like that to correctly load old
366         // animations, but let's not save "c%d" format link names in future
367         return strprintf("c%d",i+1);
368 }
369
370 int
371 ValueNode_Composite::get_link_index_from_name(const String &name)const
372 {
373         if(name.empty())
374                 throw Exception::BadLinkName(name);
375
376         if(name[0]=='c' && name.size() == 2 && name[1]-'1' >= 0 && name[1]-'1' < link_count())
377                 return name[1]-'1';
378
379         switch(get_type())
380         {
381         case ValueBase::TYPE_COLOR:
382                 if(name[0]=='r')
383                         return 0;
384                 if(name[0]=='g')
385                         return 1;
386                 if(name[0]=='b')
387                         return 2;
388                 if(name[0]=='a')
389                         return 3;
390         case ValueBase::TYPE_SEGMENT:
391                 if(name=="p1")
392                         return 0;
393                 if(name=="t1")
394                         return 1;
395                 if(name=="p2")
396                         return 2;
397                 if(name=="t2")
398                         return 3;
399         case ValueBase::TYPE_VECTOR:
400                 if(name[0]=='x')
401                         return 0;
402                 if(name[0]=='y')
403                         return 1;
404                 if(name[0]=='z')                // \todo "z"?  really?
405                         return 2;
406         case ValueBase::TYPE_BLINEPOINT:
407                 if(name[0]=='p' || name=="v1" || name=="p1")
408                         return 0;
409                 if(name=="w" || name=="width")
410                         return 1;
411                 if(name=="o" || name=="origin")
412                         return 2;
413                 if(name=="split")
414                         return 3;
415                 if(name=="t1")
416                         return 4;
417                 if(name=="t2")
418                         return 5;
419         default:
420                 break;
421         }
422
423         throw Exception::BadLinkName(name);
424 }
425
426 String
427 ValueNode_Composite::get_name()const
428 {
429         return "composite";
430 }
431
432 String
433 ValueNode_Composite::get_local_name()const
434 {
435         return _("Composite");
436 }
437
438 bool
439 ValueNode_Composite::check_type(ValueBase::Type type)
440 {
441         return
442                 type==ValueBase::TYPE_SEGMENT ||
443                 type==ValueBase::TYPE_VECTOR ||
444                 type==ValueBase::TYPE_COLOR ||
445                 type==ValueBase::TYPE_BLINEPOINT;
446 }
447
448 LinkableValueNode::Vocab
449 ValueNode_Composite::get_param_vocab()const
450 {
451         LinkableValueNode::Vocab ret;
452
453         switch(get_type())
454         {
455         case ValueBase::TYPE_COLOR:
456                 ret.push_back(ParamDesc(ValueBase(),"red")
457                         .set_local_name(_("Red"))
458                         .set_description(_("The red component of the color"))
459                 );
460                 ret.push_back(ParamDesc(ValueBase(),"green")
461                         .set_local_name(_("Green"))
462                         .set_description(_("The green component of the color"))
463                 );
464                 ret.push_back(ParamDesc(ValueBase(),"blue")
465                         .set_local_name(_("Blue"))
466                         .set_description(_("The blue component of the color"))
467                 );
468                 ret.push_back(ParamDesc(ValueBase(),"alpha")
469                         .set_local_name(_("Alpha"))
470                         .set_description(_("The alpha of the color"))
471                 );
472                 return ret;
473         case ValueBase::TYPE_SEGMENT:
474                 ret.push_back(ParamDesc(ValueBase(),"p1")
475                         .set_local_name(_("Vertex 1"))
476                         .set_description(_("The first vertex of the segment"))
477                 );
478                 ret.push_back(ParamDesc(ValueBase(),"t1")
479                         .set_local_name(_("Tangent 1"))
480                         .set_description(_("The first tangent of the segment"))
481                 );
482                 ret.push_back(ParamDesc(ValueBase(),"p2")
483                         .set_local_name(_("Vertex 2"))
484                         .set_description(_("The second vertex of the segment"))
485                 );
486                 ret.push_back(ParamDesc(ValueBase(),"t2")
487                         .set_local_name(_("Tangent 2"))
488                         .set_description(_("The second tangent of the segment"))
489                 );
490                 return ret;
491         case ValueBase::TYPE_VECTOR:
492                 ret.push_back(ParamDesc(ValueBase(),"x")
493                         .set_local_name(_("X-Axis"))
494                         .set_description(_("The X-Axis component of the vector"))
495                 );
496                 ret.push_back(ParamDesc(ValueBase(),"y")
497                         .set_local_name(_("Y-Axis"))
498                         .set_description(_("The Y-Axis component of the vector"))
499                 );
500                 return ret;
501         case ValueBase::TYPE_BLINEPOINT:
502                 ret.push_back(ParamDesc(ValueBase(),"point")
503                         .set_local_name(_("Vertex"))
504                         .set_description(_("The vertex of the BLine Point"))
505                 );
506                 ret.push_back(ParamDesc(ValueBase(),"width")
507                         .set_local_name(_("Width"))
508                         .set_description(_("The width of the BLine Point"))
509                 );
510                 ret.push_back(ParamDesc(ValueBase(),"origin")
511                         .set_local_name(_("Origin"))
512                         .set_description(_("Defines the Off and On position relative to neighbours"))
513                 );
514                 ret.push_back(ParamDesc(ValueBase(),"split")
515                         .set_local_name(_("Split"))
516                         .set_description(_("When checked, tangents are independent"))
517                 );
518                 ret.push_back(ParamDesc(ValueBase(),"t1")
519                         .set_local_name(_("Tangent 1"))
520                         .set_description(_("The first tangent of the BLine Point"))
521                 );
522                 ret.push_back(ParamDesc(ValueBase(),"t2")
523                         .set_local_name(_("Tangent 2"))
524                         .set_description(_("The second tangent of the BLine Point"))
525                 );
526                 return ret;
527         default:
528                 break;
529         }
530
531         return ret;
532 }