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