1 /* === S Y N F I G ========================================================= */
2 /*!	\file canvasinterface.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 Carlos A. Sosa Navarro
11 **  Copyright (c) 2011 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 <ETL/clock>
36 
37 #include <synfig/general.h>
38 
39 #include <synfig/canvasfilenaming.h>
40 #include <synfig/context.h>
41 #include <synfig/gradient.h>
42 #include <synfig/guidset.h>
43 #include <synfig/importer.h>
44 #include <synfig/loadcanvas.h>
45 #include <synfig/bone.h>
46 #include <synfig/pair.h>
47 #include <synfig/waypoint.h>
48 #include <synfig/valuenode_registry.h>
49 
50 #include <synfig/layers/layer_pastecanvas.h>
51 
52 #include <synfig/valuenodes/valuenode_animatedfile.h>
53 #include <synfig/valuenodes/valuenode_bline.h>
54 #include <synfig/valuenodes/valuenode_linear.h>
55 #include <synfig/valuenodes/valuenode_composite.h>
56 #include <synfig/valuenodes/valuenode_dilist.h>
57 #include <synfig/valuenodes/valuenode_reference.h>
58 #include <synfig/valuenodes/valuenode_scale.h>
59 #include <synfig/valuenodes/valuenode_stripes.h>
60 #include <synfig/valuenodes/valuenode_subtract.h>
61 #include <synfig/valuenodes/valuenode_timedswap.h>
62 #include <synfig/valuenodes/valuenode_twotone.h>
63 #include <synfig/valuenodes/valuenode_wplist.h>
64 
65 #include <synfigapp/localization.h>
66 
67 #include "action_system.h"
68 #include "canvasinterface.h"
69 #include "instance.h"
70 #include "main.h"
71 
72 #include "actions/editmodeset.h"
73 #include "actions/layeradd.h"
74 #include "actions/layerremove.h"
75 #include "actions/valuedescconvert.h"
76 #include "actions/valuenodeadd.h"
77 
78 #endif
79 
80 /* === U S I N G =========================================================== */
81 
82 using namespace std;
83 using namespace etl;
84 using namespace synfig;
85 using namespace synfigapp;
86 
87 /* === M A C R O S ========================================================= */
88 
89 /* === G L O B A L S ======================================================= */
90 
91 /* === P R O C E D U R E S ================================================= */
92 
93 /* === M E T H O D S ======================================================= */
94 
CanvasInterface(etl::loose_handle<Instance> instance,etl::handle<synfig::Canvas> canvas)95 CanvasInterface::CanvasInterface(etl::loose_handle<Instance> instance,etl::handle<synfig::Canvas> canvas):
96 	instance_(instance),
97 	canvas_(canvas),
98 	cur_time_(canvas->rend_desc().get_frame_start()),
99 	mode_(MODE_NORMAL|MODE_ANIMATE_PAST|MODE_ANIMATE_FUTURE)
100 {
101 	set_selection_manager(get_instance()->get_selection_manager());
102 	set_ui_interface(get_instance()->get_ui_interface());
103 }
104 
~CanvasInterface()105 CanvasInterface::~CanvasInterface()
106 {
107 	if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
108 		synfig::info("CanvasInterface::~CanvasInterface(): Deleted");
109 }
110 
111 void
set_time(synfig::Time x)112 CanvasInterface::set_time(synfig::Time x)
113 {
114 	if(get_canvas()->rend_desc().get_frame_rate())
115 	{
116 		float fps(get_canvas()->rend_desc().get_frame_rate());
117 		Time r(x.round(fps));
118 		//synfig::info("CanvasInterface::set_time(): %s rounded to %s\n",x.get_string(fps).c_str(),r.get_string(fps).c_str());
119 		x=r;
120 	}
121 	if(cur_time_.is_equal(x))
122 		return;
123 	get_canvas()->set_time(cur_time_=x);
124 
125 	// update the time in all the child canvases
126 	Canvas::Children children = get_canvas()->get_root()->children();
127 	handle<CanvasInterface> interface;
128 	for (Canvas::Children::iterator iter = children.begin(); iter != children.end(); iter++)
129 		if ((interface = get_instance()->find_canvas_interface(*iter)) != this)
130 			interface->set_time(interface->get_canvas()->get_time());
131 
132 	signal_time_changed()();
133 	signal_dirty_preview()();
134 }
135 
136 synfig::Time
get_time() const137 CanvasInterface::get_time()const
138 {
139 	return cur_time_;
140 }
141 
142 void
refresh_current_values()143 CanvasInterface::refresh_current_values()
144 {
145 	get_canvas()->set_time(cur_time_);
146 	signal_time_changed()();
147 	signal_dirty_preview()();
148 }
149 
150 etl::handle<CanvasInterface>
create(etl::loose_handle<Instance> instance,etl::handle<synfig::Canvas> canvas)151 CanvasInterface::create(etl::loose_handle<Instance> instance, etl::handle<synfig::Canvas> canvas)
152 {
153 	etl::handle<CanvasInterface> intrfc;
154 	intrfc=new CanvasInterface(instance,canvas);
155 	instance->canvas_interface_list().push_front(intrfc);
156 	return intrfc;
157 }
158 
159 void
set_mode(Mode x)160 CanvasInterface::set_mode(Mode x)
161 {
162 	Action::Handle 	action(Action::EditModeSet::create());
163 
164 	assert(action);
165 
166 	action->set_param("canvas",get_canvas());
167 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
168 	action->set_param("edit_mode",x);
169 
170 	if(!action->is_ready())
171 	{
172 		get_ui_interface()->error(_("Action Not Ready, unable to change mode"));
173 		assert(0);
174 		return;
175 	}
176 
177 	if(!get_instance()->perform_action(action))
178 		get_ui_interface()->error(_("Unable to change mode"));
179 
180 //	mode_=x;
181 //	signal_mode_changed_(x);
182 }
183 
184 CanvasInterface::Mode
get_mode() const185 CanvasInterface::get_mode()const
186 {
187 	return mode_;
188 }
189 
190 synfig::Layer::Handle
layer_create(const synfig::String & id,const synfig::Canvas::Handle & canvas)191 CanvasInterface::layer_create(
192 	const synfig::String &id,
193 	const synfig::Canvas::Handle &canvas )
194 {
195 	Layer::Handle layer = Layer::create(id);
196 	assert(layer);
197 	if (!layer)
198 		return Layer::Handle();
199 
200 	if (canvas!=get_canvas() && !canvas->is_inline())
201 	{
202 		synfig::error("Bad canvas passed to \"layer_create\"");
203 		return 0;
204 	}
205 
206 	// automatically export the Index parameter of new Duplicate layers
207 	if (id == "duplicate")
208 		for (int i = 1; ; i++)
209 		{
210 			String name = strprintf(_("Index %d"), i);
211 			try
212 			{
213 				canvas->find_value_node(name, true);
214 			}
215 			catch (Exception::IDNotFound x)
216 			{
217 				add_value_node(layer->dynamic_param_list().find("index")->second, id);
218 				break;
219 			}
220 		}
221 
222 	layer->set_canvas(canvas);
223 	if (etl::handle<Layer_PasteCanvas>::cast_dynamic(layer))
224 		layer->set_param("canvas", Canvas::create_inline(canvas));
225 
226 	return layer;
227 }
228 
229 void
layer_set_defaults(const synfig::Layer::Handle & layer)230 CanvasInterface::layer_set_defaults(const synfig::Layer::Handle &layer)
231 {
232 	if (!layer || !layer->get_canvas())
233 		return;
234 
235 	synfig::Canvas::Handle canvas = layer->get_canvas();
236 	synfig::String name(layer->get_name());
237 
238 	ValueBase p;
239 	p=layer->get_param("fg");
240 	p.set(synfigapp::Main::get_outline_color());
241 	if(layer->set_param("fg",p))
242 	{
243 		p=layer->get_param("bg");
244 		p.set(synfigapp::Main::get_outline_color());
245 		layer->set_param("bg",p);
246 	}
247 	else if (name == "outline" || name == "advanced_outline")
248 	{
249 		p=layer->get_param("color");
250 		p.set(synfigapp::Main::get_outline_color());
251 		layer->set_param("color",p);
252 	}
253 	else
254 	{
255 		p=layer->get_param("color");
256 		p.set(synfigapp::Main::get_fill_color());
257 		layer->set_param("color",p);
258 	}
259 	// by default, new advanced outline layers are not homogeneous
260 	if(name=="advanced_outline")
261 	{
262 		p=layer->get_param("homogeneous");
263 		p.set(false);
264 		layer->set_param("homogeneous",p);
265 	}
266 	p=layer->get_param("width");
267 	p.set(synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc()));
268 	layer->set_param("width",p);
269 
270 	p=layer->get_param("gradient");
271 	p.set(synfigapp::Main::get_gradient());
272 	layer->set_param("gradient",p);
273 
274 	if(synfigapp::Main::get_blend_method() != Color::BLEND_BY_LAYER)
275 	{
276 		p=layer->get_param("blend_method");
277 		p.set((int)synfigapp::Main::get_blend_method());
278 		layer->set_param("blend_method",p);
279 	}
280 
281 
282 	{
283 		// Grab the layer's list of parameters
284 		Layer::ParamList paramlist=layer->get_param_list();
285 		Layer::ParamList::iterator iter;
286 
287 		// loop through the static parameters
288 		for(iter=paramlist.begin();iter!=paramlist.end();++iter)
289 		{
290 			ValueNode::Handle value_node;
291 
292 			// if we find any which are list values then make them
293 			// into dynamic list valuenodes, unless every element of
294 			// the list is a blinepoint, in which case convert it to a
295 			// bline
296 			if(iter->second.get_type()==type_list)
297 			{
298 				// check whether it's a list of blinepoints or widthpoints only
299 				vector<ValueBase> list(iter->second.get_list());
300 				if (list.size())
301 				{
302 					vector<ValueBase>::iterator iter2 = list.begin();
303 					Type &type(iter2->get_type());
304 					for (iter2++; iter2 != list.end(); iter2++)
305 						if (iter2->get_type() != type)
306 							break;
307 					if (iter2 == list.end())
308 					{
309 						if (type == type_bline_point)
310 						{
311 							value_node=ValueNodeRegistry::create("bline",iter->second);
312 							ValueNode_BLine::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
313 						}
314 						else
315 						if (type == type_bone_object)
316 						{
317 							if (getenv("SYNFIG_USE_DYNAMIC_LIST_FOR_BONES"))
318 							{
319 								value_node=ValueNodeRegistry::create("dynamic_list",iter->second);
320 								ValueNode_DynamicList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
321 							}
322 							else // this is the default
323 							{
324 								value_node=ValueNodeRegistry::create("static_list",iter->second);
325 								ValueNode_StaticList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
326 							}
327 						}
328 						else
329 						if (type == types_namespace::TypePair<Bone, Bone>::instance)
330 						{
331 							if (getenv("SYNFIG_USE_DYNAMIC_LIST_FOR_BONES"))
332 							{
333 								value_node=ValueNodeRegistry::create("dynamic_list",iter->second);
334 								ValueNode_DynamicList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
335 							}
336 							else // this is the default
337 							{
338 								value_node=ValueNodeRegistry::create("static_list",iter->second);
339 								ValueNode_StaticList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
340 							}
341 						}
342 						else
343 						if (type == type_vector)
344 						{
345 							if (getenv("SYNFIG_USE_STATIC_LIST_FOR_VECTORS"))
346 							{
347 								value_node=ValueNodeRegistry::create("static_list",iter->second);
348 								ValueNode_StaticList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
349 							}
350 							else // this is the default
351 							{
352 								value_node=ValueNodeRegistry::create("dynamic_list",iter->second);
353 								ValueNode_DynamicList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
354 							}
355 						}
356 					}
357 					for (iter2 = list.begin(); iter2 != list.end(); iter2++)
358 						if (iter2->get_type() != type_width_point)
359 							break;
360 					if (iter2 == list.end())
361 					{
362 						value_node=ValueNodeRegistry::create("wplist",iter->second);
363 						ValueNode_WPList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
364 					}
365 					for (iter2 = list.begin(); iter2 != list.end(); iter2++)
366 						if (iter2->get_type() != type_dash_item)
367 							break;
368 					if (iter2 == list.end())
369 					{
370 						value_node=ValueNodeRegistry::create("dilist",iter->second);
371 						ValueNode_DIList::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
372 					}
373 				}
374 				// it has something else so just insert the dynamic list
375 				if (!value_node)
376 					value_node=ValueNodeRegistry::create("dynamic_list",iter->second);
377 			}
378 			// otherwise, if it's a type that can be converted to
379 			// 'composite' (other than the types that can be radial
380 			// composite) then do so
381 			else if (ValueNodeRegistry::check_type("composite",iter->second.get_type()) &&
382 					 (iter->second.get_type()!=type_color &&
383 					  iter->second.get_type()!=type_vector))
384 				value_node=ValueNodeRegistry::create("composite",iter->second);
385 
386 			if(value_node)
387 				layer->connect_dynamic_param(iter->first,value_node);
388 		}
389 	}
390 }
391 
392 bool
layer_add_action(const synfig::Layer::Handle & layer)393 CanvasInterface::layer_add_action(const synfig::Layer::Handle &layer)
394 {
395 	if (!layer || !layer->get_canvas())
396 		{ assert(false); return false; }
397 
398 	Action::Handle action(Action::LayerAdd::create());
399 	if (!action)
400 		{ assert(false); return false; }
401 
402 	action->set_param("canvas", layer->get_canvas());
403 	action->set_param("canvas_interface", etl::loose_handle<CanvasInterface>(this));
404 	action->set_param("new", layer);
405 
406 	if(!action->is_ready())
407 		{ get_ui_interface()->error(_("Action Not Ready")); return false; }
408 	if(!get_instance()->perform_action(action))
409 		{ get_ui_interface()->error(_("Action Failed.")); return false; }
410 
411 	return true;
412 }
413 
414 bool
layer_move_action(const synfig::Layer::Handle & layer,int depth)415 CanvasInterface::layer_move_action(const synfig::Layer::Handle &layer, int depth)
416 {
417 	if (!layer || !layer->get_canvas())
418 		{ assert(false); return false; }
419 
420 	Action::Handle action(Action::create("LayerMove"));
421 	if (!action)
422 		{ assert(false); return false; }
423 
424 	action->set_param("canvas", layer->get_canvas());
425 	action->set_param("canvas_interface", etl::loose_handle<CanvasInterface>(this));
426 	action->set_param("layer", layer);
427 	action->set_param("new_index", depth);
428 
429 	if (!action->is_ready())
430 		{ get_ui_interface()->error(_("Move Action Not Ready")); return false; }
431 	if (!get_instance()->perform_action(action))
432 		{ get_ui_interface()->error(_("Move Action Failed.")); return false; }
433 
434 	return true;
435 }
436 
437 Layer::Handle
add_layer_to(const synfig::String & id,const synfig::Canvas::Handle & canvas,int depth)438 CanvasInterface::add_layer_to(const synfig::String &id, const synfig::Canvas::Handle &canvas, int depth)
439 {
440 	synfigapp::Action::PassiveGrouper group(get_instance().get(),_("Add Layer To"));
441 
442 	Layer::Handle layer = layer_create(id, canvas);
443 	if (!layer) return Layer::Handle();
444 
445 	layer_set_defaults(layer);
446 	layer_add_action(layer);
447 	if (depth != 0)
448 		layer_move_action(layer, depth);
449 
450 	return layer;
451 }
452 
453 bool
convert(ValueDesc value_desc,synfig::String type)454 CanvasInterface::convert(ValueDesc value_desc, synfig::String type)
455 {
456 	Action::Handle 	action(Action::ValueDescConvert::create());
457 
458 	assert(action);
459 	if(!action)
460 		return 0;
461 
462 	action->set_param("canvas",get_canvas());
463 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
464 	action->set_param("value_desc",value_desc);
465 	action->set_param("type",type);
466 	action->set_param("time",get_time());
467 
468 	if(!action->is_ready())
469 	{
470 		get_ui_interface()->error(_("Action Not Ready"));
471 		return 0;
472 	}
473 
474 	if(get_instance()->perform_action(action))
475 		return true;
476 
477 	get_ui_interface()->error(_("Action Failed."));
478 	return false;
479 }
480 
481 bool
add_value_node(synfig::ValueNode::Handle value_node,synfig::String name)482 CanvasInterface::add_value_node(synfig::ValueNode::Handle value_node, synfig::String name)
483 {
484 	if(name.empty())
485 	{
486 		get_ui_interface()->error(_("Empty name!"));
487 		return false;
488 	}
489 
490 	Action::Handle 	action(Action::ValueNodeAdd::create());
491 
492 	assert(action);
493 	if(!action)
494 		return 0;
495 
496 	action->set_param("canvas",get_canvas());
497 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
498 	action->set_param("new",value_node);
499 	action->set_param("name",name);
500 
501 	if(!action->is_ready())
502 	{
503 		get_ui_interface()->error(_("Action Not Ready"));
504 		return 0;
505 	}
506 
507 	if(get_instance()->perform_action(action))
508 		return true;
509 
510 	get_ui_interface()->error(_("Action Failed."));
511 	return false;
512 }
513 
514 Action::ParamList
generate_param_list(const ValueDesc & value_desc)515 CanvasInterface::generate_param_list(const ValueDesc &value_desc)
516 {
517 	synfigapp::Action::ParamList param_list;
518 	param_list.add("time",get_time());
519 	param_list.add("canvas_interface",etl::handle<CanvasInterface>(this));
520 	param_list.add("canvas",get_canvas());
521 
522 	param_list.add("value_desc",value_desc);
523 
524 	if(value_desc.parent_is_value_node())
525 		param_list.add("parent_value_node",value_desc.get_parent_value_node());
526 
527 	if(value_desc.is_value_node())
528 		param_list.add("value_node",value_desc.get_value_node());
529 
530 	if(value_desc.is_const())
531 	{
532 		// Fix 1868911: if we put a ValueBase holding a Canvas handle
533 		// into the param_list and then export the canvas, the handle
534 		// will miss out of having its reference count reduced,
535 		// because by the time the handle is destructed the canvas
536 		// will no longer be inline.  So let's not propogate that
537 		// ValueBase any further than here.
538 		if (value_desc.get_value_type() == type_canvas)
539 			param_list.add("value",Canvas::LooseHandle(value_desc.get_value().get(Canvas::LooseHandle())));
540 		else
541 			param_list.add("value",value_desc.get_value());
542 	}
543 
544 	if(value_desc.parent_is_layer())
545 	{
546 		param_list.add("parent_layer",value_desc.get_layer());
547 		param_list.add("parent_layer_param",value_desc.get_param_name());
548 	}
549 
550 	{
551 		synfigapp::SelectionManager::ChildrenList children_list;
552 		children_list=get_selection_manager()->get_selected_children();
553 		if(!value_desc.parent_is_canvas() && children_list.size()==1)
554 		{
555 			param_list.add("dest",value_desc);
556 			param_list.add("src",children_list.front().get_value_node());
557 		}
558 	}
559 	return param_list;
560 }
561 
562 Action::ParamList
generate_param_list(const std::list<synfigapp::ValueDesc> & value_desc_list)563 CanvasInterface::generate_param_list(const std::list<synfigapp::ValueDesc> &value_desc_list)
564 {
565 	synfigapp::Action::ParamList param_list;
566 	param_list.add("time",get_time());
567 	param_list.add("canvas_interface",etl::handle<CanvasInterface>(this));
568 	param_list.add("canvas",get_canvas());
569 
570 	std::list<synfigapp::ValueDesc>::const_iterator iter;
571 	for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
572 	{
573 		param_list.add("value_desc",*iter);
574 		if(iter->is_value_node())
575 		{
576 			param_list.add("value_node",iter->get_value_node());
577 		}
578 	}
579 
580 
581 	return param_list;
582 }
583 
584 void
set_rend_desc(const synfig::RendDesc & rend_desc)585 CanvasInterface::set_rend_desc(const synfig::RendDesc &rend_desc)
586 {
587 	Action::Handle 	action(Action::create("CanvasRendDescSet"));
588 
589 	assert(action);
590 	if(!action)
591 		return;
592 
593 	action->set_param("canvas",get_canvas());
594 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
595 	action->set_param("rend_desc",rend_desc);
596 
597 	if(!get_instance()->perform_action(action))
598 		get_ui_interface()->error(_("Action Failed."));
599 }
600 
601 void
set_name(const synfig::String & x)602 CanvasInterface::set_name(const synfig::String &x)
603 {
604 	Action::Handle 	action(Action::create("CanvasNameSet"));
605 
606 	assert(action);
607 	if(!action)
608 		return;
609 
610 	action->set_param("canvas",get_canvas());
611 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
612 	action->set_param("name",x);
613 
614 	if(!get_instance()->perform_action(action))
615 		get_ui_interface()->error(_("Action Failed."));
616 
617 	signal_id_changed_();
618 }
619 
620 void
set_description(const synfig::String & x)621 CanvasInterface::set_description(const synfig::String &x)
622 {
623 	Action::Handle 	action(Action::create("CanvasDescriptionSet"));
624 
625 	assert(action);
626 	if(!action)
627 		return;
628 
629 	action->set_param("canvas",get_canvas());
630 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
631 	action->set_param("description",x);
632 
633 	if(!get_instance()->perform_action(action))
634 		get_ui_interface()->error(_("Action Failed."));
635 }
636 
637 void
set_id(const synfig::String & x)638 CanvasInterface::set_id(const synfig::String &x)
639 {
640 	Action::Handle 	action(Action::create("CanvasIdSet"));
641 
642 	assert(action);
643 	if(!action)
644 		return;
645 
646 	action->set_param("canvas",get_canvas());
647 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
648 	action->set_param("id",x);
649 
650 	if(!get_instance()->perform_action(action))
651 		get_ui_interface()->error(_("Action Failed."));
652 
653 	signal_id_changed_();
654 }
655 
656 
657 void
jump_to_next_keyframe()658 CanvasInterface::jump_to_next_keyframe()
659 {
660 	synfig::info("Current time: %s",get_time().get_string().c_str());
661 	try
662 	{
663 		synfig::Keyframe keyframe(*get_canvas()->keyframe_list().find_next(get_time()));
664 		synfig::info("Jumping to keyframe \"%s\" at %s",keyframe.get_description().c_str(),keyframe.get_time().get_string().c_str());
665 		set_time(keyframe.get_time());
666 	}
667 	catch(...) { synfig::warning("Unable to find next keyframe"); }
668 }
669 
670 void
jump_to_prev_keyframe()671 CanvasInterface::jump_to_prev_keyframe()
672 {
673 	synfig::info("Current time: %s",get_time().get_string().c_str());
674 	try
675 	{
676 		synfig::Keyframe keyframe(*get_canvas()->keyframe_list().find_prev(get_time()));
677 		synfig::info("Jumping to keyframe \"%s\" at %s",keyframe.get_description().c_str(),keyframe.get_time().get_string().c_str());
678 		set_time(keyframe.get_time());
679 	}
680 	catch(...) { synfig::warning("Unable to find prev keyframe"); }
681 }
682 
683 bool
import(const synfig::String & filename,synfig::String & errors,synfig::String & warnings,bool resize_image)684 CanvasInterface::import(const synfig::String &filename, synfig::String &errors, synfig::String &warnings, bool resize_image)
685 {
686 	Action::PassiveGrouper group(get_instance().get(),_("Import"));
687 
688 	synfig::info("Attempting to import " + filename);
689 
690 	String ext(filename_extension(filename));
691 	//if (filename_extension(filename) == "")
692 	if (ext == "")
693 	{
694 		get_ui_interface()->error(_("File name must have an extension!"));
695 		return false;
696 	}
697 
698 
699 	if (ext.size()) ext = ext.substr(1); // skip initial '.'
700 	std::transform(ext.begin(),ext.end(),ext.begin(),&::tolower);
701 
702 	String short_filename = CanvasFileNaming::make_short_filename(get_canvas()->get_file_name(), filename);
703 	String full_filename = CanvasFileNaming::make_full_filename(get_canvas()->get_file_name(), short_filename);
704 
705 	if (ext=="pgo")
706 	{
707 		synfigapp::Action::PassiveGrouper group(get_instance().get(),_("Import Lipsync"));
708 
709 		// switch
710 
711 		Layer::Handle layer_switch = layer_create("switch", get_canvas());
712 		if(!layer_switch)
713 			throw String(_("Unable to create \"Switch\" layer"));
714 
715 		layer_set_defaults(layer_switch);
716 		layer_switch->set_description(etl::basename(filename));
717 
718 		ValueNode_AnimatedFile::Handle animatedfile_node = ValueNode_AnimatedFile::create(String());
719 		animatedfile_node->set_link("filename", ValueNode_Const::create(short_filename));
720 		layer_switch->connect_dynamic_param("layer_name", ValueNode::LooseHandle(animatedfile_node));
721 
722 		if (!layer_add_action(layer_switch))
723 			throw String(_("Unable to add \"Switch\" layer"));
724 
725 		// sound
726 
727 		String soundfile = animatedfile_node->get_file_field(0, "sound");
728 		if (!soundfile.empty())
729 		{
730 			soundfile = etl::solve_relative_path(etl::dirname(full_filename), soundfile);
731 			String short_soundfile = CanvasFileNaming::make_short_filename(get_canvas()->get_file_name(), soundfile);
732 			String full_soundfile = CanvasFileNaming::make_full_filename(get_canvas()->get_file_name(), short_soundfile);
733 
734 			Layer::Handle layer_sound = layer_create("sound", get_canvas());
735 			if(!layer_sound)
736 				throw String(_("Unable to create \"Sound\" layer"));
737 
738 			layer_set_defaults(layer_sound);
739 			layer_sound->set_description(etl::basename(filename));
740 			layer_sound->set_param("filename", ValueBase(short_soundfile));
741 
742 			if (!layer_add_action(layer_sound))
743 				throw String(_("Unable to add \"Sound\" layer"));
744 		}
745 
746 		return true;
747 	}
748 
749 	if (ext=="wav" || ext=="ogg" || ext=="mp3")
750 	{
751 		Layer::Handle layer = layer_create("sound", get_canvas());
752 		if(!layer)
753 			throw String(_("Unable to create \"Sound\" layer"));
754 
755 		layer_set_defaults(layer);
756 		layer->set_description(etl::basename(filename));
757 		layer->set_param("filename", ValueBase(short_filename));
758 
759 		if (!layer_add_action(layer))
760 			throw String(_("Unable to add \"Sound\" layer"));
761 
762 		return true;
763 	}
764 
765 	if (ext=="svg") //I don't like it, but worse is nothing
766 	{
767 		Layer::Handle _new_layer(add_layer_to("group",get_canvas()));
768 		Layer::Handle _aux_layer(add_layer_to("svg_layer",get_canvas()));
769 		if(_aux_layer){
770 			_aux_layer->set_param("filename",ValueBase(short_filename));
771 			_new_layer->set_param("canvas",ValueBase(_aux_layer->get_param("canvas")));
772 			//remove aux layer
773 			Action::Handle 	action(Action::LayerRemove::create());
774 			assert(action);
775 			if(!action)
776 				return 0;
777 			action->set_param("canvas",get_canvas());
778 			action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
779 			action->set_param("layer",_aux_layer);
780 			if(!action->is_ready()){
781 				get_ui_interface()->error(_("Action Not Ready"));
782 				return 0;
783 			}
784 			if(!get_instance()->perform_action(action)){
785 				get_ui_interface()->error(_("Action Failed."));
786 				return 0;
787 			}
788 		}
789 		signal_layer_new_description()(_new_layer,etl::basename(filename));
790 		return true;
791 	}
792 
793 	// If this is a SIF file, then we need to do things slightly differently
794 	if (ext=="sif" || ext=="sifz")try
795 	{
796 		FileSystem::Handle file_system = CanvasFileNaming::make_filesystem(full_filename);
797 		if(!file_system)
798 			throw String(_("Unable to open container")) + ":\n\n" + errors;
799 
800 		Canvas::Handle outside_canvas(synfig::open_canvas_as(file_system->get_identifier(CanvasFileNaming::project_file(full_filename)), full_filename, errors, warnings));
801 		if(!outside_canvas)
802 			throw String(_("Unable to open this composition")) + ":\n\n" + errors;
803 
804 		Layer::Handle layer(add_layer_to("group",get_canvas()));
805 		if(!layer)
806 			throw String(_("Unable to create \"Group\" layer"));
807 		if(!layer->set_param("canvas",ValueBase(outside_canvas)))
808 			throw int();
809 		if(!layer->set_param("children_lock",true))
810 			throw String(_("Could not set children lock of imported canvas"));
811 		get_canvas()->register_external_canvas(full_filename, outside_canvas);
812 
813 		//layer->set_description(basename(filename));
814 		signal_layer_new_description()(layer,etl::basename(filename));
815 		return true;
816 	}
817 	catch(String x)
818 	{
819 		get_ui_interface()->error(filename + ": " + x);
820 		return false;
821 	}
822 	catch(...)
823 	{
824 		get_ui_interface()->error(_("Uncaught exception when attempting\nto open this composition -- ")+filename);
825 		return false;
826 	}
827 
828 	if(!Importer::book().count(ext))
829 	{
830 		get_ui_interface()->error(_("I don't know how to open images of this type -- ")+ext);
831 		return false;
832 	}
833 
834 	try
835 	{
836 		Layer::Handle layer(add_layer_to("Import",get_canvas()));
837 		int w,h;
838 		if(!layer)
839 			throw int();
840 		if(!layer->set_param("filename",ValueBase(short_filename)))
841 			throw int();
842 		w=layer->get_param("_width").get(int());
843 		h=layer->get_param("_height").get(int());
844 		layer->monitor(filename);
845 		if(w&&h)
846 		{
847 			Vector x, size = get_canvas()->rend_desc().get_br()-get_canvas()->rend_desc().get_tl();
848 
849 			// vector from top left of canvas to bottom right
850 			if (resize_image)
851 			{
852 				if(abs(size[0])<abs(size[1]))	// if canvas is tall and thin
853 				{
854 					x[0]=size[0];	// use full width
855 					x[1]=size[0]/w*h; // and scale for height
856 					if((size[0]<0) ^ (size[1]<0))
857 						x[1]=-x[1];
858 				}
859 				else				// else canvas is short and fat (or maybe square)
860 				{
861 					x[1]=size[1];	// use full height
862 					x[0]=size[1]/h*w; // and scale for width
863 					if((size[0]<0) ^ (size[1]<0))
864 						x[0]=-x[0];
865 				}
866 			}
867 			else
868 			{
869 				x[0] = w/60.0;
870 				x[1] = h/60.0;
871 				if((size[0]<0)) x[0]=-x[0];
872 				if((size[1]<0)) x[1]=-x[1];
873 			}
874 
875 			if(!layer->set_param("tl",ValueBase(-x/2)))
876 				throw int();
877 			if(!layer->set_param("br",ValueBase(x/2)))
878 				throw int();
879 		}
880 		else
881 		{
882 			if(!layer->set_param("tl",ValueBase(get_canvas()->rend_desc().get_tl())))
883 				throw int();
884 			if(!layer->set_param("br",ValueBase(get_canvas()->rend_desc().get_br())))
885 				throw int();
886 		}
887 
888 		layer->set_description(etl::basename(filename));
889 		signal_layer_new_description()(layer,etl::basename(filename));
890 
891 		//get_instance()->set_selected_layer(get_canvas(), layer);
892 		//get_instance()->set_selected_layer(layer, get_canvas());
893 
894 		//get_instance()->get_canvas_view(get_canvas());
895 
896 		//get_selection_manager()->set_selected_layer(layer);
897 
898 		//etl::handle<synfig::Canvas> canvas = get_canvas();
899 		//etl::handle<CanvasView> view = get_instance()->find_canvas_view(canvas);
900 		//view->layer_tree->select_layer(layer);
901 
902 		// add imported layer into switch
903 		Action::Handle action(Action::create("LayerEncapsulateSwitch"));
904 		assert(action);
905 		if(!action) return false;
906 		action->set_param("canvas",get_canvas());
907 		action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
908 		action->set_param("layer",layer);
909 		action->set_param("description",layer->get_description());
910 		if(!action->is_ready())
911 			{ get_ui_interface()->error(_("Action Not Ready")); return false; }
912 		if(!get_instance()->perform_action(action))
913 			{ get_ui_interface()->error(_("Action Failed.")); return false; }
914 
915 		Layer::LooseHandle l = layer->get_parent_paste_canvas_layer(); // get parent layer, because image is incapsulated into action switch
916 
917 		get_selection_manager()->clear_selected_layers();
918 		get_selection_manager()->set_selected_layer(l);
919 
920 		return true;
921 	}
922 	catch(...)
923 	{
924 		get_ui_interface()->error("Unable to import "+filename);
925 		group.cancel();
926 		return false;
927 	}
928 }
929 
930 
931 void
waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)932 CanvasInterface::waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
933 {
934 	//ValueNode::Handle value_node();
935 	waypoint_duplicate(value_desc.get_value_node(), waypoint);
936 }
937 
938 void
waypoint_duplicate(ValueNode::Handle value_node,synfig::Waypoint waypoint)939 CanvasInterface::waypoint_duplicate(ValueNode::Handle value_node,synfig::Waypoint waypoint)
940 {
941 	Action::Handle 	action(Action::create("WaypointSetSmart"));
942 
943 	assert(action);
944 	if(!action)
945 		return;
946 
947 	waypoint.make_unique();
948 	waypoint.set_time(get_time());
949 
950 	action->set_param("canvas",get_canvas());
951 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
952 	action->set_param("waypoint",waypoint);
953 	action->set_param("time",get_time());
954 	action->set_param("value_node",value_node);
955 
956 	if(!get_instance()->perform_action(action))
957 		get_ui_interface()->error(_("Action Failed."));
958 }
959 
960 void
waypoint_remove(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)961 CanvasInterface::waypoint_remove(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
962 {
963 	//ValueNode::Handle value_node();
964 	waypoint_remove(value_desc.get_value_node(), waypoint);
965 }
966 
967 void
waypoint_remove(ValueNode::Handle value_node,synfig::Waypoint waypoint)968 CanvasInterface::waypoint_remove(ValueNode::Handle value_node,synfig::Waypoint waypoint)
969 {
970 	Action::Handle 	action(Action::create("WaypointRemove"));
971 
972 	assert(action);
973 	if(!action)
974 		return;
975 
976 	action->set_param("canvas",get_canvas());
977 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
978 	action->set_param("waypoint",waypoint);
979 	action->set_param("value_node",value_node);
980 
981 	if(!get_instance()->perform_action(action))
982 		get_ui_interface()->error(_("Action Failed."));
983 }
984 
985 
986 void
auto_export(synfig::ValueNode::Handle)987 CanvasInterface::auto_export(synfig::ValueNode::Handle /*value_node*/)
988 {
989 /*
990 	// Check to see if we are already exported.
991 	if(value_node->is_exported())
992 		return;
993 
994 	Action::Handle 	action(Action::create("ValueNodeAdd"));
995 
996 	assert(action);
997 	if(!action)
998 		return;
999 
1000 	String name(strprintf(_("Unnamed%08d"),synfig::UniqueID().get_uid()));
1001 
1002 	action->set_param("canvas",get_canvas());
1003 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
1004 	action->set_param("new",value_node);
1005 	action->set_param("name",name);
1006 
1007 	if(!get_instance()->perform_action(action))
1008 		get_ui_interface()->error(_("Action Failed."));
1009 */
1010 }
1011 
1012 void
auto_export(const ValueDesc &)1013 CanvasInterface::auto_export(const ValueDesc& /*value_desc*/)
1014 {
1015 	// THIS FUNCTION IS DEPRECATED, AND IS NOW A STUB.
1016 #if 0
1017 	// Check to see if we are already exported.
1018 	if(value_desc.is_exported())
1019 		return;
1020 
1021 	Action::Handle 	action(Action::create("ValueDescExport"));
1022 
1023 	assert(action);
1024 	if(!action)
1025 		return;
1026 
1027 	String name(strprintf(_("Unnamed%08d"),synfig::UniqueID().get_uid()));
1028 
1029 	action->set_param("canvas",get_canvas());
1030 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
1031 	action->set_param("value_desc",value_desc);
1032 	action->set_param("name",name);
1033 
1034 	if(!get_instance()->perform_action(action))
1035 		get_ui_interface()->error(_("Action Failed."));
1036 #endif
1037 }
1038 
1039 bool
change_value(synfigapp::ValueDesc value_desc,synfig::ValueBase new_value,bool lock_animation)1040 CanvasInterface::change_value(synfigapp::ValueDesc value_desc,synfig::ValueBase new_value,bool lock_animation)
1041 {
1042 	ValueBase old_value;
1043 	old_value = value_desc.get_value(get_time());
1044 
1045 	// If this isn't really a change, then don't bother
1046 	if(new_value==old_value)
1047 		return true;
1048 
1049 	// New value should inherit all properties of original ValueBase (static, etc...)
1050 	new_value.copy_properties_of(old_value);
1051 
1052 	// If this change needs to take place elsewhere, then so be it.
1053 	if(value_desc.get_canvas())
1054 	{
1055 		if (value_desc.get_canvas()->get_root() != get_canvas()->get_root())
1056 		{
1057 			etl::handle<Instance> instance;
1058 			instance=find_instance(value_desc.get_canvas()->get_root());
1059 
1060 			if(instance)
1061 				return instance->find_canvas_interface(value_desc.get_canvas())->change_value(value_desc,new_value);
1062 			else
1063 			{
1064 				get_ui_interface()->error(_("The value you are trying to edit is in a composition\nwhich doesn't seem to be open. Open that composition and you\nshould be able to edit this value as normal."));
1065 				return false;
1066 			}
1067 		}
1068 	}
1069 #ifdef _DEBUG
1070 	else
1071 	{ synfig::warning("Can't get canvas from value desc...?"); }
1072 #endif
1073 
1074 	synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescSet"));
1075 	if(!action)
1076 	{
1077 		return false;
1078 	}
1079 
1080 	action->set_param("canvas",get_canvas());
1081 	action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
1082 	action->set_param("time",get_time());
1083 	action->set_param("value_desc",value_desc);
1084 	action->set_param("new_value",new_value);
1085 	if (lock_animation) action->set_param("lock_animation", lock_animation);
1086 
1087 	return get_instance()->perform_action(action);
1088 }
1089 
1090 void
set_meta_data(const synfig::String & key,const synfig::String & data)1091 CanvasInterface::set_meta_data(const synfig::String& key,const synfig::String& data)
1092 {
1093 	if (get_canvas()->get_meta_data(key) == data)
1094 		return;
1095 
1096     if (key=="guide_x" || key=="guide_y")
1097 	{
1098 		// Create an undoable action
1099 
1100 		synfigapp::Action::Handle action(synfigapp::Action::create("CanvasMetadataSet"));
1101 
1102 		assert(action);
1103 		if(!action)
1104 			return;
1105 
1106 		action->set_param("canvas",get_canvas());
1107 		action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
1108 		action->set_param("key",key);
1109 		action->set_param("value",data);
1110 
1111 		get_instance()->perform_action(action);
1112 	}
1113 	else
1114 	{
1115 		get_canvas()->set_meta_data(key,data);
1116 	}
1117 }
1118 
1119 void
erase_meta_data(const synfig::String & key)1120 CanvasInterface::erase_meta_data(const synfig::String& key)
1121 {
1122 	if (key=="guide_x" || key=="guide_y")
1123 	{
1124 		// Create an undoable action
1125 		synfigapp::Action::Handle action(synfigapp::Action::create("CanvasMetadataErase"));
1126 
1127 		assert(action);
1128 		if(!action)
1129 			return;
1130 
1131 		action->set_param("canvas",get_canvas());
1132 		action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
1133 		action->set_param("key",key);
1134 
1135 		get_instance()->perform_action(action);
1136 	}
1137 	else
1138 	{
1139 		get_canvas()->erase_meta_data(key);
1140 	}
1141 }
1142 
1143 // this function goes with find_important_value_descs()
1144 static int
_process_value_desc(const synfigapp::ValueDesc & value_desc,std::vector<synfigapp::ValueDesc> & out,synfig::GUIDSet & guid_set)1145 _process_value_desc(const synfigapp::ValueDesc& value_desc,std::vector<synfigapp::ValueDesc>& out, synfig::GUIDSet& guid_set)
1146 {
1147 	int ret(0);
1148 
1149 	if(value_desc.get_value_type()==type_canvas)
1150 	{
1151 		Canvas::Handle canvas;
1152 		canvas=value_desc.get_value().get(canvas);
1153 		if(!canvas || !canvas->is_inline())
1154 			return ret;
1155 		ret+=CanvasInterface::find_important_value_descs(canvas,out,guid_set);
1156 	}
1157 
1158 	if(value_desc.is_value_node())
1159 	{
1160 		ValueNode::Handle value_node(value_desc.get_value_node());
1161 
1162 		if(guid_set.count(value_node->get_guid()))
1163 			return ret;
1164 		guid_set.insert(value_node->get_guid());
1165 
1166 		if(LinkableValueNode::Handle::cast_dynamic(value_node))
1167 		{
1168 			if(ValueNode_DynamicList::Handle::cast_dynamic(value_node))
1169 			{
1170 				out.push_back(value_desc);
1171 				ret++;
1172 			}
1173 			// Process the linkable ValueNode's children
1174 			LinkableValueNode::Handle value_node_copy(LinkableValueNode::Handle::cast_dynamic(value_node));
1175 			int i;
1176 			for(i=0;i<value_node_copy->link_count();i++)
1177 			{
1178 				ValueNode::Handle link(value_node_copy->get_link(i));
1179 				if(!link->is_exported())
1180 					ret+=_process_value_desc(ValueDesc(value_node_copy,i),out,guid_set);
1181 			}
1182 		}
1183 		else if(ValueNode_Animated::Handle::cast_dynamic(value_node))
1184 		{
1185 			out.push_back(value_desc);
1186 			ret++;
1187 		}
1188 	}
1189 
1190 	return ret;
1191 }
1192 
1193 int
find_important_value_descs(synfig::Canvas::Handle canvas,std::vector<synfigapp::ValueDesc> & out,synfig::GUIDSet & guid_set)1194 CanvasInterface::find_important_value_descs(synfig::Canvas::Handle canvas,std::vector<synfigapp::ValueDesc>& out,synfig::GUIDSet& guid_set)
1195 {
1196 	int ret(0);
1197 	if(!canvas->is_inline())
1198 	{
1199 		ValueNodeList::const_iterator iter;
1200 
1201 		for(
1202 			iter=canvas->value_node_list().begin();
1203 			iter!=canvas->value_node_list().end();
1204 			++iter)
1205 			ret+=_process_value_desc(ValueDesc(canvas,(*iter)->get_id()),out,guid_set);
1206 	}
1207 
1208 	IndependentContext iter;
1209 
1210 	for(iter=canvas->get_independent_context();iter!=canvas->end();++iter)
1211 	{
1212 		Layer::Handle layer(*iter);
1213 
1214 		Layer::DynamicParamList::const_iterator iter;
1215 		for(
1216 			iter=layer->dynamic_param_list().begin();
1217 			iter!=layer->dynamic_param_list().end();
1218 			++iter)
1219 		{
1220 			if(!iter->second->is_exported())
1221 				ret+=_process_value_desc(ValueDesc(layer,iter->first),out,guid_set);
1222 		}
1223 		ValueBase value(layer->get_param("canvas"));
1224 		if(value.is_valid())
1225 			ret+=_process_value_desc(ValueDesc(layer,"canvas"),out,guid_set);
1226 	}
1227 
1228 	return ret;
1229 }
1230 
1231 int
find_important_value_descs(std::vector<synfigapp::ValueDesc> & out)1232 CanvasInterface::find_important_value_descs(std::vector<synfigapp::ValueDesc>& out)
1233 {
1234 	synfig::GUIDSet tmp;
1235 	return find_important_value_descs(get_canvas(),out,tmp);
1236 }
1237 
1238 void
seek_frame(int frames)1239 CanvasInterface::seek_frame(int frames)
1240 {
1241 	if(!frames)
1242 		return;
1243 	float fps(get_canvas()->rend_desc().get_frame_rate());
1244 	Time newtime(get_time()+(float)frames/fps);
1245 	newtime=newtime.round(fps);
1246 
1247 	if(newtime<=get_canvas()->rend_desc().get_time_start())
1248 		newtime=get_canvas()->rend_desc().get_time_start();
1249 	if(newtime>=get_canvas()->rend_desc().get_time_end())
1250 		newtime=get_canvas()->rend_desc().get_time_end();
1251 	set_time(newtime);
1252 }
1253 
1254 void
seek_time(synfig::Time time)1255 CanvasInterface::seek_time(synfig::Time time)
1256 {
1257 	if(!time)
1258 		return;
1259 
1260 	float fps(get_canvas()->rend_desc().get_frame_rate());
1261 
1262 	if(time>=synfig::Time::end())
1263 	{
1264 		set_time(get_canvas()->rend_desc().get_time_end());
1265 		return;
1266 	}
1267 	if(time<=synfig::Time::begin())
1268 	{
1269 		set_time(get_canvas()->rend_desc().get_time_start());
1270 		return;
1271 	}
1272 
1273 	Time newtime(get_time()+time);
1274 	newtime=newtime.round(fps);
1275 
1276 	if(newtime<=get_canvas()->rend_desc().get_time_start())
1277 		newtime=get_canvas()->rend_desc().get_time_start();
1278 	if(newtime>=get_canvas()->rend_desc().get_time_end())
1279 		newtime=get_canvas()->rend_desc().get_time_end();
1280 	set_time(newtime);
1281 }
1282