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