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