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 &param)
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 &param)
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 &param)
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