Use a switch statement in the operator() like the other valuenode types do.
[synfig.git] / synfig-core / trunk / src / synfig / valuenode_subtract.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_subtract.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "general.h"
33 #include "valuenode_subtract.h"
34 #include "valuenode_const.h"
35 #include <stdexcept>
36 #include "color.h"
37 #include "vector.h"
38 #include "angle.h"
39 #include "real.h"
40
41 #endif
42
43 /* === U S I N G =========================================================== */
44
45 using namespace std;
46 using namespace etl;
47 using namespace synfig;
48
49 /* === M A C R O S ========================================================= */
50
51 /* === G L O B A L S ======================================================= */
52
53 /* === P R O C E D U R E S ================================================= */
54
55 /* === M E T H O D S ======================================================= */
56
57 synfig::ValueNode_Subtract::ValueNode_Subtract():LinkableValueNode(synfig::ValueBase::TYPE_NIL)
58 {
59         set_scalar(1.0);
60 }
61
62 LinkableValueNode*
63 ValueNode_Subtract::create_new()const
64 {
65         return new ValueNode_Subtract();
66 }
67
68 ValueNode_Subtract*
69 ValueNode_Subtract::create(const ValueBase& x)
70 {
71         ValueBase::Type id(x.get_type());
72
73         ValueNode_Subtract* value_node=new ValueNode_Subtract();
74         switch(id)
75         {
76         case ValueBase::TYPE_NIL:
77                 return value_node;
78         case ValueBase::TYPE_COLOR:
79                 value_node->set_link("lhs",ValueNode_Const::create(x.get(Color())));
80                 value_node->set_link("rhs",ValueNode_Const::create(Color(0,0,0,0)));
81                 break;
82         case ValueBase::TYPE_ANGLE:
83         case ValueBase::TYPE_INTEGER:
84         case ValueBase::TYPE_REAL:
85         case ValueBase::TYPE_VECTOR:
86                 value_node->set_link("lhs",ValueNode_Const::create(ValueBase(id)));
87                 value_node->set_link("rhs",ValueNode_Const::create(ValueBase(id)));
88                 break;
89         default:
90                 assert(0);
91                 throw runtime_error("synfig::ValueNode_Subtract:Bad type "+ValueBase::type_name(id));
92         }
93
94         assert(value_node->get_lhs()->get_type()==id);
95         assert(value_node->get_rhs()->get_type()==id);
96
97         assert(value_node->get_type()==id);
98
99         return value_node;
100 }
101
102 synfig::ValueNode_Subtract::~ValueNode_Subtract()
103 {
104         unlink_all();
105 }
106
107 void
108 ValueNode_Subtract::set_scalar(Real x)
109 {
110         set_link("scalar",ValueNode_Const::create(x));
111 }
112
113 bool
114 synfig::ValueNode_Subtract::set_scalar(ValueNode::Handle x)
115 {
116         if(x->get_type()!=ValueBase::TYPE_REAL&& !PlaceholderValueNode::Handle::cast_dynamic(x))
117                 return false;
118         scalar=x;
119         return true;
120 }
121
122 bool
123 synfig::ValueNode_Subtract::set_lhs(ValueNode::Handle a)
124 {
125         ref_a=a;
126
127         if(PlaceholderValueNode::Handle::cast_dynamic(a))
128                 return true;
129
130         if(!ref_a || !ref_b)
131                 set_type(ValueBase::TYPE_NIL);
132         else
133         if(ref_a->get_type()==ValueBase::TYPE_ANGLE && ref_a->get_type()==ValueBase::TYPE_ANGLE)
134                 set_type(ValueBase::TYPE_ANGLE);
135         else
136         if(ref_a->get_type()==ValueBase::TYPE_COLOR && ref_a->get_type()==ValueBase::TYPE_COLOR)
137                 set_type(ValueBase::TYPE_COLOR);
138         else
139         if(ref_a->get_type()==ValueBase::TYPE_INTEGER && ref_a->get_type()==ValueBase::TYPE_INTEGER)
140                 set_type(ValueBase::TYPE_INTEGER);
141         else
142         if(ref_a->get_type()==ValueBase::TYPE_REAL && ref_a->get_type()==ValueBase::TYPE_REAL)
143                 set_type(ValueBase::TYPE_REAL);
144         else
145         if(ref_a->get_type()==ValueBase::TYPE_VECTOR && ref_a->get_type()==ValueBase::TYPE_VECTOR)
146                 set_type(ValueBase::TYPE_VECTOR);
147         else
148         {
149                 synfig::warning(get_id()+":(set_a):"+strprintf(_("Types seem to be off for ValueNodes %s and %s"),ref_a->get_id().c_str(),ref_b->get_id().c_str()));
150                 set_type(ValueBase::TYPE_NIL);
151         }
152
153         return true;
154 }
155
156 bool
157 synfig::ValueNode_Subtract::set_rhs(ValueNode::Handle b)
158 {
159         ref_b=b;
160
161         if(PlaceholderValueNode::Handle::cast_dynamic(b))
162                 return true;
163
164         if(!ref_a || !ref_b)
165                 set_type(ValueBase::TYPE_NIL);
166         else
167         if(ref_a->get_type()==ValueBase::TYPE_ANGLE && ref_a->get_type()==ValueBase::TYPE_ANGLE)
168                 set_type(ValueBase::TYPE_ANGLE);
169         else
170         if(ref_a->get_type()==ValueBase::TYPE_COLOR && ref_a->get_type()==ValueBase::TYPE_COLOR)
171                 set_type(ValueBase::TYPE_COLOR);
172         else
173         if(ref_a->get_type()==ValueBase::TYPE_INTEGER && ref_a->get_type()==ValueBase::TYPE_INTEGER)
174                 set_type(ValueBase::TYPE_INTEGER);
175         else
176         if(ref_a->get_type()==ValueBase::TYPE_REAL && ref_a->get_type()==ValueBase::TYPE_REAL)
177                 set_type(ValueBase::TYPE_REAL);
178         else
179         if(ref_a->get_type()==ValueBase::TYPE_VECTOR && ref_a->get_type()==ValueBase::TYPE_VECTOR)
180                 set_type(ValueBase::TYPE_VECTOR);
181         else
182         {
183                 synfig::warning(get_id()+":(set_b):"+strprintf(_("Types seem to be off for ValueNodes %s and %s"),ref_a->get_id().c_str(),ref_b->get_id().c_str()));
184                 set_type(ValueBase::TYPE_NIL);
185         }
186
187         return true;
188 }
189
190 synfig::ValueBase
191 synfig::ValueNode_Subtract::operator()(Time t)const
192 {
193         if(!ref_a || !ref_b)
194                 throw runtime_error(strprintf("ValueNode_Subtract: %s",_("One or both of my parameters aren't set!")));
195         switch(get_type())
196         {
197         case ValueBase::TYPE_ANGLE:
198                 return ((*ref_a)(t).get(Angle())-(*ref_b)(t).get(Angle()))*(*scalar)(t).get(Real());
199         case ValueBase::TYPE_COLOR:
200                 return ((*ref_a)(t).get(Color())-(*ref_b)(t).get(Color()))*(*scalar)(t).get(Real());
201         case ValueBase::TYPE_INTEGER:
202         {
203                 Real ret = ((*ref_a)(t).get(int())-(*ref_b)(t).get(int()))*(*scalar)(t).get(Real()) + 0.5f;
204                 if (ret < 0) return static_cast<int>(ret-1);
205                 return static_cast<int>(ret); 
206         }
207         case ValueBase::TYPE_REAL:
208                 return ((*ref_a)(t).get(Vector::value_type())-(*ref_b)(t).get(Vector::value_type()))*(*scalar)(t).get(Real());
209         case ValueBase::TYPE_VECTOR:
210                 return ((*ref_a)(t).get(Vector())-(*ref_b)(t).get(Vector()))*(*scalar)(t).get(Real());
211         default:
212                 assert(0);
213                 break;
214         }
215         return ValueBase();
216 }
217
218 bool
219 ValueNode_Subtract::set_link_vfunc(int i,ValueNode::Handle x)
220 {
221         assert(i>=0 && i<3);
222         switch(i)
223         {
224                 case 0:
225                         if(set_lhs(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
226                         else { return false; }
227                 case 1:
228                         if(set_rhs(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
229                         else { return false; }
230                 case 2:
231                         scalar=x;
232                         signal_child_changed()(i);signal_value_changed()();
233                         return true;
234         }
235
236         return false;
237 }
238
239 ValueNode::LooseHandle
240 ValueNode_Subtract::get_link_vfunc(int i)const
241 {
242         assert(i>=0 && i<3);
243         switch(i)
244         {
245                 case 0:
246                         return ref_a;
247                 case 1:
248                         return ref_b;
249                 case 2:
250                         return scalar;
251         }
252         return 0;
253 }
254
255 int
256 ValueNode_Subtract::link_count()const
257 {
258         return 3;
259 }
260
261 String
262 ValueNode_Subtract::link_local_name(int i)const
263 {
264         assert(i>=0 && i<3);
265         switch(i)
266         {
267                 case 0:
268                         return _("LHS");
269                 case 1:
270                         return _("RHS");
271                 case 2:
272                         return _("Scalar");
273                 default:
274                         return String();
275         }
276 }
277
278 String
279 ValueNode_Subtract::link_name(int i)const
280 {
281         assert(i>=0 && i<3);
282         switch(i)
283         {
284                 case 0:
285                         return "lhs";
286                 case 1:
287                         return "rhs";
288                 case 2:
289                         return "scalar";
290                 default:
291                         return String();
292         }
293 }
294
295 int
296 ValueNode_Subtract::get_link_index_from_name(const String &name)const
297 {
298         if(name=="lhs")
299                 return 0;
300         if(name=="rhs")
301                 return 1;
302         if(name=="scalar")
303                 return 2;
304         throw Exception::BadLinkName(name);
305 }
306
307 String
308 ValueNode_Subtract::get_name()const
309 {
310         return "subtract";
311 }
312
313 String
314 ValueNode_Subtract::get_local_name()const
315 {
316         return _("Subtract");
317 }
318
319 bool
320 ValueNode_Subtract::check_type(ValueBase::Type type)
321 {
322         return type==ValueBase::TYPE_ANGLE
323                 || type==ValueBase::TYPE_COLOR
324                 || type==ValueBase::TYPE_INTEGER
325                 || type==ValueBase::TYPE_REAL
326                 || type==ValueBase::TYPE_VECTOR;
327 }