Use LinkableValueNode members functions when possible in the derived valuenodes.
[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 bool
133 ValueNode_RadialComposite::set_link_vfunc(int i,ValueNode::Handle x)
134 {
135         assert(i>=0 && i<link_count());
136
137         if(PlaceholderValueNode::Handle::cast_dynamic(x))
138         {
139                 components[i]=x;
140                 return true;
141         }
142
143         switch(get_type())
144         {
145                 case ValueBase::TYPE_VECTOR:
146                         if(i==0 && x->get_type()!=ValueBase::TYPE_REAL)
147                                 return false;
148                         if(i==1 && x->get_type()!=ValueBase::TYPE_ANGLE)
149                                 return false;
150                         components[i]=x;
151                         return true;
152                         break;
153
154                 case ValueBase::TYPE_COLOR:
155                         if((i==0 || i==1 || i==3) && x->get_type()!=ValueBase::TYPE_REAL)
156                                 return false;
157                         if((i==2) && x->get_type()!=ValueBase::TYPE_ANGLE)
158                                 return false;
159                         components[i]=x;
160                         return true;
161                         break;
162
163
164                 default:
165                         break;
166         }
167         return false;
168 }
169
170 ValueNode::LooseHandle
171 ValueNode_RadialComposite::get_link_vfunc(int i)const
172 {
173         assert(i>=0 && i<link_count());
174
175         return components[i];
176 }
177
178 String
179 ValueNode_RadialComposite::link_name(int i)const
180 {
181         assert(i>=0 && i<link_count());
182
183         if (get_file_version() < RELEASE_VERSION_0_61_08)
184                 return strprintf("c%d",i);
185
186         return LinkableValueNode::link_name(i);
187 }
188
189 int
190 ValueNode_RadialComposite::get_link_index_from_name(const String &name)const
191 {
192         // Here we don't use the LinkableValueNode::get_link_index_from_name
193         // due to the particularities of the link index from name for old files.
194         // So we keep this alive to maintain old file compatibilities.
195         if(name.empty())
196                 throw Exception::BadLinkName(name);
197
198         if(name[0]=='c' && name.size() == 2 && name[1]-'0' >= 0 && name[1]-'0' < link_count())
199                 return name[1]-'0';
200
201         switch(get_type())
202         {
203         case ValueBase::TYPE_COLOR:
204                 if(name[0]=='y')
205                         return 0;
206                 if(name[0]=='s')
207                         return 1;
208                 if(name[0]=='h')
209                         return 2;
210                 if(name[0]=='a')
211                         return 3;
212         case ValueBase::TYPE_VECTOR:
213                 if(name[0]=='r')
214                         return 0;
215                 if(name[0]=='t')
216                         return 1;
217         default:
218                 break;
219         }
220
221         throw Exception::BadLinkName(name);
222 }
223
224 String
225 ValueNode_RadialComposite::get_name()const
226 {
227         return "radial_composite";
228 }
229
230 String
231 ValueNode_RadialComposite::get_local_name()const
232 {
233         return _("Radial Composite");
234 }
235
236 bool
237 ValueNode_RadialComposite::check_type(ValueBase::Type type)
238 {
239         return
240                 type==ValueBase::TYPE_VECTOR ||
241                 type==ValueBase::TYPE_COLOR;
242 }
243
244 LinkableValueNode::Vocab
245 ValueNode_RadialComposite::get_children_vocab_vfunc()const
246 {
247         if(children_vocab.size())
248                 return children_vocab;
249
250         LinkableValueNode::Vocab ret;
251
252         switch(get_type())
253         {
254         case ValueBase::TYPE_COLOR:
255                 ret.push_back(ParamDesc(ValueBase(),"y_luma")
256                 .set_local_name(_("Luma"))
257                 );
258                 ret.push_back(ParamDesc(ValueBase(),"saturation")
259                 .set_local_name(_("Saturation"))
260                 );
261                 ret.push_back(ParamDesc(ValueBase(),"hue")
262                 .set_local_name(_("Hue"))
263                 );
264                 ret.push_back(ParamDesc(ValueBase(),"alpha")
265                 .set_local_name(_("Saturation"))
266                 );
267                 return ret;
268                 break;
269         case ValueBase::TYPE_VECTOR:
270                 ret.push_back(ParamDesc(ValueBase(),"radius")
271                 .set_local_name(_("Radius"))
272                 .set_description(_("The length of the vector"))
273                 );
274                 ret.push_back(ParamDesc(ValueBase(),"theta")
275                 .set_local_name(_("Theta"))
276                 .set_description(_("The angle of the vector with the X axis"))
277                 );
278                 return ret;
279                 break;
280         default:
281                 break;
282         }
283
284         return ret;
285 }