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