Don't wrap the angle in a radial composite conversation from -180 to 180 degrees...
[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                         Angle old_angle = (*(ValueNode_RadialComposite::Handle::cast_dynamic(
338                                                                          value_desc.get_value_node())->get_link_vfunc(1)))(time).get(Angle());
339                         Vector vect(value.get(Vector()));
340                         components[0]=vect.mag();
341                         Angle change = Angle(Angle::tan(vect[1],vect[0])) - old_angle;
342                         while (change < Angle::deg(-180)) change += Angle::deg(360);
343                         while (change > Angle::deg(180)) change -= Angle::deg(360);
344                         components[1]=old_angle + change;
345                         n_components=2;
346                 }
347                         break;
348                 case ValueBase::TYPE_COLOR:
349                         components[0]=value.get(Color()).get_y();
350                         components[1]=value.get(Color()).get_s();
351                         components[2]=value.get(Color()).get_hue();
352                         components[3]=value.get(Color()).get_a();
353                         n_components=4;
354                         break;
355                 default:
356                         throw Error(_("Bad type for radial composite (%s)"),ValueBase::type_name(value.get_type()).c_str());
357                         break;
358                 }
359                 for(int i=0;i<n_components;i++)
360                 {
361                         ValueDesc component_value_desc(ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()),i);
362
363                         Action::Handle action(Action::create("value_desc_set"));
364
365                         if(!action)
366                                 throw Error(_("Unable to find action value_desc_set (bug)"));
367
368                         action->set_param("canvas",get_canvas());
369                         action->set_param("canvas_interface",get_canvas_interface());
370                         action->set_param("time",time);
371                         action->set_param("new_value",components[i]);
372                         action->set_param("value_desc",component_value_desc);
373
374                         if(!action->is_ready())
375                                 throw Error(Error::TYPE_NOTREADY);
376
377                         add_action(action);
378                 }
379
380                 return;
381         }
382
383         // If we are merging the tangents of a BLinePoint,
384         // we must also set the second tangent for things
385         // to interpolate properly
386         if (value_desc.parent_is_value_node() &&
387             value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT &&
388             value_desc.get_index()==3)
389         {
390                 ValueNode_Composite::Handle parent_value_node;
391                 parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
392
393                 assert(parent_value_node);
394
395                 // are we splitting or merging the tangents?
396             if (value.get(bool()))
397             {
398                         // we are splitting tangents
399
400                         Action::Handle action(Action::create("value_desc_set"));
401
402                         if(!action)
403                                 throw Error(_("Unable to find action value_desc_set (bug)"));
404
405                         action->set_param("canvas",get_canvas());
406                         action->set_param("canvas_interface",get_canvas_interface());
407                         action->set_param("time",time);
408                         action->set_param("new_value",(*parent_value_node->get_link(4))(time));
409                         action->set_param("value_desc",ValueDesc(parent_value_node,5));
410
411                         if(!action->is_ready())
412                                 throw Error(Error::TYPE_NOTREADY);
413
414                         add_action(action);
415             }
416             else
417             {
418                         // we are merging tangents
419
420                         // the merged tangent should be the average of the 2 tangents we're merging
421                         ValueBase average(((Vector)((*parent_value_node->get_link("t1"))(time)) +
422                                                            (Vector)((*parent_value_node->get_link("t2"))(time))) / 2);
423
424                         {
425                                 Action::Handle action(Action::create("value_desc_set"));
426
427                                 if(!action)
428                                         throw Error(_("Unable to find action value_desc_set (bug)"));
429
430                                 action->set_param("canvas",get_canvas());
431                                 action->set_param("canvas_interface",get_canvas_interface());
432                                 action->set_param("time",time);
433                                 action->set_param("new_value",average);
434                                 action->set_param("value_desc",ValueDesc(parent_value_node,4));
435
436                                 if(!action->is_ready())
437                                         throw Error(Error::TYPE_NOTREADY);
438
439                                 add_action(action);
440                         }
441
442                         {
443                                 Action::Handle action(Action::create("value_desc_set"));
444
445                                 if(!action)
446                                         throw Error(_("Unable to find action value_desc_set (bug)"));
447
448                                 action->set_param("canvas",get_canvas());
449                                 action->set_param("canvas_interface",get_canvas_interface());
450                                 action->set_param("time",time);
451                                 action->set_param("new_value",average);
452                                 action->set_param("value_desc",ValueDesc(parent_value_node,5));
453
454                                 if(!action->is_ready())
455                                         throw Error(Error::TYPE_NOTREADY);
456
457                                 add_action(action);
458                         }
459             }
460
461         }
462
463 /*      DEBUGPOINT();
464         if(     value_desc.parent_is_value_node())
465         {
466                 DEBUGPOINT();
467                 if(value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT)
468                 {
469                         DEBUGPOINT();
470                         if(value_desc.get_index()==4)
471                         {
472                                 DEBUGPOINT();
473                                 if((*value_desc.get_parent_value_node())(time).get(BLinePoint()).get_split_tangent_flag()==false)
474                                 {
475                                         DEBUGPOINT();
476                                 }
477                         }
478                 }
479         }
480 */
481
482
483         // If we are in animate editing mode
484         if(get_edit_mode()&MODE_ANIMATE)
485         {
486
487                 ValueNode_Animated::Handle& value_node(value_node_animated);
488
489                 // If this value isn't a ValueNode_Animated, but
490                 // it is somewhat constant, then go ahead and convert
491                 // it to a ValueNode_Animated.
492                 if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
493                 {
494                         ValueBase value;
495                         if(value_desc.is_value_node())
496                                 value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value();
497                         else
498                                 value=value_desc.get_value();
499
500                         if(!value_node)value_node=ValueNode_Animated::create(value,time);
501                         //if(!value_node)value_node=ValueNode_Animated::create(value.get_type());
502
503                         Action::Handle action;
504
505                         if(!value_desc.is_value_node())
506                         {
507                                 action=(ValueDescConnect::create());
508                                 action->set_param("dest",value_desc);
509                                 action->set_param("src",ValueNode::Handle(value_node));
510                         }
511                         else
512                         {
513                                 action=Action::create("value_node_replace");
514                                 action->set_param("dest",value_desc.get_value_node());
515                                 action->set_param("src",ValueNode::Handle(value_node));
516                         }
517
518                         action->set_param("canvas",get_canvas());
519                         action->set_param("canvas_interface",get_canvas_interface());
520
521                         if(!action->is_ready())
522                                 throw Error(Error::TYPE_NOTREADY);
523
524                                 DEBUGPOINT();
525                         add_action_front(action);
526                 }
527                 else
528                 {
529                         value_node=value_node.cast_dynamic(value_desc.get_value_node());
530                 }
531
532                                 DEBUGPOINT();
533                 if(!value_node)
534                         throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));
535
536                 Action::Handle action(WaypointSetSmart::create());
537
538                 //Waypoint waypoint(value,time);
539
540                 Waypoint waypoint(value_node->new_waypoint_at_time(time));
541                 waypoint.set_value(value);
542
543                 waypoint.set_before(synfigapp::Main::get_interpolation());
544                 waypoint.set_after(synfigapp::Main::get_interpolation());
545
546                 action->set_param("canvas",get_canvas());
547                 action->set_param("canvas_interface",get_canvas_interface());
548                 action->set_param("value_node",ValueNode::Handle(value_node));
549                 action->set_param("waypoint",waypoint);
550
551                 if(!action->is_ready())
552                         throw Error(Error::TYPE_NOTREADY);
553
554                                 DEBUGPOINT();
555                 add_action(action);
556
557                 return;
558         }
559         else
560         {
561                 if(value_desc.is_value_node())
562                 {
563                         if(ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
564                         {
565                                 Action::Handle action(ValueNodeConstSet::create());
566
567                                 action->set_param("canvas",get_canvas());
568                                 action->set_param("canvas_interface",get_canvas_interface());
569                                 action->set_param("value_node",value_desc.get_value_node());
570                                 action->set_param("new_value",value);
571
572                                 if(!action->is_ready())
573                                         throw Error(Error::TYPE_NOTREADY);
574
575                                 add_action_front(action);
576                                 return;
577                         }
578                         else
579                         if(ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()))
580                                 throw Error(_("You must be in Animate-Editing-Mode to directly manipulate this value"));
581                         else
582                                 throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));
583                 }
584                 else
585                 if(value_desc.parent_is_layer_param() && !value_desc.is_value_node())
586                 {
587                         Action::Handle layer_param_set(LayerParamSet::create());
588
589                         layer_param_set->set_param("canvas",get_canvas());
590                         layer_param_set->set_param("canvas_interface",get_canvas_interface());
591                         layer_param_set->set_param("layer",value_desc.get_layer());
592                         layer_param_set->set_param("param",value_desc.get_param_name());
593                         layer_param_set->set_param("new_value",value);
594
595                         if(!layer_param_set->is_ready())
596                                 throw Error(Error::TYPE_NOTREADY);
597
598                         add_action_front(layer_param_set);
599                         return;
600                 }
601
602                 throw Error(_("Unsupported ValueDesc type"));
603         }
604 }