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