Tidied up the appearance of the action local name as it appears in the history dialog.
[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$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "layerparamset.h"
34 #include "valuenodeconstset.h"
35 #include "valuedescconnect.h"
36 #include "waypointsetsmart.h"
37
38 #include "valuedescset.h"
39 #include <synfigapp/canvasinterface.h>
40 #include <synfig/valuenode_composite.h>
41 #include <synfig/valuenode_radialcomposite.h>
42 #include <synfig/valuenode_reference.h>
43 #include <synfigapp/main.h>
44
45 #include <synfigapp/general.h>
46
47 #endif
48
49 using namespace std;
50 using namespace etl;
51 using namespace synfig;
52 using namespace synfigapp;
53 using namespace Action;
54
55 /* === M A C R O S ========================================================= */
56
57 ACTION_INIT_NO_GET_LOCAL_NAME(Action::ValueDescSet);
58 ACTION_SET_NAME(Action::ValueDescSet,"value_desc_set");
59 ACTION_SET_LOCAL_NAME(Action::ValueDescSet,N_("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$");
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                 name = strprintf(_("'%s' -> %s"),
87                                                  (value_desc.get_layer()->get_description().empty()
88                                                   ? value_desc.get_layer()->get_local_name()
89                                                   : value_desc.get_layer()->get_description()).c_str(),
90                                                  value_desc.get_param_name().c_str());
91         else if(value_desc.parent_is_value_node())
92         {
93                 synfig::LinkableValueNode::Handle value_node(synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node()));
94                 synfig::Node* node;
95                 for(node=value_node.get();!node->parent_set.empty() && !dynamic_cast<Layer*>(node);node=*node->parent_set.begin());
96                 Layer::Handle parent_layer(dynamic_cast<Layer*>(node));
97                 if(parent_layer)
98                         name = strprintf(_("'%s' => %s"),
99                                                          (parent_layer->get_description().empty()
100                                                           ? parent_layer->get_local_name()
101                                                           : parent_layer->get_description()).c_str(),
102                                                          value_node->link_local_name(value_desc.get_index()).c_str()); 
103                 else
104                         name = value_node->link_local_name(value_desc.get_index());
105         }
106
107         return strprintf(_("Set %s"), name.c_str());
108 }
109
110 Action::ParamVocab
111 Action::ValueDescSet::get_param_vocab()
112 {
113         ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
114
115         ret.push_back(ParamDesc("value_desc",Param::TYPE_VALUEDESC)
116                 .set_local_name(_("ValueDesc"))
117         );
118
119         ret.push_back(ParamDesc("new_value",Param::TYPE_VALUE)
120                 .set_local_name(_("ValueBase"))
121         );
122
123         ret.push_back(ParamDesc("time",Param::TYPE_TIME)
124                 .set_local_name(_("Time"))
125                 .set_optional()
126         );
127
128         return ret;
129 }
130
131 bool
132 Action::ValueDescSet::is_candidate(const ParamList &x)
133 {
134         return candidate_check(get_param_vocab(),x);
135 }
136
137 bool
138 Action::ValueDescSet::set_param(const synfig::String& name, const Action::Param &param)
139 {
140         if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
141         {
142                 value_desc=param.get_value_desc();
143
144                 return true;
145         }
146
147         if(name=="new_value" && param.get_type()==Param::TYPE_VALUE)
148         {
149                 value=param.get_value();
150
151                 return true;
152         }
153
154         if(name=="time" && param.get_type()==Param::TYPE_TIME)
155         {
156                 time=param.get_time();
157
158                 return true;
159         }
160
161         return Action::CanvasSpecific::set_param(name,param);
162 }
163
164 bool
165 Action::ValueDescSet::is_ready()const
166 {
167         if(!value_desc || !value.is_valid())
168                 return false;
169         return Action::CanvasSpecific::is_ready();
170 }
171
172 void
173 Action::ValueDescSet::prepare()
174 {
175         clear();
176
177         // If our tangents are merged, and
178         // our first tangent is being manipulated,
179         // then we also need to adjust the other
180         // tangent.
181         if(     value_desc.parent_is_value_node() &&
182                 value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT &&
183                 (value_desc.get_index()==4 || value_desc.get_index()==5) &&
184                 (*value_desc.get_parent_value_node())(time).get(BLinePoint()).get_split_tangent_flag()==false)
185         {
186                 printf("a tangent got changed - #%d\n", value_desc.get_index()-3);
187
188                 {
189                         ValueNode_Composite::Handle parent_value_node;
190                         parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
191                         assert(parent_value_node);
192
193                         Vector t1((*parent_value_node->get_link("t1"))(time));
194                         Vector t2((*parent_value_node->get_link("t2"))(time));
195                         printf("current values are: t1(%.2f, %2.f)  t2(%.2f, %.2f)\n", t1[0], t1[1], t2[0], t2[1]);
196                 }
197
198                 if (value_desc.get_index()==4) {
199                         printf("copying change to tangent 2\n");
200                         DEBUGPOINT();
201                         ValueNode_Composite::Handle parent_value_node;
202                         parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
203
204                         assert(parent_value_node);
205
206                         Action::Handle action(Action::create("value_desc_set"));
207
208                         if(!action)
209                                 throw Error(_("Unable to find action value_desc_set (bug)"));
210
211                         action->set_param("canvas",get_canvas());
212                         action->set_param("canvas_interface",get_canvas_interface());
213                         action->set_param("time",time);
214                         action->set_param("new_value",value);
215                         action->set_param("value_desc",ValueDesc(parent_value_node,5));
216
217                         if(!action->is_ready())
218                                 throw Error(Error::TYPE_NOTREADY);
219
220                         add_action(action);
221                 }
222         }
223
224         // If we are a reference value node, then
225         // we need to distribute the changes to the
226         // referenced value node
227         if(value_desc.is_value_node() && ValueNode_Reference::Handle::cast_dynamic(value_desc.get_value_node()))
228         {
229                 ValueDesc reference_value_desc(ValueNode_Reference::Handle::cast_dynamic(value_desc.get_value_node()),0);
230
231                 Action::Handle action(Action::create("value_desc_set"));
232
233                 if(!action)
234                         throw Error(_("Unable to find action value_desc_set (bug)"));
235
236                 action->set_param("canvas",get_canvas());
237                 action->set_param("canvas_interface",get_canvas_interface());
238                 action->set_param("time",time);
239                 action->set_param("new_value",value);
240                 action->set_param("value_desc",reference_value_desc);
241
242                 if(!action->is_ready())
243                         throw Error(Error::TYPE_NOTREADY);
244
245                 add_action(action);
246
247                 return;
248         }
249
250         // If we are a composite value node, then
251         // we need to distribute the changes to the
252         // individual parts
253         if(value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
254         {
255                 ValueBase components[6];
256                 int n_components(0);
257                 switch(value.get_type())
258                 {
259                 case ValueBase::TYPE_VECTOR:
260                         components[0]=value.get(Vector())[0];
261                         components[1]=value.get(Vector())[1];
262                         n_components=2;
263                         break;
264                 case ValueBase::TYPE_COLOR:
265                         components[0]=value.get(Color()).get_r();
266                         components[1]=value.get(Color()).get_g();
267                         components[2]=value.get(Color()).get_b();
268                         components[3]=value.get(Color()).get_a();
269                         n_components=4;
270                         break;
271                 case ValueBase::TYPE_SEGMENT:
272                         components[0]=value.get(Segment()).p1;
273                         components[1]=value.get(Segment()).t1;
274                         components[2]=value.get(Segment()).p2;
275                         components[3]=value.get(Segment()).t2;
276                         n_components=4;
277                         break;
278                 case ValueBase::TYPE_BLINEPOINT:
279                 {
280                         BLinePoint bline_point(value);
281                         components[0]=bline_point.get_vertex();
282                         components[1]=bline_point.get_width();
283                         components[2]=bline_point.get_origin();
284                         components[3]=bline_point.get_split_tangent_flag();
285                         components[4]=bline_point.get_tangent1();
286                         components[5]=bline_point.get_tangent2();
287                         n_components=6;
288                         break;
289                 }
290                 default:
291                         throw Error(_("Bad type for composite (%s)"),ValueBase::type_local_name(value.get_type()).c_str());
292                         break;
293                 }
294
295                 for(int i=0;i<n_components;i++)
296                 {
297                         ValueDesc component_value_desc(ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()),i);
298
299                         Action::Handle action(Action::create("value_desc_set"));
300
301                         if(!action)
302                                 throw Error(_("Unable to find action value_desc_set (bug)"));
303
304                         action->set_param("canvas",get_canvas());
305                         action->set_param("canvas_interface",get_canvas_interface());
306                         action->set_param("time",time);
307                         action->set_param("new_value",components[i]);
308                         action->set_param("value_desc",component_value_desc);
309
310                         if(!action->is_ready())
311                                 throw Error(Error::TYPE_NOTREADY);
312
313                         add_action(action);
314                 }
315
316                 return;
317         }
318
319
320         // If we are a RADIAL composite value node, then
321         // we need to distribute the changes to the
322         // individual parts
323         if(value_desc.is_value_node() && ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()))
324         {
325                 ValueBase components[6];
326                 int n_components(0);
327                 switch(value.get_type())
328                 {
329                 case ValueBase::TYPE_VECTOR:
330                 {
331                         Angle old_angle = (*(ValueNode_RadialComposite::Handle::cast_dynamic(
332                                                                          value_desc.get_value_node())->get_link_vfunc(1)))(time).get(Angle());
333                         Vector vect(value.get(Vector()));
334                         components[0]=vect.mag();
335                         Angle change = Angle(Angle::tan(vect[1],vect[0])) - old_angle;
336                         while (change < Angle::deg(-180)) change += Angle::deg(360);
337                         while (change > Angle::deg(180)) change -= Angle::deg(360);
338                         components[1]=old_angle + change;
339                         n_components=2;
340                 }
341                         break;
342                 case ValueBase::TYPE_COLOR:
343                         components[0]=value.get(Color()).get_y();
344                         components[1]=value.get(Color()).get_s();
345                         components[2]=value.get(Color()).get_hue();
346                         components[3]=value.get(Color()).get_a();
347                         n_components=4;
348                         break;
349                 default:
350                         throw Error(_("Bad type for radial composite (%s)"),ValueBase::type_local_name(value.get_type()).c_str());
351                         break;
352                 }
353                 for(int i=0;i<n_components;i++)
354                 {
355                         ValueDesc component_value_desc(ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()),i);
356
357                         Action::Handle action(Action::create("value_desc_set"));
358
359                         if(!action)
360                                 throw Error(_("Unable to find action value_desc_set (bug)"));
361
362                         action->set_param("canvas",get_canvas());
363                         action->set_param("canvas_interface",get_canvas_interface());
364                         action->set_param("time",time);
365                         action->set_param("new_value",components[i]);
366                         action->set_param("value_desc",component_value_desc);
367
368                         if(!action->is_ready())
369                                 throw Error(Error::TYPE_NOTREADY);
370
371                         add_action(action);
372                 }
373
374                 return;
375         }
376
377         // If we are merging the tangents of a BLinePoint,
378         // we must also set the second tangent for things
379         // to interpolate properly
380         if (value_desc.parent_is_value_node() &&
381             value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT &&
382             value_desc.get_index()==3)
383         {
384                 ValueNode_Composite::Handle parent_value_node;
385                 parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
386
387                 assert(parent_value_node);
388
389                 // are we splitting or merging the tangents?
390             if (value.get(bool()))
391             {
392                         // we are splitting tangents
393
394                         Action::Handle action(Action::create("value_desc_set"));
395
396                         if(!action)
397                                 throw Error(_("Unable to find action value_desc_set (bug)"));
398
399                         action->set_param("canvas",get_canvas());
400                         action->set_param("canvas_interface",get_canvas_interface());
401                         action->set_param("time",time);
402                         action->set_param("new_value",(*parent_value_node->get_link(4))(time));
403                         action->set_param("value_desc",ValueDesc(parent_value_node,5));
404
405                         if(!action->is_ready())
406                                 throw Error(Error::TYPE_NOTREADY);
407
408                         add_action(action);
409             }
410             else
411             {
412                         // we are merging tangents
413
414                         // the merged tangent should be the average of the 2 tangents we're merging
415                         ValueBase average(((Vector)((*parent_value_node->get_link("t1"))(time)) +
416                                                            (Vector)((*parent_value_node->get_link("t2"))(time))) / 2);
417
418                         {
419                                 Action::Handle action(Action::create("value_desc_set"));
420
421                                 if(!action)
422                                         throw Error(_("Unable to find action value_desc_set (bug)"));
423
424                                 action->set_param("canvas",get_canvas());
425                                 action->set_param("canvas_interface",get_canvas_interface());
426                                 action->set_param("time",time);
427                                 action->set_param("new_value",average);
428                                 action->set_param("value_desc",ValueDesc(parent_value_node,4));
429
430                                 if(!action->is_ready())
431                                         throw Error(Error::TYPE_NOTREADY);
432
433                                 add_action(action);
434                         }
435
436                         {
437                                 Action::Handle action(Action::create("value_desc_set"));
438
439                                 if(!action)
440                                         throw Error(_("Unable to find action value_desc_set (bug)"));
441
442                                 action->set_param("canvas",get_canvas());
443                                 action->set_param("canvas_interface",get_canvas_interface());
444                                 action->set_param("time",time);
445                                 action->set_param("new_value",average);
446                                 action->set_param("value_desc",ValueDesc(parent_value_node,5));
447
448                                 if(!action->is_ready())
449                                         throw Error(Error::TYPE_NOTREADY);
450
451                                 add_action(action);
452                         }
453             }
454
455         }
456
457 /*      DEBUGPOINT();
458         if(     value_desc.parent_is_value_node())
459         {
460                 DEBUGPOINT();
461                 if(value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT)
462                 {
463                         DEBUGPOINT();
464                         if(value_desc.get_index()==4)
465                         {
466                                 DEBUGPOINT();
467                                 if((*value_desc.get_parent_value_node())(time).get(BLinePoint()).get_split_tangent_flag()==false)
468                                 {
469                                         DEBUGPOINT();
470                                 }
471                         }
472                 }
473         }
474 */
475
476
477         // If we are in animate editing mode
478         if(get_edit_mode()&MODE_ANIMATE)
479         {
480
481                 ValueNode_Animated::Handle& value_node(value_node_animated);
482
483                 // If this value isn't a ValueNode_Animated, but
484                 // it is somewhat constant, then go ahead and convert
485                 // it to a ValueNode_Animated.
486                 if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
487                 {
488                         ValueBase value;
489                         if(value_desc.is_value_node())
490                                 value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value();
491                         else
492                                 value=value_desc.get_value();
493
494                         if(!value_node)value_node=ValueNode_Animated::create(value,time);
495                         //if(!value_node)value_node=ValueNode_Animated::create(value.get_type());
496
497                         Action::Handle action;
498
499                         if(!value_desc.is_value_node())
500                         {
501                                 action=(ValueDescConnect::create());
502                                 action->set_param("dest",value_desc);
503                                 action->set_param("src",ValueNode::Handle(value_node));
504                         }
505                         else
506                         {
507                                 action=Action::create("value_node_replace");
508                                 action->set_param("dest",value_desc.get_value_node());
509                                 action->set_param("src",ValueNode::Handle(value_node));
510                         }
511
512                         action->set_param("canvas",get_canvas());
513                         action->set_param("canvas_interface",get_canvas_interface());
514
515                         if(!action->is_ready())
516                                 throw Error(Error::TYPE_NOTREADY);
517
518                                 DEBUGPOINT();
519                         add_action_front(action);
520                 }
521                 else
522                 {
523                         value_node=value_node.cast_dynamic(value_desc.get_value_node());
524                 }
525
526                                 DEBUGPOINT();
527                 if(!value_node)
528                         throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));
529
530                 Action::Handle action(WaypointSetSmart::create());
531
532                 //Waypoint waypoint(value,time);
533
534                 Waypoint waypoint(value_node->new_waypoint_at_time(time));
535                 waypoint.set_value(value);
536
537                 waypoint.set_before(synfigapp::Main::get_interpolation());
538                 waypoint.set_after(synfigapp::Main::get_interpolation());
539
540                 action->set_param("canvas",get_canvas());
541                 action->set_param("canvas_interface",get_canvas_interface());
542                 action->set_param("value_node",ValueNode::Handle(value_node));
543                 action->set_param("waypoint",waypoint);
544
545                 if(!action->is_ready())
546                         throw Error(Error::TYPE_NOTREADY);
547
548                                 DEBUGPOINT();
549                 add_action(action);
550
551                 return;
552         }
553         else
554         {
555                 if(value_desc.is_value_node())
556                 {
557                         if(ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
558                         {
559                                 Action::Handle action(ValueNodeConstSet::create());
560
561                                 action->set_param("canvas",get_canvas());
562                                 action->set_param("canvas_interface",get_canvas_interface());
563                                 action->set_param("value_node",value_desc.get_value_node());
564                                 action->set_param("new_value",value);
565
566                                 if(!action->is_ready())
567                                         throw Error(Error::TYPE_NOTREADY);
568
569                                 add_action_front(action);
570                                 return;
571                         }
572                         else
573                         if(ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()))
574                                 throw Error(_("You must be in Animate-Editing-Mode to directly manipulate this value"));
575                         else
576                                 throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));
577                 }
578                 else
579                 if(value_desc.parent_is_layer_param() && !value_desc.is_value_node())
580                 {
581                         Action::Handle layer_param_set(LayerParamSet::create());
582
583                         layer_param_set->set_param("canvas",get_canvas());
584                         layer_param_set->set_param("canvas_interface",get_canvas_interface());
585                         layer_param_set->set_param("layer",value_desc.get_layer());
586                         layer_param_set->set_param("param",value_desc.get_param_name());
587                         layer_param_set->set_param("new_value",value);
588
589                         if(!layer_param_set->is_ready())
590                                 throw Error(Error::TYPE_NOTREADY);
591
592                         add_action_front(layer_param_set);
593                         return;
594                 }
595
596                 throw Error(_("Unsupported ValueDesc type"));
597         }
598 }