Rename get_param_vocab to get_children_vocab and use a wrapper for the pure virtual...
[synfig.git] / synfig-core / src / synfig / valuenode_radialcomposite.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_radialcomposite.cpp
3 **      \brief Implementation of the "Radial Composite" valuenode conversion.
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007, 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_radialcomposite.h"
34 #include "valuenode_const.h"
35 #include <stdexcept>
36 #include "general.h"
37 #include "color.h"
38 #include "savecanvas.h"
39 #endif
40
41 /* === U S I N G =========================================================== */
42
43 using namespace std;
44 using namespace etl;
45 using namespace synfig;
46
47 /* === M A C R O S ========================================================= */
48
49 /* === G L O B A L S ======================================================= */
50
51 /* === P R O C E D U R E S ================================================= */
52
53 /* === M E T H O D S ======================================================= */
54
55 synfig::ValueNode_RadialComposite::ValueNode_RadialComposite(const ValueBase &value):
56         LinkableValueNode(value.get_type())
57 {
58         switch(get_type())
59         {
60                 case ValueBase::TYPE_VECTOR:
61                 {
62                         Vector vect(value.get(Vector()));
63                         set_link("r",ValueNode_Const::create(vect.mag()));
64                         set_link("t",ValueNode_Const::create(Angle(Angle::tan(vect[1],vect[0]))));
65                 }
66                         break;
67                 case ValueBase::TYPE_COLOR:
68                         set_link("y",ValueNode_Const::create(value.get(Color()).get_y()));
69                         set_link("s",ValueNode_Const::create(value.get(Color()).get_s()));
70                         set_link("h",ValueNode_Const::create(value.get(Color()).get_hue()));
71                         set_link("a",ValueNode_Const::create(value.get(Color()).get_a()));
72                         break;
73                 default:
74                         assert(0);
75                         throw Exception::BadType(ValueBase::type_local_name(get_type()));
76         }
77 }
78
79 ValueNode_RadialComposite::~ValueNode_RadialComposite()
80 {
81         unlink_all();
82 }
83
84 ValueNode_RadialComposite*
85 ValueNode_RadialComposite::create(const ValueBase &value)
86 {
87         return new ValueNode_RadialComposite(value);
88 }
89
90 LinkableValueNode*
91 ValueNode_RadialComposite::create_new()const
92 {
93         return new ValueNode_RadialComposite(ValueBase(get_type()));
94 }
95
96 ValueBase
97 synfig::ValueNode_RadialComposite::operator()(Time t)const
98 {
99         if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
100                 printf("%s:%d operator()\n", __FILE__, __LINE__);
101
102         switch(get_type())
103         {
104                 case ValueBase::TYPE_VECTOR:
105                 {
106                         Real mag;
107                         Angle angle;
108                         assert(components[0] && components[1]);
109                         mag=(*components[0])(t).get(mag);
110                         angle=(*components[1])(t).get(angle);
111                         return Vector(Angle::cos(angle).get()*mag,Angle::sin(angle).get()*mag);
112                 }
113                 case ValueBase::TYPE_COLOR:
114                 {
115                         assert(components[0] && components[1] && components[2] && components[3]);
116                         return Color::YUV(
117                                 (*components[0])(t).get(Real()),
118                                 (*components[1])(t).get(Real()),
119                                 (*components[2])(t).get(Angle()),
120                                 (*components[3])(t).get(Real())
121                         );
122                 }
123                 default:
124                         synfig::error(string("ValueNode_RadialComposite::operator():")+_("Bad type for radialcomposite"));
125                         assert(components[0]);
126                         return (*components[0])(t);
127         }
128 }
129
130 int
131 ValueNode_RadialComposite::link_count()const
132 {
133         switch(get_type())
134         {
135         case ValueBase::TYPE_VECTOR:
136                 return 2;
137         case ValueBase::TYPE_COLOR:
138                 return 4;
139         default:
140                 synfig::warning(string("ValueNode_RadialComposite::component_count():")+_("Bad type for radialcomposite"));
141                 return 1;
142         }
143 }
144
145 bool
146 ValueNode_RadialComposite::set_link_vfunc(int i,ValueNode::Handle x)
147 {
148         assert(i>=0 && i<link_count());
149
150         if(PlaceholderValueNode::Handle::cast_dynamic(x))
151         {
152                 components[i]=x;
153                 return true;
154         }
155
156         switch(get_type())
157         {
158                 case ValueBase::TYPE_VECTOR:
159                         if(i==0 && x->get_type()!=ValueBase::TYPE_REAL)
160                                 return false;
161                         if(i==1 && x->get_type()!=ValueBase::TYPE_ANGLE)
162                                 return false;
163                         components[i]=x;
164                         return true;
165                         break;
166
167                 case ValueBase::TYPE_COLOR:
168                         if((i==0 || i==1 || i==3) && x->get_type()!=ValueBase::TYPE_REAL)
169                                 return false;
170                         if((i==2) && x->get_type()!=ValueBase::TYPE_ANGLE)
171                                 return false;
172                         components[i]=x;
173                         return true;
174                         break;
175
176
177                 default:
178                         break;
179         }
180         return false;
181 }
182
183 ValueNode::LooseHandle
184 ValueNode_RadialComposite::get_link_vfunc(int i)const
185 {
186         assert(i>=0 && i<link_count());
187
188         return components[i];
189 }
190
191 String
192 ValueNode_RadialComposite::link_local_name(int i)const
193 {
194         assert(i>=0 && i<link_count());
195
196         switch(get_type())
197         {
198                 case ValueBase::TYPE_VECTOR:
199                         if(i==0)
200                                 return _("Radius");
201                         else if(i==1)
202                                 return _("Theta");
203                         break;
204
205                 case ValueBase::TYPE_COLOR:
206                         if(i==0)
207                                 return _("Luma");
208                         else if(i==1)
209                                 return _("Saturation");
210                         else if(i==2)
211                                 return _("Hue");
212                         else if(i==3)
213                                 return _("Alpha");
214                         break;
215
216                 default:
217                         break;
218         }
219
220         assert(0);
221         // notice that Composite counts from 1 and Radial Composite counts
222         // from 0!  we need to keep it like that to correctly load old
223         // animations, but let's not save "c%d" format link names in future
224         return etl::strprintf(_("C%d"),i);
225 }
226
227
228 String
229 ValueNode_RadialComposite::link_name(int i)const
230 {
231         assert(i>=0 && i<link_count());
232
233         if (get_file_version() < RELEASE_VERSION_0_61_08)
234                 return strprintf("c%d",i);
235
236         switch(get_type())
237         {
238         case ValueBase::TYPE_COLOR:
239                 switch(i)
240                 {
241                 case 0: return "y_luma"; // the 'luma' attribute is recognised by the fact that it starts with a 'y'
242                 case 1: return "saturation";
243                 case 2: return "hue";
244                 case 3: return "alpha";
245                 }
246                 break;
247         case ValueBase::TYPE_VECTOR:
248                 switch(i)
249                 {
250                 case 0: return "radius";
251                 case 1: return "theta";
252                 }
253                 break;
254         default:
255                 break;
256         }
257
258         assert(0);
259         // notice that Composite counts from 1 and Radial Composite counts
260         // from 0!  we need to keep it like that to correctly load old
261         // animations, but let's not save "c%d" format link names in future
262         return strprintf("c%d",i);
263 }
264
265 int
266 ValueNode_RadialComposite::get_link_index_from_name(const String &name)const
267 {
268         if(name.empty())
269                 throw Exception::BadLinkName(name);
270
271         if(name[0]=='c' && name.size() == 2 && name[1]-'0' >= 0 && name[1]-'0' < link_count())
272                 return name[1]-'0';
273
274         switch(get_type())
275         {
276         case ValueBase::TYPE_COLOR:
277                 if(name[0]=='y')
278                         return 0;
279                 if(name[0]=='s')
280                         return 1;
281                 if(name[0]=='h')
282                         return 2;
283                 if(name[0]=='a')
284                         return 3;
285         case ValueBase::TYPE_VECTOR:
286                 if(name[0]=='r')
287                         return 0;
288                 if(name[0]=='t')
289                         return 1;
290         default:
291                 break;
292         }
293
294         throw Exception::BadLinkName(name);
295 }
296
297 String
298 ValueNode_RadialComposite::get_name()const
299 {
300         return "radial_composite";
301 }
302
303 String
304 ValueNode_RadialComposite::get_local_name()const
305 {
306         return _("Radial Composite");
307 }
308
309 bool
310 ValueNode_RadialComposite::check_type(ValueBase::Type type)
311 {
312         return
313                 type==ValueBase::TYPE_VECTOR ||
314                 type==ValueBase::TYPE_COLOR;
315 }
316
317 LinkableValueNode::Vocab
318 ValueNode_RadialComposite::get_children_vocab_vfunc()const
319 {
320         LinkableValueNode::Vocab ret;
321
322         switch(get_type())
323         {
324         case ValueBase::TYPE_COLOR:
325                 ret.push_back(ParamDesc(ValueBase(),"y_luma")
326                 .set_local_name(_("Luma"))
327                 );
328                 ret.push_back(ParamDesc(ValueBase(),"saturation")
329                 .set_local_name(_("Saturation"))
330                 );
331                 ret.push_back(ParamDesc(ValueBase(),"hue")
332                 .set_local_name(_("Hue"))
333                 );
334                 ret.push_back(ParamDesc(ValueBase(),"alpha")
335                 .set_local_name(_("Saturation"))
336                 );
337                 return ret;
338                 break;
339         case ValueBase::TYPE_VECTOR:
340                 ret.push_back(ParamDesc(ValueBase(),"radius")
341                 .set_local_name(_("Radius"))
342                 .set_description(_("The length of the vector"))
343                 );
344                 ret.push_back(ParamDesc(ValueBase(),"theta")
345                 .set_local_name(_("Theta"))
346                 .set_description(_("The angle of the vector with the X axis"))
347                 );
348                 return ret;
349                 break;
350         default:
351                 break;
352         }
353
354         return ret;
355 }