56323147d6eb17313d43ae23da67f7394b5a83ea
[synfig.git] / synfig-core / trunk / src / synfig / valuenode_repeat_gradient.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_repeat_gradient.cpp
3 **      \brief Template File
4 **
5 **      $Id: valuenode_repeat_gradient.cpp 604 2007-09-05 14:29:02Z dooglus $
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_repeat_gradient.h"
34 #include "valuenode_const.h"
35 #include <stdexcept>
36 #include "color.h"
37 #include "gradient.h"
38
39 #endif
40
41 /* === U S I N G =========================================================== */
42
43 using namespace std;
44 using namespace etl;
45 using namespace synfig;
46
47 /* === M A C R O S ========================================================= */
48
49 /* === G L O B A L S ======================================================= */
50
51 /* === P R O C E D U R E S ================================================= */
52
53 /* === M E T H O D S ======================================================= */
54
55 synfig::ValueNode_Repeat_Gradient::ValueNode_Repeat_Gradient(const Gradient& x):LinkableValueNode(synfig::ValueBase::TYPE_GRADIENT)
56 {
57         set_link("gradient",ValueNode_Const::create(x));
58         set_link("count",count_=ValueNode_Const::create(int(3)));
59         set_link("width",ValueNode_Const::create(0.5));
60         set_link("specify_start",ValueNode_Const::create(true));
61         set_link("specify_end",ValueNode_Const::create(true));
62         set_link("start_color",ValueNode_Const::create(Color::alpha()));
63         set_link("end_color",ValueNode_Const::create(Color::alpha()));
64 }
65
66 LinkableValueNode*
67 ValueNode_Repeat_Gradient::create_new()const
68 {
69         return new ValueNode_Repeat_Gradient(Gradient());
70 }
71
72 ValueNode_Repeat_Gradient*
73 ValueNode_Repeat_Gradient::create(const ValueBase& x)
74 {
75         ValueBase::Type id(x.get_type());
76
77         if(id!=ValueBase::TYPE_GRADIENT)
78         {
79                 assert(0);
80                 throw runtime_error("synfig::ValueNode_Repeat_Gradient:Bad type "+ValueBase::type_name(id));
81         }
82
83         ValueNode_Repeat_Gradient* value_node=new ValueNode_Repeat_Gradient(x.get(Gradient()));
84
85         assert(value_node->get_type()==id);
86
87         return value_node;
88 }
89
90 synfig::ValueNode_Repeat_Gradient::~ValueNode_Repeat_Gradient()
91 {
92         unlink_all();
93 }
94
95 bool
96 synfig::ValueNode_Repeat_Gradient::set_gradient(ValueNode::Handle a)
97 {
98         if(a->get_type()!=ValueBase::TYPE_GRADIENT)
99                 return false;
100
101         gradient_=a;
102
103         return true;
104 }
105
106 bool
107 synfig::ValueNode_Repeat_Gradient::set_width(ValueNode::Handle x)
108 {
109         if(x->get_type()!=ValueBase::TYPE_REAL)
110                 return false;
111
112         width_=x;
113
114         return true;
115 }
116
117 bool
118 synfig::ValueNode_Repeat_Gradient::set_count(ValueNode::Handle b)
119 {
120         if(b->get_type()!=ValueBase::TYPE_INTEGER)
121                 return false;
122         count_=b;
123         return true;
124 }
125
126 bool
127 synfig::ValueNode_Repeat_Gradient::set_specify_start(ValueNode::Handle a)
128 {
129         if(a->get_type()!=ValueBase::TYPE_BOOL)
130                 return false;
131         specify_start_=a;
132         return true;
133 }
134
135 bool
136 synfig::ValueNode_Repeat_Gradient::set_specify_end(ValueNode::Handle a)
137 {
138         if(a->get_type()!=ValueBase::TYPE_BOOL)
139                 return false;
140         specify_end_=a;
141         return true;
142 }
143
144 bool
145 synfig::ValueNode_Repeat_Gradient::set_start_color(ValueNode::Handle a)
146 {
147         if(a->get_type()!=ValueBase::TYPE_COLOR)
148                 return false;
149         start_color_=a;
150         return true;
151 }
152
153 bool
154 synfig::ValueNode_Repeat_Gradient::set_end_color(ValueNode::Handle a)
155 {
156         if(a->get_type()!=ValueBase::TYPE_COLOR)
157                 return false;
158         end_color_=a;
159         return true;
160 }
161
162 synfig::ValueBase
163 synfig::ValueNode_Repeat_Gradient::operator()(Time t)const
164 {
165         const int count((*count_)(t).get(int()));
166         int i;
167         Gradient ret;
168
169         if(count<=0)
170                 return ret;
171
172         const Gradient gradient((*gradient_)(t).get(Gradient()));
173         const float width(max(0.0,min(1.0,(*width_)(t).get(Real()))));
174         const bool specify_start((*specify_start_)(t).get(bool()));
175         const bool specify_end((*specify_end_)(t).get(bool()));
176
177         const float gradient_width_a(width/count);
178         const float gradient_width_b((1.0-width)/count);
179
180         Gradient::const_iterator iter;
181         Gradient::const_reverse_iterator riter;
182         if (specify_start)
183                 ret.push_back(Gradient::CPoint(0,(*start_color_)(t).get(Color())));
184         for(i=0;i<count;i++)
185         {
186                 float pos(float(i)/count);
187                 if (width != 0.0)
188                         for(iter=gradient.begin();iter!=gradient.end();iter++)
189                                 ret.push_back(Gradient::CPoint(pos+gradient_width_a*iter->pos,iter->color));
190                 pos+=gradient_width_a;
191                 if (width != 1.0)
192                         for(riter=gradient.rbegin();riter!=gradient.rend();riter++)
193                                 ret.push_back(Gradient::CPoint(pos+gradient_width_b*(1-(riter->pos)),riter->color));
194         }
195         if (specify_end)
196                 ret.push_back(Gradient::CPoint(1,(*end_color_)(t).get(Color())));
197         return ret;
198 }
199
200 bool
201 ValueNode_Repeat_Gradient::set_link_vfunc(int i,ValueNode::Handle x)
202 {
203         assert(i>=0 && i<link_count());
204         switch(i)
205         {
206                 case 0:
207                         if(set_gradient(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
208                         else { return false; }
209                 case 1:
210                         if(set_count(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
211                         else { return false; }
212                 case 2:
213                         if(set_width(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
214                         else { return false; }
215                 case 3:
216                         if(set_specify_start(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
217                         else { return false; }
218                 case 4:
219                         if(set_specify_end(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
220                         else { return false; }
221                 case 5:
222                         if(set_start_color(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
223                         else { return false; }
224                 case 6:
225                         if(set_end_color(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
226                         else { return false; }
227         }
228
229         return false;
230 }
231
232 ValueNode::LooseHandle
233 ValueNode_Repeat_Gradient::get_link_vfunc(int i)const
234 {
235         assert(i>=0 && i<link_count());
236         switch(i)
237         {
238                 case 0:  return gradient_;
239                 case 1:  return count_;
240                 case 2:  return width_;
241                 case 3:  return specify_start_;
242                 case 4:  return specify_end_;
243                 case 5:  return start_color_;
244                 case 6:  return end_color_;
245             default: return 0;
246         }
247 }
248
249 int
250 ValueNode_Repeat_Gradient::link_count()const
251 {
252         return 7;
253 }
254
255 String
256 ValueNode_Repeat_Gradient::link_local_name(int i)const
257 {
258         assert(i>=0 && i<link_count());
259         switch(i)
260         {
261                 case 0:  return _("Gradient");
262                 case 1:  return _("Count");
263                 case 2:  return _("Width");
264                 case 3:  return _("Specify Start");
265                 case 4:  return _("Specify End");
266                 case 5:  return _("Start Color");
267                 case 6:  return _("End Color");
268                 default: return String();
269         }
270 }
271
272 String
273 ValueNode_Repeat_Gradient::link_name(int i)const
274 {
275         assert(i>=0 && i<link_count());
276         switch(i)
277         {
278                 case 0:  return "gradient";
279                 case 1:  return "count";
280                 case 2:  return "width";
281                 case 3:  return "specify_start";
282                 case 4:  return "specify_end";
283                 case 5:  return "start_color";
284                 case 6:  return "end_color";
285                 default: return String();
286         }
287 }
288
289 int
290 ValueNode_Repeat_Gradient::get_link_index_from_name(const String &name)const
291 {
292         if(name=="gradient") return 0;
293         if(name=="count")    return 1;
294         if(name=="width")    return 2;
295         if(name=="specify_start") return 3;
296         if(name=="specify_end")   return 4;
297         if(name=="start_color")   return 5;
298         if(name=="end_color")     return 6;
299         throw Exception::BadLinkName(name);
300 }
301
302 String
303 ValueNode_Repeat_Gradient::get_name()const
304 {
305         return "repeat_gradient";
306 }
307
308 String
309 ValueNode_Repeat_Gradient::get_local_name()const
310 {
311         return _("Repeat Gradient");
312 }
313
314 bool
315 ValueNode_Repeat_Gradient::check_type(ValueBase::Type type)
316 {
317         return type==ValueBase::TYPE_GRADIENT;
318 }