Fix 1795913. Subtract now works with colors.
[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         if(get_type()==ValueBase::TYPE_ANGLE)
196                 return ((*ref_a)(t).get(Angle())-(*ref_b)(t).get(Angle()))*(*scalar)(t).get(Real());
197         if(get_type()==ValueBase::TYPE_COLOR)
198                 return ((*ref_a)(t).get(Color())-(*ref_b)(t).get(Color()))*(*scalar)(t).get(Real());
199         if(get_type()==ValueBase::TYPE_INTEGER)
200                 return ((*ref_a)(t).get(int())-(*ref_b)(t).get(int()))*(*scalar)(t).get(Real());
201         if(get_type()==ValueBase::TYPE_REAL)
202                 return ((*ref_a)(t).get(Vector::value_type())-(*ref_b)(t).get(Vector::value_type()))*(*scalar)(t).get(Real());
203         if(get_type()==ValueBase::TYPE_VECTOR)
204                 return ((*ref_a)(t).get(Vector())-(*ref_b)(t).get(Vector()))*(*scalar)(t).get(Real());
205
206         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()));
207         return ValueBase();
208 }
209
210 bool
211 ValueNode_Subtract::set_link_vfunc(int i,ValueNode::Handle x)
212 {
213         assert(i>=0 && i<3);
214         switch(i)
215         {
216                 case 0:
217                         if(set_lhs(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
218                         else { return false; }
219                 case 1:
220                         if(set_rhs(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
221                         else { return false; }
222                 case 2:
223                         scalar=x;
224                         signal_child_changed()(i);signal_value_changed()();
225                         return true;
226         }
227
228         return false;
229 }
230
231 ValueNode::LooseHandle
232 ValueNode_Subtract::get_link_vfunc(int i)const
233 {
234         assert(i>=0 && i<3);
235         switch(i)
236         {
237                 case 0:
238                         return ref_a;
239                 case 1:
240                         return ref_b;
241                 case 2:
242                         return scalar;
243         }
244         return 0;
245 }
246
247 int
248 ValueNode_Subtract::link_count()const
249 {
250         return 3;
251 }
252
253 String
254 ValueNode_Subtract::link_local_name(int i)const
255 {
256         assert(i>=0 && i<3);
257         switch(i)
258         {
259                 case 0:
260                         return _("LHS");
261                 case 1:
262                         return _("RHS");
263                 case 2:
264                         return _("Scalar");
265                 default:
266                         return String();
267         }
268 }
269
270 String
271 ValueNode_Subtract::link_name(int i)const
272 {
273         assert(i>=0 && i<3);
274         switch(i)
275         {
276                 case 0:
277                         return "lhs";
278                 case 1:
279                         return "rhs";
280                 case 2:
281                         return "scalar";
282                 default:
283                         return String();
284         }
285 }
286
287 int
288 ValueNode_Subtract::get_link_index_from_name(const String &name)const
289 {
290         if(name=="lhs")
291                 return 0;
292         if(name=="rhs")
293                 return 1;
294         if(name=="scalar")
295                 return 2;
296         throw Exception::BadLinkName(name);
297 }
298
299 String
300 ValueNode_Subtract::get_name()const
301 {
302         return "subtract";
303 }
304
305 String
306 ValueNode_Subtract::get_local_name()const
307 {
308         return _("Subtract");
309 }
310
311 bool
312 ValueNode_Subtract::check_type(ValueBase::Type type)
313 {
314         return type==ValueBase::TYPE_ANGLE
315                 || type==ValueBase::TYPE_COLOR
316                 || type==ValueBase::TYPE_INTEGER
317                 || type==ValueBase::TYPE_REAL
318                 || type==ValueBase::TYPE_VECTOR;
319 }