825284c76b9fd993abb6198d70f435ff7f225d26
[synfig.git] / synfig-studio / trunk / src / synfigapp / canvasinterface.cpp
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 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 //#include <iostream>
33
34 #include <ETL/clock>
35 #include <synfig/valuenode_scale.h>
36 #include <synfig/valuenode_timedswap.h>
37 #include <synfig/valuenode_composite.h>
38 #include <synfig/valuenode_subtract.h>
39 #include <synfig/valuenode_linear.h>
40 #include <synfig/valuenode_reference.h>
41 #include <synfig/valuenode_twotone.h>
42 #include <synfig/valuenode_stripes.h>
43
44 #include <synfig/waypoint.h>
45 #include <synfig/loadcanvas.h>
46 #include <synfig/importer.h>
47 #include <synfig/guidset.h>
48
49 #include "canvasinterface.h"
50 #include "instance.h"
51
52 #include "actions/layeradd.h"
53 #include "actions/valuedescconvert.h"
54 #include "actions/valuenodeadd.h"
55 #include "actions/editmodeset.h"
56 #include "action_system.h"
57
58 #include "main.h"
59
60 #include <synfig/gradient.h>
61
62 #endif
63
64 /* === U S I N G =========================================================== */
65
66 using namespace std;
67 using namespace etl;
68 using namespace synfig;
69 using namespace synfigapp;
70
71 /* === M A C R O S ========================================================= */
72
73 /* === G L O B A L S ======================================================= */
74
75 /* === P R O C E D U R E S ================================================= */
76
77 /* === M E T H O D S ======================================================= */
78
79 CanvasInterface::CanvasInterface(loose_handle<Instance> instance,handle<Canvas> canvas):
80         instance_(instance),
81         canvas_(canvas),
82         cur_time_(canvas->rend_desc().get_frame_start()),
83         mode_(MODE_NORMAL|MODE_ANIMATE_PAST|MODE_ANIMATE_FUTURE)
84 {
85         set_selection_manager(get_instance()->get_selection_manager());
86         set_ui_interface(get_instance()->get_ui_interface());
87 }
88
89 CanvasInterface::~CanvasInterface()
90 {
91         synfig::info("synfigapp::CanvasInterface::~CanvasInterface(): Deleted");
92 }
93
94 void
95 CanvasInterface::set_time(synfig::Time x)
96 {
97         if(get_canvas()->rend_desc().get_frame_rate())
98         {
99                 float fps(get_canvas()->rend_desc().get_frame_rate());
100                 Time r(x.round(fps));
101                 //synfig::info("CanvasInterface::set_time(): %s rounded to %s\n",x.get_string(fps).c_str(),r.get_string(fps).c_str());
102                 x=r;
103         }
104         if(cur_time_.is_equal(x))
105                 return;
106         get_canvas()->set_time(cur_time_=x);
107
108         // update the time in all the child canvases
109         Canvas::Children children = get_canvas()->get_root()->children();
110         for (Canvas::Children::iterator iter = children.begin(); iter != children.end(); iter++)
111                 if (handle<CanvasInterface> interface = get_instance()->find_canvas_interface(*iter))
112                         interface->set_time(interface->get_canvas()->get_time());
113
114         signal_time_changed()();
115         signal_dirty_preview()();
116 }
117
118 synfig::Time
119 CanvasInterface::get_time()const
120 {
121         return cur_time_;
122 }
123
124 void
125 CanvasInterface::refresh_current_values()
126 {
127         get_canvas()->set_time(cur_time_);
128         signal_time_changed()();
129         signal_dirty_preview()();
130 }
131
132 etl::handle<CanvasInterface>
133 CanvasInterface::create(loose_handle<Instance> instance,handle<Canvas> canvas)
134 {
135         etl::handle<CanvasInterface> intrfc;
136         intrfc=new CanvasInterface(instance,canvas);
137         instance->canvas_interface_list().push_front(intrfc);
138         return intrfc;
139 }
140
141 void
142 CanvasInterface::set_mode(Mode x)
143 {
144         Action::Handle  action(Action::EditModeSet::create());
145
146         assert(action);
147
148         action->set_param("canvas",get_canvas());
149         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
150         action->set_param("edit_mode",x);
151
152         if(!action->is_ready())
153         {
154                 get_ui_interface()->error(_("Action Not Ready, unable to change mode"));
155                 assert(0);
156                 return;
157         }
158
159         if(!get_instance()->perform_action(action))
160                 get_ui_interface()->error(_("Unable to change mode"));
161
162 //      mode_=x;
163 //      signal_mode_changed_(x);
164 }
165
166 CanvasInterface::Mode
167 CanvasInterface::get_mode()const
168 {
169         return mode_;
170 }
171
172
173
174 Layer::Handle
175 CanvasInterface::add_layer_to(String name, Canvas::Handle canvas, int depth)
176 {
177         synfigapp::Action::PassiveGrouper group(get_instance().get(),_("Add Layer To"));
178
179         Layer::Handle   layer(Layer::create(name));
180
181         assert(layer);
182
183         if(!layer)
184                 return 0;
185
186         if(canvas!=get_canvas() && !canvas->is_inline())
187         {
188                 synfig::error("Bad canvas passed to \"add_layer_to\"");
189                 return 0;
190         }
191
192         layer->set_canvas(canvas);
193
194         // Apply some defaults
195         if(layer->set_param("fg",synfigapp::Main::get_foreground_color()))
196                 layer->set_param("bg",synfigapp::Main::get_background_color());
197         else
198                 layer->set_param("color",synfigapp::Main::get_foreground_color());
199
200         layer->set_param("width",synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc()));
201         layer->set_param("gradient",synfigapp::Main::get_gradient());
202         if(name!="zoom")
203                 layer->set_param("amount",synfigapp::Main::get_opacity());
204         layer->set_param("blend_method",synfigapp::Main::get_blend_method());
205
206         {
207                 // Grab the layer's list pf parameters
208                 Layer::ParamList paramlist=layer->get_param_list();
209                 Layer::ParamList::iterator iter;
210                 for(iter=paramlist.begin();iter!=paramlist.end();++iter)
211                 {
212                         ValueNode::Handle value_node;
213
214                         if(iter->second.get_type()==ValueBase::TYPE_LIST)
215                                 value_node=LinkableValueNode::create("dynamic_list",iter->second);
216                         else if(LinkableValueNode::check_type("composite",iter->second.get_type()) &&
217                                 (iter->second.get_type()!=ValueBase::TYPE_COLOR && iter->second.get_type()!=ValueBase::TYPE_VECTOR)
218                         )
219                                 value_node=LinkableValueNode::create("composite",iter->second);
220
221                         if(value_node)
222                                 layer->connect_dynamic_param(iter->first,value_node);
223                 }
224         }
225
226         // Action to add the layer
227         Action::Handle  action(Action::LayerAdd::create());
228
229         assert(action);
230         if(!action)
231                 return 0;
232
233         action->set_param("canvas",canvas);
234         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
235         action->set_param("new",layer);
236
237         if(!action->is_ready())
238         {
239                 get_ui_interface()->error(_("Action Not Ready"));
240                 return 0;
241         }
242
243         if(!get_instance()->perform_action(action))
244         {
245                 get_ui_interface()->error(_("Action Failed."));
246                 return 0;
247         }
248
249         synfig::info("DEPTH=%d",depth);
250         // Action to move the layer (if necessary)
251         if(depth>0)
252         {
253                 Action::Handle  action(Action::create("layer_move"));
254
255                 assert(action);
256                 if(!action)
257                         return 0;
258
259                 action->set_param("canvas",canvas);
260                 action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
261                 action->set_param("layer",layer);
262                 action->set_param("new_index",depth);
263
264                 if(!action->is_ready())
265                 {
266                         get_ui_interface()->error(_("Move Action Not Ready"));
267                         return 0;
268                 }
269
270                 if(!get_instance()->perform_action(action))
271                 {
272                         get_ui_interface()->error(_("Move Action Failed."));
273                         return 0;
274                 }
275         }
276
277
278         return layer;
279 }
280
281
282 bool
283 CanvasInterface::convert(ValueDesc value_desc, String type)
284 {
285         Action::Handle  action(Action::ValueDescConvert::create());
286
287         assert(action);
288         if(!action)
289                 return 0;
290
291         action->set_param("canvas",get_canvas());
292         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
293         action->set_param("value_desc",value_desc);
294         action->set_param("type",type);
295
296         if(!action->is_ready())
297         {
298                 get_ui_interface()->error(_("Action Not Ready"));
299                 return 0;
300         }
301
302         if(get_instance()->perform_action(action))
303                 return true;
304
305         get_ui_interface()->error(_("Action Failed."));
306         return false;
307 }
308
309 bool
310 CanvasInterface::add_value_node(synfig::ValueNode::Handle value_node, synfig::String name)
311 {
312         if(name.empty())
313         {
314                 get_ui_interface()->error(_("Empty name!"));
315                 return false;
316         }
317
318         Action::Handle  action(Action::ValueNodeAdd::create());
319
320         assert(action);
321         if(!action)
322                 return 0;
323
324         action->set_param("canvas",get_canvas());
325         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
326         action->set_param("new",value_node);
327         action->set_param("name",name);
328
329         if(!action->is_ready())
330         {
331                 get_ui_interface()->error(_("Action Not Ready"));
332                 return 0;
333         }
334
335         if(get_instance()->perform_action(action))
336                 return true;
337
338         get_ui_interface()->error(_("Action Failed."));
339         return false;
340 }
341
342 Action::ParamList
343 CanvasInterface::generate_param_list(const ValueDesc &value_desc)
344 {
345         synfigapp::Action::ParamList param_list;
346         param_list.add("time",get_time());
347         param_list.add("canvas_interface",etl::handle<CanvasInterface>(this));
348         param_list.add("canvas",get_canvas());
349
350         param_list.add("value_desc",value_desc);
351
352         if(value_desc.parent_is_value_node())
353                 param_list.add("parent_value_node",value_desc.get_parent_value_node());
354
355         if(value_desc.is_value_node())
356                 param_list.add("value_node",value_desc.get_value_node());
357
358         if(value_desc.is_const())
359                 param_list.add("value",value_desc.get_value());
360
361         if(value_desc.parent_is_layer_param())
362         {
363                 param_list.add("parent_layer",value_desc.get_layer());
364                 param_list.add("parent_layer_param",value_desc.get_param_name());
365         }
366
367         {
368                 synfigapp::SelectionManager::ChildrenList children_list;
369                 children_list=get_selection_manager()->get_selected_children();
370                 if(!value_desc.parent_is_canvas() && children_list.size()==1)
371                 {
372                         param_list.add("dest",value_desc);
373                         param_list.add("src",children_list.front().get_value_node());
374                 }
375         }
376         return param_list;
377 }
378
379 Action::ParamList
380 CanvasInterface::generate_param_list(const std::list<synfigapp::ValueDesc> &value_desc_list)
381 {
382         synfigapp::Action::ParamList param_list;
383         param_list.add("time",get_time());
384         param_list.add("canvas_interface",etl::handle<CanvasInterface>(this));
385         param_list.add("canvas",get_canvas());
386
387         std::list<synfigapp::ValueDesc>::const_iterator iter;
388         for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
389         {
390                 param_list.add("value_desc",*iter);
391                 if(iter->is_value_node())
392                 {
393                         param_list.add("value_node",iter->get_value_node());
394                 }
395         }
396
397
398         return param_list;
399 }
400
401 void
402 CanvasInterface::set_rend_desc(const synfig::RendDesc &rend_desc)
403 {
404         Action::Handle  action(Action::create("canvas_rend_desc_set"));
405
406         assert(action);
407         if(!action)
408                 return;
409
410         action->set_param("canvas",get_canvas());
411         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
412         action->set_param("rend_desc",rend_desc);
413
414         if(!get_instance()->perform_action(action))
415                 get_ui_interface()->error(_("Action Failed."));
416 }
417
418 bool
419 CanvasInterface::set_name(const String &x)
420 {
421         //! \todo This needs to be converted into an action
422         get_canvas()->set_name(x);
423         signal_id_changed_();
424         return true;
425 }
426
427 bool
428 CanvasInterface::set_description(const String &x)
429 {
430         //! \todo This needs to be converted into an action
431         get_canvas()->set_description(x);
432         return true;
433 }
434
435 bool
436 CanvasInterface::set_id(const String &x)
437 {
438         //! \todo This needs to be converted into an action
439         get_canvas()->set_id(x);
440         signal_id_changed_();
441         return true;
442 }
443
444
445 void
446 CanvasInterface::jump_to_next_keyframe()
447 {
448         synfig::info("Current time: %s",get_time().get_string().c_str());
449         try
450         {
451                 synfig::Keyframe keyframe(*get_canvas()->keyframe_list().find_next(get_time()));
452                 synfig::info("Jumping to keyframe \"%s\" at %s",keyframe.get_description().c_str(),keyframe.get_time().get_string().c_str());
453                 set_time(keyframe.get_time());
454         }
455         catch(...) { synfig::warning("Unable to find next keyframe"); }
456 }
457
458 void
459 CanvasInterface::jump_to_prev_keyframe()
460 {
461         synfig::info("Current time: %s",get_time().get_string().c_str());
462         try
463         {
464                 synfig::Keyframe keyframe(*get_canvas()->keyframe_list().find_prev(get_time()));
465                 synfig::info("Jumping to keyframe \"%s\" at %s",keyframe.get_description().c_str(),keyframe.get_time().get_string().c_str());
466                 set_time(keyframe.get_time());
467         }
468         catch(...) { synfig::warning("Unable to find prev keyframe"); }
469 }
470
471 bool
472 CanvasInterface::import(const synfig::String &filename, bool /*copy*/)
473 {
474         Action::PassiveGrouper group(get_instance().get(),_("Import Image"));
475
476         synfig::info("Attempting to import "+filename);
477
478
479         if(find(filename.begin(),filename.end(),'.')==filename.end())
480         {
481                 get_ui_interface()->error("Filename must have an extension!");
482                 return false;
483         }
484
485         String ext(String(filename.begin()+filename.find_last_of('.')+1,filename.end()));
486         std::transform(ext.begin(),ext.end(),ext.begin(),&::tolower);
487
488         // If this is a SIF file, then we need to do things slightly differently
489         if(ext=="sif" || ext=="sifz")try
490         {
491
492                 Canvas::Handle outside_canvas(synfig::open_canvas(filename));
493                 if(!outside_canvas)
494                         throw String(_("Unable to open this composition"));
495
496                 Layer::Handle layer(add_layer_to("PasteCanvas",get_canvas()));
497                 if(!layer)
498                         throw String(_("Unable to create \"Paste Canvas\" layer"));
499                 if(!layer->set_param("canvas",ValueBase(outside_canvas)))
500                         throw int();
501
502                 //layer->set_description(basename(filename));
503                 signal_layer_new_description()(layer,filename);
504                 return true;
505         }
506         catch(String x)
507         {
508                 get_ui_interface()->error(x+" -- "+filename);
509                 return false;
510         }
511         catch(...)
512         {
513                 get_ui_interface()->error(_("Uncaught exception when attempting\nto open this composition -- ")+filename);
514                 return false;
515         }
516
517         if(!Importer::book().count(ext))
518         {
519                 get_ui_interface()->error(_("I don't know how to open images of this type -- ")+ext);
520                 return false;
521         }
522
523         try
524         {
525                 Layer::Handle layer(add_layer_to("Import",get_canvas()));
526                 int w,h;
527                 if(!layer)
528                         throw int();
529                 if(!layer->set_param("filename",ValueBase(filename)))
530                         throw int();
531                 w=layer->get_param("_width").get(int());
532                 h=layer->get_param("_height").get(int());
533                 if(w&&h)
534                 {
535                         Vector size=ValueBase(get_canvas()->rend_desc().get_br()-get_canvas()->rend_desc().get_tl());
536                         Vector x;
537                         if(size[0]<size[1])
538                         {
539                                 x[0]=size[0];
540                                 x[1]=size[0]/w*h;
541                                 if(size[0]<0 ^ size[1]<0)
542                                         x[1]=-x[1];
543                         }
544                         else
545                         {
546                                 x[1]=size[1];
547                                 x[0]=size[1]/h*w;
548                                 if(size[0]<0 ^ size[1]<0)
549                                         x[0]=-x[0];
550                         }
551                         if(!layer->set_param("tl",ValueBase(-x/2)))
552                                 throw int();
553                         if(!layer->set_param("br",ValueBase(x/2)))
554                                 throw int();
555                 }
556                 else
557                 {
558                         if(!layer->set_param("tl",ValueBase(get_canvas()->rend_desc().get_tl())))
559                                 throw int();
560                         if(!layer->set_param("br",ValueBase(get_canvas()->rend_desc().get_br())))
561                                 throw int();
562                 }
563
564                 layer->set_description(basename(filename));
565                 signal_layer_new_description()(layer,filename);
566
567                 return true;
568         }
569         catch(...)
570         {
571                 get_ui_interface()->error("Unable to import "+filename);
572                 group.cancel();
573                 return false;
574         }
575 }
576
577
578 void
579 CanvasInterface::waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
580 {
581         Action::Handle  action(Action::create("waypoint_set_smart"));
582
583         assert(action);
584         if(!action)
585                 return;
586
587         waypoint.make_unique();
588         waypoint.set_time(get_time());
589
590         ValueNode::Handle value_node(value_desc.get_value_node());
591
592         action->set_param("canvas",get_canvas());
593         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
594         action->set_param("waypoint",waypoint);
595         action->set_param("time",get_time());
596         action->set_param("value_node",value_node);
597
598         if(!get_instance()->perform_action(action))
599                 get_ui_interface()->error(_("Action Failed."));
600 }
601
602 void
603 CanvasInterface::waypoint_remove(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
604 {
605         Action::Handle  action(Action::create("waypoint_remove"));
606
607         assert(action);
608         if(!action)
609                 return;
610
611         ValueNode::Handle value_node(value_desc.get_value_node());
612
613         action->set_param("canvas",get_canvas());
614         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
615         action->set_param("waypoint",waypoint);
616         action->set_param("value_node",value_node);
617
618         if(!get_instance()->perform_action(action))
619                 get_ui_interface()->error(_("Action Failed."));
620 }
621
622
623 void
624 CanvasInterface::auto_export(ValueNode::Handle /*value_node*/)
625 {
626 /*
627         // Check to see if we are already exported.
628         if(value_node->is_exported())
629                 return;
630
631         Action::Handle  action(Action::create("value_node_add"));
632
633         assert(action);
634         if(!action)
635                 return;
636
637         String name(strprintf(_("Unnamed%08d"),synfig::UniqueID().get_uid()));
638
639         action->set_param("canvas",get_canvas());
640         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
641         action->set_param("new",value_node);
642         action->set_param("name",name);
643
644         if(!get_instance()->perform_action(action))
645                 get_ui_interface()->error(_("Action Failed."));
646 */
647 }
648
649 void
650 CanvasInterface::auto_export(const ValueDesc& /*value_desc*/)
651 {
652         // THIS FUNCTION IS DEPRECATED, AND IS NOW A STUB.
653 #if 0
654         // Check to see if we are already exported.
655         if(value_desc.is_exported())
656                 return;
657
658         Action::Handle  action(Action::create("value_desc_export"));
659
660         assert(action);
661         if(!action)
662                 return;
663
664         String name(strprintf(_("Unnamed%08d"),synfig::UniqueID().get_uid()));
665
666         action->set_param("canvas",get_canvas());
667         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
668         action->set_param("value_desc",value_desc);
669         action->set_param("name",name);
670
671         if(!get_instance()->perform_action(action))
672                 get_ui_interface()->error(_("Action Failed."));
673 #endif
674 }
675
676 bool
677 CanvasInterface::change_value(synfigapp::ValueDesc value_desc,synfig::ValueBase new_value)
678 {
679         // If this isn't really a change, then don't bother
680         if(new_value==value_desc.get_value(get_time()))
681                 return true;
682
683         // If this change needs to take place elsewhere, then so be it.
684         if(value_desc.get_canvas() && value_desc.get_canvas()->get_root()!=get_canvas()->get_root())do
685         {
686                 etl::handle<Instance> instance;
687                 instance=find_instance(value_desc.get_canvas()->get_root());
688
689                 if(instance)
690                         return instance->find_canvas_interface(value_desc.get_canvas())->change_value(value_desc,new_value);
691                 else
692                 {
693                         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."));
694                         return false;
695                 }
696         }while(0);
697 #ifdef _DEBUG
698         else
699         { synfig::warning("Can't get canvas from value desc...?"); }
700 #endif
701
702         synfigapp::Action::Handle action(synfigapp::Action::create("value_desc_set"));
703         if(!action)
704         {
705                 return false;
706         }
707
708         action->set_param("canvas",get_canvas());
709         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
710         action->set_param("time",get_time());
711         action->set_param("value_desc",value_desc);
712         action->set_param("new_value",new_value);
713
714         return get_instance()->perform_action(action);
715 }
716
717 void
718 CanvasInterface::set_meta_data(const synfig::String& key,const synfig::String& data)
719 {
720         get_canvas()->set_meta_data(key,data);
721 }
722
723
724 // this function goes with find_important_value_descs()
725 static int
726 _process_value_desc(const synfigapp::ValueDesc& value_desc,std::vector<synfigapp::ValueDesc>& out, synfig::GUIDSet& guid_set)
727 {
728         int ret(0);
729
730         if(value_desc.get_value_type()==ValueBase::TYPE_CANVAS)
731         {
732                 Canvas::Handle canvas;
733                 canvas=value_desc.get_value().get(canvas);
734                 if(!canvas || !canvas->is_inline())
735                         return ret;
736                 ret+=CanvasInterface::find_important_value_descs(canvas,out,guid_set);
737         }
738
739         if(value_desc.is_value_node())
740         {
741                 ValueNode::Handle value_node(value_desc.get_value_node());
742
743                 if(guid_set.count(value_node->get_guid()))
744                         return ret;
745                 guid_set.insert(value_node->get_guid());
746
747                 if(LinkableValueNode::Handle::cast_dynamic(value_node))
748                 {
749                         if(ValueNode_DynamicList::Handle::cast_dynamic(value_node))
750                         {
751                                 out.push_back(value_desc);
752                                 ret++;
753                         }
754                         // Process the linkable ValueNode's children
755                         LinkableValueNode::Handle value_node_copy(LinkableValueNode::Handle::cast_dynamic(value_node));
756                         int i;
757                         for(i=0;i<value_node_copy->link_count();i++)
758                         {
759                                 ValueNode::Handle link(value_node_copy->get_link(i));
760                                 if(!link->is_exported())
761                                         ret+=_process_value_desc(ValueDesc(value_node_copy,i),out,guid_set);
762                         }
763                 }
764                 else if(ValueNode_Animated::Handle::cast_dynamic(value_node))
765                 {
766                         out.push_back(value_desc);
767                         ret++;
768                 }
769         }
770
771         return ret;
772 }
773
774 int
775 CanvasInterface::find_important_value_descs(synfig::Canvas::Handle canvas,std::vector<synfigapp::ValueDesc>& out,synfig::GUIDSet& guid_set)
776 {
777         int ret(0);
778         if(!canvas->is_inline())
779         {
780                 ValueNodeList::const_iterator iter;
781
782                 for(
783                         iter=canvas->value_node_list().begin();
784                         iter!=canvas->value_node_list().end();
785                         ++iter)
786                         ret+=_process_value_desc(ValueDesc(canvas,(*iter)->get_id()),out,guid_set);
787         }
788
789         Canvas::const_iterator iter;
790
791         for(iter=canvas->begin();iter!=canvas->end();++iter)
792         {
793                 Layer::Handle layer(*iter);
794
795                 Layer::DynamicParamList::const_iterator iter;
796                 for(
797                         iter=layer->dynamic_param_list().begin();
798                         iter!=layer->dynamic_param_list().end();
799                         ++iter)
800                 {
801                         if(!iter->second->is_exported())
802                                 ret+=_process_value_desc(ValueDesc(layer,iter->first),out,guid_set);
803                 }
804                 ValueBase value(layer->get_param("canvas"));
805                 if(value.is_valid())
806                         ret+=_process_value_desc(ValueDesc(layer,"canvas"),out,guid_set);
807         }
808
809         return ret;
810 }
811
812 int
813 CanvasInterface::find_important_value_descs(std::vector<synfigapp::ValueDesc>& out)
814 {
815         synfig::GUIDSet tmp;
816         return find_important_value_descs(get_canvas(),out,tmp);
817 }
818
819 void
820 CanvasInterface::seek_frame(int frames)
821 {
822         if(!frames)
823                 return;
824         float fps(get_canvas()->rend_desc().get_frame_rate());
825         Time newtime(get_time()+(float)frames/fps);
826         newtime=newtime.round(fps);
827
828         if(newtime<=get_canvas()->rend_desc().get_time_start())
829                 newtime=get_canvas()->rend_desc().get_time_start();
830         if(newtime>=get_canvas()->rend_desc().get_time_end())
831                 newtime=get_canvas()->rend_desc().get_time_end();
832         set_time(newtime);
833 }
834
835 void
836 CanvasInterface::seek_time(synfig::Time time)
837 {
838         if(!time)
839                 return;
840
841         float fps(get_canvas()->rend_desc().get_frame_rate());
842
843         if(time>=synfig::Time::end())
844         {
845                 set_time(get_canvas()->rend_desc().get_time_end());
846                 return;
847         }
848         if(time<=synfig::Time::begin())
849         {
850                 set_time(get_canvas()->rend_desc().get_time_start());
851                 return;
852         }
853
854         Time newtime(get_time()+time);
855         newtime=newtime.round(fps);
856
857         if(newtime<=get_canvas()->rend_desc().get_time_start())
858                 newtime=get_canvas()->rend_desc().get_time_start();
859         if(newtime>=get_canvas()->rend_desc().get_time_end())
860                 newtime=get_canvas()->rend_desc().get_time_end();
861         set_time(newtime);
862 }