New version 0.2 of the Time Loop layer. It uses the same parameters as the recently...
[synfig.git] / synfig-core / trunk / src / modules / lyr_std / timeloop.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file timeloop.cpp
3 **      \brief Implementation of the "Time Loop" layer
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
10 **
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.
15 **
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.
20 **      \endlegal
21 **
22 ** === N O T E S ===========================================================
23 **
24 ** ========================================================================= */
25
26 /* === H E A D E R S ======================================================= */
27
28 #ifdef USING_PCH
29 #       include "pch.h"
30 #else
31 #ifdef HAVE_CONFIG_H
32 #       include <config.h>
33 #endif
34
35 #include "timeloop.h"
36 #include <synfig/valuenode.h>
37 #include <synfig/valuenode_const.h>
38 #include <synfig/valuenode_subtract.h>
39 #include <synfig/time.h>
40 #include <synfig/context.h>
41 #include <synfig/paramdesc.h>
42 #include <synfig/renddesc.h>
43 #include <synfig/value.h>
44
45 #endif
46
47 using namespace synfig;
48 using namespace std;
49 using namespace etl;
50
51 /* === M A C R O S ========================================================= */
52
53 /* === G L O B A L S ======================================================= */
54
55 SYNFIG_LAYER_INIT(Layer_TimeLoop);
56 SYNFIG_LAYER_SET_NAME(Layer_TimeLoop,"timeloop");
57 SYNFIG_LAYER_SET_LOCAL_NAME(Layer_TimeLoop,N_("Time Loop"));
58 SYNFIG_LAYER_SET_CATEGORY(Layer_TimeLoop,N_("Other"));
59 SYNFIG_LAYER_SET_VERSION(Layer_TimeLoop,"0.2");
60 SYNFIG_LAYER_SET_CVS_ID(Layer_TimeLoop,"$Id$");
61
62 /* === P R O C E D U R E S ================================================= */
63
64 /* === M E T H O D S ======================================================= */
65
66 Layer_TimeLoop::Layer_TimeLoop()
67 {
68         link_time=0;
69         local_time=0;
70         duration=1;
71 }
72
73 Layer_TimeLoop::~Layer_TimeLoop()
74 {
75 }
76
77 bool
78 Layer_TimeLoop::set_param(const String & param, const ValueBase &value)
79 {
80         if(old_version)
81         {
82                 IMPORT(start_time);
83                 IMPORT(end_time);
84         }
85         else
86         {
87                 IMPORT(local_time);
88                 IMPORT(link_time);
89                 IMPORT(duration);
90         }
91
92         return Layer::set_param(param,value);
93 }
94
95 ValueBase
96 Layer_TimeLoop::get_param(const String & param)const
97 {
98         EXPORT(link_time);
99         EXPORT(local_time);
100         EXPORT(duration);
101         EXPORT_NAME();
102         EXPORT_VERSION();
103
104         return Layer::get_param(param);
105 }
106
107 Layer::Vocab
108 Layer_TimeLoop::get_param_vocab()const
109 {
110         Layer::Vocab ret(Layer::get_param_vocab());
111
112         ret.push_back(ParamDesc("link_time")
113                 .set_local_name(_("Link Time"))
114         );
115
116         ret.push_back(ParamDesc("local_time")
117                 .set_local_name(_("Local Time"))
118         );
119
120         ret.push_back(ParamDesc("duration")
121                 .set_local_name(_("Duration"))
122         );
123
124         return ret;
125 }
126
127 bool
128 Layer_TimeLoop::set_version(const String &ver)
129 {
130         if (ver=="0.1")
131                 old_version = true;
132
133         return true;
134 }
135
136 void
137 Layer_TimeLoop::reset_version()
138 {
139         // if we're not converting from an old version of the layer, there's nothing to do
140         if (!old_version)
141                 return;
142
143         old_version = false;
144
145         // these are the conversions to go from 0.1 to 0.2:
146         //
147         //       local_time = start_time
148         //       duration = end_time - start_time
149         //       if (time < start_time)
150         //         link_time = -duration : if we want to reproduce the old behaviour - do we?
151         //       else
152         //               link_time = 0
153
154         // convert the static parameters
155         local_time = start_time;
156         duration = end_time - start_time;
157         //! \todo layer version 0.1 acted differently before start_time was reached - possibly due to a bug
158         link_time = 0;
159
160         // convert the dynamic parameters
161         const DynamicParamList &dpl = dynamic_param_list();
162
163         // if neither start_time nor end_time are dynamic, there's nothing more to do
164         if (dpl.count("start_time") == 0 && dpl.count("end_time") == 0)
165                 return;
166
167         etl::rhandle<ValueNode> start_time_value_node, end_time_value_node;
168         LinkableValueNode* duration_value_node;
169
170         if (dpl.count("start_time"))
171         {
172                 start_time_value_node = dpl.find("start_time")->second;
173                 disconnect_dynamic_param("start_time");
174         }
175         else
176                 start_time_value_node = ValueNode_Const::create(start_time);
177
178         if (dpl.count("end_time"))
179         {
180                 end_time_value_node = dpl.find("end_time")->second;
181                 disconnect_dynamic_param("end_time");
182         }
183         else
184                 end_time_value_node = ValueNode_Const::create(end_time);
185
186         duration_value_node = ValueNode_Subtract::create(Time(0));
187         duration_value_node->set_link("lhs", end_time_value_node);
188         duration_value_node->set_link("rhs", start_time_value_node);
189
190         connect_dynamic_param("local_time", start_time_value_node);
191         connect_dynamic_param("duration",   duration_value_node);
192         connect_dynamic_param("link_time",  ValueNode_Const::create(Time(0)));
193 }
194
195 void
196 Layer_TimeLoop::set_time(Context context, Time t)const
197 {
198         if (duration == 0)
199                 t = link_time;
200         else if (duration > 0)
201         {
202                 t -= local_time;
203                 t -= floor(t / duration) * duration;
204                 t  = link_time + t;
205         }
206         else
207         {
208                 t -= local_time;
209                 t -= floor(t / -duration) * -duration;
210                 t  = link_time - t;
211         }
212
213         context.set_time(t);
214 }
215
216 Color
217 Layer_TimeLoop::get_color(Context context, const Point &pos)const
218 {
219         return context.get_color(pos);
220 }
221
222 bool
223 Layer_TimeLoop::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
224 {
225         return context.accelerated_render(surface,quality,renddesc,cb);
226 }