Add a new type of valuenode conversion for gradients: "repeat gradient" which lets...
[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 "gradient.h"
37
38 #endif
39
40 /* === U S I N G =========================================================== */
41
42 using namespace std;
43 using namespace etl;
44 using namespace synfig;
45
46 /* === M A C R O S ========================================================= */
47
48 /* === G L O B A L S ======================================================= */
49
50 /* === P R O C E D U R E S ================================================= */
51
52 /* === M E T H O D S ======================================================= */
53
54 synfig::ValueNode_Repeat_Gradient::ValueNode_Repeat_Gradient():LinkableValueNode(synfig::ValueBase::TYPE_GRADIENT)
55 {
56         set_link("gradient",ValueNode_Const::create(Gradient()));
57         set_link("count",count_=ValueNode_Const::create(int(3)));
58         set_link("width",ValueNode_Const::create(0.5));
59 }
60
61 LinkableValueNode*
62 ValueNode_Repeat_Gradient::create_new()const
63 {
64         return new ValueNode_Repeat_Gradient();
65 }
66
67 ValueNode_Repeat_Gradient*
68 ValueNode_Repeat_Gradient::create(const ValueBase& x)
69 {
70         ValueBase::Type id(x.get_type());
71
72         if(id!=ValueBase::TYPE_GRADIENT)
73         {
74                 assert(0);
75                 throw runtime_error("synfig::ValueNode_Repeat_Gradient:Bad type "+ValueBase::type_name(id));
76         }
77
78         ValueNode_Repeat_Gradient* value_node=new ValueNode_Repeat_Gradient();
79         value_node->set_gradient(ValueNode_Const::create(x.get(Gradient())));
80
81         assert(value_node->get_type()==id);
82
83         return value_node;
84 }
85
86 synfig::ValueNode_Repeat_Gradient::~ValueNode_Repeat_Gradient()
87 {
88         unlink_all();
89 }
90
91 bool
92 synfig::ValueNode_Repeat_Gradient::set_gradient(ValueNode::Handle a)
93 {
94         if(a->get_type()!=ValueBase::TYPE_GRADIENT)
95                 return false;
96
97         gradient_=a;
98
99         return true;
100 }
101
102 bool
103 synfig::ValueNode_Repeat_Gradient::set_width(ValueNode::Handle x)
104 {
105         if(x->get_type()!=ValueBase::TYPE_REAL)
106                 return false;
107
108         width_=x;
109
110         return true;
111 }
112
113 bool
114 synfig::ValueNode_Repeat_Gradient::set_count(ValueNode::Handle b)
115 {
116         if(b->get_type()!=ValueBase::TYPE_INTEGER)
117                 return false;
118         count_=b;
119         return true;
120 }
121
122 synfig::ValueBase
123 synfig::ValueNode_Repeat_Gradient::operator()(Time t)const
124 {
125         const int count((*count_)(t).get(int()));
126         int i;
127         Gradient ret;
128
129         if(count<=0)
130                 return ret;
131
132         const Gradient gradient((*gradient_)(t).get(Gradient()));
133         const float width(max(0.0,min(1.0,(*width_)(t).get(Real()))));
134
135         const float gradient_width_a(width/count);
136         const float gradient_width_b((1.0-width)/count);
137
138         Gradient::const_iterator iter;
139         Gradient::const_reverse_iterator riter;
140         for(i=0;i<count;i++)
141         {
142                 float pos(float(i)/count);
143                 if (width != 0.0)
144                         for(iter=gradient.begin();iter!=gradient.end();iter++)
145                                 ret.push_back(Gradient::CPoint(pos+gradient_width_a*iter->pos,iter->color));
146                 pos+=gradient_width_a;
147                 if (width != 1.0)
148                         for(riter=gradient.rbegin();riter!=gradient.rend();riter++)
149                                 ret.push_back(Gradient::CPoint(pos+gradient_width_b*(1-(riter->pos)),riter->color));
150         }
151         return ret;
152 }
153
154 bool
155 ValueNode_Repeat_Gradient::set_link_vfunc(int i,ValueNode::Handle x)
156 {
157         assert(i>=0 && i<link_count());
158         switch(i)
159         {
160                 case 0:
161                         if(set_gradient(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
162                         else { return false; }
163                 case 1:
164                         if(set_count(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
165                         else { return false; }
166                 case 2:
167                         if(set_width(x)) { signal_child_changed()(i);signal_value_changed()(); return true; }
168                         else { return false; }
169         }
170
171         return false;
172 }
173
174 ValueNode::LooseHandle
175 ValueNode_Repeat_Gradient::get_link_vfunc(int i)const
176 {
177         assert(i>=0 && i<link_count());
178         switch(i)
179         {
180                 case 0:  return gradient_;
181                 case 1:  return count_;
182                 case 2:  return width_;
183             default: return 0;
184         }
185 }
186
187 int
188 ValueNode_Repeat_Gradient::link_count()const
189 {
190         return 3;
191 }
192
193 String
194 ValueNode_Repeat_Gradient::link_local_name(int i)const
195 {
196         assert(i>=0 && i<link_count());
197         switch(i)
198         {
199                 case 0:  return _("Gradient");
200                 case 1:  return _("Count");
201                 case 2:  return _("Width");
202                 default: return String();
203         }
204 }
205
206 String
207 ValueNode_Repeat_Gradient::link_name(int i)const
208 {
209         assert(i>=0 && i<link_count());
210         switch(i)
211         {
212                 case 0:  return "gradient";
213                 case 1:  return "count";
214                 case 2:  return "width";
215                 default: return String();
216         }
217 }
218
219 int
220 ValueNode_Repeat_Gradient::get_link_index_from_name(const String &name)const
221 {
222         if(name=="gradient") return 0;
223         if(name=="count")    return 1;
224         if(name=="width")    return 2;
225         throw Exception::BadLinkName(name);
226 }
227
228 String
229 ValueNode_Repeat_Gradient::get_name()const
230 {
231         return "repeat_gradient";
232 }
233
234 String
235 ValueNode_Repeat_Gradient::get_local_name()const
236 {
237         return _("Repeat Gradient");
238 }
239
240 bool
241 ValueNode_Repeat_Gradient::check_type(ValueBase::Type type)
242 {
243         return type==ValueBase::TYPE_GRADIENT;
244 }