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