When editing an angle duck, signal the angle it was rotated through, rather than...
[synfig.git] / synfig-studio / trunk / src / gtkmm / duckmatic.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file duckmatic.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 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32 #include <fstream>
33 #include <iostream>
34 #include <algorithm>
35
36 #include <ETL/hermite>
37
38 #include "duckmatic.h"
39 #include <synfigapp/value_desc.h>
40 #include <synfig/general.h>
41 #include <synfig/paramdesc.h>
42 #include <synfig/valuenode_timedswap.h>
43 #include <synfig/valuenode_animated.h>
44 #include <synfig/valuenode_composite.h>
45 #include <synfig/valuenode_scale.h>
46 #include <synfig/valuenode_bline.h>
47
48 #include <synfig/curve_helper.h>
49
50 #include <sigc++/retype_return.h>
51 #include <sigc++/retype.h>
52 #include <sigc++/hide.h>
53 #include <sigc++/bind.h>
54
55 #include "canvasview.h"
56
57 #include "onemoment.h"
58
59 #endif
60
61 /* === U S I N G =========================================================== */
62
63 using namespace std;
64 using namespace etl;
65 using namespace synfig;
66 using namespace studio;
67
68 /* === M A C R O S ========================================================= */
69
70 /* 0.33333333333333333 makes for nice short tangent handles,
71    1.0 makes them draw as their real length */
72 #define TANGENT_HANDLE_SCALE 0.33333333333333333
73
74 /* leave this alone or the bezier won't lie on top of the bline */
75 #define TANGENT_BEZIER_SCALE 0.33333333333333333
76
77 /* === G L O B A L S ======================================================= */
78
79 /* === P R O C E D U R E S ================================================= */
80
81 /* === M E T H O D S ======================================================= */
82
83 /* === E N T R Y P O I N T ================================================= */
84
85 Duckmatic::Duckmatic():
86         type_mask(Duck::TYPE_ALL-Duck::TYPE_WIDTH),
87         grid_snap(false),
88         guide_snap(false),
89         grid_size(1.0/4.0,1.0/4.0),
90         show_persistent_strokes(true)
91 {
92         axis_lock=false;
93         drag_offset_=Point(0,0);
94         clear_duck_dragger();
95 }
96
97 Duckmatic::~Duckmatic()
98 {
99         clear_ducks();
100         //synfig::info("Duckmatic::~Duckmatic(): Deleted. Duck Count=%d",Duck::duck_count);
101 }
102
103 void
104 Duckmatic::clear_ducks()
105 {
106         duck_data_share_map.clear();
107         duck_map.clear();
108
109         //duck_list_.clear();
110         bezier_list_.clear();
111         stroke_list_.clear();
112
113         if(show_persistent_strokes)
114                 stroke_list_=persistent_stroke_list_;
115 }
116
117 //! Returns \a true if the given duck is currently selected
118 bool
119 Duckmatic::duck_is_selected(const etl::handle<Duck> &duck)const
120 {
121         return duck && selected_ducks.count(duck->get_guid());
122 }
123
124 void
125 Duckmatic::set_grid_size(const synfig::Vector &s)
126 {
127         if(grid_size!=s)
128         {
129                 grid_size=s;
130                 signal_grid_changed();
131         }
132 }
133
134 void
135 Duckmatic::set_grid_snap(bool x)
136 {
137         if(grid_snap!=x)
138         {
139                 grid_snap=x;
140                 signal_grid_changed();
141         }
142 }
143
144 void
145 Duckmatic::set_guide_snap(bool x)
146 {
147         if(guide_snap!=x)
148         {
149                 guide_snap=x;
150                 signal_grid_changed();
151         }
152 }
153
154 Duckmatic::GuideList::iterator
155 Duckmatic::find_guide_x(synfig::Point pos, float radius)
156 {
157         GuideList::iterator iter,best(guide_list_x_.end());
158         float dist(radius);
159         for(iter=guide_list_x_.begin();iter!=guide_list_x_.end();++iter)
160         {
161                 float amount(abs(*iter-pos[0]));
162                 if(amount<dist)
163                 {
164                         dist=amount;
165                         best=iter;
166                 }
167         }
168         return best;
169 }
170
171 Duckmatic::GuideList::iterator
172 Duckmatic::find_guide_y(synfig::Point pos, float radius)
173 {
174         GuideList::iterator iter,best(guide_list_y_.end());
175         float dist(radius);
176         for(iter=guide_list_y_.begin();iter!=guide_list_y_.end();++iter)
177         {
178                 float amount(abs(*iter-pos[1]));
179                 if(amount<=dist)
180                 {
181                         dist=amount;
182                         best=iter;
183                 }
184         }
185         return best;
186 }
187
188 void
189 Duckmatic::clear_selected_ducks()
190 {
191         selected_ducks.clear();
192         signal_duck_selection_changed_();
193 }
194
195 etl::handle<Duckmatic::Duck>
196 Duckmatic::get_selected_duck()const
197 {
198         if(selected_ducks.empty() || duck_map.empty())
199                 return 0;
200         return duck_map.find(*selected_ducks.begin())->second;
201 }
202
203 void
204 Duckmatic::refresh_selected_ducks()
205 {
206 /*
207         std::set<etl::handle<Duck> >::iterator iter;
208         std::set<etl::handle<Duck> > new_set;
209         if(duck_list().empty())
210         {
211                 selected_duck_list.clear();
212                 signal_duck_selection_changed_();
213                 return;
214         }
215
216         for(iter=selected_duck_list.begin();iter!=selected_duck_list.end();++iter)
217         {
218                 etl::handle<Duck> similar(find_similar_duck(*iter));
219                 if(similar)
220                 {
221                         new_set.insert(similar);
222                 }
223         }
224         selected_duck_list=new_set;
225 */
226         GUIDSet old_set(selected_ducks);
227         GUIDSet::const_iterator iter;
228
229         for(iter=old_set.begin();iter!=old_set.end();++iter)
230         {
231                 if(duck_map.count(*iter)==0)
232                         selected_ducks.erase(*iter);
233         }
234
235         signal_duck_selection_changed_();
236 }
237
238 bool
239 Duckmatic::is_duck_group_selectable(const etl::handle<Duck>& x)const
240 {
241         const Type type(get_type_mask());
242
243         if(( x->get_type() && (!(type & x->get_type())) ) )
244         {
245                 return false;
246         }
247         if(x->get_value_desc().parent_is_layer_param() && type & Duck::TYPE_POSITION)
248         {
249                 Layer::Handle layer(x->get_value_desc().get_layer());
250                 String layer_name(layer->get_name());
251                 if(
252                         layer_name=="outline" ||
253                         layer_name=="region" ||
254                         layer_name=="polygon" ||
255                         layer_name=="curve_gradient"
256                 )
257                         return false;
258                 if((layer_name=="PasteCanvas"|| layer_name=="paste_canvas") &&
259                    !layer->get_param("children_lock").get(bool()))
260                         return false;
261         }
262         return true;
263 }
264
265 void
266 Duckmatic::select_all_ducks()
267 {
268         DuckMap::const_iterator iter;
269         for(iter=duck_map.begin();iter!=duck_map.end();++iter)
270                 if(is_duck_group_selectable(iter->second))
271                         select_duck(iter->second);
272 }
273
274 void
275 Duckmatic::toggle_select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)
276 {
277         Vector vmin, vmax;
278         vmin[0]=std::min(tl[0],br[0]);
279         vmin[1]=std::min(tl[1],br[1]);
280         vmax[0]=std::max(tl[0],br[0]);
281         vmax[1]=std::max(tl[1],br[1]);
282
283         DuckMap::const_iterator iter;
284         for(iter=duck_map.begin();iter!=duck_map.end();++iter)
285         {
286                 Point p(iter->second->get_trans_point());
287                 if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1] &&
288                    is_duck_group_selectable(iter->second))
289                         toggle_select_duck(iter->second);
290         }
291 }
292
293 void
294 Duckmatic::select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)
295 {
296         Vector vmin, vmax;
297         vmin[0]=std::min(tl[0],br[0]);
298         vmin[1]=std::min(tl[1],br[1]);
299         vmax[0]=std::max(tl[0],br[0]);
300         vmax[1]=std::max(tl[1],br[1]);
301
302 //      Type type(get_type_mask());
303
304         DuckMap::const_iterator iter;
305         for(iter=duck_map.begin();iter!=duck_map.end();++iter)
306         {
307                 Point p(iter->second->get_trans_point());
308                 if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1])
309                 {
310                         if(is_duck_group_selectable(iter->second))
311                                 select_duck(iter->second);
312                 }
313         }
314 }
315
316 int
317 Duckmatic::count_selected_ducks()const
318 {
319         return selected_ducks.size();
320 }
321
322 void
323 Duckmatic::select_duck(const etl::handle<Duck> &duck)
324 {
325         if(duck)
326         {
327                 selected_ducks.insert(duck->get_guid());
328                 signal_duck_selection_changed_();
329         }
330 }
331
332 DuckList
333 Duckmatic::get_selected_ducks()const
334 {
335         DuckList ret;
336         GUIDSet::const_iterator iter;
337         const Type type(get_type_mask());
338
339         for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
340         {
341                 const DuckMap::const_iterator d_iter(duck_map.find(*iter));
342
343                 if(d_iter==duck_map.end())
344                         continue;
345
346                 if(( d_iter->second->get_type() && (!(type & d_iter->second->get_type())) ) )
347                         continue;
348
349                 ret.push_back(d_iter->second);
350         }
351         return ret;
352 }
353
354 DuckList
355 Duckmatic::get_duck_list()const
356 {
357         DuckList ret;
358         DuckMap::const_iterator iter;
359         for(iter=duck_map.begin();iter!=duck_map.end();++iter)
360                 ret.push_back(iter->second);
361         return ret;
362 }
363
364 void
365 Duckmatic::unselect_duck(const etl::handle<Duck> &duck)
366 {
367         if(duck && selected_ducks.count(duck->get_guid()))
368         {
369                 selected_ducks.erase(duck->get_guid());
370                 signal_duck_selection_changed_();
371         }
372 }
373
374 void
375 Duckmatic::toggle_select_duck(const etl::handle<Duck> &duck)
376 {
377         if(duck_is_selected(duck))
378                 unselect_duck(duck);
379         else
380                 select_duck(duck);
381 }
382
383 void
384 Duckmatic::translate_selected_ducks(const synfig::Vector& vector)
385 {
386         if(duck_dragger_)
387                 duck_dragger_->duck_drag(this,vector);
388 }
389
390 void
391 Duckmatic::start_duck_drag(const synfig::Vector& offset)
392 {
393         if(duck_dragger_)
394                 duck_dragger_->begin_duck_drag(this,offset);
395
396         //drag_offset_=offset;
397         drag_offset_=find_duck(offset)->get_trans_point();
398 }
399
400 bool
401 Duckmatic::end_duck_drag()
402 {
403         if(duck_dragger_)
404                 return duck_dragger_->end_duck_drag(this);
405         return false;
406 }
407
408 Point
409 Duckmatic::snap_point_to_grid(const Point& x, float radius)const
410 {
411         Point ret(x);
412
413         GuideList::const_iterator guide_x,guide_y;
414         bool has_guide_x(false), has_guide_y(false);
415
416         guide_x=find_guide_x(ret,radius);
417         if(guide_x!=guide_list_x_.end())
418                 has_guide_x=true;
419
420         guide_y=find_guide_y(ret,radius);
421         if(guide_y!=guide_list_y_.end())
422                 has_guide_y=true;
423
424         if(get_grid_snap())
425         {
426                 Point snap(
427                         floor(ret[0]/get_grid_size()[0]+0.5)*get_grid_size()[0],
428                         floor(ret[1]/get_grid_size()[1]+0.5)*get_grid_size()[1]
429                 );
430
431                 if(abs(snap[0]-ret[0])<=radius && (!has_guide_x || abs(snap[0]-ret[0])<=abs(*guide_x-ret[0])))
432                         ret[0]=snap[0],has_guide_x=false;
433                 if(abs(snap[1]-ret[1])<=radius && (!has_guide_y || abs(snap[1]-ret[1])<=abs(*guide_y-ret[1])))
434                         ret[1]=snap[1],has_guide_y=false;
435         }
436
437         if(guide_snap)
438         {
439                 if(has_guide_x)
440                         ret[0]=*guide_x;
441                 if(has_guide_y)
442                         ret[1]=*guide_y;
443         }
444
445         if(axis_lock)
446         {
447                 ret-=drag_offset_;
448                 if(abs(ret[0])<abs(ret[1]))
449                         ret[0]=0;
450                 else
451                         ret[1]=0;
452                 ret+=drag_offset_;
453         }
454
455         return ret;
456 }
457
458 void
459 DuckDrag_Translate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
460 {
461         last_translate_=Vector(0,0);
462         {
463                 drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
464
465                 snap=Vector(0,0);
466         }
467
468         const DuckList selected_ducks(duckmatic->get_selected_ducks());
469         DuckList::const_iterator iter;
470
471         positions.clear();
472         for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
473         {
474                 Point p((*iter)->get_trans_point());
475                 positions.push_back(p);
476         }
477 }
478
479 bool
480 DuckDrag_Translate::end_duck_drag(Duckmatic* duckmatic)
481 {
482         if(last_translate_.mag()>0.0001)
483         {
484                 duckmatic->signal_edited_selected_ducks();
485                 return true;
486         }
487         else
488         {
489                 duckmatic->signal_user_click_selected_ducks(0);
490                 return false;
491         }
492 }
493
494 void
495 DuckDrag_Translate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
496 {
497         const DuckList selected_ducks(duckmatic->get_selected_ducks());
498         DuckList::const_iterator iter;
499
500         synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_);
501         int i;
502
503         for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
504         {
505                 if((*iter)->get_type()!=Duck::TYPE_VERTEX &&
506                    (*iter)->get_type()!=Duck::TYPE_POSITION)
507                         continue;
508                 (*iter)->set_trans_point(positions[i]+vect);
509         }
510         for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
511         {
512                 if((*iter)->get_type()==Duck::TYPE_VERTEX ||
513                    (*iter)->get_type()==Duck::TYPE_POSITION)
514                         continue;
515                 (*iter)->set_trans_point(positions[i]+vect);
516         }
517         last_translate_=vect;
518 }
519
520 void
521 Duckmatic::signal_edited_selected_ducks()
522 {
523         const DuckList ducks(get_selected_ducks());
524         DuckList::const_iterator iter;
525
526         synfig::GUIDSet old_set(selected_ducks);
527
528         // If we have more than 20 things to move, then display
529         // something to explain that it may take a moment
530         smart_ptr<OneMoment> wait; if(ducks.size()>20)wait.spawn();
531
532         // Go ahead and call everyone's signals
533         for(iter=ducks.begin();iter!=ducks.end();++iter)
534         {
535                 if ((*iter)->get_type() == Duck::TYPE_ANGLE)
536                 {
537                         if(!(*iter)->signal_edited_angle()((*iter)->get_rotations()))
538                         {
539                                 selected_ducks=old_set;
540                                 throw String("Bad edit");
541                         }
542                 }
543                 else
544                 {
545                         if(!(*iter)->signal_edited()((*iter)->get_point()))
546                         {
547                                 selected_ducks=old_set;
548                                 throw String("Bad edit");
549                         }
550                 }
551         }
552         selected_ducks=old_set;
553 }
554
555 void
556 Duckmatic::signal_user_click_selected_ducks(int button)
557 {
558         const DuckList ducks(get_selected_ducks());
559         DuckList::const_iterator iter;
560
561         for(iter=ducks.begin();iter!=ducks.end();++iter)
562         {
563                 (*iter)->signal_user_click(button)();
564         }
565 }
566
567 void
568 Duckmatic::add_duck(const etl::handle<Duck> &duck)
569 {
570         //if(!duck_map.count(duck->get_guid()))
571         {
572                 if(duck_data_share_map.count(duck->get_data_guid()))
573                 {
574                         duck->set_shared_point(duck_data_share_map[duck->get_data_guid()]);
575                 }
576                 else
577                 {
578                         etl::smart_ptr<synfig::Point> point(new Point(duck->get_point()));
579                         duck->set_shared_point(point);
580                         duck_data_share_map[duck->get_data_guid()]=point;
581                 }
582
583                 duck_map.insert(duck);
584         }
585
586         last_duck_guid=duck->get_guid();
587 }
588
589 void
590 Duckmatic::add_bezier(const etl::handle<Bezier> &bezier)
591 {
592         bezier_list_.push_back(bezier);
593 }
594
595 void
596 Duckmatic::add_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
597 {
598         assert(stroke_point_list);
599
600         std::list<etl::handle<Stroke> >::iterator iter;
601
602         for(iter=stroke_list_.begin();iter!=stroke_list_.end();++iter)
603         {
604                 if((*iter)->stroke_data==stroke_point_list)
605                         return;
606         }
607
608         etl::handle<Stroke> stroke(new Stroke());
609
610         stroke->stroke_data=stroke_point_list;
611         stroke->color=color;
612
613         stroke_list_.push_back(stroke);
614 }
615
616 void
617 Duckmatic::add_persistent_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
618 {
619         add_stroke(stroke_point_list,color);
620         persistent_stroke_list_.push_back(stroke_list_.back());
621 }
622
623 void
624 Duckmatic::clear_persistent_strokes()
625 {
626         persistent_stroke_list_.clear();
627 }
628
629 void
630 Duckmatic::set_show_persistent_strokes(bool x)
631 {
632         if(x!=show_persistent_strokes)
633         {
634                 show_persistent_strokes=x;
635                 if(x)
636                         stroke_list_=persistent_stroke_list_;
637                 else
638                         stroke_list_.clear();
639         }
640 }
641
642 void
643 Duckmatic::erase_duck(const etl::handle<Duck> &duck)
644 {
645         duck_map.erase(duck->get_guid());
646 }
647
648 etl::handle<Duckmatic::Duck>
649 Duckmatic::find_similar_duck(etl::handle<Duck> duck)
650 {
651         DuckMap::const_iterator iter(duck_map.find(duck->get_guid()));
652         if(iter!=duck_map.end())
653                 return iter->second;
654         return 0;
655
656 /*      std::list<handle<Duck> >::reverse_iterator iter;
657
658         for(iter=duck_list_.rbegin();iter!=duck_list_.rend();++iter)
659         {
660                 if(*iter!=duck && **iter==*duck)
661                 {
662                         //synfig::info("Found similar duck! (iter:%08x vs. duck:%08x)",iter->get(), duck.get());
663                         return *iter;
664                 }
665         }
666         return 0;
667 */
668 }
669
670 etl::handle<Duckmatic::Duck>
671 Duckmatic::add_similar_duck(etl::handle<Duck> duck)
672 {
673         etl::handle<Duck> similar(find_similar_duck(duck));
674         if(!similar)
675         {
676                 add_duck(duck);
677                 return duck;
678         }
679         return similar;
680 }
681
682 void
683 Duckmatic::erase_bezier(const etl::handle<Bezier> &bezier)
684 {
685         std::list<handle<Bezier> >::iterator iter;
686
687         for(iter=bezier_list_.begin();iter!=bezier_list_.end();++iter)
688         {
689                 if(*iter==bezier)
690                 {
691                         bezier_list_.erase(iter);
692                         return;
693                 }
694         }
695         synfig::warning("Unable to find bezier to erase!");
696 }
697
698 etl::handle<Duckmatic::Duck>
699 Duckmatic::last_duck()const
700 {
701         DuckMap::const_iterator iter(duck_map.find(last_duck_guid));
702         if(iter!=duck_map.end())
703                 return iter->second;
704         return 0;
705 }
706
707 etl::handle<Duckmatic::Bezier>
708 Duckmatic::last_bezier()const
709 {
710         return bezier_list_.back();
711 }
712
713 etl::handle<Duckmatic::Duck>
714 Duckmatic::find_duck(synfig::Point point, synfig::Real radius, Duck::Type type)
715 {
716         if(radius==0)radius=10000000;
717
718         if(type==Duck::TYPE_DEFAULT)
719                 type=get_type_mask();
720
721         Real closest(10000000);
722         etl::handle<Duck> ret;
723
724         DuckMap::const_iterator iter;
725
726         for(iter=duck_map.begin();iter!=duck_map.end();++iter)
727         {
728                 const Duck::Handle& duck(iter->second);
729
730                 if(!duck->get_editable())
731                         continue;
732                 Real dist((duck->get_trans_point()-point).mag_squared());
733
734                 if(duck->get_type()&Duck::TYPE_VERTEX)
735                         dist*=1.0001;
736
737                 if(dist<=closest && !( duck->get_type() && (!(type & duck->get_type())) ) )
738                 {
739                         {
740                                 closest=dist;
741                                 ret=duck;
742                         }
743                 }
744         }
745
746         if(radius==0 || closest<radius*radius)
747                 return ret;
748
749         return 0;
750 }
751
752 etl::handle<Duckmatic::Bezier>
753 Duckmatic::find_bezier(synfig::Point point, synfig::Real radius,float* location)
754 {
755         return find_bezier(point,radius,radius,location);
756 }
757
758 etl::handle<Duckmatic::Bezier>
759 Duckmatic::find_bezier(synfig::Point pos, synfig::Real scale, synfig::Real radius, float* location)
760 {
761         if(radius==0)radius=10000000;
762         Real closest(10000000);
763         etl::handle<Bezier> ret;
764
765         bezier<Point>   curve;
766
767         Real    d,step;
768         float   time = 0;
769         float   best_time = 0;
770
771         for(std::list<handle<Bezier> >::const_iterator iter=bezier_list().begin();iter!=bezier_list().end();++iter)
772         {
773                 curve[0] = (*iter)->p1->get_trans_point();
774                 curve[1] = (*iter)->c1->get_trans_point();
775                 curve[2] = (*iter)->c2->get_trans_point();
776                 curve[3] = (*iter)->p2->get_trans_point();
777                 curve.sync();
778
779 #if 0
780                 // I don't know why this doesn't work
781                 time=curve.find_closest(pos,6);
782                 d=((curve(time)-pos).mag_squared());
783
784 #else
785                 //set the step size based on the size of the picture
786                 d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag()     + (curve[3]-curve[2]).mag();
787
788                 step = d/(2*scale); //want to make the distance between lines happy
789
790                 step = max(step,0.01); //100 samples should be plenty
791                 step = min(step,0.1); //10 is minimum
792
793                 d = find_closest(curve,pos,step,&closest,&time);
794 #endif
795
796                 if(d < closest)
797                 {
798                         closest = d;
799                         ret = *iter;
800                         best_time=time;
801                 }
802         }
803
804         if(closest < radius*radius)
805         {
806                 if(location)
807                         *location = best_time;  // We need to square-root this because we were dealing with squared distances
808
809                 return ret;
810         }
811
812         return 0;
813 }
814
815 bool
816 Duckmatic::save_sketch(const synfig::String& filename)const
817 {
818         std::ofstream file(filename.c_str());
819
820         if(!file)return false;
821
822         file<<"SKETCH"<<endl;
823
824         std::list<etl::handle<Stroke> >::const_iterator iter;
825
826         for(iter=persistent_stroke_list_.begin();iter!=persistent_stroke_list_.end();++iter)
827         {
828                 file<<"C "
829                         <<(*iter)->color.get_r()<<' '
830                         <<(*iter)->color.get_g()<<' '
831                         <<(*iter)->color.get_b()
832                 <<endl;
833                 std::list<synfig::Point>::const_iterator viter;
834                 for(viter=(*iter)->stroke_data->begin();viter!=(*iter)->stroke_data->end();++viter)
835                 {
836                         file<<"V "
837                                 <<(*viter)[0]<<' '
838                                 <<(*viter)[1]
839                         <<endl;
840                 }
841         }
842         if(!file)return false;
843         sketch_filename_=filename;
844         signal_sketch_saved_();
845         return true;
846 }
847
848 bool
849 Duckmatic::load_sketch(const synfig::String& filename)
850 {
851         std::ifstream file(filename.c_str());
852
853         if(!file)
854                 return false;
855
856         std::string line;
857         getline(file,line);
858
859         if(line!="SKETCH")
860         {
861                 synfig::error("Not a sketch");
862                 return false;
863         }
864
865         etl::smart_ptr<std::list<synfig::Point> > stroke_data;
866
867         while(file)
868         {
869                 getline(file,line);
870
871                 if(line.empty())
872                         continue;
873
874                 switch(line[0])
875                 {
876                 case 'C':
877                 case 'c':
878                         {
879                                 stroke_data.spawn();
880                                 float r,g,b;
881                                 if(!strscanf(line,"C %f %f %f",&r, &g, &b))
882                                 {
883                                         synfig::warning("Bad color line \"%s\"",line.c_str());
884                                         r=0;g=0;b=0;
885                                 }
886                                 add_persistent_stroke(stroke_data, synfig::Color(r,g,b));
887                         }
888                         break;
889                 case 'V':
890                 case 'v':
891                         if(!stroke_data)
892                         {
893                                 stroke_data.spawn();
894                                 add_persistent_stroke(stroke_data, synfig::Color(0,0,0));
895                         }
896                         float x,y;
897                         if(!strscanf(line,"V %f %f",&x, &y))
898                                 synfig::warning("Bad vertex \"%s\"",line.c_str());
899                         else
900                                 stroke_data->push_back(synfig::Vector(x,y));
901                         break;
902                 default:
903                         synfig::warning("Unexpected sketch token '%c'",line[0]);
904                         break;
905                 }
906         }
907
908         sketch_filename_=filename;
909         return true;
910 }
911
912 Duckmatic::Push::Push(Duckmatic *duckmatic_):
913         duckmatic_(duckmatic_)
914 {
915         duck_map=duckmatic_->duck_map;
916         bezier_list_=duckmatic_->bezier_list_;
917         duck_data_share_map=duckmatic_->duck_data_share_map;
918         stroke_list_=duckmatic_->stroke_list_;
919         duck_dragger_=duckmatic_->duck_dragger_;
920         needs_restore=true;
921 }
922
923 Duckmatic::Push::~Push()
924 {
925         if(needs_restore)
926                 restore();
927 }
928
929 void
930 Duckmatic::Push::restore()
931 {
932         duckmatic_->duck_map=duck_map;
933         duckmatic_->bezier_list_=bezier_list_;
934         duckmatic_->duck_data_share_map=duck_data_share_map;
935         duckmatic_->stroke_list_=stroke_list_;
936         duckmatic_->duck_dragger_=duck_dragger_;
937         needs_restore=false;
938 }
939
940 inline String guid_string(const synfigapp::ValueDesc& x)
941 {
942         if(x.parent_is_layer_param())
943                 return strprintf("%s",x.get_layer()->get_guid().get_string().c_str())+x.get_param_name();
944         //if(x.is_value_node())
945                 return strprintf("%s",x.get_value_node()->get_guid().get_string().c_str());
946 }
947
948 inline GUID calc_duck_guid(const synfigapp::ValueDesc& x,const synfig::TransformStack& transform_stack)
949 {
950         GUID ret(0);
951
952         if(x.parent_is_layer_param())
953         {
954                 ret=x.get_layer()->get_guid()^GUID::hasher(x.get_param_name());
955         }
956         else
957         {
958                 ret=x.get_value_node()->get_guid();
959         }
960
961         ret^=transform_stack.get_guid();
962         return ret;
963 }
964
965 /*
966 Duck::Handle
967 Duckmatic::create_duck_from(const synfigapp::ValueDesc& value_desc,etl::handle<CanvasView> canvas_view, const synfig::TransformStack& transform_stack, int modifier, synfig::ParamDesc *param_desc)
968 {
969         GUID duck_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(modifier));
970         etl::handle<Duck> duck=new Duck();
971
972         return duck;
973 }
974 */
975
976 bool
977 Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handle<CanvasView> canvas_view, const synfig::TransformStack& transform_stack, synfig::ParamDesc *param_desc, int multiple)
978 {
979         ValueBase::Type type=value_desc.get_value_type();
980 #define REAL_COOKIE             reinterpret_cast<synfig::ParamDesc*>(28)
981         switch(type)
982         {
983         case ValueBase::TYPE_REAL:
984
985                 if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
986                 {
987                         etl::handle<Duck> duck=new Duck();
988                         duck->set_transform_stack(transform_stack);
989                         duck->set_radius(true);
990                         duck->set_type(Duck::TYPE_RADIUS);
991
992                         duck->set_point(Point(value_desc.get_value(get_time()).get(Real()),0));
993                         duck->set_name(guid_string(value_desc));
994                         if(value_desc.is_value_node())
995                         {
996                                 // If the ValueNode can be directly manipulated,
997                                 // then set it as so.
998                                 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
999                         }
1000                         else
1001                         {
1002                                 duck->set_editable(true);
1003                         }
1004
1005                         if(param_desc && param_desc!=REAL_COOKIE)
1006                         {
1007                                 if(!param_desc->get_origin().empty())
1008                                 {
1009                                         synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1010                                         /*
1011                                         duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1012                                         */
1013                                         add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1014                                         duck->set_origin(last_duck());
1015                                 }
1016                                 duck->set_scalar(param_desc->get_scalar());
1017                         }
1018
1019                         duck->signal_edited().clear(); // value_desc.get_value_type() == ValueBase::TYPE_REAL:
1020                         duck->signal_edited().connect(
1021                                 sigc::bind(
1022                                         sigc::mem_fun(
1023                                                 *canvas_view,
1024                                                 &studio::CanvasView::on_duck_changed
1025                                         ),
1026                                         value_desc
1027                                 )
1028                         );
1029                         duck->set_value_desc(value_desc);
1030
1031                         duck->signal_user_click(2).connect(
1032                                 sigc::bind(
1033                                         sigc::bind(
1034                                                 sigc::mem_fun(
1035                                                         *canvas_view,
1036                                                         &studio::CanvasView::popup_param_menu
1037                                                 ),
1038                                                 0.0f
1039                                         ),
1040                                         value_desc
1041                                 )
1042                         );
1043
1044                         duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1045
1046                         add_duck(duck);
1047
1048                         return true;
1049                 }
1050                 break;
1051
1052         case ValueBase::TYPE_ANGLE:
1053
1054                 if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
1055                 {
1056                         etl::handle<Duck> duck=new Duck();
1057                         duck->set_type(Duck::TYPE_ANGLE);
1058                         duck->set_transform_stack(transform_stack);
1059                         synfig::Angle angle;
1060
1061                         angle=value_desc.get_value(get_time()).get(Angle());
1062                         duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1063                         duck->set_name(guid_string(value_desc));
1064                         if(value_desc.is_value_node())
1065                         {
1066                                 ValueNode::Handle value_node=value_desc.get_value_node();
1067                                 //duck->set_name(strprintf("%x",value_node.get()));
1068
1069                                 // If the ValueNode can be directly manipulated,
1070                                 // then set it as so.
1071                                 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1072                         }
1073                         else
1074                         {
1075                                 //angle=(value_desc.get_value().get(Angle()));
1076                                 //duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1077                                 //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1078                                 duck->set_editable(true);
1079                         }
1080
1081                         if(param_desc && param_desc!=REAL_COOKIE)
1082                         {
1083                                 if(!param_desc->get_origin().empty())
1084                                 {
1085                                         synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1086                                         /*
1087                                         duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1088                                         */
1089                                         add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1090                                         duck->set_origin(last_duck());
1091                                 }
1092                                 duck->set_scalar(param_desc->get_scalar());
1093                         }
1094
1095                         duck->signal_edited().clear(); // value_desc.get_value_type() == ValueBase::TYPE_ANGLE:
1096                         duck->signal_edited_angle().clear();
1097                         duck->signal_edited_angle().connect(
1098                                 sigc::bind(
1099                                         sigc::mem_fun(
1100                                                 *canvas_view,
1101                                                 &studio::CanvasView::on_duck_angle_changed
1102                                         ),
1103                                         value_desc
1104                                 )
1105                         );
1106                         duck->set_value_desc(value_desc);
1107
1108                         duck->signal_user_click(2).connect(
1109                                 sigc::bind(
1110                                         sigc::bind(
1111                                                 sigc::mem_fun(
1112                                                         *canvas_view,
1113                                                         &studio::CanvasView::popup_param_menu
1114                                                 ),
1115                                                 0.0f
1116                                         ),
1117                                         value_desc
1118                                 )
1119                         );
1120                         duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1121
1122                         add_duck(duck);
1123
1124                         return true;
1125                 }
1126                 break;
1127
1128         case ValueBase::TYPE_VECTOR:
1129                 {
1130                         etl::handle<Duck> duck=new Duck();
1131                         duck->set_transform_stack(transform_stack);
1132
1133                         duck->set_point(value_desc.get_value(get_time()).get(Point()));
1134                         duck->set_name(guid_string(value_desc));
1135                         if(value_desc.is_value_node())
1136                         {
1137                                 //duck->set_name(strprintf("%x",value_desc.get_value_node().get()));
1138
1139                                 // If the ValueNode can be directly manipulated,
1140                                 // then set it as so.
1141                                 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1142                         }
1143                         else
1144                         {
1145                                 //duck->set_point(value_desc.get_value().get(Point()));
1146                                 //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1147                                 duck->set_editable(true);
1148                         }
1149
1150                         // If we were passed a parameter description
1151                         if(param_desc)
1152                         {
1153                                 if(!param_desc->get_connect().empty())
1154                                 {
1155                                         synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_connect());
1156                                         Duck::Handle connect_duck;
1157                                         if(duck_map.find(calc_duck_guid(value_desc_origin,transform_stack)^GUID::hasher(0))!=duck_map.end())
1158                                         {
1159                                                 connect_duck=duck_map[calc_duck_guid(value_desc_origin,transform_stack)^GUID::hasher(0)];
1160                                         }
1161                                         else
1162                                         {
1163                                                 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1164                                                 connect_duck=last_duck();
1165                                         }
1166                                         duck->set_connect_duck(connect_duck);
1167                                 }
1168                                 if(!param_desc->get_box().empty())
1169                                 {
1170                                         synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_box());
1171                                         add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1172                                         duck->set_box_duck(last_duck());
1173                                 }
1174
1175                                 // If we have an origin
1176                                 if(!param_desc->get_origin().empty())
1177                                 {
1178                                         synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1179                                         /*
1180                                         duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1181                                         */
1182                                         add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1183                                         duck->set_origin(last_duck());
1184                                         duck->set_type(Duck::TYPE_VERTEX);
1185                                 }
1186                                 else
1187                                         duck->set_type(Duck::TYPE_POSITION);
1188
1189                                 duck->set_scalar(param_desc->get_scalar());
1190                         }
1191                         else
1192                                 duck->set_type(Duck::TYPE_POSITION);
1193
1194                         duck->signal_edited().clear(); // value_desc.get_value_type() == ValueBase::TYPE_VECTOR:
1195                         duck->signal_edited().connect(
1196                                 sigc::bind(
1197                                         sigc::mem_fun(
1198                                                 *canvas_view,
1199                                                 &studio::CanvasView::on_duck_changed
1200                                         ),
1201                                         value_desc
1202                                 )
1203                         );
1204                         duck->set_value_desc(value_desc);
1205
1206                         duck->signal_user_click(2).connect(
1207                                 sigc::bind(
1208                                         sigc::bind(
1209                                                 sigc::mem_fun(
1210                                                         *canvas_view,
1211                                                         &studio::CanvasView::popup_param_menu
1212                                                 ),
1213                                                 1.0f
1214                                         ),
1215                                         value_desc
1216                                 )
1217                         );
1218                         duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1219                         add_duck(duck);
1220
1221                         return true;
1222                 }
1223                 break;
1224 /*      case ValueBase::TYPE_SEGMENT:
1225                 {
1226                         etl::handle<Bezier> bezier(new Bezier());
1227                         ValueNode_Composite::Handle value_node;
1228
1229                         if(value_desc.is_value_node() &&
1230                                 (value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
1231                         )
1232                         {
1233                                 if(!add_to_ducks(synfigapp::ValueDesc(value_node,0),canvas_view,transform_stack))
1234                                         return false;
1235                                 bezier->p1=last_duck();
1236                                 bezier->p1->set_type(Duck::TYPE_VERTEX);
1237                                 if(!add_to_ducks(synfigapp::ValueDesc(value_node,1),canvas_view,transform_stack))
1238                                         return false;
1239                                 bezier->c1=last_duck();
1240                                 bezier->c1->set_type(Duck::TYPE_TANGENT);
1241                                 bezier->c1->set_origin(bezier->p1);
1242                                 bezier->c1->set_scalar(TANGENT_BEZIER_SCALE);
1243                                 bezier->c1->set_tangent(true);
1244
1245                                 if(!add_to_ducks(synfigapp::ValueDesc(value_node,2),canvas_view,transform_stack))
1246                                         return false;
1247                                 bezier->p2=last_duck();
1248                                 bezier->p2->set_type(Duck::TYPE_VERTEX);
1249                                 if(!add_to_ducks(synfigapp::ValueDesc(value_node,3),canvas_view,transform_stack))
1250                                         return false;
1251                                 bezier->c2=last_duck();
1252                                 bezier->c2->set_type(Duck::TYPE_TANGENT);
1253                                 bezier->c2->set_origin(bezier->p2);
1254                                 bezier->c2->set_scalar(-TANGENT_BEZIER_SCALE);
1255                                 bezier->c2->set_tangent(true);
1256
1257                                 bezier->signal_user_click(2).connect(
1258                                         sigc::bind(
1259                                                 sigc::mem_fun(
1260                                                         *canvas_view,
1261                                                         &studio::CanvasView::popup_param_menu_bezier
1262                                                 ),
1263                                                 value_desc
1264                                         )
1265                                 );
1266
1267                                 add_bezier(bezier);
1268                         }
1269                         else if(value_desc.get_value().is_valid())
1270                         {
1271                                 Segment segment=value_desc.get_value();
1272                                 etl::handle<Duck> duck_p,duck_c;
1273                                 synfig::String name;
1274                                 if(param_desc)
1275                                 {
1276                                         name=param_desc->get_local_name();
1277                                 }
1278                                 else
1279                                 {
1280                                         name=guid_string(value_desc);
1281                                 }
1282
1283                                 duck_p=new class Duck(segment.p1);
1284                                 duck_p->set_name(name+".P1");
1285                                 duck_p->set_type(Duck::TYPE_VERTEX);
1286                                 add_duck(duck_p);
1287
1288                                 duck_c=new class Duck(segment.t1);
1289                                 duck_c->set_name(name+".T1");
1290                                 duck_c->set_type(Duck::TYPE_TANGENT);
1291                                 add_duck(duck_c);
1292                                 duck_c->set_origin(duck_p);
1293                                 duck_c->set_scalar(TANGENT_HANDLE_SCALE);
1294                                 duck_c->set_tangent(true);
1295
1296                                 bezier->p1=duck_p;
1297                                 bezier->c1=duck_c;
1298
1299                                 duck_p=new class Duck(segment.p2);
1300                                 duck_p->set_name(name+".P2");
1301                                 duck_p->set_type(Duck::TYPE_VERTEX);
1302                                 add_duck(duck_p);
1303
1304                                 duck_c=new class Duck(segment.t2);
1305                                 duck_c->set_type(Duck::TYPE_TANGENT);
1306                                 duck_c->set_name(name+".T2");
1307                                 add_duck(duck_c);
1308                                 duck_c->set_origin(duck_p);
1309                                 duck_c->set_scalar(-TANGENT_HANDLE_SCALE);
1310                                 duck_c->set_tangent(true);
1311
1312                                 bezier->p2=duck_p;
1313                                 bezier->c2=duck_c;
1314                                 add_bezier(bezier);
1315                         }
1316
1317                         return true;
1318                 }
1319                 break;
1320 */
1321         case ValueBase::TYPE_BLINEPOINT:
1322         {
1323
1324                 if(value_desc.is_value_node() &&
1325                         ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
1326                 )
1327                 {
1328                         ValueNode_Composite::Handle value_node;
1329                         value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node());
1330
1331                         if(!add_to_ducks(synfigapp::ValueDesc(value_node,0),canvas_view,transform_stack))
1332                                 return false;
1333                         etl::handle<Duck> vertex_duck(last_duck());
1334                         vertex_duck->set_type(Duck::TYPE_VERTEX);
1335                         if(!add_to_ducks(synfigapp::ValueDesc(value_node,4),canvas_view,transform_stack))
1336                                 return false;
1337                         etl::handle<Duck> t1_duck(last_duck());
1338
1339                         t1_duck->set_origin(vertex_duck);
1340                         t1_duck->set_scalar(-TANGENT_HANDLE_SCALE);
1341                         t1_duck->set_tangent(true);
1342
1343                         etl::handle<Duck> t2_duck;
1344
1345                         // If the tangents are split
1346                         if((*value_node->get_link("split"))(get_time()).get(bool()))
1347                         {
1348                                 if(!add_to_ducks(synfigapp::ValueDesc(value_node,5),canvas_view,transform_stack))
1349                                         return false;
1350                                 t2_duck=last_duck();
1351                                 t2_duck->set_origin(vertex_duck);
1352                                 t2_duck->set_scalar(TANGENT_HANDLE_SCALE);
1353                                 t2_duck->set_tangent(true);
1354                         }
1355                         else
1356                         {
1357                                 if(!add_to_ducks(synfigapp::ValueDesc(value_node,4),canvas_view,transform_stack))
1358                                         return false;
1359                                 t2_duck=last_duck();
1360                                 t2_duck->set_origin(vertex_duck);
1361                                 t2_duck->set_scalar(TANGENT_HANDLE_SCALE);
1362                                 t2_duck->set_tangent(true);
1363                         }
1364                         return true;
1365                 }
1366
1367         }
1368         break;
1369         case ValueBase::TYPE_LIST:
1370         {
1371                 // Check for BLine
1372                 if(value_desc.is_value_node() &&
1373                         ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node())
1374                 )
1375                 {
1376                         ValueNode_BLine::Handle value_node;
1377                         value_node=ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node());
1378
1379                         int i,first=-1;
1380
1381                         etl::handle<Bezier> bezier;
1382                         etl::handle<Duck> first_duck;
1383                         etl::handle<Duck> duck, tduck;
1384
1385                         for(i=0;i<value_node->link_count();i++)
1386                         {
1387                                 float amount(value_node->list[i].amount_at_time(get_time()));
1388                                 if(amount<0.9999f)
1389                                         continue;
1390                                 if(first==-1)first=i;
1391
1392                                 BLinePoint bline_point((*value_node->get_link(i))(get_time()));
1393
1394                                 ValueNode_Composite::Handle vertex_value_node(
1395                                         ValueNode_Composite::Handle::cast_dynamic(
1396                                                 value_node->get_link(i)
1397                                         )
1398                                 );
1399
1400                                 // Add the vertex duck
1401                                 if(vertex_value_node)
1402                                 {
1403                                         if(add_to_ducks(synfigapp::ValueDesc(vertex_value_node,0),canvas_view,transform_stack))
1404                                         {
1405                                                 duck=last_duck();
1406                                                 if(i==first)
1407                                                         first_duck=duck;
1408                                                 duck->set_type(Duck::TYPE_VERTEX);
1409
1410                                                 duck->signal_user_click(2).clear();
1411                                                 duck->signal_user_click(2).connect(
1412                                                         sigc::bind(
1413                                                                 sigc::bind(
1414                                                                         sigc::mem_fun(
1415                                                                                 *canvas_view,
1416                                                                                 &studio::CanvasView::popup_param_menu
1417                                                                         ),
1418                                                                         1.0f
1419                                                                 ),
1420                                                                 synfigapp::ValueDesc(value_node,i)
1421                                                         )
1422                                                 );
1423                                                 duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
1424
1425                                                 if(param_desc)
1426                                                 {
1427                                                         if(!param_desc->get_origin().empty())
1428                                                         {
1429                                                                 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1430                                                                 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1431                                                                 duck->set_origin(last_duck());
1432 /*
1433                                                                 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1434                                                                 if(value.same_type_as(synfig::Point()))
1435                                                                         duck->set_origin(value.get(synfig::Point()));
1436 */
1437                                                         }
1438                                                 }
1439                                         }
1440                                         else
1441                                                 return false;
1442                                 }
1443                                 else
1444                                 {
1445                                         duck=new Duck(bline_point.get_vertex());
1446                                         if(i==first)
1447                                                 first_duck=duck;
1448                                         duck->set_transform_stack(transform_stack);
1449                                         duck->set_editable(false);
1450                                         //duck->set_name(strprintf("%x-vertex",value_node->get_link(i).get()));
1451                                         duck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".v");
1452
1453                                         duck->set_type(Duck::TYPE_VERTEX);
1454                                         if(param_desc)
1455                                         {
1456                                                 if(!param_desc->get_origin().empty())
1457                                                 {
1458                                                                 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1459                                                                 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1460                                                                 duck->set_origin(last_duck());
1461 /*
1462                                                                 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1463                                                                 if(value.same_type_as(synfig::Point()))
1464                                                                         duck->set_origin(value.get(synfig::Point()));
1465 */
1466                                                 }
1467                                         }
1468                                         duck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".v"));
1469                                         duck=add_similar_duck(duck);
1470 //                                      add_duck(duck);
1471                                 }
1472
1473                                 // Add the width duck only if we have a hint of scale
1474                                 if(param_desc && !param_desc->get_hint().empty())
1475                                 {
1476                                         etl::handle<Duck> width;
1477                                         if(add_to_ducks(synfigapp::ValueDesc(vertex_value_node,1),canvas_view,transform_stack,REAL_COOKIE))
1478                                         {
1479                                                 width=last_duck();
1480                                                 width->set_origin(duck);
1481                                                 width->set_type(Duck::TYPE_WIDTH);
1482                                                 width->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".w");
1483                                                 {
1484                                                         ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_hint()).get_value(get_time()));
1485                                                         if(value.same_type_as(synfig::Real()))
1486                                                                 width->set_scalar(value.get(synfig::Real())*0.5f);
1487                                                 }
1488                                         }
1489                                         else
1490                                                 synfig::error("Unable to add width duck!");
1491                                 }
1492
1493                                 if(bezier)
1494                                 {
1495                                         // Add the tangent1 duck
1496                                         if(vertex_value_node)
1497                                         {
1498                                                 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,4),canvas_view,transform_stack))
1499                                                         return false;
1500                                                 tduck=last_duck();
1501                                         }
1502                                         else
1503                                         {
1504                                                 tduck=new Duck(bline_point.get_tangent1());
1505                                                 tduck->set_transform_stack(transform_stack);
1506                                                 tduck->set_editable(false);
1507                                                 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t1");
1508 //                                              tduck->set_name(strprintf("%x-tangent1",value_node->get_link(i).get()));
1509                                                 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1510                                                 tduck=add_similar_duck(tduck);
1511 //                                              add_duck(duck);
1512                                         }
1513
1514                                         tduck->set_origin(duck);
1515                                         tduck->set_scalar(-TANGENT_BEZIER_SCALE);
1516                                         tduck->set_tangent(true);
1517
1518                                         bezier->p2=duck;
1519                                         bezier->c2=tduck;
1520
1521                                         bezier->signal_user_click(2).connect(
1522                                                 sigc::bind(
1523                                                         sigc::mem_fun(
1524                                                                 *canvas_view,
1525                                                                 &studio::CanvasView::popup_param_menu_bezier
1526                                                         ),
1527                                                         synfigapp::ValueDesc(value_node,i)
1528                                                 )
1529                                         );
1530
1531                                         duck->signal_user_click(2).clear();
1532                                         duck->signal_user_click(2).connect(
1533                                                 sigc::bind(
1534                                                         sigc::bind(
1535                                                                 sigc::mem_fun(
1536                                                                         *canvas_view,
1537                                                                         &studio::CanvasView::popup_param_menu
1538                                                                 ),
1539                                                                 1.0f
1540                                                         ),
1541                                                         synfigapp::ValueDesc(value_node,i)
1542                                                 )
1543                                         );
1544                                         duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
1545
1546                                         add_bezier(bezier);
1547                                         bezier=0;
1548                                 }
1549
1550                                 if(i+1>=value_node->link_count() && !value_node->get_loop())
1551                                         continue;
1552
1553                                 bezier=new Bezier();
1554
1555                                 // Add the tangent2 duck
1556                                 if(vertex_value_node)
1557                                 {
1558                                         int i=bline_point.get_split_tangent_flag()?5:4;
1559                                         if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,i),canvas_view,transform_stack,0,2))
1560                                                 return false;
1561                                         tduck=last_duck();
1562                                 }
1563                                 else
1564                                 {
1565                                         if(bline_point.get_split_tangent_flag())
1566                                         {
1567                                                 tduck=new Duck(bline_point.get_tangent2());
1568                                                 tduck->set_transform_stack(transform_stack);
1569                                                 //tduck->set_name(strprintf("%x-tangent2",value_node->get_link(i).get()));
1570                                                 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t2");
1571                                                 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t2"));
1572                                         }
1573                                         else
1574                                         {
1575                                                 tduck=new Duck(bline_point.get_tangent1());
1576                                                 tduck->set_transform_stack(transform_stack);
1577                                                 //tduck->set_name(strprintf("%x-tangent1",value_node->get_link(i).get()));
1578                                                 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t1");
1579                                                 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1580                                         }
1581                                         tduck->set_editable(false);
1582                                         tduck=add_similar_duck(tduck);
1583 //                                      add_duck(duck);
1584                                         if(param_desc)
1585                                         {
1586                                                                 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1587                                                                 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1588                                                                 duck->set_origin(last_duck());
1589 /*
1590                                                                 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1591                                                                 if(value.same_type_as(synfig::Point()))
1592                                                                         duck->set_origin(value.get(synfig::Point()));
1593 */
1594 //                                              if(!param_desc->get_origin().empty())
1595 //                                                      duck->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
1596                                         }
1597                                         duck->signal_user_click(2).clear();
1598                                         duck->signal_user_click(2).connect(
1599                                                 sigc::bind(
1600                                                         sigc::bind(
1601                                                                 sigc::mem_fun(
1602                                                                         *canvas_view,
1603                                                                         &studio::CanvasView::popup_param_menu
1604                                                                 ),
1605                                                                 1.0f
1606                                                         ),
1607                                                         synfigapp::ValueDesc(value_node,0)
1608                                                 )
1609                                         );
1610                                         duck->set_value_desc(synfigapp::ValueDesc(value_node,0));
1611
1612                                 }
1613
1614                                 tduck->set_origin(duck);
1615                                 tduck->set_scalar(TANGENT_BEZIER_SCALE);
1616                                 tduck->set_tangent(true);
1617
1618                                 bezier->p1=duck;
1619                                 bezier->c1=tduck;
1620
1621                         }
1622                         // Loop if necessary
1623                         if(bezier && value_node->get_loop())
1624                         {
1625                                 BLinePoint bline_point((*value_node->get_link(first))(get_time()));
1626
1627                                 ValueNode_Composite::Handle vertex_value_node(
1628                                         ValueNode_Composite::Handle::cast_dynamic(
1629                                                 value_node->get_link(first)
1630                                         )
1631                                 );
1632
1633                                 // Add the vertex duck
1634                                 duck=first_duck;
1635                                 /*
1636                                 if(vertex_value_node)
1637                                 {
1638                                         if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,0),canvas_view,transform_stack))
1639                                                 return false;
1640                                         duck=last_duck();
1641                                         if(param_desc)
1642                                         {
1643                                                 if(!param_desc->get_origin().empty())
1644                                                         duck->set_origin(value_desc.get_layer()->get_param(param_desc->get_origin()).get(synfig::Point()));
1645                                         }
1646                                         duck->set_type(Duck::TYPE_VERTEX);
1647                                 }
1648                                 else
1649                                 {
1650                                         duck=new Duck(bline_point.get_vertex());
1651                                         duck->set_transform_stack(transform_stack);
1652                                         if(param_desc)
1653                                         {
1654                                                 if(!param_desc->get_origin().empty())
1655                                                         duck->set_origin(value_desc.get_layer()->get_param(param_desc->get_origin()).get(synfig::Point()));
1656                                         }
1657                                         duck->set_editable(false);
1658                                         duck->set_name(strprintf("%x-vertex",value_node->get_link(first).get()));
1659                                         duck->set_type(Duck::TYPE_VERTEX);
1660                                         duck=add_similar_duck(duck);
1661                                 }
1662                                 */
1663
1664                                         // Add the tangent1 duck
1665                                         if(vertex_value_node)
1666                                         {
1667                                                 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,4),canvas_view,transform_stack))
1668                                                         return false;
1669                                                 tduck=last_duck();
1670                                         }
1671                                         else
1672                                         {
1673                                                 tduck=new Duck(bline_point.get_tangent1());
1674                                                 tduck->set_transform_stack(transform_stack);
1675                                                 tduck->set_editable(false);
1676                                                 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,first))+".t1");
1677                                                 //tduck->set_name(strprintf("%x-tangent1",value_node->get_link(first).get()));
1678                                                 tduck=add_similar_duck(tduck);
1679                                                 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1680                                                 //add_duck(duck);
1681                                         }
1682
1683                                         tduck->set_origin(duck);
1684                                         tduck->set_scalar(-TANGENT_BEZIER_SCALE);
1685                                         tduck->set_tangent(true);
1686
1687                                         bezier->p2=duck;
1688                                         bezier->c2=tduck;
1689                                         bezier->signal_user_click(2).connect(
1690                                                 sigc::bind(
1691                                                         sigc::mem_fun(
1692                                                                 *canvas_view,
1693                                                                 &studio::CanvasView::popup_param_menu_bezier
1694                                                         ),
1695                                                         synfigapp::ValueDesc(value_node,first)
1696                                                 )
1697                                         );
1698                                         duck->signal_user_click(2).clear();
1699                                         duck->signal_user_click(2).connect(
1700                                                 sigc::bind(
1701                                                         sigc::bind(
1702                                                                 sigc::mem_fun(
1703                                                                         *canvas_view,
1704                                                                         &studio::CanvasView::popup_param_menu
1705                                                                 ),
1706                                                                 1.0f
1707                                                         ),
1708                                                         synfigapp::ValueDesc(value_node,first)
1709                                                 )
1710                                         );
1711                                         duck->set_value_desc(synfigapp::ValueDesc(value_node,first));
1712
1713                                         add_bezier(bezier);
1714                                         bezier=0;
1715
1716                         }
1717                         return true;
1718                 }
1719                 else // Check for DynamicList
1720                 if(value_desc.is_value_node() &&
1721                         ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node())
1722                 )
1723                 {
1724                         ValueNode_DynamicList::Handle value_node;
1725                         value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node());
1726                         int i;
1727
1728                         if(value_node->get_contained_type()==ValueBase::TYPE_VECTOR)
1729                         {
1730                                 Bezier bezier;
1731                                 for(i=0;i<value_node->link_count();i++)
1732                                 {
1733                                         if(!value_node->list[i].status_at_time(get_time()))
1734                                                 continue;
1735                                         if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
1736                                                 return false;
1737                                         etl::handle<Duck> duck(last_duck());
1738
1739                                         if(param_desc)
1740                                         {
1741                                                                 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1742                                                                 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1743                                                                 duck->set_origin(last_duck());
1744 /*
1745                                                                 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1746                                                                 if(value.same_type_as(synfig::Point()))
1747                                                                         duck->set_origin(value.get(synfig::Point()));
1748 */
1749 //                                              if(!param_desc->get_origin().empty())
1750 //                                                      last_duck()->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
1751                                         }
1752                                         duck->set_type(Duck::TYPE_VERTEX);
1753                                         bezier.p1=bezier.p2;bezier.c1=bezier.c2;
1754                                         bezier.p2=bezier.c2=duck;
1755
1756                                         if(i>0)
1757                                         {
1758                                                 handle<Bezier> bezier_(new Bezier());
1759                                                 bezier_->p1=bezier.p1;
1760                                                 bezier_->c1=bezier.c1;
1761                                                 bezier_->p2=bezier.p2;
1762                                                 bezier_->c2=bezier.c2;
1763                                                 add_bezier(bezier_);
1764                                                 last_bezier()->signal_user_click(2).connect(
1765                                                         sigc::bind(
1766                                                                 sigc::mem_fun(
1767                                                                         *canvas_view,
1768                                                                         &studio::CanvasView::popup_param_menu_bezier
1769                                                                 ),
1770                                                                 synfigapp::ValueDesc(value_node,i)
1771                                                         )
1772                                                 );
1773                                         }
1774                                 }
1775                         }
1776                         /*else if(value_node->get_contained_type()==ValueBase::TYPE_SEGMENT)
1777                         {
1778                                 for(i=0;i<value_node->link_count();i++)
1779                                 {
1780                                         if(!value_node->list[i].status_at_time(get_time()))
1781                                                 continue;
1782                                         if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
1783                                                 return false;
1784                                 }
1785                         }
1786                         */
1787                         else
1788                                 return false;
1789                 }
1790                 else
1791                 {
1792                         // WRITEME
1793                 }
1794
1795                 return true;
1796         }
1797
1798         break;
1799         default:
1800                 break;
1801         }
1802         return false;
1803 }