Use LinkableValueNode members functions when possible in the derived valuenodes.
[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         Vocab ret(get_children_vocab());
64         set_children_vocab(ret);
65         switch(get_type())
66         {
67                 case ValueBase::TYPE_VECTOR:
68                         set_link("x",ValueNode_Const::create(value.get(Vector())[0]));
69                         set_link("y",ValueNode_Const::create(value.get(Vector())[1]));
70                         break;
71                 case ValueBase::TYPE_COLOR:
72                         set_link("r",ValueNode_Const::create(value.get(Color()).get_r()));
73                         set_link("g",ValueNode_Const::create(value.get(Color()).get_g()));
74                         set_link("b",ValueNode_Const::create(value.get(Color()).get_b()));
75                         set_link("a",ValueNode_Const::create(value.get(Color()).get_a()));
76                         break;
77                 case ValueBase::TYPE_SEGMENT:
78                         set_link("p1",ValueNode_Const::create(value.get(Segment()).p1));
79                         set_link("t1",ValueNode_Const::create(value.get(Segment()).t1));
80                         set_link("p2",ValueNode_Const::create(value.get(Segment()).p2));
81                         set_link("t2",ValueNode_Const::create(value.get(Segment()).t2));
82                         break;
83                 case ValueBase::TYPE_BLINEPOINT:
84                 {
85                         BLinePoint bline_point(value);
86                         set_link("point",ValueNode_Const::create(bline_point.get_vertex()));
87                         set_link("width",ValueNode_Const::create(bline_point.get_width()));
88                         set_link("origin",ValueNode_Const::create(bline_point.get_origin()));
89                         set_link("split",ValueNode_Const::create(bline_point.get_split_tangent_flag()));
90                         set_link("t1",ValueNode_RadialComposite::create(bline_point.get_tangent1()));
91                         set_link("t2",ValueNode_RadialComposite::create(bline_point.get_tangent2()));
92                         break;
93                 }
94                 default:
95                         assert(0);
96                         throw Exception::BadType(ValueBase::type_local_name(get_type()));
97         }
98 }
99
100 ValueNode_Composite::~ValueNode_Composite()
101 {
102         unlink_all();
103 }
104
105 ValueNode_Composite*
106 ValueNode_Composite::create(const ValueBase &value)
107 {
108         return new ValueNode_Composite(value);
109 }
110
111 LinkableValueNode*
112 ValueNode_Composite::create_new()const
113 {
114         return new ValueNode_Composite(ValueBase(get_type()));
115 }
116
117 ValueBase
118 synfig::ValueNode_Composite::operator()(Time t)const
119 {
120         if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
121                 printf("%s:%d operator()\n", __FILE__, __LINE__);
122
123         switch(get_type())
124         {
125                 case ValueBase::TYPE_VECTOR:
126                 {
127                         Vector vect;
128                         assert(components[0] && components[1]);
129                         vect[0]=(*components[0])(t).get(Vector::value_type());
130                         vect[1]=(*components[1])(t).get(Vector::value_type());
131                         return vect;
132                 }
133                 case ValueBase::TYPE_COLOR:
134                 {
135                         Color color;
136                         assert(components[0] && components[1] && components[2] && components[3]);
137                         color.set_r((*components[0])(t).get(Vector::value_type()));
138                         color.set_g((*components[1])(t).get(Vector::value_type()));
139                         color.set_b((*components[2])(t).get(Vector::value_type()));
140                         color.set_a((*components[3])(t).get(Vector::value_type()));
141                         return color;
142                 }
143                 case ValueBase::TYPE_SEGMENT:
144                 {
145                         Segment seg;
146                         assert(components[0] && components[1] && components[2] && components[3]);
147                         seg.p1=(*components[0])(t).get(Point());
148                         seg.t1=(*components[1])(t).get(Vector());
149                         seg.p2=(*components[2])(t).get(Point());
150                         seg.t2=(*components[3])(t).get(Vector());
151                         return seg;
152                 }
153                 case ValueBase::TYPE_BLINEPOINT:
154                 {
155                         BLinePoint ret;
156                         assert(components[0] && components[1] && components[2] && components[3] && components[4] && components[5]);
157                         ret.set_vertex((*components[0])(t).get(Point()));
158                         ret.set_width((*components[1])(t).get(Real()));
159                         ret.set_origin((*components[2])(t).get(Real()));
160                         ret.set_split_tangent_flag((*components[3])(t).get(bool()));
161                         ret.set_tangent1((*components[4])(t).get(Vector()));
162                         if(ret.get_split_tangent_flag())
163                                 ret.set_tangent2((*components[5])(t).get(Vector()));
164                         return ret;
165                 }
166                 default:
167                         synfig::error(string("ValueNode_Composite::operator():")+_("Bad type for composite"));
168                         assert(components[0]);
169                         return (*components[0])(t);
170         }
171 }
172
173 bool
174 ValueNode_Composite::set_link_vfunc(int i,ValueNode::Handle x)
175 {
176         assert(i>=0 && i<link_count());
177
178         if(PlaceholderValueNode::Handle::cast_dynamic(x))
179         {
180                 components[i]=x;
181                 return true;
182         }
183
184         switch(get_type())
185         {
186                 case ValueBase::TYPE_VECTOR:
187                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
188                         {
189                                 components[i]=x;
190                                 return true;
191                         }
192                         break;
193
194                 case ValueBase::TYPE_COLOR:
195                         if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
196                         {
197                                 components[i]=x;
198                                 return true;
199                         }
200                         break;
201
202                 case ValueBase::TYPE_SEGMENT:
203                         if(x->get_type()==ValueBase(Point()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x))
204                         {
205                                 components[i]=x;
206                                 return true;
207                         }
208                         break;
209
210                 case ValueBase::TYPE_BLINEPOINT:
211                         if((i==0 || i==4 || i==5) && x->get_type()==ValueBase(Point()).get_type())
212                         {
213                                 components[i]=x;
214                                 return true;
215                         }
216                         if((i==1 || i==2) && x->get_type()==ValueBase(Real()).get_type())
217                         {
218                                 components[i]=x;
219                                 return true;
220                         }
221                         if(i==3 && x->get_type()==ValueBase(bool()).get_type())
222                         {
223                                 components[i]=x;
224                                 return true;
225                         }
226                         break;
227
228                 default:
229                         break;
230         }
231         return false;
232 }
233
234 ValueNode::LooseHandle
235 ValueNode_Composite::get_link_vfunc(int i)const
236 {
237         assert(i>=0 && i<link_count());
238
239         return components[i];
240 }
241
242 String
243 ValueNode_Composite::link_name(int i)const
244 {
245         assert(i>=0 && i<link_count());
246
247         if (get_file_version() < RELEASE_VERSION_0_61_08)
248                 return strprintf("c%d",i+1);
249
250         return LinkableValueNode::link_name(i);
251 }
252
253 int
254 ValueNode_Composite::get_link_index_from_name(const String &name)const
255 {
256         // Here we don't use the LinkableValueNode::get_link_index_from_name
257         // due to the particularities of the link index from name for old files.
258         // So we keep this alive to maintain old file compatibilities.
259         if(name.empty())
260                 throw Exception::BadLinkName(name);
261
262         if(name[0]=='c' && name.size() == 2 && name[1]-'1' >= 0 && name[1]-'1' < link_count())
263                 return name[1]-'1';
264
265         switch(get_type())
266         {
267         case ValueBase::TYPE_COLOR:
268                 if(name[0]=='r')
269                         return 0;
270                 if(name[0]=='g')
271                         return 1;
272                 if(name[0]=='b')
273                         return 2;
274                 if(name[0]=='a')
275                         return 3;
276         case ValueBase::TYPE_SEGMENT:
277                 if(name=="p1")
278                         return 0;
279                 if(name=="t1")
280                         return 1;
281                 if(name=="p2")
282                         return 2;
283                 if(name=="t2")
284                         return 3;
285         case ValueBase::TYPE_VECTOR:
286                 if(name[0]=='x')
287                         return 0;
288                 if(name[0]=='y')
289                         return 1;
290                 if(name[0]=='z')                // \todo "z"?  really?
291                         return 2;
292         case ValueBase::TYPE_BLINEPOINT:
293                 if(name[0]=='p' || name=="v1" || name=="p1")
294                         return 0;
295                 if(name=="w" || name=="width")
296                         return 1;
297                 if(name=="o" || name=="origin")
298                         return 2;
299                 if(name=="split")
300                         return 3;
301                 if(name=="t1")
302                         return 4;
303                 if(name=="t2")
304                         return 5;
305         default:
306                 break;
307         }
308
309         throw Exception::BadLinkName(name);
310 }
311
312 String
313 ValueNode_Composite::get_name()const
314 {
315         return "composite";
316 }
317
318 String
319 ValueNode_Composite::get_local_name()const
320 {
321         return _("Composite");
322 }
323
324 bool
325 ValueNode_Composite::check_type(ValueBase::Type type)
326 {
327         return
328                 type==ValueBase::TYPE_SEGMENT ||
329                 type==ValueBase::TYPE_VECTOR ||
330                 type==ValueBase::TYPE_COLOR ||
331                 type==ValueBase::TYPE_BLINEPOINT;
332 }
333
334 LinkableValueNode::Vocab
335 ValueNode_Composite::get_children_vocab_vfunc()const
336 {
337         if(children_vocab.size())
338                 return children_vocab;
339
340         LinkableValueNode::Vocab ret;
341
342         switch(get_type())
343         {
344         case ValueBase::TYPE_COLOR:
345                 ret.push_back(ParamDesc(ValueBase(),"red")
346                         .set_local_name(_("Red"))
347                         .set_description(_("The red component of the color"))
348                 );
349                 ret.push_back(ParamDesc(ValueBase(),"green")
350                         .set_local_name(_("Green"))
351                         .set_description(_("The green component of the color"))
352                 );
353                 ret.push_back(ParamDesc(ValueBase(),"blue")
354                         .set_local_name(_("Blue"))
355                         .set_description(_("The blue component of the color"))
356                 );
357                 ret.push_back(ParamDesc(ValueBase(),"alpha")
358                         .set_local_name(_("Alpha"))
359                         .set_description(_("The alpha of the color"))
360                 );
361                 return ret;
362         case ValueBase::TYPE_SEGMENT:
363                 ret.push_back(ParamDesc(ValueBase(),"p1")
364                         .set_local_name(_("Vertex 1"))
365                         .set_description(_("The first vertex of the segment"))
366                 );
367                 ret.push_back(ParamDesc(ValueBase(),"t1")
368                         .set_local_name(_("Tangent 1"))
369                         .set_description(_("The first tangent of the segment"))
370                 );
371                 ret.push_back(ParamDesc(ValueBase(),"p2")
372                         .set_local_name(_("Vertex 2"))
373                         .set_description(_("The second vertex of the segment"))
374                 );
375                 ret.push_back(ParamDesc(ValueBase(),"t2")
376                         .set_local_name(_("Tangent 2"))
377                         .set_description(_("The second tangent of the segment"))
378                 );
379                 return ret;
380         case ValueBase::TYPE_VECTOR:
381                 ret.push_back(ParamDesc(ValueBase(),"x")
382                         .set_local_name(_("X-Axis"))
383                         .set_description(_("The X-Axis component of the vector"))
384                 );
385                 ret.push_back(ParamDesc(ValueBase(),"y")
386                         .set_local_name(_("Y-Axis"))
387                         .set_description(_("The Y-Axis component of the vector"))
388                 );
389                 return ret;
390         case ValueBase::TYPE_BLINEPOINT:
391                 ret.push_back(ParamDesc(ValueBase(),"point")
392                         .set_local_name(_("Vertex"))
393                         .set_description(_("The vertex of the BLine Point"))
394                 );
395                 ret.push_back(ParamDesc(ValueBase(),"width")
396                         .set_local_name(_("Width"))
397                         .set_description(_("The width of the BLine Point"))
398                 );
399                 ret.push_back(ParamDesc(ValueBase(),"origin")
400                         .set_local_name(_("Origin"))
401                         .set_description(_("Defines the Off and On position relative to neighbours"))
402                 );
403                 ret.push_back(ParamDesc(ValueBase(),"split")
404                         .set_local_name(_("Split"))
405                         .set_description(_("When checked, tangents are independent"))
406                 );
407                 ret.push_back(ParamDesc(ValueBase(),"t1")
408                         .set_local_name(_("Tangent 1"))
409                         .set_description(_("The first tangent of the BLine Point"))
410                 );
411                 ret.push_back(ParamDesc(ValueBase(),"t2")
412                         .set_local_name(_("Tangent 2"))
413                         .set_description(_("The second tangent of the BLine Point"))
414                 );
415                 return ret;
416         default:
417                 break;
418         }
419
420         return ret;
421 }