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