1 /* === S Y N F I G ========================================================= */
2 /*! \file waypointsetsmart.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
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.
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.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
32 #include "waypointsetsmart.h"
33 #include "valuenodelinkconnect.h"
34 #include "valuenodereplace.h"
36 #include "waypointset.h"
37 #include "waypointadd.h"
39 #include "valuedescconnect.h"
40 #include <synfigapp/canvasinterface.h>
41 #include <synfig/exception.h>
42 #include <synfigapp/main.h>
48 using namespace synfig;
49 using namespace synfigapp;
50 using namespace Action;
52 /* === M A C R O S ========================================================= */
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$");
69 /* === G L O B A L S ======================================================= */
71 /* === P R O C E D U R E S ================================================= */
73 /* === M E T H O D S ======================================================= */
75 Action::WaypointSetSmart::WaypointSetSmart()
77 waypoint.set_time(Time::begin()-1);
83 Action::WaypointSetSmart::get_param_vocab()
85 ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
87 ret.push_back(ParamDesc("value_node",Param::TYPE_VALUENODE)
88 .set_local_name(_("Destination ValueNode (Animated)"))
91 ret.push_back(ParamDesc("waypoint",Param::TYPE_WAYPOINT)
92 .set_local_name(_("New Waypoint"))
93 .set_desc(_("Waypoint to be added"))
97 ret.push_back(ParamDesc("waypoint_model",Param::TYPE_WAYPOINTMODEL)
98 .set_local_name(_("Waypoint Model"))
102 ret.push_back(ParamDesc("time",Param::TYPE_TIME)
103 .set_local_name(_("Time"))
104 .set_desc(_("Time where waypoint is to be added"))
112 Action::WaypointSetSmart::is_candidate(const ParamList &x)
114 if(candidate_check(get_param_vocab(),x))
116 if(!ValueNode_Animated::Handle::cast_dynamic(x.find("value_node")->second.get_value_node()))
118 // We need either a waypoint or a time.
119 if(x.count("waypoint") || x.count("time"))
127 Action::WaypointSetSmart::set_param(const synfig::String& name, const Action::Param ¶m)
129 if(name=="value_node" && param.get_type()==Param::TYPE_VALUENODE)
131 value_node=ValueNode_Animated::Handle::cast_dynamic(param.get_value_node());
136 return static_cast<bool>(value_node);
138 if(name=="waypoint" && param.get_type()==Param::TYPE_WAYPOINT && !time_set)
140 waypoint=param.get_waypoint();
146 if(name=="time" && param.get_type()==Param::TYPE_TIME && waypoint.get_time()==(Time::begin()-1))
148 waypoint.set_time(param.get_time());
158 if(name=="model" && param.get_type()==Param::TYPE_WAYPOINTMODEL)
163 waypoint.apply_model(param.get_waypoint_model());
168 return Action::CanvasSpecific::set_param(name,param);
172 Action::WaypointSetSmart::is_ready()const
175 synfig::error("Missing value_node");
177 if(waypoint.get_time()==(Time::begin()-1))
178 synfig::error("Missing waypoint");
180 if(!value_node || waypoint.get_time()==(Time::begin()-1))
182 return Action::CanvasSpecific::is_ready();
185 // This function is called if a time is specified, but not
186 // a waypoint. In this case, we need to calculate the value
189 Action::WaypointSetSmart::calc_waypoint()
192 Time time=waypoint.get_time();
195 // Trivial case, we are sitting on a waypoint
196 waypoint=*value_node->find(waypoint.get_time());
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());
205 Time time=waypoint.get_time();
206 ValueNode_Animated::WaypointList &waypoint_list(value_node->waypoint_list());
207 ValueNode_Animated::WaypointList::iterator iter;
209 if(waypoint_list.empty())
211 waypoint.set_value((*value_node)(time));
215 ValueNode_Animated::WaypointList::iterator closest=waypoint_list.begin();
217 for(iter=waypoint_list.begin();iter!=waypoint_list.end();++iter)
219 const Real dist(abs(iter->get_time()-time));
220 if(dist<abs(closest->get_time()-time))
223 if(!closest->is_static())
224 waypoint.set_value_node(closest->get_value_node());
226 waypoint.set_value((*value_node)(time));
231 Action::WaypointSetSmart::enclose_waypoint(const synfig::Waypoint& waypoint)
233 times.insert(waypoint.get_time());
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());
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
246 Time curr_time(waypoint.get_time());
248 //while(value_node->waypoint_list().front().get_time()<=curr_time)
250 // Try to find prev keyframe
251 Keyframe keyframe(*get_canvas()->keyframe_list().find_prev(curr_time));
252 curr_time=keyframe.get_time();
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());
258 if(times.count(keyframe.get_time()))
263 if(waypoint.get_time().is_equal(keyframe.get_time()))
269 times.insert(keyframe.get_time());
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());
276 catch(synfig::Exception::NotFound)
278 Action::Handle action(WaypointAdd::create());
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));
284 if(!value_node->waypoint_list().empty())
286 action->set_param("time",keyframe.get_time());
290 synfig::Waypoint tmp;
292 tmp.set_value(waypoint.get_value());
293 tmp.set_time(keyframe.get_time());
294 action->set_param("waypoint",tmp);
297 assert(action->is_ready());
298 if(!action->is_ready())
299 throw Error(Error::TYPE_NOTREADY);
305 catch(Error x) { throw x; }
306 catch(synfig::Exception::NotFound) { DEBUGPOINT(); }
307 catch(int) { DEBUGPOINT(); }
308 catch(...) { DEBUGPOINT(); }
312 if(get_edit_mode()&MODE_ANIMATE_FUTURE)try
314 Time curr_time(waypoint.get_time());
316 //while(value_node->waypoint_list().back().get_time()>=curr_time)
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();
327 if(times.count(keyframe.get_time())|| waypoint.get_time().is_equal(keyframe.get_time()))
330 times.insert(keyframe.get_time());
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());
340 catch(synfig::Exception::NotFound)
342 Action::Handle action(WaypointAdd::create());
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));
348 if(!value_node->waypoint_list().empty())
350 action->set_param("time",keyframe.get_time());
354 synfig::Waypoint tmp;
356 tmp.set_value(waypoint.get_value());
357 tmp.set_time(keyframe.get_time());
358 action->set_param("waypoint",tmp);
361 assert(action->is_ready());
362 if(!action->is_ready())
363 throw Error(Error::TYPE_NOTREADY);
370 catch(Error x) { throw x; }
371 catch(synfig::Exception::NotFound) { DEBUGPOINT(); }
372 catch(int) { DEBUGPOINT(); }
373 catch(...) { DEBUGPOINT(); }
378 Action::WaypointSetSmart::prepare()
384 // First we need to to add any waypoints necessary to
385 // maintain the integrity of the keyframes.
386 enclose_waypoint(waypoint);
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));
394 if(iter == value_node->waypoint_list().end())
397 enclose_waypoint(*iter);
399 Action::Handle action(WaypointSet::create());
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);
406 assert(action->is_ready());
407 if(!action->is_ready())
408 throw Error(Error::TYPE_NOTREADY);
414 catch(synfig::Exception::NotFound){ } catch(int){ }
418 //synfig::info("WaypointSetSmart: Replace?");
420 // Check to see if a waypoint exists at this point in time
421 WaypointList::iterator iter=value_node->find(waypoint.get_time());
423 waypoint.mimic(*iter);
425 enclose_waypoint(*iter);
427 Action::Handle action(WaypointSet::create());
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);
434 assert(action->is_ready());
435 if(!action->is_ready())
436 throw Error(Error::TYPE_NOTREADY);
442 catch(synfig::Exception::NotFound){ } catch(int){ }
446 //synfig::info("WaypointSetSmart: Add?");
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());
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);
457 assert(action->is_ready());
458 if(!action->is_ready())
459 throw Error(Error::TYPE_NOTREADY);
465 catch(synfig::Exception::NotFound){ } catch(int){ }
467 throw Error(_("Unable to determine how to procede. This is a bug."));