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