Removed a DEBUGPOINT().
[synfig.git] / synfig-studio / trunk / src / synfigapp / actions / waypointsetsmart.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file waypointsetsmart.cpp
3 **      \brief Template File
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 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "waypointsetsmart.h"
34 #include "valuenodelinkconnect.h"
35 #include "valuenodereplace.h"
36
37 #include "waypointset.h"
38 #include "waypointadd.h"
39
40 #include "valuedescconnect.h"
41 #include <synfigapp/canvasinterface.h>
42 #include <synfig/exception.h>
43 #include <synfigapp/main.h>
44
45 #include <synfigapp/general.h>
46
47 #endif
48
49 using namespace std;
50 using namespace etl;
51 using namespace synfig;
52 using namespace synfigapp;
53 using namespace Action;
54
55 /* === M A C R O S ========================================================= */
56
57 ACTION_INIT(Action::WaypointSetSmart);
58 ACTION_SET_NAME(Action::WaypointSetSmart,"waypoint_set_smart");
59 ACTION_SET_LOCAL_NAME(Action::WaypointSetSmart,N_("Add Waypoint"));
60 ACTION_SET_TASK(Action::WaypointSetSmart,"set");
61 ACTION_SET_CATEGORY(Action::WaypointSetSmart,Action::CATEGORY_WAYPOINT|Action::CATEGORY_VALUEDESC|Action::CATEGORY_VALUENODE);
62 ACTION_SET_PRIORITY(Action::WaypointSetSmart,0);
63 ACTION_SET_VERSION(Action::WaypointSetSmart,"0.0");
64 ACTION_SET_CVS_ID(Action::WaypointSetSmart,"$Id$");
65
66
67 /*#ifdef DEBUGPOINT
68 #undef DEBUGPOINT
69 #endif
70 #define DEBUGPOINT()
71 */
72 /* === G L O B A L S ======================================================= */
73
74 /* === P R O C E D U R E S ================================================= */
75
76 /* === M E T H O D S ======================================================= */
77
78 Action::WaypointSetSmart::WaypointSetSmart()
79 {
80         waypoint.set_time(Time::begin()-1);
81         time_set=false;
82         set_dirty(true);
83 }
84
85 Action::ParamVocab
86 Action::WaypointSetSmart::get_param_vocab()
87 {
88         ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
89
90         ret.push_back(ParamDesc("value_node",Param::TYPE_VALUENODE)
91                 .set_local_name(_("Destination ValueNode (Animated)"))
92         );
93
94         ret.push_back(ParamDesc("waypoint",Param::TYPE_WAYPOINT)
95                 .set_local_name(_("New Waypoint"))
96                 .set_desc(_("Waypoint to be added"))
97                 .set_optional()
98         );
99
100         ret.push_back(ParamDesc("waypoint_model",Param::TYPE_WAYPOINTMODEL)
101                 .set_local_name(_("Waypoint Model"))
102                 .set_optional()
103         );
104
105         ret.push_back(ParamDesc("time",Param::TYPE_TIME)
106                 .set_local_name(_("Time"))
107                 .set_desc(_("Time where waypoint is to be added"))
108                 .set_optional()
109         );
110
111         return ret;
112 }
113
114 bool
115 Action::WaypointSetSmart::is_candidate(const ParamList &x)
116 {
117         if(candidate_check(get_param_vocab(),x))
118         {
119                 if(!ValueNode_Animated::Handle::cast_dynamic(x.find("value_node")->second.get_value_node()))
120                         return false;
121                 // We need either a waypoint or a time.
122                 if(x.count("waypoint") || x.count("time"))
123                         return true;
124                 return false;
125         }
126         return false;
127 }
128
129 bool
130 Action::WaypointSetSmart::set_param(const synfig::String& name, const Action::Param &param)
131 {
132         if(name=="value_node" && param.get_type()==Param::TYPE_VALUENODE)
133         {
134                 value_node=ValueNode_Animated::Handle::cast_dynamic(param.get_value_node());
135                 DEBUGPOINT();
136                 if(time_set)
137                         calc_waypoint();
138
139                 return static_cast<bool>(value_node);
140         }
141         if(name=="waypoint" && param.get_type()==Param::TYPE_WAYPOINT && !time_set)
142         {
143                 waypoint=param.get_waypoint();
144                 DEBUGPOINT();
145
146                 return true;
147         }
148
149         if(name=="time" && param.get_type()==Param::TYPE_TIME && waypoint.get_time()==(Time::begin()-1))
150         {
151                 waypoint.set_time(param.get_time());
152                 time_set=true;
153
154                 if(value_node)
155                         calc_waypoint();
156                 DEBUGPOINT();
157
158                 return true;
159         }
160
161         if(name=="model" && param.get_type()==Param::TYPE_WAYPOINTMODEL)
162         {
163                 if(value_node)
164                         calc_waypoint();
165
166                 waypoint.apply_model(param.get_waypoint_model());
167
168                 return true;
169         }
170
171         return Action::CanvasSpecific::set_param(name,param);
172 }
173
174 bool
175 Action::WaypointSetSmart::is_ready()const
176 {
177         if(!value_node)
178                 synfig::error("Missing value_node");
179
180         if(waypoint.get_time()==(Time::begin()-1))
181                 synfig::error("Missing waypoint");
182
183         if(!value_node || waypoint.get_time()==(Time::begin()-1))
184                 return false;
185         return Action::CanvasSpecific::is_ready();
186 }
187
188 // This function is called if a time is specified, but not
189 // a waypoint. In this case, we need to calculate the value
190 // of the waypoint
191 void
192 Action::WaypointSetSmart::calc_waypoint()
193 {
194         DEBUGPOINT();
195         Time time=waypoint.get_time();
196         try
197         {
198                 // Trivial case, we are sitting on a waypoint
199                 waypoint=*value_node->find(waypoint.get_time());
200         }
201         catch(...)
202         {
203                 waypoint=value_node->new_waypoint_at_time(time);
204                 waypoint.set_before(synfigapp::Main::get_interpolation());
205                 waypoint.set_after(synfigapp::Main::get_interpolation());
206         }
207 /*
208         Time time=waypoint.get_time();
209         ValueNode_Animated::WaypointList &waypoint_list(value_node->waypoint_list());
210         ValueNode_Animated::WaypointList::iterator iter;
211
212         if(waypoint_list.empty())
213         {
214                 waypoint.set_value((*value_node)(time));
215                 return;
216         }
217
218         ValueNode_Animated::WaypointList::iterator closest=waypoint_list.begin();
219
220         for(iter=waypoint_list.begin();iter!=waypoint_list.end();++iter)
221         {
222                 const Real dist(abs(iter->get_time()-time));
223                 if(dist<abs(closest->get_time()-time))
224                         closest=iter;
225         }
226         if(!closest->is_static())
227                 waypoint.set_value_node(closest->get_value_node());
228         else
229                 waypoint.set_value((*value_node)(time));
230 */
231 }
232
233 void
234 Action::WaypointSetSmart::enclose_waypoint(const synfig::Waypoint& waypoint)
235 {
236         times.insert(waypoint.get_time());
237
238         try {
239                 times.insert(value_node->find(waypoint)->get_time());
240 //              synfig::info(__FILE__":%d: value_node->find(waypoint)->get_time()=%s",__LINE__,value_node->find(waypoint)->get_time().get_string().c_str());
241 //              DEBUGPOINT();
242         }catch (...) { }
243
244 //      DEBUGPOINT();
245         // First we need to to add any waypoints necessary to
246         // maintain the integrity of the keyframes.
247         if(get_edit_mode()&MODE_ANIMATE_PAST) try
248         {
249                 Time curr_time(waypoint.get_time());
250
251                 //while(value_node->waypoint_list().front().get_time()<=curr_time)
252                 {
253                         // Try to find prev keyframe
254                         Keyframe keyframe(*get_canvas()->keyframe_list().find_prev(curr_time));
255                         curr_time=keyframe.get_time();
256
257 //                      synfig::info(__FILE__":%d: prev_keyframe->time=%s",__LINE__,keyframe.get_time().get_string().c_str());
258 //                      synfig::info(__FILE__":%d: waypoint->time=%s",__LINE__,waypoint.get_time().get_string().c_str());
259
260 //                      DEBUGPOINT();
261                         if(times.count(keyframe.get_time()))
262                         {
263 //                              DEBUGPOINT();
264                                 throw int();
265                         }
266                         if(waypoint.get_time().is_equal(keyframe.get_time()))
267                         {
268 //                              DEBUGPOINT();
269                                 throw int();
270                         }
271
272                         times.insert(keyframe.get_time());
273 //                      DEBUGPOINT();
274                         try
275                         {
276                                 value_node->find(keyframe.get_time());
277 //                              synfig::info(__FILE__":%d: waypointtime=%s",__LINE__,value_node->find(keyframe.get_time())->get_time().get_string().c_str());
278                         }
279                         catch(synfig::Exception::NotFound)
280                         {
281                                 Action::Handle action(WaypointAdd::create());
282
283                                 action->set_param("canvas",get_canvas());
284                                 action->set_param("canvas_interface",get_canvas_interface());
285                                 action->set_param("value_node",ValueNode::Handle(value_node));
286
287                                 if(!value_node->waypoint_list().empty())
288                                 {
289                                         action->set_param("time",keyframe.get_time());
290                                 }
291                                 else
292                                 {
293                                         synfig::Waypoint tmp;
294
295                                         tmp.set_value(waypoint.get_value());
296                                         tmp.set_time(keyframe.get_time());
297                                         action->set_param("waypoint",tmp);
298                                 }
299
300                                 assert(action->is_ready());
301                                 if(!action->is_ready())
302                                         throw Error(Error::TYPE_NOTREADY);
303
304                                 add_action(action);
305                         }
306                 }
307         }
308         catch(Error x) { throw x; }
309         catch(synfig::Exception::NotFound) { DEBUGPOINT(); }
310         catch(int) { DEBUGPOINT(); }
311         catch(...) { DEBUGPOINT(); }
312                         //DEBUGPOINT();
313
314                 //DEBUGPOINT();
315         if(get_edit_mode()&MODE_ANIMATE_FUTURE)try
316         {
317                 Time curr_time(waypoint.get_time());
318
319                 //while(value_node->waypoint_list().back().get_time()>=curr_time)
320                 {
321
322                         //DEBUGPOINT();
323                         // Try to find next keyframe
324                         //synfig::info("FUTURE waypoint.get_time()=%s",waypoint.get_time().get_string().c_str());
325                         Keyframe keyframe(*get_canvas()->keyframe_list().find_next(curr_time));
326                         //synfig::info("FUTURE keyframe.get_time()=%s",keyframe.get_time().get_string().c_str());
327                         curr_time=keyframe.get_time();
328
329                         //DEBUGPOINT();
330                         if(times.count(keyframe.get_time())|| waypoint.get_time().is_equal(keyframe.get_time()))
331                                 throw int();
332                         else
333                                 times.insert(keyframe.get_time());
334                         //DEBUGPOINT();
335
336                         try
337                         {
338                                 value_node->find(keyframe.get_time());
339                                 synfig::info(__FILE__":%d: time=%s",__LINE__,keyframe.get_time().get_string().c_str());
340                                 synfig::info(__FILE__":%d: waypointtime=%s",__LINE__,value_node->find(keyframe.get_time())->get_time().get_string().c_str());
341
342                         }
343                         catch(synfig::Exception::NotFound)
344                         {
345                                 Action::Handle action(WaypointAdd::create());
346
347                                 action->set_param("canvas",get_canvas());
348                                 action->set_param("canvas_interface",get_canvas_interface());
349                                 action->set_param("value_node",ValueNode::Handle(value_node));
350
351                                 if(!value_node->waypoint_list().empty())
352                                 {
353                                         action->set_param("time",keyframe.get_time());
354                                 }
355                                 else
356                                 {
357                                         synfig::Waypoint tmp;
358
359                                         tmp.set_value(waypoint.get_value());
360                                         tmp.set_time(keyframe.get_time());
361                                         action->set_param("waypoint",tmp);
362                                 }
363
364                                 assert(action->is_ready());
365                                 if(!action->is_ready())
366                                         throw Error(Error::TYPE_NOTREADY);
367
368                                 add_action(action);
369                         }
370                 }
371                         //DEBUGPOINT();
372         }
373         catch(Error x) { throw x; }
374         catch(synfig::Exception::NotFound) { DEBUGPOINT(); }
375         catch(int) { DEBUGPOINT(); }
376         catch(...) { DEBUGPOINT(); }
377                 //DEBUGPOINT();
378 }
379
380 void
381 Action::WaypointSetSmart::prepare()
382 {
383                 //DEBUGPOINT();
384         clear();
385         times.clear();
386
387         // First we need to to add any waypoints necessary to
388         // maintain the integrity of the keyframes.
389         enclose_waypoint(waypoint);
390
391         try
392         {
393                 //synfig::info("WaypointSetSmart: Move/Update?");
394                 // Lets try to replace the old waypoint, if it exists
395                 WaypointList::iterator iter(value_node->find(waypoint));
396
397                 if(iter == value_node->waypoint_list().end())
398                         throw int();
399
400                 enclose_waypoint(*iter);
401
402                 Action::Handle action(WaypointSet::create());
403
404                 action->set_param("canvas",get_canvas());
405                 action->set_param("canvas_interface",get_canvas_interface());
406                 action->set_param("value_node",ValueNode::Handle(value_node));
407                 action->set_param("waypoint",waypoint);
408
409                 assert(action->is_ready());
410                 if(!action->is_ready())
411                         throw Error(Error::TYPE_NOTREADY);
412
413                 add_action(action);
414
415                 return;
416         }
417         catch(synfig::Exception::NotFound){ } catch(int){ }
418
419         try
420         {
421                 //synfig::info("WaypointSetSmart: Replace?");
422                 //DEBUGPOINT();
423                 // Check to see if a waypoint exists at this point in time
424                 WaypointList::iterator iter=value_node->find(waypoint.get_time());
425
426                 waypoint.mimic(*iter);
427
428                 enclose_waypoint(*iter);
429
430                 Action::Handle action(WaypointSet::create());
431
432                 action->set_param("canvas",get_canvas());
433                 action->set_param("canvas_interface",get_canvas_interface());
434                 action->set_param("value_node",ValueNode::Handle(value_node));
435                 action->set_param("waypoint",waypoint);
436
437                 assert(action->is_ready());
438                 if(!action->is_ready())
439                         throw Error(Error::TYPE_NOTREADY);
440
441                 add_action(action);
442
443                 return;
444         }
445         catch(synfig::Exception::NotFound){ } catch(int){ }
446
447         try
448         {
449                 //synfig::info("WaypointSetSmart: Add?");
450                 //DEBUGPOINT();
451                 // At this point we know that the old waypoint doesn't exist,
452                 // so we need to create it.
453                 Action::Handle action(WaypointAdd::create());
454
455                 action->set_param("canvas",get_canvas());
456                 action->set_param("canvas_interface",get_canvas_interface());
457                 action->set_param("value_node",ValueNode::Handle(value_node));
458                 action->set_param("waypoint",waypoint);
459
460                 assert(action->is_ready());
461                 if(!action->is_ready())
462                         throw Error(Error::TYPE_NOTREADY);
463
464                 add_action(action);
465
466                 return;
467         }
468         catch(synfig::Exception::NotFound){ } catch(int){ }
469
470         throw Error(_("Unable to determine how to proceed. This is a bug."));
471 }