1 /* === S Y N F I G ========================================================= */
2 /*! \file valuenode_random.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
33 #include "valuenode_random.h"
34 #include "synfig/valuenode_const.h"
35 #include "synfig/general.h"
36 #include "synfig/color.h"
41 /* === U S I N G =========================================================== */
45 using namespace synfig;
47 /* === M A C R O S ========================================================= */
49 /* === G L O B A L S ======================================================= */
51 /* === P R O C E D U R E S ================================================= */
53 /* === M E T H O D S ======================================================= */
55 ValueNode_Random::ValueNode_Random(const ValueBase &value):
56 LinkableValueNode(value.get_type())
58 Vocab ret(get_children_vocab());
59 set_children_vocab(ret);
60 random.set_seed(time(NULL));
62 set_link("radius",ValueNode_Const::create(Real(1)));
63 set_link("seed",ValueNode_Const::create(random.get_seed()));
64 set_link("speed",ValueNode_Const::create(Real(1)));
65 set_link("smooth",ValueNode_Const::create(int(RandomNoise::SMOOTH_CUBIC)));
66 set_link("loop",ValueNode_Const::create(Real(0)));
70 case ValueBase::TYPE_ANGLE:
71 set_link("link",ValueNode_Const::create(value.get(Angle())));
73 case ValueBase::TYPE_BOOL:
74 set_link("link",ValueNode_Const::create(value.get(bool())));
76 case ValueBase::TYPE_COLOR:
77 set_link("link",ValueNode_Const::create(value.get(Color())));
79 case ValueBase::TYPE_INTEGER:
80 set_link("link",ValueNode_Const::create(value.get(int())));
82 case ValueBase::TYPE_REAL:
83 set_link("link",ValueNode_Const::create(value.get(Real())));
85 case ValueBase::TYPE_TIME:
86 set_link("link",ValueNode_Const::create(value.get(Time())));
88 case ValueBase::TYPE_VECTOR:
89 set_link("link",ValueNode_Const::create(value.get(Vector())));
92 throw Exception::BadType(ValueBase::type_local_name(get_type()));
97 ValueNode_Random::create_new()const
99 return new ValueNode_Random(get_type());
103 ValueNode_Random::create(const ValueBase &x)
105 return new ValueNode_Random(x);
108 ValueNode_Random::~ValueNode_Random()
114 ValueNode_Random::operator()(Time t)const
116 typedef const RandomNoise::SmoothType Smooth;
118 Real radius = (*radius_)(t).get(Real());
119 int seed = (*seed_)(t).get(int());
120 int smooth = (*smooth_)(t).get(int());
121 float speed = (*speed_ )(t).get(Real());
122 int loop = int((((*loop_ )(t).get(Real())) * speed) + 0.5);
125 random.set_seed(seed);
129 case ValueBase::TYPE_ANGLE:
130 return ((*link_)(t).get( Angle()) +
131 Angle::deg(random(Smooth(smooth), 0, 0, 0, speed, loop) * radius));
133 case ValueBase::TYPE_BOOL:
134 return round_to_int((*link_)(t).get( bool()) +
135 random(Smooth(smooth), 0, 0, 0, speed, loop) * radius) > 0;
137 case ValueBase::TYPE_COLOR:
138 return (((*link_)(t).get( Color()) +
139 Color(random(Smooth(smooth), 0, 0, 0, speed, loop),
140 random(Smooth(smooth), 1, 0, 0, speed, loop),
141 random(Smooth(smooth), 2, 0, 0, speed, loop), 0) * radius).clamped());
143 case ValueBase::TYPE_INTEGER:
144 return round_to_int((*link_)(t).get( int()) +
145 random(Smooth(smooth), 0, 0, 0, speed, loop) * radius);
147 case ValueBase::TYPE_REAL:
148 return ((*link_)(t).get( Real()) +
149 random(Smooth(smooth), 0, 0, 0, speed, loop) * radius);
151 case ValueBase::TYPE_TIME:
152 return ((*link_)(t).get( Time()) +
153 random(Smooth(smooth), 0, 0, 0, speed, loop) * radius);
155 case ValueBase::TYPE_VECTOR:
157 float length(random(Smooth(smooth), 0, 0, 0, speed, loop) * radius);
158 Angle::rad angle(random(Smooth(smooth), 1, 0, 0, speed, loop) * PI);
160 return ((*link_)(t).get(Vector()) +
161 Vector(Angle::cos(angle).get(), Angle::sin(angle).get()) * length);
174 ValueNode_Random::get_name()const
180 ValueNode_Random::get_local_name()const
186 ValueNode_Random::set_link_vfunc(int i,ValueNode::Handle value)
188 assert(i>=0 && i<link_count());
192 case 0: CHECK_TYPE_AND_SET_VALUE(link_, get_type());
193 case 1: CHECK_TYPE_AND_SET_VALUE(radius_, ValueBase::TYPE_REAL);
194 case 2: CHECK_TYPE_AND_SET_VALUE(seed_, ValueBase::TYPE_INTEGER);
195 case 3: CHECK_TYPE_AND_SET_VALUE(speed_, ValueBase::TYPE_REAL);
196 case 4: CHECK_TYPE_AND_SET_VALUE(smooth_, ValueBase::TYPE_INTEGER);
197 case 5: CHECK_TYPE_AND_SET_VALUE(loop_, ValueBase::TYPE_REAL);
202 ValueNode::LooseHandle
203 ValueNode_Random::get_link_vfunc(int i)const
205 assert(i>=0 && i<link_count());
209 case 0: return link_;
210 case 1: return radius_;
211 case 2: return seed_;
212 case 3: return speed_;
213 case 4: return smooth_;
214 case 5: return loop_;
220 ValueNode_Random::check_type(ValueBase::Type type)
223 type==ValueBase::TYPE_ANGLE ||
224 type==ValueBase::TYPE_BOOL ||
225 type==ValueBase::TYPE_COLOR ||
226 type==ValueBase::TYPE_INTEGER ||
227 type==ValueBase::TYPE_REAL ||
228 type==ValueBase::TYPE_TIME ||
229 type==ValueBase::TYPE_VECTOR ;
233 ValueNode_Random::clone(const GUID& deriv_guid)const
235 ValueNode_Random* ret = (ValueNode_Random*)LinkableValueNode::clone(deriv_guid);
236 ret->randomize_seed();
241 ValueNode_Random::randomize_seed()
243 int i = get_link_index_from_name("seed");
244 ValueNode::Handle link = get_link_vfunc(i);
245 if(!link->is_exported() && link->get_name() == "constant")
247 int seed = time(NULL) + rand();
248 if (seed < 0) seed = -seed;
249 random.set_seed(seed);
250 set_link(i, ValueNode_Const::create(seed));
254 LinkableValueNode::Vocab
255 ValueNode_Random::get_children_vocab_vfunc()const
257 if(children_vocab.size())
258 return children_vocab;
260 LinkableValueNode::Vocab ret;
262 ret.push_back(ParamDesc(ValueBase(),"link")
263 .set_local_name(_("Link"))
264 .set_description(_("The value node source that provides the central value"))
267 ret.push_back(ParamDesc(ValueBase(),"radius")
268 .set_local_name(_("Radius"))
269 .set_description(_("The value of the maximum random difference"))
272 ret.push_back(ParamDesc(ValueBase(),"seed")
273 .set_local_name(_("Seed"))
274 .set_description(_("Seeds the random number generator"))
277 ret.push_back(ParamDesc(ValueBase(),"speed")
278 .set_local_name(_("Speed"))
279 .set_description(_("Defines how often a new random value is chosen (in choices per second) "))
282 ret.push_back(ParamDesc(ValueBase(),"smooth")
283 .set_local_name(_("Interpolation"))
284 .set_description(_("Determines how the value is interpolated from one random choice to the next"))
286 .add_enum_value(RandomNoise::SMOOTH_DEFAULT,"default",_("No interpolation"))
287 .add_enum_value(RandomNoise::SMOOTH_LINEAR,"linear",_("Linear"))
288 .add_enum_value(RandomNoise::SMOOTH_COSINE,"cosine",_("Cosine"))
289 .add_enum_value(RandomNoise::SMOOTH_SPLINE,"spline",_("Spline"))
290 .add_enum_value(RandomNoise::SMOOTH_CUBIC,"cubic",_("Cubic"))
294 ret.push_back(ParamDesc(ValueBase(),"loop")
295 .set_local_name(_("Loop Time"))
296 .set_description(_("Makes the random value repeat after the given time"))