1 /* === S Y N F I G ========================================================= */
2 /*! \file valuedescset.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007 Chris Moore
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.
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.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
33 #include "layerparamset.h"
34 #include "valuenodeconstset.h"
35 #include "valuedescconnect.h"
36 #include "waypointsetsmart.h"
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>
45 #include <synfigapp/general.h>
51 using namespace synfig;
52 using namespace synfigapp;
53 using namespace Action;
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__; }
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$");
69 /* === G L O B A L S ======================================================= */
71 /* === P R O C E D U R E S ================================================= */
73 /* === M E T H O D S ======================================================= */
75 Action::ValueDescSet::ValueDescSet():
81 Action::ValueDescSet::get_local_name()const
83 String name("ValueDesc");
88 else if(value_desc.parent_is_layer_param())
90 if(value_desc.get_layer()->get_description().empty())
91 name=value_desc.get_layer()->get_local_name();
93 name=value_desc.get_layer()->get_description();
94 name+="->"+value_desc.get_param_name();
96 else if(value_desc.parent_is_value_node())
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());
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));
106 if(parent_layer->get_description().empty())
107 name=parent_layer->get_local_name()+"=>"+name;
109 name=parent_layer->get_description()+"=>"+name;
113 return strprintf(_("Set %s"),name.c_str());
117 Action::ValueDescSet::get_param_vocab()
119 ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
121 ret.push_back(ParamDesc("value_desc",Param::TYPE_VALUEDESC)
122 .set_local_name(_("ValueDesc"))
125 ret.push_back(ParamDesc("new_value",Param::TYPE_VALUE)
126 .set_local_name(_("ValueBase"))
129 ret.push_back(ParamDesc("time",Param::TYPE_TIME)
130 .set_local_name(_("Time"))
138 Action::ValueDescSet::is_candidate(const ParamList &x)
140 return candidate_check(get_param_vocab(),x);
144 Action::ValueDescSet::set_param(const synfig::String& name, const Action::Param ¶m)
146 if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
148 value_desc=param.get_value_desc();
153 if(name=="new_value" && param.get_type()==Param::TYPE_VALUE)
155 value=param.get_value();
160 if(name=="time" && param.get_type()==Param::TYPE_TIME)
162 time=param.get_time();
167 return Action::CanvasSpecific::set_param(name,param);
171 Action::ValueDescSet::is_ready()const
173 if(!value_desc || !value.is_valid())
175 return Action::CanvasSpecific::is_ready();
179 Action::ValueDescSet::prepare()
183 // If our tangents are merged, and
184 // our first tangent is being manipulated,
185 // then we also need to adjust the other
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)
192 printf("a tangent got changed - #%d\n", value_desc.get_index()-3);
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);
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]);
204 if (value_desc.get_index()==4) {
205 printf("copying change to tangent 2\n");
207 ValueNode_Composite::Handle parent_value_node;
208 parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
210 assert(parent_value_node);
212 Action::Handle action(Action::create("value_desc_set"));
215 throw Error(_("Unable to find action value_desc_set (bug)"));
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));
223 if(!action->is_ready())
224 throw Error(Error::TYPE_NOTREADY);
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()))
235 ValueDesc reference_value_desc(ValueNode_Reference::Handle::cast_dynamic(value_desc.get_value_node()),0);
237 Action::Handle action(Action::create("value_desc_set"));
240 throw Error(_("Unable to find action value_desc_set (bug)"));
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);
248 if(!action->is_ready())
249 throw Error(Error::TYPE_NOTREADY);
256 // If we are a composite value node, then
257 // we need to distribute the changes to the
259 if(value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
261 ValueBase components[6];
263 switch(value.get_type())
265 case ValueBase::TYPE_VECTOR:
266 components[0]=value.get(Vector())[0];
267 components[1]=value.get(Vector())[1];
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();
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;
284 case ValueBase::TYPE_BLINEPOINT:
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();
297 throw Error("Bad type for composite (%s)",ValueBase::type_name(value.get_type()).c_str());
301 for(int i=0;i<n_components;i++)
303 ValueDesc component_value_desc(ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()),i);
305 Action::Handle action(Action::create("value_desc_set"));
308 throw Error(_("Unable to find action value_desc_set (bug)"));
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);
316 if(!action->is_ready())
317 throw Error(Error::TYPE_NOTREADY);
326 // If we are a RADIAL composite value node, then
327 // we need to distribute the changes to the
329 if(value_desc.is_value_node() && ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()))
331 ValueBase components[6];
333 switch(value.get_type())
335 case ValueBase::TYPE_VECTOR:
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;
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();
356 throw Error(_("Bad type for radial composite (%s)"),ValueBase::type_name(value.get_type()).c_str());
359 for(int i=0;i<n_components;i++)
361 ValueDesc component_value_desc(ValueNode_RadialComposite::Handle::cast_dynamic(value_desc.get_value_node()),i);
363 Action::Handle action(Action::create("value_desc_set"));
366 throw Error(_("Unable to find action value_desc_set (bug)"));
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);
374 if(!action->is_ready())
375 throw Error(Error::TYPE_NOTREADY);
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)
390 ValueNode_Composite::Handle parent_value_node;
391 parent_value_node=parent_value_node.cast_dynamic(value_desc.get_parent_value_node());
393 assert(parent_value_node);
395 // are we splitting or merging the tangents?
396 if (value.get(bool()))
398 // we are splitting tangents
400 Action::Handle action(Action::create("value_desc_set"));
403 throw Error(_("Unable to find action value_desc_set (bug)"));
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));
411 if(!action->is_ready())
412 throw Error(Error::TYPE_NOTREADY);
418 // we are merging tangents
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);
425 Action::Handle action(Action::create("value_desc_set"));
428 throw Error(_("Unable to find action value_desc_set (bug)"));
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));
436 if(!action->is_ready())
437 throw Error(Error::TYPE_NOTREADY);
443 Action::Handle action(Action::create("value_desc_set"));
446 throw Error(_("Unable to find action value_desc_set (bug)"));
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));
454 if(!action->is_ready())
455 throw Error(Error::TYPE_NOTREADY);
464 if( value_desc.parent_is_value_node())
467 if(value_desc.get_parent_value_node()->get_type()==ValueBase::TYPE_BLINEPOINT)
470 if(value_desc.get_index()==4)
473 if((*value_desc.get_parent_value_node())(time).get(BLinePoint()).get_split_tangent_flag()==false)
483 // If we are in animate editing mode
484 if(get_edit_mode()&MODE_ANIMATE)
487 ValueNode_Animated::Handle& value_node(value_node_animated);
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()))
495 if(value_desc.is_value_node())
496 value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value();
498 value=value_desc.get_value();
500 if(!value_node)value_node=ValueNode_Animated::create(value,time);
501 //if(!value_node)value_node=ValueNode_Animated::create(value.get_type());
503 Action::Handle action;
505 if(!value_desc.is_value_node())
507 action=(ValueDescConnect::create());
508 action->set_param("dest",value_desc);
509 action->set_param("src",ValueNode::Handle(value_node));
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));
518 action->set_param("canvas",get_canvas());
519 action->set_param("canvas_interface",get_canvas_interface());
521 if(!action->is_ready())
522 throw Error(Error::TYPE_NOTREADY);
525 add_action_front(action);
529 value_node=value_node.cast_dynamic(value_desc.get_value_node());
534 throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));
536 Action::Handle action(WaypointSetSmart::create());
538 //Waypoint waypoint(value,time);
540 Waypoint waypoint(value_node->new_waypoint_at_time(time));
541 waypoint.set_value(value);
543 waypoint.set_before(synfigapp::Main::get_interpolation());
544 waypoint.set_after(synfigapp::Main::get_interpolation());
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);
551 if(!action->is_ready())
552 throw Error(Error::TYPE_NOTREADY);
561 if(value_desc.is_value_node())
563 if(ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
565 Action::Handle action(ValueNodeConstSet::create());
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);
572 if(!action->is_ready())
573 throw Error(Error::TYPE_NOTREADY);
575 add_action_front(action);
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"));
582 throw Error(_("Direct manipulation of this ValueNode type is not yet supported"));
585 if(value_desc.parent_is_layer_param() && !value_desc.is_value_node())
587 Action::Handle layer_param_set(LayerParamSet::create());
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);
595 if(!layer_param_set->is_ready())
596 throw Error(Error::TYPE_NOTREADY);
598 add_action_front(layer_param_set);
602 throw Error(_("Unsupported ValueDesc type"));