1 /* === S Y N F I G ========================================================= */
2 /*!	\file timepointscopy.cpp
3 **	\brief Copy the Time Points File
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2004 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 <synfig/general.h>
33 
34 #include "timepointscopy.h"
35 #include <synfig/layers/layer_pastecanvas.h>
36 #include <synfigapp/canvasinterface.h>
37 #include <synfig/valuenodes/valuenode_dynamiclist.h>
38 #include <synfig/valuenodes/valuenode_animated.h>
39 
40 #include "activepointsimpleadd.h"
41 #include "waypointsimpleadd.h"
42 #include <synfigapp/timegather.h>
43 
44 #include <typeinfo>
45 
46 #include <synfigapp/localization.h>
47 
48 #endif
49 
50 using namespace std;
51 using namespace etl;
52 using namespace synfig;
53 using namespace synfigapp;
54 using namespace Action;
55 
56 /* === M A C R O S ========================================================= */
57 
58 ACTION_INIT(Action::TimepointsCopy);
59 ACTION_SET_NAME(Action::TimepointsCopy,"TimepointsCopy");
60 ACTION_SET_LOCAL_NAME(Action::TimepointsCopy,N_("Copy Time Points"));
61 ACTION_SET_TASK(Action::TimepointsCopy,"copy");
62 ACTION_SET_CATEGORY(Action::TimepointsCopy,Action::CATEGORY_WAYPOINT|Action::CATEGORY_ACTIVEPOINT);
63 ACTION_SET_PRIORITY(Action::TimepointsCopy,0);
64 ACTION_SET_VERSION(Action::TimepointsCopy,"0.0");
65 ACTION_SET_CVS_ID(Action::TimepointsCopy,"$Id$");
66 
67 /* === G L O B A L S ======================================================= */
68 
69 /* === P R O C E D U R E S ================================================= */
70 
71 /* === M E T H O D S ======================================================= */
72 
TimepointsCopy()73 Action::TimepointsCopy::TimepointsCopy()
74 {
75 	timedelta = 0;
76 	set_dirty(false);
77 }
78 
79 Action::ParamVocab
get_param_vocab()80 Action::TimepointsCopy::get_param_vocab()
81 {
82 	ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
83 
84 	ret.push_back(ParamDesc("addlayer",Param::TYPE_VALUE)
85 		.set_local_name(_("New Selected Layer"))
86 		.set_desc(_("A layer to add to our selected list"))
87 		.set_supports_multiple()
88 		.set_optional()
89 	);
90 
91 	ret.push_back(ParamDesc("addcanvas",Param::TYPE_CANVAS)
92 		.set_local_name(_("New Selected Canvas"))
93 		.set_desc(_("A canvas to add to our selected list"))
94 		.set_supports_multiple()
95 		.set_optional()
96 	);
97 
98 	ret.push_back(ParamDesc("addvaluedesc",Param::TYPE_VALUEDESC)
99 		.set_local_name(_("New Selected ValueBase"))
100 		.set_desc(_("A valuenode's description to add to our selected list"))
101 		.set_supports_multiple()
102 		.set_optional()
103 	);
104 
105 	ret.push_back(ParamDesc("addtime",Param::TYPE_TIME)
106 		.set_local_name(_("New Selected Time Point"))
107 		.set_desc(_("A time point to add to our selected list"))
108 		.set_supports_multiple()
109 	);
110 
111 	ret.push_back(ParamDesc("deltatime",Param::TYPE_TIME)
112 		.set_local_name(_("Time adjustment"))
113 		.set_desc(_("The amount of time to adjust all the selected points"))
114 	);
115 
116 	return ret;
117 }
118 
119 bool
is_candidate(const ParamList & x)120 Action::TimepointsCopy::is_candidate(const ParamList &x)
121 {
122 	if(!candidate_check(get_param_vocab(),x))
123 		return false;
124 
125 	if(	x.find("addlayer") == x.end() &&
126 		x.find("addcanvas") == x.end() &&
127 		x.find("addvaluedesc") == x.end())
128 		return false;
129 	return true;
130 }
131 
132 bool
set_param(const synfig::String & name,const Action::Param & param)133 Action::TimepointsCopy::set_param(const synfig::String& name, const Action::Param &param)
134 {
135 	if(name=="addlayer" && param.get_type()==Param::TYPE_LAYER)
136 	{
137 		//add a layer to the list
138 		sel_layers.push_back(param.get_layer());
139 		//synfig::info("action got layer");
140 
141 		return true;
142 	}
143 
144 	if(name=="addcanvas" && param.get_type()==Param::TYPE_CANVAS)
145 	{
146 		//add a layer to the list
147 		sel_canvases.push_back(param.get_canvas());
148 		//synfig::info("action got canvas");
149 
150 		return true;
151 	}
152 
153 	if(name=="addvaluedesc" && param.get_type()==Param::TYPE_VALUEDESC)
154 	{
155 		//add a layer to the list
156 		sel_values.push_back(param.get_value_desc());
157 		//synfig::info("action got valuedesc");
158 
159 		return true;
160 	}
161 
162 	if(name=="addtime" && param.get_type()==Param::TYPE_TIME)
163 	{
164 		//add a layer to the list
165 		sel_times.insert(param.get_time());
166 		//synfig::info("action got time");
167 
168 		return true;
169 	}
170 
171 	if(name=="deltatime" && param.get_type()==Param::TYPE_TIME)
172 	{
173 		timedelta = param.get_time();
174 		//synfig::info("action got time to move");
175 
176 		return true;
177 	}
178 
179 	return Action::CanvasSpecific::set_param(name,param);
180 }
181 
182 bool
is_ready() const183 Action::TimepointsCopy::is_ready()const
184 {
185 	if((sel_layers.empty() && sel_canvases.empty() && sel_values.empty()) || sel_times.empty())
186 		return false;
187 	return Action::CanvasSpecific::is_ready();
188 }
189 
190 void
prepare()191 Action::TimepointsCopy::prepare()
192 {
193 	clear();
194 
195 	//synfig::info("Preparing TimepointsCopy by %f secs",(float)timemove);
196 
197 	if(sel_times.empty()) return;
198 
199 	//all our lists should be set correctly...
200 
201 	//build our sub-action list
202 	// 	and yes we do need to store it temporarily so we don't duplicate
203 	//		an operation on a specific valuenode, etc....
204 	timepoints_ref	match;
205 
206 	Time fps = get_canvas()->rend_desc().get_frame_rate();
207 
208 	//std::vector<synfig::Layer::Handle>
209 	//synfig::info("Layers %d", sel_layers.size());
210 	{
211 		std::vector<synfig::Layer::Handle>::iterator i = sel_layers.begin(),
212 													end = sel_layers.end();
213 
214 		for(; i != end; ++i)
215 		{
216 			//synfig::info("Recurse through a layer");
217 			recurse_layer(*i,sel_times,match);
218 		}
219 	}
220 
221 	//std::vector<synfig::Canvas::Handle>	sel_canvases;
222 	//synfig::info("Canvases %d", sel_canvases.size());
223 	{
224 		std::vector<synfig::Canvas::Handle>::iterator 	i = sel_canvases.begin(),
225 														end = sel_canvases.end();
226 
227 		for(; i != end; ++i)
228 		{
229 			//synfig::info("Recurse through a canvas");
230 			recurse_canvas(*i,sel_times,match);
231 		}
232 	}
233 
234 	//std::vector<synfigapp::ValueDesc>
235 	//synfig::info("ValueBasedescs %d", sel_values.size());
236 	{
237 		std::vector<synfigapp::ValueDesc>::iterator 	i = sel_values.begin(),
238 													end = sel_values.end();
239 
240 		for(; i != end; ++i)
241 		{
242 			//synfig::info("Recurse through a valuedesc");
243 			recurse_valuedesc(*i,sel_times,match);
244 		}
245 	}
246 
247 	//synfig::info("built list of waypoints/activepoints to modify");
248 	//synfig::info("\t There are %d waypoint sets and %d activepointsets",
249 	//				match.waypointbiglist.size(), match.actpointbiglist.size());
250 	//process them...
251 	{
252 		//must build from both lists
253 		timepoints_ref::waytracker::const_iterator 	i = match.waypointbiglist.begin(),
254 													end = match.waypointbiglist.end();
255 		for(; i != end; ++i)
256 		{
257 			synfig::Time dilated_timedelta(timedelta * i->time_dilation);
258 			//iterate through each waypoint for this specific valuenode
259 			std::set<synfig::Waypoint>::const_iterator 	j = i->waypoints.begin(),
260 														end = i->waypoints.end();
261 			for(; j != end; ++j)
262 			{
263 				Action::Handle action(WaypointSimpleAdd::create());
264 
265 				action->set_param("canvas",get_canvas());
266 				action->set_param("canvas_interface",get_canvas_interface());
267 				action->set_param("value_node",ValueNode::Handle(i->val));
268 
269 				//synfig::info("add waypoint mod...");
270 				//NOTE: We may want to store the old time for undoing the action...
271 				Waypoint neww;
272 				Waypoint w = *j;
273 				w.set_time((w.get_time() + dilated_timedelta).round(fps));
274 				w.mimic(neww); //make sure the new waypoint has a new id
275 
276 				action->set_param("waypoint",w);
277 
278 				//run the action now that we've added everything
279 				assert(action->is_ready());
280 				if(!action->is_ready())
281 					throw Error(Error::TYPE_NOTREADY);
282 
283 				add_action_front(action);
284 			}
285 		}
286 	}
287 	{
288 		//must build from both lists
289 		timepoints_ref::acttracker::const_iterator 	i = match.actpointbiglist.begin(),
290 													end = match.actpointbiglist.end();
291 		for(; i != end; ++i)
292 		{
293 			synfig::Time dilated_timedelta(timedelta * i->time_dilation);
294 			//iterate through each activepoint for this specific valuenode
295 			std::set<synfig::Activepoint>::const_iterator 	j = i->activepoints.begin(),
296 															jend = i->activepoints.end();
297 			for(; j != jend; ++j)
298 			{
299 				Action::Handle action(ActivepointSimpleAdd::create());
300 
301 				action->set_param("canvas",get_canvas());
302 				action->set_param("canvas_interface",get_canvas_interface());
303 				action->set_param("value_desc",i->val);
304 
305 				//NOTE: We may want to store the old time for undoing the action...
306 				Activepoint newa;
307 				Activepoint a = *j;
308 				a.set_time((a.get_time() + dilated_timedelta).round(fps));
309 				a.mimic(newa); //make sure the new activepoint has a new id
310 
311 				action->set_param("activepoint",a);
312 
313 				assert(action->is_ready());
314 				if(!action->is_ready())
315 				{
316 					throw Error(Error::TYPE_NOTREADY);
317 				}
318 
319 				add_action_front(action);
320 			}
321 		}
322 	}
323 }
324 
325 void
perform()326 Action::TimepointsCopy::perform()
327 {
328 	Action::Super::perform();
329 }
330