Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-studio / tags / synfigstudio_0_61_03 / synfig-studio / src / synfigapp / actions / valuedescset.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuedescset.cpp
3 **      \brief Template File
4 **
5 **      $Id: valuedescset.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 "layerparamset.h"
33 #include "valuenodeconstset.h"
34 #include "valuedescconnect.h"
35 #include "waypointsetsmart.h"
36
37 #include "valuedescset.h"
38 #include <synfigapp/canvasinterface.h>
39 #include <synfig/valuenode_composite.h>
40 #include <synfig/valuenode_radialcomposite.h>
41 #include <synfig/valuenode_reference.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 #define ACTION_INIT2(class) \
54         Action::Base* class::create() { return new class(); }   \
55         synfig::String class::get_name()const { return name__; }        
56
57 ACTION_INIT2(Action::ValueDescSet);
58 ACTION_SET_NAME(Action::ValueDescSet,"value_desc_set");
59 ACTION_SET_LOCAL_NAME(Action::ValueDescSet,"Set ValueDesc");
60 ACTION_SET_TASK(Action::ValueDescSet,"set");
61 ACTION_SET_CATEGORY(Action::ValueDescSet,Action::CATEGORY_VALUEDESC);
62 ACTION_SET_PRIORITY(Action::ValueDescSet,0);
63 ACTION_SET_VERSION(Action::ValueDescSet,"0.0");
64 ACTION_SET_CVS_ID(Action::ValueDescSet,"$Id: valuedescset.cpp,v 1.1.1.1 2005/01/07 03:34:37 darco Exp $");
65
66 /* === G L O B A L S ======================================================= */
67
68 /* === P R O C E D U R E S ================================================= */
69
70 /* === M E T H O D S ======================================================= */
71
72 Action::ValueDescSet::ValueDescSet():
73         time(0)
74 {
75 }
76
77 synfig::String
78 Action::ValueDescSet::get_local_name()const
79 {
80         String name("ValueDesc");
81         
82         if(!value_desc)
83         {
84         }
85         else if(value_desc.parent_is_layer_param())
86         {
87                 if(value_desc.get_layer()->get_description().empty())
88                         name=value_desc.get_layer()->get_local_name();
89                 else
90                         name=value_desc.get_layer()->get_description();
91                 name+="->"+value_desc.get_param_name();
92         }
93         else if(value_desc.parent_is_value_node())
94         {
95                 synfig::LinkableValueNode::Handle value_node(synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node()));
96                 name=value_node->link_local_name(value_desc.get_index());
97                 
98                 synfig::Node* node;
99                 for(node=value_node.get();!node->parent_set.empty() && !dynamic_cast<Layer*>(node);node=*node->parent_set.begin());
100                 Layer::Handle parent_layer(dynamic_cast<Layer*>(node));
101                 if(parent_layer)
102                 {
103                         if(parent_layer->get_description().empty())
104                                 name=parent_layer->get_local_name()+"=>"+name;
105                         else
106                                 name=parent_layer->get_description()+"=>"+name;
107                 }
108         }
109
110         return strprintf(_("Set %s"),name.c_str());
111 }
112
113 Action::ParamVocab
114 Action::ValueDescSet::get_param_vocab()
115 {
116         ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
117         
118         ret.push_back(ParamDesc("value_desc",Param::TYPE_VALUEDESC)
119                 .set_local_name(_("ValueDesc"))
120         );
121
122         ret.push_back(ParamDesc("new_value",Param::TYPE_VALUE)
123                 .set_local_name(_("ValueBase"))
124         );
125
126         ret.push_back(ParamDesc("time",Param::TYPE_TIME)
127                 .set_local_name(_("Time"))
128                 .set_optional()
129         );
130         
131         return ret;
132 }
133
134 bool
135 Action::ValueDescSet::is_canidate(const ParamList &x)
136 {
137         return canidate_check(get_param_vocab(),x);
138 }
139
140 bool
141 Action::ValueDescSet::set_param(const synfig::String& name, const Action::Param &param)
142 {
143         if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
144         {
145                 value_desc=param.get_value_desc();
146                 
147                 return true;
148         }
149
150         if(name=="new_value" && param.get_type()==Param::TYPE_VALUE)
151         {
152                 value=param.get_value();
153                 
154                 return true;
155         }
156
157         if(name=="time" && param.get_type()==Param::TYPE_TIME)
158         {
159                 time=param.get_time();
160                 
161                 return true;
162         }
163
164         return Action::CanvasSpecific::set_param(name,param);
165 }
166
167 bool
168 Action::ValueDescSet::is_ready()const
169 {
170         if(!value_desc || !value.is_valid())
171                 return false;
172         return Action::CanvasSpecific::is_ready();
173 }
174
175 void
176 Action::ValueDescSet::prepare()
177 {
178         clear();
179
180         // If our tangents are merged, and
181         // our first tangent is being manipulated,
182         // then we also need to adjust the other
183         // tangent.
184         if(     value_desc.parent_is_value_node()
185         &&      value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT
186         &&      value_desc.get_index()==4
187         &&      (*value_desc.get_parent_value_node())(time).get(BLinePoint()).get_split_tangent_flag()==false
188         )
189         {
190                 DEBUGPOINT();
191                 ValueNode_Composite::Handle parent_value_node;
192                 parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
193                 
194                 assert(parent_value_node);
195                 
196                 Action::Handle action(Action::create("value_desc_set"));
197         
198                 if(!action)
199                         throw Error(_("Unable to find action value_desc_set (bug)"));
200                 
201                 action->set_param("canvas",get_canvas());
202                 action->set_param("canvas_interface",get_canvas_interface());
203                 action->set_param("time",time);
204                 action->set_param("new_value",value);
205                 action->set_param("value_desc",ValueDesc(parent_value_node,5));
206                 
207                 if(!action->is_ready())
208                         throw Error(Error::TYPE_NOTREADY);
209         
210                 add_action(action);                     
211         }
212
213         // If we are a reference value node, then
214         // we need to distribute the changes to the
215         // referenced value node
216         if(value_desc.is_value_node() && ValueNode_Reference::Handle::cast_dynamic(value_desc.get_value_node()))
217         {
218                 ValueDesc reference_value_desc(ValueNode_Reference::Handle::cast_dynamic(value_desc.get_value_node()),0);
219
220                 Action::Handle action(Action::create("value_desc_set"));
221
222                 if(!action)
223                         throw Error(_("Unable to find action value_desc_set (bug)"));
224                 
225                 action->set_param("canvas",get_canvas());
226                 action->set_param("canvas_interface",get_canvas_interface());
227                 action->set_param("time",time);
228                 action->set_param("new_value",value);
229                 action->set_param("value_desc",reference_value_desc);
230                 
231                 if(!action->is_ready())
232                         throw Error(Error::TYPE_NOTREADY);
233
234                 add_action(action);                     
235         
236                 return;
237         }
238         
239         // If we are a composite value node, then
240         // we need to distribute the changes to the
241         // individual parts
242         if(value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
243         {
244                 ValueBase components[6];
245                 int n_components(0);
246                 switch(value.get_type())
247                 {
248                 case ValueBase::TYPE_VECTOR:
249                         components[0]=value.get(Vector())[0];
250                         components[1]=value.get(Vector())[1];
251                         n_components=2;
252                         break;
253                 case ValueBase::TYPE_COLOR:
254                         components[0]=value.get(Color()).get_r();
255                         components[1]=value.get(Color()).get_g();
256                         components[2]=value.get(Color()).get_b();
257                         components[3]=value.get(Color()).get_a();
258                         n_components=4;
259                         break;
260                 case ValueBase::TYPE_SEGMENT:
261                         components[0]=value.get(Segment()).p1;
262                         components[1]=value.get(Segment()).t1;
263                         components[2]=value.get(Segment()).p2;
264                         components[3]=value.get(Segment()).t2;
265                         n_components=4;
266                         break;
267                 case ValueBase::TYPE_BLINEPOINT:
268                 {
269                         BLinePoint bline_point(value);
270                         components[0]=bline_point.get_vertex();
271                         components[1]=bline_point.get_width();
272                         components[2]=bline_point.get_origin();
273                         components[3]=bline_point.get_split_tangent_flag();
274                         components[4]=bline_point.get_tangent1();
275                         components[5]=bline_point.get_tangent2();
276                         n_components=6;
277                         break;
278                 }
279                 default:
280                         throw Error("Bad type for composite (%s)",ValueBase::type_name(value.get_type()).c_str());                      
281                         break;
282                 }
283                 
284                 for(int i=0;i<n_components;i++)
285                 {
286                         ValueDesc component_value_desc(ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()),i);
287
288                         Action::Handle action(Action::create("value_desc_set"));
289         
290                         if(!action)
291                                 throw Error(_("Unable to find action value_desc_set (bug)"));
292                         
293                         action->set_param("canvas",get_canvas());
294                         action->set_param("canvas_interface",get_canvas_interface());
295                         action->set_param("time",time);
296                         action->set_param("new_value",components[i]);
297                         action->set_param("value_desc",component_value_desc);
298                         
299                         if(!action->is_ready())
300                                 throw Error(Error::TYPE_NOTREADY);
301         
302                         add_action(action);                     
303                 }
304                 
305                 return;
306         }
307
308         
309         // If we are a RADIAL composite value node, then
310         // we need to distribute the changes to the
311         // individual parts
312         if(value_desc.is_value_node() && ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()))
313         {
314                 ValueBase components[6];
315                 int n_components(0);
316                 switch(value.get_type())
317                 {
318                 case ValueBase::TYPE_VECTOR:
319                 {
320                         Vector vect(value.get(Vector()));
321                         components[0]=vect.mag();
322                         components[1]=Angle(Angle::tan(vect[1],vect[0]));
323                         n_components=2;
324                 }
325                         break;
326                 case ValueBase::TYPE_COLOR:
327                         components[0]=value.get(Color()).get_y();
328                         components[1]=value.get(Color()).get_s();
329                         components[2]=value.get(Color()).get_hue();
330                         components[3]=value.get(Color()).get_a();
331                         n_components=4;
332                         break;
333                 default:
334                         throw Error("Bad type for radial composite (%s)",ValueBase::type_name(value.get_type()).c_str());                       
335                         break;
336                 }
337                 for(int i=0;i<n_components;i++)
338                 {
339                         ValueDesc component_value_desc(ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()),i);
340
341                         Action::Handle action(Action::create("value_desc_set"));
342         
343                         if(!action)
344                                 throw Error(_("Unable to find action value_desc_set (bug)"));
345                         
346                         action->set_param("canvas",get_canvas());
347                         action->set_param("canvas_interface",get_canvas_interface());
348                         action->set_param("time",time);
349                         action->set_param("new_value",components[i]);
350                         action->set_param("value_desc",component_value_desc);
351                         
352                         if(!action->is_ready())
353                                 throw Error(Error::TYPE_NOTREADY);
354         
355                         add_action(action);                     
356                 }
357                 
358                 return;
359         }
360
361         // If we are merging the tangents of a BLinePoint,
362         // we must also set the second tangent for things
363         // to interpolate properly
364         if(     value_desc.parent_is_value_node()
365         &&      value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT
366         &&      value_desc.get_index()==3
367 //      &&      value.get(bool())==false        // Actually, we want to do this any time the split flag is tweaked with
368         )
369         {
370                 ValueNode_Composite::Handle parent_value_node;
371                 parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
372                 
373                 assert(parent_value_node);
374                 
375                 Action::Handle action(Action::create("value_desc_set"));
376         
377                 if(!action)
378                         throw Error(_("Unable to find action value_desc_set (bug)"));
379                 
380                 action->set_param("canvas",get_canvas());
381                 action->set_param("canvas_interface",get_canvas_interface());
382                 action->set_param("time",time);
383                 action->set_param("new_value",(*parent_value_node->get_link(4))(time));
384                 action->set_param("value_desc",ValueDesc(parent_value_node,5));
385                 
386                 if(!action->is_ready())
387                         throw Error(Error::TYPE_NOTREADY);
388         
389                 add_action(action);                     
390         }
391
392 /*      DEBUGPOINT();
393         if(     value_desc.parent_is_value_node())
394         {
395                 DEBUGPOINT();
396                 if(value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT)
397                 {
398                         DEBUGPOINT();
399                         if(value_desc.get_index()==4)
400                         {
401                                 DEBUGPOINT();
402                                 if((*value_desc.get_parent_value_node())(time).get(BLinePoint()).get_split_tangent_flag()==false)
403                                 {
404                                         DEBUGPOINT();
405                                 }
406                         }
407                 }
408         }
409 */      
410
411         
412         // If we are in animate editing mode
413         if(get_edit_mode()&MODE_ANIMATE)
414         {
415
416                 ValueNode_Animated::Handle& value_node(value_node_animated);
417
418                 // If this value isn't a ValueNode_Animated, but
419                 // it is somewhat constant, then go ahead and convert
420                 // it to a ValueNode_Animated.
421                 if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
422                 {
423                         ValueBase value;
424                         if(value_desc.is_value_node())
425                                 value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value();
426                         else
427                                 value=value_desc.get_value();
428                         
429                         if(!value_node)value_node=ValueNode_Animated::create(value,time);
430                         //if(!value_node)value_node=ValueNode_Animated::create(value.get_type());
431                         
432                         Action::Handle action;
433                         
434                         if(!value_desc.is_value_node())
435                         {
436                                 action=(ValueDescConnect::create());
437                                 action->set_param("dest",value_desc);
438                                 action->set_param("src",ValueNode::Handle(value_node));
439                         }
440                         else
441                         {
442                                 action=Action::create("value_node_replace");
443                                 action->set_param("dest",value_desc.get_value_node());
444                                 action->set_param("src",ValueNode::Handle(value_node));
445                         }
446                         
447                         action->set_param("canvas",get_canvas());
448                         action->set_param("canvas_interface",get_canvas_interface());
449                         
450                         if(!action->is_ready())
451                                 throw Error(Error::TYPE_NOTREADY);
452         
453                                 DEBUGPOINT();
454                         add_action_front(action);
455                 }
456                 else
457                 {
458                         value_node=value_node.cast_dynamic(value_desc.get_value_node());
459                 }
460                 
461                                 DEBUGPOINT();
462                 if(!value_node)
463                         throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));              
464                 
465                 Action::Handle action(WaypointSetSmart::create());
466                 
467                 //Waypoint waypoint(value,time);
468                 
469                 Waypoint waypoint(value_node->new_waypoint_at_time(time));
470                 waypoint.set_value(value);
471                 
472                 waypoint.set_before(synfigapp::Main::get_interpolation());
473                 waypoint.set_after(synfigapp::Main::get_interpolation());
474                 
475                 action->set_param("canvas",get_canvas());
476                 action->set_param("canvas_interface",get_canvas_interface());
477                 action->set_param("value_node",ValueNode::Handle(value_node));
478                 action->set_param("waypoint",waypoint);
479                 
480                 if(!action->is_ready())
481                         throw Error(Error::TYPE_NOTREADY);
482
483                                 DEBUGPOINT();
484                 add_action(action);
485                 
486                 return;
487         }
488         else
489         {
490                 if(value_desc.is_value_node())
491                 {
492                         if(ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
493                         {
494                                 Action::Handle action(ValueNodeConstSet::create());
495                                 
496                                 action->set_param("canvas",get_canvas());
497                                 action->set_param("canvas_interface",get_canvas_interface());
498                                 action->set_param("value_node",value_desc.get_value_node());
499                                 action->set_param("new_value",value);
500                                 
501                                 if(!action->is_ready())
502                                         throw Error(Error::TYPE_NOTREADY);
503                 
504                                 add_action_front(action);
505                                 return;
506                         }
507                         else
508                         if(ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()))
509                                 throw Error(_("You must be in Animate-Editing-Mode to directly manipulate this value"));                
510                         else
511                                 throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));              
512                 }
513                 else
514                 if(value_desc.parent_is_layer_param() && !value_desc.is_value_node())
515                 {
516                         Action::Handle layer_param_set(LayerParamSet::create());
517                         
518                         layer_param_set->set_param("canvas",get_canvas());
519                         layer_param_set->set_param("canvas_interface",get_canvas_interface());
520                         layer_param_set->set_param("layer",value_desc.get_layer());
521                         layer_param_set->set_param("param",value_desc.get_param_name());
522                         layer_param_set->set_param("new_value",value);
523         
524                         if(!layer_param_set->is_ready())
525                                 throw Error(Error::TYPE_NOTREADY);
526                         
527                         add_action_front(layer_param_set);
528                         return;
529                 }
530
531                 throw Error(_("Unsupported ValueDesc type"));
532         }
533 }