Rearranged a bit so I can see what's missing.
[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_ANGLE:
79         case ValueBase::TYPE_COLOR:
80         case ValueBase::TYPE_INTEGER:
81         case ValueBase::TYPE_REAL:
82         case ValueBase::TYPE_VECTOR:
83                 value_node->set_link("lhs",ValueNode_Const::create(ValueBase(id)));
84                 value_node->set_link("rhs",ValueNode_Const::create(ValueBase(id)));
85                 break;
86         default:
87                 assert(0);
88                 throw runtime_error("synfig::ValueNode_Subtract:Bad type "+ValueBase::type_name(id));
89         }
90
91         assert(value_node->get_lhs()->get_type()==id);
92         assert(value_node->get_rhs()->get_type()==id);
93
94         assert(value_node->get_type()==id);
95
96         return value_node;
97 }
98
99 synfig::ValueNode_Subtract::~ValueNode_Subtract()
100 {
101         unlink_all();
102 }
103
104 void
105 ValueNode_Subtract::set_scalar(Real x)
106 {
107         set_link("scalar",ValueNode_Const::create(x));
108 }
109
110 bool
111 synfig::ValueNode_Subtract::set_scalar(ValueNode::Handle x)
112 {
113         if(x->get_type()!=ValueBase::TYPE_REAL&& !PlaceholderValueNode::Handle::cast_dynamic(x))
114                 return false;
115         scalar=x;
116         return true;
117 }
118
119 bool
120 synfig::ValueNode_Subtract::set_lhs(ValueNode::Handle a)
121 {
122         ref_a=a;
123
124         if(PlaceholderValueNode::Handle::cast_dynamic(a))
125                 return true;
126
127         if(!ref_a || !ref_b)
128                 set_type(ValueBase::TYPE_NIL);
129         else
130         if(ref_a->get_type()==ValueBase::TYPE_ANGLE && ref_a->get_type()==ValueBase::TYPE_ANGLE)
131                 set_type(ValueBase::TYPE_ANGLE);
132         else
133         if(ref_a->get_type()==ValueBase::TYPE_COLOR && ref_a->get_type()==ValueBase::TYPE_COLOR)
134                 set_type(ValueBase::TYPE_COLOR);
135         else
136         if(ref_a->get_type()==ValueBase::TYPE_INTEGER && ref_a->get_type()==ValueBase::TYPE_INTEGER)
137                 set_type(ValueBase::TYPE_INTEGER);
138         else
139         if(ref_a->get_type()==ValueBase::TYPE_REAL && ref_a->get_type()==ValueBase::TYPE_REAL)
140                 set_type(ValueBase::TYPE_REAL);
141         else
142         if(ref_a->get_type()==ValueBase::TYPE_VECTOR && ref_a->get_type()==ValueBase::TYPE_VECTOR)
143                 set_type(ValueBase::TYPE_VECTOR);
144         else
145         {
146                 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()));
147                 set_type(ValueBase::TYPE_NIL);
148         }
149
150         return true;
151 }
152
153 bool
154 synfig::ValueNode_Subtract::set_rhs(ValueNode::Handle b)
155 {
156         ref_b=b;
157
158         if(PlaceholderValueNode::Handle::cast_dynamic(b))
159                 return true;
160
161         if(!ref_a || !ref_b)
162                 set_type(ValueBase::TYPE_NIL);
163         else
164         if(ref_a->get_type()==ValueBase::TYPE_ANGLE && ref_a->get_type()==ValueBase::TYPE_ANGLE)
165                 set_type(ValueBase::TYPE_ANGLE);
166         else
167         if(ref_a->get_type()==ValueBase::TYPE_COLOR && ref_a->get_type()==ValueBase::TYPE_COLOR)
168                 set_type(ValueBase::TYPE_COLOR);
169         else
170         if(ref_a->get_type()==ValueBase::TYPE_INTEGER && ref_a->get_type()==ValueBase::TYPE_INTEGER)
171                 set_type(ValueBase::TYPE_INTEGER);
172         else
173         if(ref_a->get_type()==ValueBase::TYPE_REAL && ref_a->get_type()==ValueBase::TYPE_REAL)
174                 set_type(ValueBase::TYPE_REAL);
175         else
176         if(ref_a->get_type()==ValueBase::TYPE_VECTOR && ref_a->get_type()==ValueBase::TYPE_VECTOR)
177                 set_type(ValueBase::TYPE_VECTOR);
178         else
179         {
180                 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()));
181                 set_type(ValueBase::TYPE_NIL);
182         }
183
184         return true;
185 }
186
187 synfig::ValueBase
188 synfig::ValueNode_Subtract::operator()(Time t)const
189 {
190         if(!ref_a || !ref_b)
191                 throw runtime_error(strprintf("ValueNode_Subtract: %s",_("One or both of my parameters aren't set!")));
192         if(get_type()==ValueBase::TYPE_ANGLE)
193                 return ((*ref_a)(t).get(Angle())-(*ref_b)(t).get(Angle()))*(*scalar)(t).get(Real());
194         if(get_type()==ValueBase::TYPE_COLOR)
195                 return ((*ref_a)(t).get(Color())-(*ref_b)(t).get(Color()))*(*scalar)(t).get(Real());
196         if(get_type()==ValueBase::TYPE_INTEGER)
197                 return ((*ref_a)(t).get(int())-(*ref_b)(t).get(int()))*(*scalar)(t).get(Real());
198         if(get_type()==ValueBase::TYPE_REAL)
199                 return ((*ref_a)(t).get(Vector::value_type())-(*ref_b)(t).get(Vector::value_type()))*(*scalar)(t).get(Real());
200         if(get_type()==ValueBase::TYPE_VECTOR)
201                 return ((*ref_a)(t).get(Vector())-(*ref_b)(t).get(Vector()))*(*scalar)(t).get(Real());
202
203         synfig::error(get_id()+':'+strprintf(_("Cannot subtract types of %s and %s"),ValueBase::type_name(ref_a->get_type()).c_str(),ValueBase::type_name(ref_b->get_type()).c_str()));
204         return ValueBase();
205 }
206
207 bool
208 ValueNode_Subtract::set_link_vfunc(int i,ValueNode::Handle x)
209 {
210         assert(i>=0 && i<3);
211         switch(i)
212         {
213                 case 0:
214                         if(set_lhs(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
215                         else { return false; }
216                 case 1:
217                         if(set_rhs(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
218                         else { return false; }
219                 case 2:
220                         scalar=x;
221                         signal_child_changed()(i);signal_value_changed()();
222                         return true;
223         }
224
225         return false;
226 }
227
228 ValueNode::LooseHandle
229 ValueNode_Subtract::get_link_vfunc(int i)const
230 {
231         assert(i>=0 && i<3);
232         switch(i)
233         {
234                 case 0:
235                         return ref_a;
236                 case 1:
237                         return ref_b;
238                 case 2:
239                         return scalar;
240         }
241         return 0;
242 }
243
244 int
245 ValueNode_Subtract::link_count()const
246 {
247         return 3;
248 }
249
250 String
251 ValueNode_Subtract::link_local_name(int i)const
252 {
253         assert(i>=0 && i<3);
254         switch(i)
255         {
256                 case 0:
257                         return _("LHS");
258                 case 1:
259                         return _("RHS");
260                 case 2:
261                         return _("Scalar");
262                 default:
263                         return String();
264         }
265 }
266
267 String
268 ValueNode_Subtract::link_name(int i)const
269 {
270         assert(i>=0 && i<3);
271         switch(i)
272         {
273                 case 0:
274                         return "lhs";
275                 case 1:
276                         return "rhs";
277                 case 2:
278                         return "scalar";
279                 default:
280                         return String();
281         }
282 }
283
284 int
285 ValueNode_Subtract::get_link_index_from_name(const String &name)const
286 {
287         if(name=="lhs")
288                 return 0;
289         if(name=="rhs")
290                 return 1;
291         if(name=="scalar")
292                 return 2;
293         throw Exception::BadLinkName(name);
294 }
295
296 String
297 ValueNode_Subtract::get_name()const
298 {
299         return "subtract";
300 }
301
302 String
303 ValueNode_Subtract::get_local_name()const
304 {
305         return _("Subtract");
306 }
307
308 bool
309 ValueNode_Subtract::check_type(ValueBase::Type type)
310 {
311         return type==ValueBase::TYPE_ANGLE
312                 || type==ValueBase::TYPE_COLOR
313                 || type==ValueBase::TYPE_INTEGER
314                 || type==ValueBase::TYPE_REAL
315                 || type==ValueBase::TYPE_VECTOR;
316 }