666fc80420ab1f0c4e2c6f2744d283d54f34ec93
[synfig.git] / synfig-studio / trunk / src / synfigapp / actions / keyframesetdelta.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file keyframesetdelta.cpp
3 **      \brief Template File
4 **
5 **      $Id$
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 "keyframesetdelta.h"
33 #include <synfigapp/canvasinterface.h>
34 #include <synfig/valuenode_dynamiclist.h>
35 #include <synfig/valuenode_animated.h>
36 #include "activepointsetsmart.h"
37 #include "waypointsetsmart.h"
38
39 #include <synfigapp/general.h>
40
41 #endif
42
43 using namespace std;
44 using namespace etl;
45 using namespace synfig;
46 using namespace synfigapp;
47 using namespace Action;
48
49 /* === M A C R O S ========================================================= */
50
51 ACTION_INIT(Action::KeyframeSetDelta);
52 ACTION_SET_NAME(Action::KeyframeSetDelta,"keyframe_set_delta");
53 ACTION_SET_LOCAL_NAME(Action::KeyframeSetDelta,N_("Set Keyframe Delta"));
54 ACTION_SET_TASK(Action::KeyframeSetDelta,"set");
55 ACTION_SET_CATEGORY(Action::KeyframeSetDelta,Action::CATEGORY_KEYFRAME|Action::CATEGORY_HIDDEN);
56 ACTION_SET_PRIORITY(Action::KeyframeSetDelta,0);
57 ACTION_SET_VERSION(Action::KeyframeSetDelta,"0.0");
58 ACTION_SET_CVS_ID(Action::KeyframeSetDelta,"$Id$");
59
60 /* === G L O B A L S ======================================================= */
61
62 /* === P R O C E D U R E S ================================================= */
63
64 /* === M E T H O D S ======================================================= */
65
66 Action::KeyframeSetDelta::KeyframeSetDelta():
67         delta(0)
68 {
69         keyframe.set_time(Time::end());
70         set_dirty(false);
71 }
72
73 Action::ParamVocab
74 Action::KeyframeSetDelta::get_param_vocab()
75 {
76         ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
77
78         ret.push_back(ParamDesc("keyframe",Param::TYPE_KEYFRAME)
79                 .set_local_name(_("Keyframe"))
80         );
81         ret.push_back(ParamDesc("delta",Param::TYPE_KEYFRAME)
82                 .set_local_name(_("Delta"))
83         );
84
85         return ret;
86 }
87
88 bool
89 Action::KeyframeSetDelta::is_candidate(const ParamList &x)
90 {
91         return candidate_check(get_param_vocab(),x);
92 }
93
94 bool
95 Action::KeyframeSetDelta::set_param(const synfig::String& name, const Action::Param &param)
96 {
97         if(name=="keyframe" && param.get_type()==Param::TYPE_KEYFRAME)
98         {
99                 keyframe=param.get_keyframe();
100                 return true;
101         }
102         if(name=="delta" && param.get_type()==Param::TYPE_TIME)
103         {
104                 delta=param.get_time();
105                 return true;
106         }
107
108         return Action::CanvasSpecific::set_param(name,param);
109 }
110
111 bool
112 Action::KeyframeSetDelta::is_ready()const
113 {
114         if(keyframe.get_time()==Time::end())
115                 return false;
116         return Action::CanvasSpecific::is_ready();
117 }
118
119 void
120 Action::KeyframeSetDelta::prepare()
121 {
122         clear();
123         value_desc_list.clear();
124         get_canvas_interface()->find_important_value_descs(value_desc_list);
125
126
127         Time time(get_canvas()->keyframe_list().find(keyframe)->get_time());
128
129         std::vector<synfigapp::ValueDesc>::iterator iter;
130                 DEBUGPOINT();
131         for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
132         {
133                 ValueDesc& value_desc(*iter);
134                 ValueNode_Animated::Handle value_node(
135                         ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node())
136                 );
137
138                 if(!value_node)
139                         continue;
140
141                 try{
142                         value_node->find(time);
143                         // if we got to this point, then we know that
144                         // a waypoint already exists here and we don't
145                         // need to add a new one.
146                         continue;
147                 }catch(...)
148                 {
149                         // Make sure there is something previous
150                         try{
151                                 value_node->find_prev(time);
152                         }catch(...)
153                         {
154                                 continue;
155                         }
156                 }
157                 Action::Handle action(Action::create("waypoint_set_smart"));
158
159                 action->set_param("canvas",get_canvas());
160                 action->set_param("canvas_interface",get_canvas_interface());
161                 action->set_param("value_node",ValueNode::Handle::cast_static(value_node));
162
163                 action->set_param("time",time);
164
165                 assert(action->is_ready());
166                 if(!action->is_ready())
167                         throw Error(Error::TYPE_NOTREADY);
168
169                 add_action(action);
170         }
171 }
172
173 void
174 Action::KeyframeSetDelta::perform()
175 {
176         if(!delta)
177                 return;
178         Action::Super::perform();
179
180 //      Time location(keyframe.get_time());
181         Time location(get_canvas()->keyframe_list().find(keyframe)->get_time());
182         Time delta(delta);
183
184         get_canvas()->keyframe_list().insert_time(location,delta);
185
186         std::vector<synfigapp::ValueDesc>::iterator iter;
187         for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
188         {
189                 ValueDesc& value_desc(*iter);
190                 if(!value_desc.is_value_node())
191                         continue;
192                 ValueNode_Animated::Handle animated(
193                         ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node())
194                 );
195                 if(animated)
196                 {
197                         animated->insert_time(location,delta);
198                         continue;
199                 }
200                 ValueNode_DynamicList::Handle dyn_list(
201                         ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node())
202                 );
203                 if(dyn_list)
204                 {
205                         dyn_list->insert_time(location,delta);
206                         continue;
207                 }
208         }
209
210         // Signal that something has changed
211         if(get_canvas_interface())
212         {
213                 get_canvas_interface()->signal_keyframe_changed()(keyframe);
214         }
215         else synfig::warning("CanvasInterface not set on action");
216 }
217
218 void
219 Action::KeyframeSetDelta::undo()
220 {
221         if(!delta)
222                 return;
223
224 //      Time location(keyframe.get_time());
225         Time location(get_canvas()->keyframe_list().find(keyframe)->get_time());
226         Time delta(-delta);
227
228         get_canvas()->keyframe_list().insert_time(location,delta);
229
230         std::vector<synfigapp::ValueDesc>::iterator iter;
231         for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
232         {
233                 ValueDesc& value_desc(*iter);
234                 if(!value_desc.is_value_node())
235                         continue;
236                 ValueNode_Animated::Handle animated(
237                         ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node())
238                 );
239                 if(animated)
240                 {
241                         animated->insert_time(location,delta);
242                         continue;
243                 }
244                 ValueNode_DynamicList::Handle dyn_list(
245                         ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node())
246                 );
247                 if(dyn_list)
248                 {
249                         dyn_list->insert_time(location,delta);
250                         continue;
251                 }
252         }
253
254         Action::Super::undo();
255
256         // Signal that something has changed
257         if(get_canvas_interface())
258         {
259                 get_canvas_interface()->signal_keyframe_changed()(keyframe);
260         }
261         else synfig::warning("CanvasInterface not set on action");
262 }