Use LinkableValueNode members functions when possible in the derived valuenodes.
[synfig.git] / synfig-core / src / synfig / valuenode_scale.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_scale.cpp
3 **      \brief Implementation of the "Scale" 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 "general.h"
34 #include "valuenode_scale.h"
35 #include "valuenode_const.h"
36 #include <stdexcept>
37 #include "color.h"
38 #include "vector.h"
39 #include "time.h"
40 #include "angle.h"
41 #include <ETL/misc>
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 ValueNode_Scale::ValueNode_Scale(const ValueBase &value):
60         LinkableValueNode(value.get_type())
61 {
62         Vocab ret(get_children_vocab());
63         set_children_vocab(ret);
64         set_link("scalar",ValueNode::Handle(ValueNode_Const::create(Real(1.0))));
65         ValueBase::Type id(value.get_type());
66
67         switch(id)
68         {
69         case ValueBase::TYPE_ANGLE:
70                 set_link("link",ValueNode_Const::create(value.get(Angle())));
71                 break;
72         case ValueBase::TYPE_COLOR:
73                 set_link("link",ValueNode_Const::create(value.get(Color())));
74                 break;
75         case ValueBase::TYPE_INTEGER:
76                 set_link("link",ValueNode_Const::create(value.get(int())));
77                 break;
78         case ValueBase::TYPE_REAL:
79                 set_link("link",ValueNode_Const::create(value.get(Real())));
80                 break;
81         case ValueBase::TYPE_TIME:
82                 set_link("link",ValueNode_Const::create(value.get(Time())));
83                 break;
84         case ValueBase::TYPE_VECTOR:
85                 set_link("link",ValueNode_Const::create(value.get(Vector())));
86                 break;
87         default:
88                 assert(0);
89                 throw runtime_error(get_local_name()+_(":Bad type ")+ValueBase::type_local_name(id));
90         }
91
92         assert(value_node);
93         assert(value_node->get_type()==id);
94         assert(get_type()==id);
95 }
96
97 LinkableValueNode*
98 ValueNode_Scale::create_new()const
99 {
100         return new ValueNode_Scale(get_type());
101 }
102
103 ValueNode_Scale*
104 ValueNode_Scale::create(const ValueBase& value)
105 {
106         return new ValueNode_Scale(value);
107 }
108
109 synfig::ValueNode_Scale::~ValueNode_Scale()
110 {
111         unlink_all();
112 }
113
114 synfig::ValueBase
115 synfig::ValueNode_Scale::operator()(Time t)const
116 {
117         if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
118                 printf("%s:%d operator()\n", __FILE__, __LINE__);
119
120         if(!value_node || !scalar)
121                 throw runtime_error(strprintf("ValueNode_Scale: %s",_("One or both of my parameters aren't set!")));
122         else if(get_type()==ValueBase::TYPE_ANGLE)
123                 return (*value_node)(t).get(Angle())*(*scalar)(t).get(Real());
124         else if(get_type()==ValueBase::TYPE_COLOR)
125         {
126                 Color ret((*value_node)(t).get(Color()));
127                 Real s((*scalar)(t).get(Real()));
128                 ret.set_r(ret.get_r()*s);
129                 ret.set_g(ret.get_g()*s);
130                 ret.set_b(ret.get_b()*s);
131                 return ret;
132         }
133         else if(get_type()==ValueBase::TYPE_INTEGER)
134                 return round_to_int((*value_node)(t).get(int())*(*scalar)(t).get(Real()));
135         else if(get_type()==ValueBase::TYPE_REAL)
136                 return (*value_node)(t).get(Real())*(*scalar)(t).get(Real());
137         else if(get_type()==ValueBase::TYPE_TIME)
138                 return (*value_node)(t).get(Time())*(*scalar)(t).get(Time());
139         else if(get_type()==ValueBase::TYPE_VECTOR)
140                 return (*value_node)(t).get(Vector())*(*scalar)(t).get(Real());
141
142         assert(0);
143         return ValueBase();
144 }
145
146 synfig::ValueBase
147 synfig::ValueNode_Scale::get_inverse(Time t, const synfig::Vector &target_value) const
148 {
149         Real scalar_value((*scalar)(t).get(Real()));
150         if(scalar_value==0)
151                         throw runtime_error(strprintf("ValueNode_Scale: %s",_("Attempting to get the inverse of a non invertible Valuenode")));
152         else
153                 {
154                         switch (get_type())
155                         {
156                                 case ValueBase::TYPE_REAL:
157                                         return target_value.mag() / scalar_value;
158                                 case ValueBase::TYPE_ANGLE:
159                                         return Angle::tan(target_value[1] / scalar_value ,target_value[0] / scalar_value);
160                                 default:
161                                         return target_value / scalar_value;
162                         }
163                 }
164         return ValueBase();
165 }
166
167 synfig::ValueBase
168 synfig::ValueNode_Scale::get_inverse(Time t, const synfig::Angle &target_value) const
169 {
170         Real scalar_value((*scalar)(t).get(Real()));
171         if(scalar_value==0)
172                         throw runtime_error(strprintf("ValueNode_Scale: %s",_("Attempting to get the inverse of a non invertible Valuenode")));
173         else
174                 {
175                         switch (get_type())
176                         {
177                                         default:
178                                         return target_value / scalar_value;
179                         }
180                 }
181         return ValueBase();
182 }
183
184 bool
185 synfig::ValueNode_Scale::is_invertible(Time t) const
186 {
187         Real scalar_value((*scalar)(t).get(Real()));
188         return (!scalar_value==0);
189 }
190
191 bool
192 ValueNode_Scale::set_link_vfunc(int i,ValueNode::Handle value)
193 {
194         assert(i>=0 && i<link_count());
195
196         switch(i)
197         {
198         case 0: CHECK_TYPE_AND_SET_VALUE(value_node, get_type());
199         case 1: CHECK_TYPE_AND_SET_VALUE(scalar,     ValueBase::TYPE_REAL);
200         }
201         return false;
202 }
203
204 ValueNode::LooseHandle
205 ValueNode_Scale::get_link_vfunc(int i)const
206 {
207         assert(i>=0 && i<link_count());
208
209         if(i==0)
210                 return value_node;
211         else if(i==1)
212                 return scalar;
213         return 0;
214 }
215
216 String
217 ValueNode_Scale::get_name()const
218 {
219         return "scale";
220 }
221
222 String
223 ValueNode_Scale::get_local_name()const
224 {
225         return _("Scale");
226 }
227
228 bool
229 ValueNode_Scale::check_type(ValueBase::Type type)
230 {
231         return
232                 type==ValueBase::TYPE_ANGLE ||
233                 type==ValueBase::TYPE_COLOR ||
234                 type==ValueBase::TYPE_INTEGER ||
235                 type==ValueBase::TYPE_REAL ||
236                 type==ValueBase::TYPE_TIME ||
237                 type==ValueBase::TYPE_VECTOR;
238 }
239
240 LinkableValueNode::Vocab
241 ValueNode_Scale::get_children_vocab_vfunc()const
242 {
243         if(children_vocab.size())
244                 return children_vocab;
245
246         LinkableValueNode::Vocab ret;
247
248         ret.push_back(ParamDesc(ValueBase(),"link")
249                 .set_local_name(_("Link"))
250                 .set_description(_("The value node used to scale"))
251         );
252
253         ret.push_back(ParamDesc(ValueBase(),"scalar")
254                 .set_local_name(_("Scalar"))
255                 .set_description(_("Value that multiplies the value node"))
256         );
257
258         return ret;
259 }