1 /* === S Y N F I G ========================================================= */
2 /*! \file blinepointtangentsplit.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, 2008 Chris Moore
10 ** Copyright (c) 2009 Nikita Kitaev
11 ** Copyright (c) 2012 Carlos López
12 **
13 ** This package is free software; you can redistribute it and/or
14 ** modify it under the terms of the GNU General Public License as
15 ** published by the Free Software Foundation; either version 2 of
16 ** the License, or (at your option) any later version.
17 **
18 ** This package is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 ** General Public License for more details.
22 ** \endlegal
23 */
24 /* ========================================================================= */
25
26 /* === H E A D E R S ======================================================= */
27
28 #ifdef USING_PCH
29 # include "pch.h"
30 #else
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #include <synfig/general.h>
36
37 #include "blinepointtangentsplit.h"
38 #include "valuedescset.h"
39
40 #include "activepointset.h"
41 #include "activepointadd.h"
42
43 #include "valuedescconnect.h"
44 #include <synfigapp/canvasinterface.h>
45
46 #include <synfigapp/localization.h>
47 #include <synfig/valuenodes/valuenode_radialcomposite.h>
48
49 #endif
50
51 using namespace std;
52 using namespace etl;
53 using namespace synfig;
54 using namespace synfigapp;
55 using namespace Action;
56
57 /* === M A C R O S ========================================================= */
58
59 ACTION_INIT_NO_GET_LOCAL_NAME(Action::BLinePointTangentSplit);
60 ACTION_SET_NAME(Action::BLinePointTangentSplit,"BLinePointTangentSplit");
61 ACTION_SET_LOCAL_NAME(Action::BLinePointTangentSplit,N_("Split Tangents"));
62 ACTION_SET_TASK(Action::BLinePointTangentSplit,"disconnect");
63 ACTION_SET_CATEGORY(Action::BLinePointTangentSplit,Action::CATEGORY_VALUENODE);
64 ACTION_SET_PRIORITY(Action::BLinePointTangentSplit,0);
65 ACTION_SET_VERSION(Action::BLinePointTangentSplit,"0.1");
66 ACTION_SET_CVS_ID(Action::BLinePointTangentSplit,"$Id$");
67
68 ACTION_INIT_NO_GET_LOCAL_NAME(Action::BLinePointTangentSplitRadius);
69 ACTION_SET_NAME(Action::BLinePointTangentSplitRadius,"BLinePointTangentSplitRadius");
70 ACTION_SET_LOCAL_NAME(Action::BLinePointTangentSplitRadius,N_("Split Tangents's Radius"));
71 ACTION_SET_TASK(Action::BLinePointTangentSplitRadius,"type_vector");
72 ACTION_SET_CATEGORY(Action::BLinePointTangentSplitRadius,Action::CATEGORY_VALUENODE);
73 ACTION_SET_PRIORITY(Action::BLinePointTangentSplitRadius,0);
74 ACTION_SET_VERSION(Action::BLinePointTangentSplitRadius,"0.0");
75 ACTION_SET_CVS_ID(Action::BLinePointTangentSplitRadius,"$Id$");
76
77 ACTION_INIT_NO_GET_LOCAL_NAME(Action::BLinePointTangentSplitAngle);
78 ACTION_SET_NAME(Action::BLinePointTangentSplitAngle,"BLinePointTangentSplitAngle");
79 ACTION_SET_LOCAL_NAME(Action::BLinePointTangentSplitAngle,N_("Split Tangents's Angle"));
80 ACTION_SET_TASK(Action::BLinePointTangentSplitAngle,"type_angle");
81 ACTION_SET_CATEGORY(Action::BLinePointTangentSplitAngle,Action::CATEGORY_VALUENODE);
82 ACTION_SET_PRIORITY(Action::BLinePointTangentSplitAngle,0);
83 ACTION_SET_VERSION(Action::BLinePointTangentSplitAngle,"0.0");
84 ACTION_SET_CVS_ID(Action::BLinePointTangentSplitAngle,"$Id$");
85
86 /* === G L O B A L S ======================================================= */
87
88 /* === P R O C E D U R E S ================================================= */
89
90 /* === M E T H O D S ======================================================= */
91
92
93 //// BLINEPOINT TANGENT SPLIT //////////
BLinePointTangentSplit()94 Action::BLinePointTangentSplit::BLinePointTangentSplit()
95 {
96 time=(Time::begin()-1);
97 set_dirty(true);
98 }
99
100 synfig::String
get_local_name() const101 Action::BLinePointTangentSplit::get_local_name()const
102 {
103 return strprintf(_("Split Tangents of '%s'"), ((ValueNode::Handle)(value_node))->get_description().c_str());
104 }
105
106 Action::ParamVocab
get_param_vocab()107 Action::BLinePointTangentSplit::get_param_vocab()
108 {
109 ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
110 ret.push_back(ParamDesc("value_node",Param::TYPE_VALUENODE)
111 .set_local_name(_("ValueNode of Spline Point"))
112 );
113 ret.push_back(ParamDesc("time",Param::TYPE_TIME)
114 .set_local_name(_("Time"))
115 );
116 return ret;
117 }
118
119 bool
is_candidate(const ParamList & x)120 Action::BLinePointTangentSplit::is_candidate(const ParamList &x)
121 {
122 if(candidate_check(get_param_vocab(),x))
123 {
124 ValueNode_Composite::Handle value_node;
125 value_node=ValueNode_Composite::Handle::cast_dynamic(x.find("value_node")->second.get_value_node());
126 if(!value_node || value_node->get_type()!=type_bline_point)
127 {
128 // Before return false, let's check whether the value_node
129 // is radial composite and vector type
130 ValueNode_RadialComposite::Handle radial_value_node;
131 radial_value_node=ValueNode_RadialComposite::Handle::cast_dynamic(x.find("value_node")->second.get_value_node());
132 if(radial_value_node && radial_value_node->get_type()==type_vector)
133 // value_node is radial composite and vector (user rigth click on a tangent)
134 {
135 ValueNode_Composite::Handle blinepoint=NULL;
136 std::set<Node*>::iterator iter;
137 // now check if the parent of radial_value_node is a blinepoint type
138 for(iter=radial_value_node->parent_set.begin();iter!=radial_value_node->parent_set.end();++iter)
139 {
140 blinepoint=ValueNode_Composite::Handle::cast_dynamic(*iter);
141 if(blinepoint && blinepoint->get_type()==type_bline_point)
142 break;
143 }
144 if(blinepoint)
145 value_node=blinepoint;
146 }
147 }
148 // at this point we should have a value node and it should be blinepoint
149 // if we haven't, then return false
150 if(!value_node || value_node->get_type()!=type_bline_point)
151 return false;
152 synfig::Time time(x.find("time")->second.get_time());
153 bool split_radius=(*value_node->get_link("split_radius"))(time).get(bool());
154 bool split_angle=(*value_node->get_link("split_angle"))(time).get(bool());
155 if(split_radius==true && split_angle==true)
156 return false;
157 return true;
158 }
159 return false;
160 }
161
162 bool
set_param(const synfig::String & name,const Action::Param & param)163 Action::BLinePointTangentSplit::set_param(const synfig::String& name, const Action::Param ¶m)
164 {
165 if(name=="value_node" && param.get_type()==Param::TYPE_VALUENODE)
166 {
167 value_node=value_node.cast_dynamic(param.get_value_node());
168 if(value_node && value_node->get_type()==type_bline_point)
169 return true;
170 ValueNode_RadialComposite::Handle radial_value_node;
171 radial_value_node=ValueNode_RadialComposite::Handle::cast_dynamic(param.get_value_node());
172 if(radial_value_node && radial_value_node->get_type()==type_vector)
173 // value_node is radial composite and vector (user rigth click on a tangent)
174 {
175 ValueNode_Composite::Handle blinepoint;
176 std::set<Node*>::iterator iter;
177 // now check if the parent of value_node is a blinepoint type
178 for(iter=radial_value_node->parent_set.begin();iter!=radial_value_node->parent_set.end();++iter)
179 {
180 blinepoint=ValueNode_Composite::Handle::cast_dynamic(*iter);
181 if(blinepoint && blinepoint->get_type()==type_bline_point)
182 {
183 value_node=blinepoint;
184 return true;
185 }
186 }
187 return false;
188 }
189 return false;
190 }
191 if(name=="time" && param.get_type()==Param::TYPE_TIME)
192 {
193 time=param.get_time();
194 return true;
195 }
196 return Action::CanvasSpecific::set_param(name,param);
197 }
198
199 bool
is_ready() const200 Action::BLinePointTangentSplit::is_ready()const
201 {
202 if(!value_node)
203 synfig::error("Missing or bad value_node");
204 if(time==(Time::begin()-1))
205 synfig::error("Missing time");
206 if(!value_node || time==(Time::begin()-1))
207 return false;
208 return Action::CanvasSpecific::is_ready();
209 }
210
211 void
prepare()212 Action::BLinePointTangentSplit::prepare()
213 {
214 clear();
215 {
216 Action::Handle action;
217 action=Action::create("ValueDescSet");
218 if(!action)
219 throw Error(_("Couldn't find action \"ValueDescSet\""));
220 action->set_param("canvas",get_canvas());
221 action->set_param("canvas_interface",get_canvas_interface());
222 action->set_param("value_desc",ValueDesc(value_node,value_node->get_link_index_from_name("split_radius")));
223 action->set_param("time",time);
224 action->set_param("new_value",synfig::ValueBase(true));
225 assert(action->is_ready());
226 if(!action->is_ready())
227 throw Error(Error::TYPE_NOTREADY);
228 add_action(action);
229 }
230 {
231 Action::Handle action;
232 action=Action::create("ValueDescSet");
233 if(!action)
234 throw Error(_("Couldn't find action \"ValueDescSet\""));
235 action->set_param("canvas",get_canvas());
236 action->set_param("canvas_interface",get_canvas_interface());
237 action->set_param("value_desc",ValueDesc(value_node,value_node->get_link_index_from_name("split_angle")));
238 action->set_param("time",time);
239 action->set_param("new_value",synfig::ValueBase(true));
240 assert(action->is_ready());
241 if(!action->is_ready())
242 throw Error(Error::TYPE_NOTREADY);
243 add_action(action);
244 }
245 }
246
247
248 //// BLINEPOINT TANGENT SPLIT RADIUS //////////
BLinePointTangentSplitRadius()249 Action::BLinePointTangentSplitRadius::BLinePointTangentSplitRadius()
250 {
251 time=(Time::begin()-1);
252 set_dirty(true);
253 }
254
255 synfig::String
get_local_name() const256 Action::BLinePointTangentSplitRadius::get_local_name()const
257 {
258 return strprintf(_("Split Tangents's Radius of '%s'"), ((ValueNode::Handle)(value_node))->get_description().c_str());
259 }
260
261 Action::ParamVocab
get_param_vocab()262 Action::BLinePointTangentSplitRadius::get_param_vocab()
263 {
264 ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
265 ret.push_back(ParamDesc("value_node",Param::TYPE_VALUENODE)
266 .set_local_name(_("ValueNode of Spline Point"))
267 );
268 ret.push_back(ParamDesc("time",Param::TYPE_TIME)
269 .set_local_name(_("Time"))
270 );
271 return ret;
272 }
273
274 bool
is_candidate(const ParamList & x)275 Action::BLinePointTangentSplitRadius::is_candidate(const ParamList &x)
276 {
277 if(candidate_check(get_param_vocab(),x))
278 {
279 ValueNode_Composite::Handle value_node;
280 value_node=ValueNode_Composite::Handle::cast_dynamic(x.find("value_node")->second.get_value_node());
281 if(!value_node || value_node->get_type()!=type_bline_point)
282 {
283 // Before return false, let's check whether the value_node
284 // is radial composite and vector type
285 ValueNode_RadialComposite::Handle radial_value_node;
286 radial_value_node=ValueNode_RadialComposite::Handle::cast_dynamic(x.find("value_node")->second.get_value_node());
287 if(radial_value_node && radial_value_node->get_type()==type_vector)
288 // value_node is radial composite and vector (user rigth click on a tangent)
289 {
290 ValueNode_Composite::Handle blinepoint=NULL;
291 std::set<Node*>::iterator iter;
292 // now check if the parent of radial_value_node is a blinepoint type
293 for(iter=radial_value_node->parent_set.begin();iter!=radial_value_node->parent_set.end();++iter)
294 {
295 blinepoint=ValueNode_Composite::Handle::cast_dynamic(*iter);
296 if(blinepoint && blinepoint->get_type()==type_bline_point)
297 break;
298 }
299 if(blinepoint)
300 value_node=blinepoint;
301 }
302 }
303 // at this point we should have a value node and it should be blinepoint
304 // if we haven't, then return false
305 if(!value_node || value_node->get_type()!=type_bline_point)
306 return false;
307 synfig::Time time(x.find("time")->second.get_time());
308 bool split_radius=(*value_node->get_link("split_radius"))(time).get(bool());
309 if(split_radius==true)
310 return false;
311 return true;
312 }
313 return false;
314 }
315
316 bool
set_param(const synfig::String & name,const Action::Param & param)317 Action::BLinePointTangentSplitRadius::set_param(const synfig::String& name, const Action::Param ¶m)
318 {
319 if(name=="value_node" && param.get_type()==Param::TYPE_VALUENODE)
320 {
321 value_node=value_node.cast_dynamic(param.get_value_node());
322 if(value_node && value_node->get_type()==type_bline_point)
323 return true;
324 ValueNode_RadialComposite::Handle radial_value_node;
325 radial_value_node=ValueNode_RadialComposite::Handle::cast_dynamic(param.get_value_node());
326 if(radial_value_node && radial_value_node->get_type()==type_vector)
327 // value_node is radial composite and vector (user rigth click on a tangent)
328 {
329 ValueNode_Composite::Handle blinepoint;
330 std::set<Node*>::iterator iter;
331 // now check if the parent of value_node is a blinepoint type
332 for(iter=radial_value_node->parent_set.begin();iter!=radial_value_node->parent_set.end();++iter)
333 {
334 blinepoint=ValueNode_Composite::Handle::cast_dynamic(*iter);
335 if(blinepoint && blinepoint->get_type()==type_bline_point)
336 {
337 value_node=blinepoint;
338 return true;
339 }
340 }
341 return false;
342 }
343 return false;
344 }
345 if(name=="time" && param.get_type()==Param::TYPE_TIME)
346 {
347 time=param.get_time();
348 return true;
349 }
350 return Action::CanvasSpecific::set_param(name,param);
351 }
352
353 bool
is_ready() const354 Action::BLinePointTangentSplitRadius::is_ready()const
355 {
356 if(!value_node)
357 synfig::error("Missing or bad value_node");
358 if(time==(Time::begin()-1))
359 synfig::error("Missing time");
360 if(!value_node || time==(Time::begin()-1))
361 return false;
362 return Action::CanvasSpecific::is_ready();
363 }
364
365 void
prepare()366 Action::BLinePointTangentSplitRadius::prepare()
367 {
368 clear();
369 {
370 Action::Handle action;
371 action=Action::create("ValueDescSet");
372 if(!action)
373 throw Error(_("Couldn't find action \"ValueDescSet\""));
374 action->set_param("canvas",get_canvas());
375 action->set_param("canvas_interface",get_canvas_interface());
376 action->set_param("value_desc",ValueDesc(value_node,value_node->get_link_index_from_name("split_radius")));
377 action->set_param("time",time);
378 action->set_param("new_value",synfig::ValueBase(true));
379 assert(action->is_ready());
380 if(!action->is_ready())
381 throw Error(Error::TYPE_NOTREADY);
382 add_action(action);
383 }
384 }
385
386 //// BLINEPOINT TANGENT SPLIT ANGLE //////////
BLinePointTangentSplitAngle()387 Action::BLinePointTangentSplitAngle::BLinePointTangentSplitAngle()
388 {
389 time=(Time::begin()-1);
390 set_dirty(true);
391 }
392
393 synfig::String
get_local_name() const394 Action::BLinePointTangentSplitAngle::get_local_name()const
395 {
396 return strprintf(_("Split Tangents's Angle of '%s'"), ((ValueNode::Handle)(value_node))->get_description().c_str());
397 }
398
399 Action::ParamVocab
get_param_vocab()400 Action::BLinePointTangentSplitAngle::get_param_vocab()
401 {
402 ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
403 ret.push_back(ParamDesc("value_node",Param::TYPE_VALUENODE)
404 .set_local_name(_("ValueNode of Spline Point"))
405 );
406 ret.push_back(ParamDesc("time",Param::TYPE_TIME)
407 .set_local_name(_("Time"))
408 );
409 return ret;
410 }
411
412 bool
is_candidate(const ParamList & x)413 Action::BLinePointTangentSplitAngle::is_candidate(const ParamList &x)
414 {
415 if(candidate_check(get_param_vocab(),x))
416 {
417 ValueNode_Composite::Handle value_node;
418 value_node=ValueNode_Composite::Handle::cast_dynamic(x.find("value_node")->second.get_value_node());
419 if(!value_node || value_node->get_type()!=type_bline_point)
420 {
421 // Before return false, let's check whether the value_node
422 // is radial composite and vector type
423 ValueNode_RadialComposite::Handle radial_value_node;
424 radial_value_node=ValueNode_RadialComposite::Handle::cast_dynamic(x.find("value_node")->second.get_value_node());
425 if(radial_value_node && radial_value_node->get_type()==type_vector)
426 // value_node is radial composite and vector (user rigth click on a tangent)
427 {
428 ValueNode_Composite::Handle blinepoint=NULL;
429 std::set<Node*>::iterator iter;
430 // now check if the parent of radial_value_node is a blinepoint type
431 for(iter=radial_value_node->parent_set.begin();iter!=radial_value_node->parent_set.end();++iter)
432 {
433 blinepoint=ValueNode_Composite::Handle::cast_dynamic(*iter);
434 if(blinepoint && blinepoint->get_type()==type_bline_point)
435 break;
436 }
437 if(blinepoint)
438 value_node=blinepoint;
439 }
440 }
441 // at this point we should have a value node and it should be blinepoint
442 // if we haven't, then return false
443 if(!value_node || value_node->get_type()!=type_bline_point)
444 return false;
445 synfig::Time time(x.find("time")->second.get_time());
446 bool split_angle=(*value_node->get_link("split_angle"))(time).get(bool());
447 if(split_angle==true)
448 return false;
449 return true;
450 }
451 return false;
452 }
453
454 bool
set_param(const synfig::String & name,const Action::Param & param)455 Action::BLinePointTangentSplitAngle::set_param(const synfig::String& name, const Action::Param ¶m)
456 {
457 if(name=="value_node" && param.get_type()==Param::TYPE_VALUENODE)
458 {
459 value_node=value_node.cast_dynamic(param.get_value_node());
460 if(value_node && value_node->get_type()==type_bline_point)
461 return true;
462 ValueNode_RadialComposite::Handle radial_value_node;
463 radial_value_node=ValueNode_RadialComposite::Handle::cast_dynamic(param.get_value_node());
464 if(radial_value_node && radial_value_node->get_type()==type_vector)
465 // value_node is radial composite and vector (user rigth click on a tangent)
466 {
467 ValueNode_Composite::Handle blinepoint;
468 std::set<Node*>::iterator iter;
469 // now check if the parent of value_node is a blinepoint type
470 for(iter=radial_value_node->parent_set.begin();iter!=radial_value_node->parent_set.end();++iter)
471 {
472 blinepoint=ValueNode_Composite::Handle::cast_dynamic(*iter);
473 if(blinepoint && blinepoint->get_type()==type_bline_point)
474 {
475 value_node=blinepoint;
476 return true;
477 }
478 }
479 return false;
480 }
481 return false;
482 }
483 if(name=="time" && param.get_type()==Param::TYPE_TIME)
484 {
485 time=param.get_time();
486 return true;
487 }
488 return Action::CanvasSpecific::set_param(name,param);
489 }
490
491 bool
is_ready() const492 Action::BLinePointTangentSplitAngle::is_ready()const
493 {
494 if(!value_node)
495 synfig::error("Missing or bad value_node");
496 if(time==(Time::begin()-1))
497 synfig::error("Missing time");
498 if(!value_node || time==(Time::begin()-1))
499 return false;
500 return Action::CanvasSpecific::is_ready();
501 }
502
503 void
prepare()504 Action::BLinePointTangentSplitAngle::prepare()
505 {
506 clear();
507 {
508 Action::Handle action;
509 action=Action::create("ValueDescSet");
510 if(!action)
511 throw Error(_("Couldn't find action \"ValueDescSet\""));
512 action->set_param("canvas",get_canvas());
513 action->set_param("canvas_interface",get_canvas_interface());
514 action->set_param("value_desc",ValueDesc(value_node,value_node->get_link_index_from_name("split_angle")));
515 action->set_param("time",time);
516 action->set_param("new_value",synfig::ValueBase(true));
517 assert(action->is_ready());
518 if(!action->is_ready())
519 throw Error(Error::TYPE_NOTREADY);
520 add_action(action);
521 }
522 }
523