61b6c647ec72f4fe849efefc233065a174e907a7
[synfig.git] /
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 **
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 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "valuenode_composite.h"
34 #include "valuenode_const.h"
35 #include <stdexcept>
36 #include "general.h"
37 #include "valuenode_radialcomposite.h"
38 #include "vector.h"
39 #include "color.h"
40 #include "segment.h"
41 #include "savecanvas.h"
42
43 #endif
44
45 /* === U S I N G =========================================================== */
46
47 using namespace std;
48 using namespace etl;
49 using namespace synfig;
50
51 /* === M A C R O S ========================================================= */
52
53 /* === G L O B A L S ======================================================= */
54
55 /* === P R O C E D U R E S ================================================= */
56
57 /* === M E T H O D S ======================================================= */
58
59 synfig::ValueNode_Composite::ValueNode_Composite(const ValueBase &value):
60         LinkableValueNode(value.get_type())
61 {
62         switch(get_type())
63         {
64                 case ValueBase::TYPE_VECTOR:
65                         set_link("x",ValueNode_Const::create(value.get(Vector())[0]));
66                         set_link("y",ValueNode_Const::create(value.get(Vector())[1]));
67                         break;
68                 case ValueBase::TYPE_COLOR:
69                         set_link("r",ValueNode_Const::create(value.get(Color()).get_r()));
70                         set_link("g",ValueNode_Const::create(value.get(Color()).get_g()));
71                         set_link("b",ValueNode_Const::create(value.get(Color()).get_b()));
72                         set_link("a",ValueNode_Const::create(value.get(Color()).get_a()));
73                         break;
74                 case ValueBase::TYPE_SEGMENT:
75                         set_link("p1",ValueNode_Const::create(value.get(Segment()).p1));
76                         set_link("t1",ValueNode_Const::create(value.get(Segment()).t1));
77                         set_link("p2",ValueNode_Const::create(value.get(Segment()).p2));
78                         set_link("t2",ValueNode_Const::create(value.get(Segment()).t2));
79                         break;
80                 case ValueBase::TYPE_BLINEPOINT:
81                 {
82                         BLinePoint bline_point(value);
83                         set_link(0,ValueNode_Const::create(bline_point.get_vertex()));
84                         set_link(1,ValueNode_Const::create(bline_point.get_width()));
85                         set_link(2,ValueNode_Const::create(bline_point.get_origin()));
86                         set_link(3,ValueNode_Const::create(bline_point.get_split_tangent_flag()));
87                         set_link(4,ValueNode_RadialComposite::create(bline_point.get_tangent1()));
88                         set_link(5,ValueNode_RadialComposite::create(bline_point.get_tangent2()));
89                         break;
90                 }
91                 default:
92                         assert(0);
93                         throw Exception::BadType(ValueBase::type_local_name(get_type()));
94         }
95 }
96
97 ValueNode_Composite::~ValueNode_Composite()
98 {
99         unlink_all();
100 }
101
102 ValueNode_Composite*
103 ValueNode_Composite::create(const ValueBase &value)
104 {
105         return new ValueNode_Composite(value);
106 }
107
108 LinkableValueNode*
109 ValueNode_Composite::create_new()const
110 {
111         return new ValueNode_Composite(ValueBase(get_type()));
112 }
113
114 ValueBase
115 synfig::ValueNode_Composite::operator()(Time t)const
116 {
117         switch(get_type())
118         {
119                 case ValueBase::TYPE_VECTOR:
120                 {
121                         Vector vect;
122                         assert(components[0] && components[1]);
123                         vect[0]=(*components[0])(t).get(Vector::value_type());
124                         vect[1]=(*components[1])(t).get(Vector::value_type());
125                         return vect;
126                 }
127                 case ValueBase::TYPE_COLOR:
128                 {
129                         Color color;
130                         assert(components[0] && components[1] && components[2] && components[3]);
131                         color.set_r((*components[0])(t).get(Vector::value_type()));
132                         color.set_g((*components[1])(t).get(Vector::value_type()));
133                         color.set_b((*components[2])(t).get(Vector::value_type()));
134                         color.set_a((*components[3])(t).get(Vector::value_type()));
135                         return color;
136                 }
137                 case ValueBase::TYPE_SEGMENT:
138                 {
139                         Segment seg;
140                         assert(components[0] && components[1] && components[2] && components[3]);
141                         seg.p1=(*components[0])(t).get(Point());
142                         seg.t1=(*components[1])(t).get(Vector());
143                         seg.p2=(*components[2])(t).get(Point());
144                         seg.t2=(*components[3])(t).get(Vector());
145                         return seg;
146                 }
147                 case ValueBase::TYPE_BLINEPOINT:
148                 {
149                         BLinePoint ret;
150                         assert(components[0] && components[1] && components[2] && components[3] && components[4] && components[5]);
151                         ret.set_vertex((*components[0])(t).get(Point()));
152                         ret.set_width((*components[1])(t).get(Real()));
153                         ret.set_origin((*components[2])(t).get(Real()));
154                         ret.set_split_tangent_flag((*components[3])(t).get(bool()));
155                         ret.set_tangent1((*components[4])(t).get(Vector()));
156                         if(ret.get_split_tangent_flag())
157                                 ret.set_tangent2((*components[5])(t).get(Vector()));
158                         return ret;
159                 }
160                 default:
161                         synfig::error(string("ValueNode_Composite::operator():")+_("Bad type for composite"));
162                         assert(components[0]);
163                         return (*components[0])(t);
164         }
165 }
166
167 int
168 ValueNode_Composite::link_count()const
169 {
170         switch(get_type())
171         {
172         case ValueBase::TYPE_VECTOR:
173                 return 2;
174         case ValueBase::TYPE_COLOR:
175                 return 4;
176         case ValueBase::TYPE_SEGMENT:
177                 return 4;
178         case ValueBase::TYPE_BLINEPOINT:
179                 return 6;
180         default:
181                 synfig::warning(string("ValueNode_Composite::component_count():")+_("Bad type for composite"));
182                 return 1;
183         }
184 }
185
186 bool
187 ValueNode_Composite::set_link_vfunc(int i,ValueNode::Handle x)
188 {
189         assert(i>=0 && i<link_count());
190
191         if(PlaceholderValueNode::Handle::cast_dynamic(x))
192         {
193                 components[i]=x;
194                 return true;
195         }
196
197         switch(get_type())
198         {
199                 case ValueBase::TYPE_VECTOR:
200                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
201                         {
202                                 components[i]=x;
203                                 return true;
204                         }
205                         break;
206
207                 case ValueBase::TYPE_COLOR:
208                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
209                         {
210                                 components[i]=x;
211                                 return true;
212                         }
213                         break;
214
215                 case ValueBase::TYPE_SEGMENT:
216                         if(x->get_type()==ValueBase(Point()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
217                         {
218                                 components[i]=x;
219                                 return true;
220                         }
221                         break;
222
223                 case ValueBase::TYPE_BLINEPOINT:
224                         if((i==0 || i==4 || i==5) && x->get_type()==ValueBase(Point()).get_type())
225                         {
226                                 components[i]=x;
227                                 return true;
228                         }
229                         if((i==1 || i==2) && x->get_type()==ValueBase(Real()).get_type())
230                         {
231                                 components[i]=x;
232                                 return true;
233                         }
234                         if(i==3 && x->get_type()==ValueBase(bool()).get_type())
235                         {
236                                 components[i]=x;
237                                 return true;
238                         }
239                         break;
240
241                 default:
242                         break;
243         }
244         return false;
245 }
246
247 ValueNode::LooseHandle
248 ValueNode_Composite::get_link_vfunc(int i)const
249 {
250         assert(i>=0 && i<link_count());
251
252         return components[i];
253 }
254
255 String
256 ValueNode_Composite::link_local_name(int i)const
257 {
258         assert(i>=0 && i<link_count());
259
260         switch(get_type())
261         {
262                 case ValueBase::TYPE_VECTOR:
263                         return strprintf("%c-Axis",'X'+i);
264
265                 case ValueBase::TYPE_COLOR:
266                         if(i==0)
267                                 return _("Red");
268                         else if(i==1)
269                                 return _("Green");
270                         else if(i==2)
271                                 return _("Blue");
272                         else if(i==3)
273                                 return _("Alpha");
274
275                 case ValueBase::TYPE_SEGMENT:
276                         if(i==0)
277                                 return _("Vertex 1");
278                         else if(i==1)
279                                 return _("Tangent 1");
280                         else if(i==2)
281                                 return _("Vertex 2");
282                         else if(i==3)
283                                 return _("Tangent 2");
284
285                 case ValueBase::TYPE_BLINEPOINT:
286                         if(i==0)
287                                 return _("Vertex");
288                         else if(i==1)
289                                 return _("Width");
290                         else if(i==2)
291                                 return _("Origin");
292                         else if(i==3)
293                                 return _("Split Tangents");
294                         else if(i==4)
295                                 return _("Tangent 1");
296                         else if(i==5)
297                                 return _("Tangent 2");
298
299                 default:
300                         assert(0);
301                         // notice that Composite counts from 1 and Radial Composite counts
302                         // from 0!  we need to keep it like that to correctly load old
303                         // animations, but let's not save "c%d" format link names in future
304                         return etl::strprintf(_("C%d"),i+1);
305         }
306 }
307
308
309 String
310 ValueNode_Composite::link_name(int i)const
311 {
312         assert(i>=0 && i<link_count());
313
314         if (get_file_version() < RELEASE_VERSION_0_61_08)
315                 return strprintf("c%d",i+1);
316
317         switch(get_type())
318         {
319         case ValueBase::TYPE_COLOR:
320                 switch(i)
321                 {
322                 case 0: return "red";
323                 case 1: return "green";
324                 case 2: return "blue";
325                 case 3: return "alpha";
326                 }
327                 break;
328         case ValueBase::TYPE_SEGMENT:
329                 switch(i)
330                 {
331                 case 0: return "p1";
332                 case 1: return "t1";
333                 case 2: return "p2";
334                 case 3: return "t2";
335                 }
336                 break;
337         case ValueBase::TYPE_VECTOR:
338                 switch(i)
339                 {
340                 case 0: return "x";
341                 case 1: return "y";
342                 }
343                 break;
344         case ValueBase::TYPE_BLINEPOINT:
345                 switch(i)
346                 {
347                 case 0: return "point";
348                 case 1: return "width";
349                 case 2: return "origin";
350                 case 3: return "split";
351                 case 4: return "t1";
352                 case 5: return "t2";
353                 }
354                 break;
355         default:
356                 break;
357         }
358
359         assert(0);
360         // notice that Composite counts from 1 and Radial Composite counts
361         // from 0!  we need to keep it like that to correctly load old
362         // animations, but let's not save "c%d" format link names in future
363         return strprintf("c%d",i+1);
364 }
365
366 int
367 ValueNode_Composite::get_link_index_from_name(const String &name)const
368 {
369         if(name.empty())
370                 throw Exception::BadLinkName(name);
371
372         if(name[0]=='c' && name.size() == 2 && name[1]-'1' >= 0 && name[1]-'1' < link_count())
373                 return name[1]-'1';
374
375         switch(get_type())
376         {
377         case ValueBase::TYPE_COLOR:
378                 if(name[0]=='r')
379                         return 0;
380                 if(name[0]=='g')
381                         return 1;
382                 if(name[0]=='b')
383                         return 2;
384                 if(name[0]=='a')
385                         return 3;
386         case ValueBase::TYPE_SEGMENT:
387                 if(name=="p1")
388                         return 0;
389                 if(name=="t1")
390                         return 1;
391                 if(name=="p2")
392                         return 2;
393                 if(name=="t2")
394                         return 3;
395         case ValueBase::TYPE_VECTOR:
396                 if(name[0]=='x')
397                         return 0;
398                 if(name[0]=='y')
399                         return 1;
400                 if(name[0]=='z')                // \todo "z"?  really?
401                         return 2;
402         case ValueBase::TYPE_BLINEPOINT:
403                 if(name[0]=='p' || name=="v1" || name=="p1")
404                         return 0;
405                 if(name=="w" || name=="width")
406                         return 1;
407                 if(name=="o" || name=="origin")
408                         return 2;
409                 if(name=="split")
410                         return 3;
411                 if(name=="t1")
412                         return 4;
413                 if(name=="t2")
414                         return 5;
415         default:
416                 break;
417         }
418
419         throw Exception::BadLinkName(name);
420 }
421
422 String
423 ValueNode_Composite::get_name()const
424 {
425         return "composite";
426 }
427
428 String
429 ValueNode_Composite::get_local_name()const
430 {
431         return _("Composite");
432 }
433
434 bool
435 ValueNode_Composite::check_type(ValueBase::Type type)
436 {
437         return
438                 type==ValueBase::TYPE_SEGMENT ||
439                 type==ValueBase::TYPE_VECTOR ||
440                 type==ValueBase::TYPE_COLOR ||
441                 type==ValueBase::TYPE_BLINEPOINT;
442 }