source: synfigstudio/trunk/fuentes/src/gui/duckmatic.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 118.0 KB
Line 
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, 2008 Chris Moore
10**      Copyright (c) 2009, 2011 Nikita Kitaev
11**  Copyright (c) 2011 Carlos López
12**  Copyright (c) 2015 Blanchi Jérôme
13**
14**      This package is free software; you can redistribute it and/or
15**      modify it under the terms of the GNU General Public License as
16**      published by the Free Software Foundation; either version 2 of
17**      the License, or (at your option) any later version.
18**
19**      This package is distributed in the hope that it will be useful,
20**      but WITHOUT ANY WARRANTY; without even the implied warranty of
21**      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22**      General Public License for more details.
23**      \endlegal
24*/
25/* ========================================================================= */
26
27/* === H E A D E R S ======================================================= */
28
29#ifdef USING_PCH
30#       include "pch.h"
31#else
32#ifdef HAVE_CONFIG_H
33#       include <config.h>
34#endif
35#include <fstream>
36#include <iostream>
37#include <algorithm>
38
39#include <ETL/hermite>
40
41#include "duckmatic.h"
42#include "ducktransform_scale.h"
43#include "ducktransform_translate.h"
44#include "ducktransform_rotate.h"
45#include <synfigapp/value_desc.h>
46#include <synfigapp/canvasinterface.h>
47#include <synfig/general.h>
48#include <synfig/paramdesc.h>
49#include <synfig/valuenodes/valuenode_timedswap.h>
50#include <synfig/valuenodes/valuenode_animated.h>
51#include <synfig/valuenodes/valuenode_composite.h>
52#include <synfig/valuenodes/valuenode_range.h>
53#include <synfig/valuenodes/valuenode_scale.h>
54#include <synfig/valuenodes/valuenode_bline.h>
55#include <synfig/valuenodes/valuenode_wplist.h>
56#include <synfig/valuenodes/valuenode_blinecalctangent.h>
57#include <synfig/valuenodes/valuenode_blinecalcvertex.h>
58#include <synfig/valuenodes/valuenode_blinecalcwidth.h>
59#include <synfig/valuenodes/valuenode_staticlist.h>
60#include <synfig/valuenodes/valuenode_bone.h>
61#include <synfig/valuenodes/valuenode_boneinfluence.h>
62#include <synfig/valuenodes/valuenode_boneweightpair.h>
63#include <synfig/pair.h>
64
65#include <synfig/curve_helper.h>
66
67#include <synfig/context.h>
68#include <synfig/layers/layer_pastecanvas.h>
69
70#include <sigc++/sigc++.h>
71
72#include "ducktransform_matrix.h"
73#include "ducktransform_rotate.h"
74#include "ducktransform_translate.h"
75#include "ducktransform_scale.h"
76#include "ducktransform_origin.h"
77#include "canvasview.h"
78
79#include "onemoment.h"
80
81#include "general.h"
82
83#endif
84
85/* === U S I N G =========================================================== */
86
87using namespace std;
88using namespace etl;
89using namespace synfig;
90using namespace studio;
91
92/* === M A C R O S ========================================================= */
93
94/* 0.33333333333333333 makes for nice short tangent handles,
95   1.0 makes them draw as their real length */
96#define TANGENT_HANDLE_SCALE 0.33333333333333333
97
98/* leave this alone or the bezier won't lie on top of the bline */
99#define TANGENT_BEZIER_SCALE 0.33333333333333333
100
101/* === I N L I N E ======================================================= */
102synfig::GUID calc_duck_guid(const synfigapp::ValueDesc& value_desc, const synfig::TransformStack& transform_stack);
103void set_duck_value_desc(Duck& duck, const synfigapp::ValueDesc& value_desc, const synfig::TransformStack& transform_stack);
104void set_duck_value_desc(Duck& duck, const synfigapp::ValueDesc& value_desc, const synfig::String& sub_name, const synfig::TransformStack& transform_stack);
105
106/* === P R O C E D U R E S ================================================= */
107
108/* === M E T H O D S ======================================================= */
109
110/* === E N T R Y P O I N T ================================================= */
111
112Duckmatic::Duckmatic(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface):
113        canvas_interface(canvas_interface),
114        type_mask(Duck::TYPE_ALL-Duck::TYPE_WIDTH-Duck::TYPE_BONE_RECURSIVE-Duck::TYPE_WIDTHPOINT_POSITION),
115        alternative_mode_(false),
116        lock_animation_mode_(false),
117        grid_snap(false),
118        guide_snap(false),
119        grid_size(1.0/4.0,1.0/4.0),
120        grid_color(synfig::Color(159.0/255.0,159.0/255.0,159.0/255.0)),
121        guides_color(synfig::Color(111.0/255.0,111.0/255.0,1.0)),
122        zoom(1.0),
123        prev_zoom(1.0),
124        show_persistent_strokes(true),
125        axis_lock(false),
126        drag_offset_(0, 0)
127{
128        clear_duck_dragger();
129        clear_bezier_dragger();
130}
131
132Duckmatic::~Duckmatic()
133{
134        clear_ducks();
135
136        if (Duck::duck_count)
137                synfig::error("%d ducks not yet deleted!", Duck::duck_count);
138
139        if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
140                synfig::info("Duckmatic::~Duckmatic(): Deleted");
141}
142
143void
144Duckmatic::clear_ducks()
145{
146        for(;!duck_changed_connections.empty();duck_changed_connections.pop_back())duck_changed_connections.back().disconnect();
147
148        duck_data_share_map.clear();
149        duck_map.clear();
150
151        //duck_list_.clear();
152        bezier_list_.clear();
153        stroke_list_.clear();
154
155        if(show_persistent_strokes)
156                stroke_list_=persistent_stroke_list_;
157}
158
159
160/*
161-- ** -- D U C K  M A N I P U L A T I O N  M E T H O D S-----------------------
162*/
163
164bool
165Duckmatic::duck_is_selected(const etl::handle<Duck> &duck)const
166{
167    return duck && selected_ducks.count(duck->get_guid());
168}
169
170void
171Duckmatic::clear_selected_ducks()
172{
173        selected_ducks.clear();
174        signal_duck_selection_changed_();
175}
176
177etl::handle<Duckmatic::Duck>
178Duckmatic::get_selected_duck()const
179{
180        if(selected_ducks.empty() || duck_map.empty())
181                return 0;
182        return duck_map.find(*selected_ducks.begin())->second;
183}
184
185etl::handle<Duckmatic::Bezier>
186Duckmatic::get_selected_bezier()const
187{
188        return selected_bezier;
189}
190
191void
192Duckmatic::refresh_selected_ducks()
193{
194/*
195        std::set<etl::handle<Duck> >::iterator iter;
196        std::set<etl::handle<Duck> > new_set;
197        if(duck_list().empty())
198        {
199                selected_duck_list.clear();
200                signal_duck_selection_changed_();
201                return;
202        }
203
204        for(iter=selected_duck_list.begin();iter!=selected_duck_list.end();++iter)
205        {
206                etl::handle<Duck> similar(find_similar_duck(*iter));
207                if(similar)
208                {
209                        new_set.insert(similar);
210                }
211        }
212        selected_duck_list=new_set;
213*/
214        GUIDSet old_set(selected_ducks);
215        GUIDSet::const_iterator iter;
216
217        for(iter=old_set.begin();iter!=old_set.end();++iter)
218        {
219                if(duck_map.count(*iter)==0)
220                        selected_ducks.erase(*iter);
221        }
222
223        signal_duck_selection_changed_();
224}
225
226bool
227Duckmatic::is_duck_group_selectable(const etl::handle<Duck>& x)const
228{
229        const Type type(get_type_mask());
230
231        if (((x->get_type() && (!(type & x->get_type()))) ||
232                 !x->get_editable()))
233                return false;
234
235        synfigapp::ValueDesc value_desc(x->get_value_desc());
236        if(value_desc.parent_is_layer() && (type & Duck::TYPE_POSITION))
237        {
238                Layer::Handle layer(value_desc.get_layer());
239                String layer_name(layer->get_name());
240
241                if (layer_name == "outline" || layer_name == "region" || layer_name == "plant" ||
242                        layer_name == "polygon" || layer_name == "curve_gradient" || layer_name == "advanced_outline")
243                        return false;
244
245                if(etl::handle<Layer_PasteCanvas>::cast_dynamic(layer) &&
246                   !layer->get_param("children_lock").get(bool()))
247                        return false;
248        }
249        else if (value_desc.parent_is_value_node())
250        {
251                if (ValueNode_BLineCalcVertex::Handle::cast_dynamic(value_desc.get_value_node()))
252                        return false;
253                if (value_desc.parent_is_linkable_value_node())
254                {
255                        LinkableValueNode::Handle parent_value_node(value_desc.get_parent_value_node());
256                        if (ValueNode_Composite::Handle::cast_dynamic(parent_value_node))
257                        {
258                                if (parent_value_node->get_type() == type_bline_point &&
259                                        ValueNode_BLineCalcVertex::Handle::cast_dynamic(
260                                                parent_value_node->get_link("point")))
261                                        return false;
262                                // widths ducks of the widthpoints
263                                // Do not avoid selection of the width ducks from widthpoints
264                                //if (parent_value_node->get_type() == type_width_point)
265                                //      return false;
266                        }
267                        else if (ValueNode_BLine::Handle::cast_dynamic(parent_value_node))
268                        {
269                                ValueNode_Composite::Handle composite(ValueNode_Composite::Handle::cast_dynamic(
270                                                                                                                  value_desc.get_value_node()));
271                                if (composite &&
272                                        ValueNode_BLineCalcVertex::Handle::cast_dynamic(composite->get_link("point")))
273                                        return false;
274                        }
275                        // position ducks of the widthpoints
276                        else if (ValueNode_WPList::Handle::cast_dynamic(parent_value_node))
277                                return false;
278
279                }
280        }
281        return true;
282}
283
284void
285Duckmatic::select_all_ducks()
286{
287        DuckMap::const_iterator iter;
288        for(iter=duck_map.begin();iter!=duck_map.end();++iter)
289                if(is_duck_group_selectable(iter->second))
290                        select_duck(iter->second);
291                else
292                        unselect_duck(iter->second);
293}
294
295void
296Duckmatic::unselect_all_ducks()
297{
298        DuckMap::const_iterator iter;
299        for(iter=duck_map.begin();iter!=duck_map.end();++iter)
300                unselect_duck(iter->second);
301}
302
303void
304Duckmatic::toggle_select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)
305{
306        Vector vmin, vmax;
307        vmin[0]=std::min(tl[0],br[0]);
308        vmin[1]=std::min(tl[1],br[1]);
309        vmax[0]=std::max(tl[0],br[0]);
310        vmax[1]=std::max(tl[1],br[1]);
311
312        {
313            DuckMap::const_iterator iter;
314        for(iter=duck_map.begin();iter!=duck_map.end();++iter)
315        {
316            Point p(iter->second->get_trans_point());
317            if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1] &&
318               is_duck_group_selectable(iter->second))
319                toggle_select_duck(iter->second);
320        }
321        }
322}
323
324void
325Duckmatic::select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)
326{
327        Vector vmin, vmax;
328        vmin[0]=std::min(tl[0],br[0]);
329        vmin[1]=std::min(tl[1],br[1]);
330        vmax[0]=std::max(tl[0],br[0]);
331        vmax[1]=std::max(tl[1],br[1]);
332
333//      Type type(get_type_mask());
334
335        DuckMap::const_iterator iter;
336        for(iter=duck_map.begin();iter!=duck_map.end();++iter)
337        {
338                Point p(iter->second->get_trans_point());
339                if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1])
340                {
341                        if(is_duck_group_selectable(iter->second))
342                                select_duck(iter->second);
343                }
344        }
345}
346
347int
348Duckmatic::count_selected_ducks()const
349{
350        return selected_ducks.size();
351}
352
353void
354Duckmatic::select_duck(const etl::handle<Duck> &duck)
355{
356        if(duck)
357        {
358                selected_ducks.insert(duck->get_guid());
359                signal_duck_selection_changed_();
360        }
361}
362
363DuckList
364Duckmatic::get_selected_ducks()const
365{
366        DuckList ret;
367        GUIDSet::const_iterator iter;
368        const Type type(get_type_mask());
369
370        for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
371        {
372                const DuckMap::const_iterator d_iter(duck_map.find(*iter));
373
374                if(d_iter==duck_map.end())
375                        continue;
376
377                if(( d_iter->second->get_type() && (!(type & d_iter->second->get_type())) ) )
378                        continue;
379
380                ret.push_back(d_iter->second);
381        }
382        return ret;
383}
384
385
386DuckList
387Duckmatic::get_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)const
388{
389    Vector vmin, vmax;
390    vmin[0]=std::min(tl[0],br[0]);
391    vmin[1]=std::min(tl[1],br[1]);
392    vmax[0]=std::max(tl[0],br[0]);
393    vmax[1]=std::max(tl[1],br[1]);
394
395    DuckList ret;
396
397//  Type type(get_type_mask());
398
399    DuckMap::const_iterator iter;
400    for(iter=duck_map.begin();iter!=duck_map.end();++iter)
401    {
402        Point p(iter->second->get_trans_point());
403        if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1])
404        {
405          //  if(is_duck_group_selectable(iter->second))
406            ret.push_back(iter->second);
407        }
408    }
409    return ret;
410}
411
412DuckList
413Duckmatic::get_duck_list()const
414{
415        DuckList ret;
416        DuckMap::const_iterator iter;
417        for(iter=duck_map.begin();iter!=duck_map.end();++iter) if (iter->second->get_type()&Duck::TYPE_POSITION) ret.push_back(iter->second);
418        for(iter=duck_map.begin();iter!=duck_map.end();++iter) if (iter->second->get_type()&Duck::TYPE_VERTEX  ) ret.push_back(iter->second);
419        for(iter=duck_map.begin();iter!=duck_map.end();++iter) if (iter->second->get_type()&Duck::TYPE_TANGENT ) ret.push_back(iter->second);
420        for(iter=duck_map.begin();iter!=duck_map.end();++iter)
421                if (!(iter->second->get_type()&Duck::TYPE_POSITION) &&
422                        !(iter->second->get_type()&Duck::TYPE_VERTEX) &&
423                        !(iter->second->get_type()&Duck::TYPE_TANGENT))
424                        ret.push_back(iter->second);
425        return ret;
426}
427
428void
429Duckmatic::unselect_duck(const etl::handle<Duck> &duck)
430{
431        if(duck && selected_ducks.count(duck->get_guid()))
432        {
433                selected_ducks.erase(duck->get_guid());
434                signal_duck_selection_changed_();
435        }
436}
437
438void
439Duckmatic::toggle_select_duck(const etl::handle<Duck> &duck)
440{
441        if(duck_is_selected(duck))
442                unselect_duck(duck);
443        else
444                select_duck(duck);
445}
446
447void
448Duckmatic::translate_selected_ducks(const synfig::Vector& vector)
449{
450        if(duck_dragger_)
451                duck_dragger_->duck_drag(this,vector);
452}
453
454void
455Duckmatic::start_duck_drag(const synfig::Vector& offset)
456{
457        if(duck_dragger_)
458                duck_dragger_->begin_duck_drag(this,offset);
459
460        //drag_offset_=offset;
461        drag_offset_=find_duck(offset)->get_trans_point();
462}
463
464bool
465Duckmatic::end_duck_drag()
466{
467    if(duck_dragger_)
468        return duck_dragger_->end_duck_drag(this);
469    return false;
470}
471
472void
473Duckmatic::update_ducks()
474{
475        Time time(get_time());
476        DuckList duck_list(get_duck_list());
477        const DuckList selected_ducks(get_selected_ducks());
478        DuckList::const_iterator selected_iter;
479        if(get_selected_bezier())
480        {
481                etl::handle<Duck> c1(get_selected_bezier()->c1);
482                etl::handle<Duck> c2(get_selected_bezier()->c2);
483                if(c1->get_value_desc().parent_is_linkable_value_node())
484                {
485                        ValueNode_Composite::Handle composite(ValueNode_Composite::Handle::cast_dynamic(c1->get_value_desc().get_parent_value_node()));
486                        LinkableValueNode::Handle duck_value_node(LinkableValueNode::Handle::cast_dynamic(c1->get_value_desc().get_value_node()));
487                        // it belongs to a composite and it is a BLinePoint
488                        if(composite && composite->get_type() == type_bline_point && duck_value_node)
489                        {
490                                int index(c1->get_value_desc().get_index());
491                                etl::handle<Duck> origin_duck=c1->get_origin_duck();
492                                // Search all the rest of ducks
493                                DuckList::iterator iter;
494                                for (iter=duck_list.begin(); iter!=duck_list.end(); iter++)
495                                        // if the other duck has the same origin and it is tangent type
496                                        if ( (*iter)->get_origin_duck()==origin_duck && (*iter)->get_type() == Duck::TYPE_TANGENT)
497                                        {
498                                                ValueNode_Composite::Handle iter_composite;
499                                                iter_composite=ValueNode_Composite::Handle::cast_dynamic((*iter)->get_value_desc().get_parent_value_node());
500                                                // and their parent valuenode are the same
501                                                if(iter_composite.get() == composite.get())
502                                                {
503                                                        BLinePoint bp=(*composite)(time).get(BLinePoint());
504                                                        int t1_index=composite->get_link_index_from_name("t1");
505                                                        int t2_index=composite->get_link_index_from_name("t2");
506                                                        if(index==t1_index && (*iter)->get_value_desc().get_index()!=t1_index)
507                                                        {
508                                                                bp.set_tangent1(c1->get_point());
509                                                                Vector t2(bp.get_tangent2());
510                                                                (*iter)->set_point(Point(t2));
511                                                        }
512                                                        else if(index==t2_index && (*iter)->get_value_desc().get_index()!=t2_index)
513                                                        {
514                                                                // Create a new BLinePoint
515                                                                BLinePoint nbp;
516                                                                // Terporary set the flags for the new BLinePoint to all split
517                                                                nbp.set_split_tangent_both(true);
518                                                                // Now we can set the tangents. Tangent2 won't be modified by tangent1
519                                                                nbp.set_tangent1(c1->get_point());
520                                                                nbp.set_tangent2(bp.get_tangent1());
521                                                                // Now update the flags
522                                                                nbp.set_split_tangent_radius(bp.get_split_tangent_radius());
523                                                                nbp.set_split_tangent_angle(bp.get_split_tangent_angle());
524                                                                // Now retrieve the updated tangent2 (which will be stored as t1, see below)
525                                                                Vector t1(nbp.get_tangent2());
526                                                                (*iter)->set_point(Point(t1));
527                                                        }
528                                                }
529                                        }
530                        }
531                }
532                if(c2->get_value_desc().parent_is_linkable_value_node())
533                {
534                        ValueNode_Composite::Handle composite(ValueNode_Composite::Handle::cast_dynamic(c2->get_value_desc().get_parent_value_node()));
535                        LinkableValueNode::Handle duck_value_node(LinkableValueNode::Handle::cast_dynamic(c2->get_value_desc().get_value_node()));
536                        // it belongs to a composite and it is a BLinePoint
537                        if(composite && composite->get_type() == type_bline_point && duck_value_node)
538                        {
539                                int index(c2->get_value_desc().get_index());
540                                etl::handle<Duck> origin_duck=c2->get_origin_duck();
541                                // Search all the rest of ducks
542                                DuckList::iterator iter;
543                                for (iter=duck_list.begin(); iter!=duck_list.end(); iter++)
544                                        // if the other duck has the same origin and it is tangent type
545                                        if ( (*iter)->get_origin_duck()==origin_duck && (*iter)->get_type() == Duck::TYPE_TANGENT)
546                                        {
547                                                ValueNode_Composite::Handle iter_composite;
548                                                iter_composite=ValueNode_Composite::Handle::cast_dynamic((*iter)->get_value_desc().get_parent_value_node());
549                                                // and their parent valuenode are the same
550                                                if(iter_composite.get() == composite.get())
551                                                {
552                                                        BLinePoint bp=(*composite)(time).get(BLinePoint());
553                                                        int t1_index=composite->get_link_index_from_name("t1");
554                                                        int t2_index=composite->get_link_index_from_name("t2");
555                                                        if(index==t1_index && (*iter)->get_value_desc().get_index()!=t1_index)
556                                                        {
557                                                                bp.set_tangent1(c2->get_point());
558                                                                Vector t2(bp.get_tangent2());
559                                                                (*iter)->set_point(Point(t2));
560                                                        }
561                                                        else if(index==t2_index && (*iter)->get_value_desc().get_index()!=t2_index)
562                                                        {
563                                                                // Create a new BLinePoint
564                                                                BLinePoint nbp;
565                                                                // Terporary set the flags for the new BLinePoint to all split
566                                                                nbp.set_split_tangent_both(true);
567                                                                // Now we can set the tangents. Tangent2 won't be modified by tangent1
568                                                                nbp.set_tangent1(c2->get_point());
569                                                                nbp.set_tangent2(bp.get_tangent1());
570                                                                // Now update the flags
571                                                                nbp.set_split_tangent_radius(bp.get_split_tangent_radius());
572                                                                nbp.set_split_tangent_angle(bp.get_split_tangent_angle());
573                                                                // Now retrieve the updated tangent2 (which will be stored as t1, see below)
574                                                                Vector t1(nbp.get_tangent2());
575                                                                (*iter)->set_point(Point(t1));
576                                                        }
577                                                }
578                                        }
579                        }
580                }
581        }
582        for (selected_iter=selected_ducks.begin(); selected_iter!=selected_ducks.end(); ++selected_iter)
583        {
584                etl::handle<Duck> duck(*selected_iter);
585                if(!duck)
586                        return;
587                if (duck->get_type() == Duck::TYPE_VERTEX || duck->get_type() == Duck::TYPE_POSITION)
588                {
589                        ValueNode_BLineCalcVertex::Handle bline_vertex =
590                                ValueNode_BLineCalcVertex::Handle::cast_dynamic(duck->get_value_desc().get_value_node());
591                        if (!bline_vertex && duck->get_value_desc().parent_is_value_desc()) {
592                                ValueNode_Composite::Handle composite =
593                                        ValueNode_Composite::Handle::cast_dynamic(duck->get_value_desc().get_value_node());
594                                if (composite)
595                                        bline_vertex =
596                                                ValueNode_BLineCalcVertex::Handle::cast_dynamic(
597                                                        composite->get_link(
598                                                                duck->get_value_desc().get_sub_name() ));
599                        }
600
601                        if (bline_vertex)
602                        {
603                                synfig::Real radius = 0.0;
604                                synfig::Point point(0.0, 0.0);
605                                ValueNode_BLine::Handle bline(ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link("bline")));
606                                Real amount = synfig::find_closest_point((*bline)(time), duck->get_point(), radius, bline->get_loop(), &point);
607                                bool homogeneous((*(bline_vertex->get_link("homogeneous")))(time).get(bool()));
608                                if(homogeneous)
609                                        amount=std_to_hom((*bline)(time), amount, ((*(bline_vertex->get_link("loop")))(time).get(bool())), bline->get_loop() );
610                                ValueNode::Handle vertex_amount_value_node(bline_vertex->get_link("amount"));
611                                duck->set_point(point);
612
613                                DuckList::iterator iter;
614                                for (iter=duck_list.begin(); iter!=duck_list.end(); iter++)
615                                {
616                                        if ( (*iter)->get_origin_duck()==duck /*&& !duck_is_selected(*iter)*/ )
617                                        {
618                                                ValueNode::Handle duck_value_node = (*iter)->get_value_desc().get_value_node();
619                                                if (duck_value_node)
620                                                {
621                                                        ValueNode_Composite::Handle duck_value_node_composite = ValueNode_Composite::Handle::cast_dynamic(duck_value_node);
622                                                        ValueNode::Handle sub_duck_value_node =
623                                                                        duck_value_node_composite && (*iter)->get_value_desc().parent_is_value_desc()
624                                                                  ? ValueNode::Handle(duck_value_node_composite->get_link( (*iter)->get_value_desc().get_sub_name() ))
625                                                                  : duck_value_node;
626                                                        if (sub_duck_value_node)
627                                                        {
628                                                                if ( ValueNode_BLineCalcTangent::Handle bline_tangent =
629                                                                                ValueNode_BLineCalcTangent::Handle::cast_dynamic(sub_duck_value_node) )
630                                                                {
631                                                                        if (bline_tangent->get_link("amount") == vertex_amount_value_node)
632                                                                        {
633                                                                                synfig::Type &type(bline_tangent->get_type());
634                                                                                if (type == type_angle)
635                                                                                {
636                                                                                        Angle angle((*bline_tangent)(time, amount).get(Angle()));
637                                                                                        (*iter)->set_point(Point(Angle::cos(angle).get(), Angle::sin(angle).get()));
638                                                                                        (*iter)->set_rotations(Angle::deg(0)); //hack: rotations are a relative value
639                                                                                }
640                                                                                else
641                                                                                if (type == type_real)
642                                                                                        (*iter)->set_point(Point((*bline_tangent)(time, amount).get(Real()), 0));
643                                                                                else
644                                                                                if (type == type_vector)
645                                                                                        (*iter)->set_point((*bline_tangent)(time, amount).get(Vector()));
646                                                                        }
647                                                                } else
648                                                                if ( ValueNode_BLineCalcWidth::Handle bline_width =
649                                                                                ValueNode_BLineCalcWidth::Handle::cast_dynamic(sub_duck_value_node) )
650                                                                {
651                                                                        if (bline_width->get_link("amount") == vertex_amount_value_node)
652                                                                                (*iter)->set_point(Point((*bline_width)(time, amount).get(Real()), 0));
653                                                                }
654                                                        }
655                                                }
656                                        }
657                                }
658                        }
659                }
660                // We are moving a tangent handle
661                else
662                if(duck->get_type() == Duck::TYPE_TANGENT)
663                {
664                        if (duck->get_value_desc().parent_is_value_desc()
665                         && duck->get_value_desc().is_value_node() )
666                        {
667                                ValueNode_Composite::Handle composite(ValueNode_Composite::Handle::cast_dynamic(duck->get_value_desc().get_value_node()));
668                                if (composite && composite->get_type() == type_bline_point)
669                                {
670                                        ValueNode::Handle duck_value_node(composite->get_link(duck->get_value_desc().get_sub_name()));
671                                        // it belongs to a composite and it is a BLinePoint
672                                        if (duck_value_node)
673                                        {
674                                                int index(duck->get_value_desc().get_index());
675                                                etl::handle<Duck> origin_duck=duck->get_origin_duck();
676                                                // Search all the rest of ducks
677                                                DuckList::iterator iter;
678                                                for (iter=duck_list.begin(); iter!=duck_list.end(); iter++)
679                                                {
680                                                        // if the other duck has the same origin and it is tangent type
681                                                        if ( (*iter)->get_origin_duck()==origin_duck && (*iter)->get_type() == Duck::TYPE_TANGENT)
682                                                        {
683                                                                ValueNode_Composite::Handle iter_composite;
684                                                                iter_composite=ValueNode_Composite::Handle::cast_dynamic((*iter)->get_value_desc().get_parent_value_node());
685                                                                // and their parent valuenode are the same
686                                                                if(iter_composite.get() == composite.get())
687                                                                {
688                                                                        // Check if the other tangent is also selected, in that case
689                                                                        // it is going to be moved itself so don't update it.
690                                                                        bool selected=false;
691                                                                        DuckList::const_iterator iter2;
692                                                                        for(iter2=selected_ducks.begin(); iter2!=selected_ducks.end(); ++iter2)
693                                                                                if(*iter == *iter2)
694                                                                                        selected=true;
695                                                                        if(!selected)
696                                                                        {
697                                                                                BLinePoint bp=(*composite)(time).get(BLinePoint());
698                                                                                int t1_index=composite->get_link_index_from_name("t1");
699                                                                                int t2_index=composite->get_link_index_from_name("t2");
700                                                                                if(index==t1_index && (*iter)->get_value_desc().get_index()!=t1_index)
701                                                                                {
702                                                                                        bp.set_tangent1(duck->get_point());
703                                                                                        Vector t2(bp.get_tangent2());
704                                                                                        (*iter)->set_point(Point(t2));
705                                                                                }
706                                                                                else if(index==t2_index && (*iter)->get_value_desc().get_index()!=t2_index)
707                                                                                {
708                                                                                        // Create a new BLinePoint
709                                                                                        BLinePoint nbp;
710                                                                                        // Terporary set the flags for the new BLinePoint to all split
711                                                                                        nbp.set_split_tangent_both(true);
712                                                                                        // Now we can set the tangents. Tangent2 won't be modified by tangent1
713                                                                                        nbp.set_tangent1(duck->get_point());
714                                                                                        nbp.set_tangent2(bp.get_tangent1());
715                                                                                        // Now update the flags
716                                                                                        nbp.set_split_tangent_radius(bp.get_split_tangent_radius());
717                                                                                        nbp.set_split_tangent_angle(bp.get_split_tangent_angle());
718                                                                                        // Now retrieve the updated tangent2 (which will be stored as t1, see below)
719                                                                                        Vector t1(nbp.get_tangent2());
720                                                                                        (*iter)->set_point(Point(t1));
721                                                                                }
722                                                                        }
723                                                                }
724                                                        }
725                                                }
726                                        }
727                                }
728                        }
729                }
730        }
731}
732
733
734void
735Duckmatic::start_bezier_drag(const synfig::Vector& offset, float bezier_click_pos)
736{
737        if(bezier_dragger_)
738                bezier_dragger_->begin_bezier_drag(this,offset,bezier_click_pos);
739}
740
741void
742Duckmatic::translate_selected_bezier(const synfig::Vector& vector)
743{
744        if(bezier_dragger_)
745                bezier_dragger_->bezier_drag(this,vector);
746}
747
748bool
749Duckmatic::end_bezier_drag()
750{
751        if(bezier_dragger_)
752                return bezier_dragger_->end_bezier_drag(this);
753        return false;
754}
755
756/*
757-- ** -- grid and guide M E T H O D S----------------------------
758*/
759
760void
761Duckmatic::set_grid_size(const synfig::Vector &s)
762{
763    if(grid_size!=s)
764    {
765        grid_size=s;
766        signal_grid_changed();
767    }
768}
769
770void
771Duckmatic::set_grid_color(const synfig::Color &c)
772{
773    if(grid_color!=c)
774    {
775        grid_color=c;
776        signal_grid_changed();
777    }
778}
779
780void
781Duckmatic::set_grid_snap(bool x)
782{
783    if(grid_snap!=x)
784    {
785        grid_snap=x;
786        signal_grid_changed();
787    }
788}
789
790void
791Duckmatic::set_guide_snap(bool x)
792{
793    if(guide_snap!=x)
794    {
795        guide_snap=x;
796        signal_grid_changed();
797    }
798}
799
800void
801Duckmatic::set_guides_color(const synfig::Color &c)
802{
803    if(guides_color!=c)
804    {
805        guides_color=c;
806        signal_grid_changed();
807    }
808}
809
810Duckmatic::GuideList::iterator
811Duckmatic::find_guide_x(synfig::Point pos, float radius)
812{
813    GuideList::iterator iter,best(guide_list_x_.end());
814    float dist(radius);
815    for(iter=guide_list_x_.begin();iter!=guide_list_x_.end();++iter)
816    {
817        float amount(abs(*iter-pos[0]));
818        if(amount<dist)
819        {
820            dist=amount;
821            best=iter;
822        }
823    }
824    return best;
825}
826
827Duckmatic::GuideList::iterator
828Duckmatic::find_guide_y(synfig::Point pos, float radius)
829{
830    GuideList::iterator iter,best(guide_list_y_.end());
831    float dist(radius);
832    for(iter=guide_list_y_.begin();iter!=guide_list_y_.end();++iter)
833    {
834        float amount(abs(*iter-pos[1]));
835        if(amount<=dist)
836        {
837            dist=amount;
838            best=iter;
839        }
840    }
841    return best;
842}
843
844Point
845Duckmatic::snap_point_to_grid(const synfig::Point& x)const
846{
847        Point ret(x);
848        float radius(0.1/zoom);
849
850        GuideList::const_iterator guide_x,guide_y;
851        bool has_guide_x(false), has_guide_y(false);
852
853        guide_x=find_guide_x(ret,radius);
854        if(guide_x!=guide_list_x_.end())
855                has_guide_x=true;
856
857        guide_y=find_guide_y(ret,radius);
858        if(guide_y!=guide_list_y_.end())
859                has_guide_y=true;
860
861        if(get_grid_snap())
862        {
863                Point snap(
864                        floor(ret[0]/get_grid_size()[0]+0.5)*get_grid_size()[0],
865                        floor(ret[1]/get_grid_size()[1]+0.5)*get_grid_size()[1]);
866
867                if(abs(snap[0]-ret[0])<=radius && (!has_guide_x || abs(snap[0]-ret[0])<=abs(*guide_x-ret[0])))
868                        ret[0]=snap[0],has_guide_x=false;
869                if(abs(snap[1]-ret[1])<=radius && (!has_guide_y || abs(snap[1]-ret[1])<=abs(*guide_y-ret[1])))
870                        ret[1]=snap[1],has_guide_y=false;
871        }
872
873        if(guide_snap)
874        {
875                if(has_guide_x)
876                        ret[0]=*guide_x;
877                if(has_guide_y)
878                        ret[1]=*guide_y;
879        }
880
881        if(axis_lock)
882        {
883                ret-=drag_offset_;
884                if(abs(ret[0])<abs(ret[1]))
885                        ret[0]=0;
886                else
887                        ret[1]=0;
888                ret+=drag_offset_;
889        }
890
891        return ret;
892}
893
894/*
895-- ** -- S I G N A L S  M E T H O D S----------------------------
896*/
897void
898Duckmatic::signal_user_click_selected_ducks(int button)
899{
900    const DuckList ducks(get_selected_ducks());
901    DuckList::const_iterator iter;
902
903    for(iter=ducks.begin();iter!=ducks.end();++iter)
904    {
905        (*iter)->signal_user_click(button)();
906    }
907}
908
909void
910Duckmatic::signal_edited_duck(const etl::handle<Duck> &duck, bool moving)
911{
912    if (moving && !duck->get_edit_immediatelly()) return;
913
914    if (duck->get_type() == Duck::TYPE_ANGLE)
915    {
916        if(!duck->signal_edited()(*duck))
917        {
918            throw String("Bad edit");
919        }
920    }
921    else if (App::restrict_radius_ducks &&
922             duck->is_radius())
923    {
924        Point point(duck->get_point());
925        bool changed = false;
926
927        if (point[0] < 0)
928        {
929            point[0] = 0;
930            changed = true;
931        }
932        if (point[1] < 0)
933        {
934            point[1] = 0;
935            changed = true;
936        }
937
938        if (changed) duck->set_point(point);
939
940        if(!duck->signal_edited()(*duck))
941        {
942            throw String("Bad edit");
943        }
944    }
945    else
946    {
947        if(!duck->signal_edited()(*duck))
948        {
949            throw String("Bad edit");
950        }
951    }
952}
953
954
955void
956Duckmatic::signal_edited_selected_ducks(bool moving)
957{
958    const DuckList ducks(get_selected_ducks());
959    DuckList::const_iterator iter;
960
961    synfig::GUIDSet old_set(selected_ducks);
962
963    // If we have more than 20 things to move, then display
964    // something to explain that it may take a moment
965    //smart_ptr<OneMoment> wait; if(ducks.size()>20)wait.spawn();
966    for(iter=ducks.begin();iter!=ducks.end();++iter)
967    {
968        try
969        {
970            if (!moving || (*iter)->get_edit_immediatelly())
971                signal_edited_duck(*iter);
972        }
973        catch (String)
974        {
975            selected_ducks=old_set;
976            throw;
977        }
978    }
979    selected_ducks=old_set;
980}
981
982bool
983Duckmatic::on_duck_changed(const studio::Duck &duck,const synfigapp::ValueDesc& value_desc)
984{
985    bool lock_animation = get_lock_animation_mode();
986    synfig::Point value=duck.get_point();
987    synfig::Type &type(value_desc.get_value_type());
988    if (type == type_real)
989    {
990        if (value_desc.parent_is_value_node())
991        {
992            etl::handle<ValueNode_Bone> bone_node =
993                etl::handle<ValueNode_Bone>::cast_dynamic(
994                    value_desc.get_parent_value_node());
995            if (bone_node)
996            {
997                int index1 = bone_node->get_link_index_from_name("scalex");
998                int index2 = bone_node->get_link_index_from_name("scalelx");
999                int angleIndex = bone_node->get_link_index_from_name("angle");
1000                if (value_desc.get_index() == index1
1001                 || value_desc.get_index() == index2)
1002                {
1003                    //Bone bone((*bone_node)(get_time()).get(Bone()));
1004                    //Real prev_duck_length = bone.get_length() * bone.get_scalex() * bone.get_scalex();
1005                    //Real duck_length = duck.get_point().mag();
1006                    //Real prev_length = value_desc.get_value(get_time()).get(Real());
1007                    //Real new_length = prev_length == 0.f || prev_duck_length == 0.f
1008                    //                ? duck_length
1009                    //                : prev_length * duck_length / prev_duck_length;
1010                    Real new_length = duck.get_point().mag();
1011                    Angle angle = (*bone_node->get_link(angleIndex))(get_time()).get(Angle());
1012                    angle += duck.get_rotations();
1013                    return canvas_interface->change_value(synfigapp::ValueDesc(bone_node, angleIndex, value_desc.get_parent_desc()), angle, lock_animation)
1014                        && canvas_interface->change_value(value_desc, new_length, lock_animation);
1015                }
1016            }
1017        }
1018
1019        // Zoom duck value (PasteCanvas and Zoom layers) should be
1020        // converted back from exponent to normal
1021        if( duck.get_exponential() ) {
1022            return canvas_interface->change_value(value_desc,log(value.mag()),lock_animation);
1023        } else {
1024            return canvas_interface->change_value(value_desc,value.mag(),lock_animation);
1025        }
1026    }
1027    else
1028    if (type == type_angle)
1029        //return canvas_interface->change_value(value_desc,Angle::tan(value[1],value[0]),lock_animation);
1030        return canvas_interface->change_value(value_desc, value_desc.get_value(get_time()).get(Angle()) + duck.get_rotations(),lock_animation);
1031    else
1032    if (type == type_transformation)
1033    {
1034        if (get_alternative_mode()
1035         && duck.get_alternative_editable()
1036         && duck.get_alternative_value_desc().is_valid()
1037         && duck.get_alternative_value_desc().parent_is_layer()
1038         && etl::handle<Layer_PasteCanvas>::cast_dynamic(duck.get_alternative_value_desc().get_layer())
1039         && duck.get_alternative_value_desc().get_param_name() == "origin")
1040        {
1041            Point origin = duck.get_alternative_value_desc().get_value(get_time()).get(Point());
1042            Transformation transformation = duck.get_value_desc().get_value(get_time()).get(Transformation());
1043            Point delta_offset = value - transformation.offset;
1044            Point delta_origin = transformation.back_transform(delta_offset, false);
1045            transformation.offset += delta_offset;
1046            origin += delta_origin;
1047            return canvas_interface->change_value(duck.get_alternative_value_desc(), origin, lock_animation)
1048                && canvas_interface->change_value(duck.get_value_desc(), transformation, lock_animation);
1049        }
1050        else
1051        {
1052            Transformation transformation = value_desc.get_value(get_time()).get(Transformation());
1053            Point axis_x_one(1, transformation.angle);
1054            Point axis_y_one(1, transformation.angle + Angle::deg(90.f) + transformation.skew_angle);
1055
1056            switch(duck.get_type()) {
1057            case Duck::TYPE_POSITION:
1058                transformation.offset = value;
1059                break;
1060            case Duck::TYPE_ANGLE:
1061                transformation.angle += duck.get_rotations();
1062                break;
1063            case Duck::TYPE_SKEW:
1064                transformation.skew_angle += duck.get_rotations();
1065                break;
1066            case Duck::TYPE_SCALE:
1067                transformation.scale = transformation.scale.multiply_coords(duck.get_point());
1068                break;
1069            case Duck::TYPE_SCALE_X:
1070                transformation.scale[0] *= duck.get_point()[0];
1071                break;
1072            case Duck::TYPE_SCALE_Y:
1073                transformation.scale[1] *= duck.get_point()[0];
1074                break;
1075            default:
1076                break;
1077            }
1078
1079            return canvas_interface->change_value(value_desc, transformation, lock_animation);
1080        }
1081        return false;
1082    }
1083    else
1084    if (type == type_bline_point)
1085    {
1086        BLinePoint point = value_desc.get_value(get_time()).get(BLinePoint());
1087        switch(duck.get_type()) {
1088        case Duck::TYPE_VERTEX:
1089            point.set_vertex(duck.get_point());
1090            break;
1091        case Duck::TYPE_WIDTH:
1092            point.set_width(duck.get_point().mag());
1093            break;
1094        case Duck::TYPE_TANGENT:
1095            if (duck.get_scalar() < 0.f)
1096                point.set_tangent1(duck.get_point());
1097            else
1098            if (point.get_merge_tangent_both())
1099                point.set_tangent1(duck.get_point());
1100            else
1101            if (point.get_split_tangent_both())
1102                point.set_tangent2(duck.get_point());
1103            else
1104            if (point.get_split_tangent_angle())
1105            {
1106                point.set_tangent1( Point(duck.get_point().mag(), point.get_tangent1().angle()) );
1107                point.set_tangent2(duck.get_point());
1108            }
1109            else
1110            {
1111                point.set_tangent1( Point(point.get_tangent1().mag(), duck.get_point().angle()) );
1112                point.set_tangent2(duck.get_point());
1113            }
1114            break;
1115        default:
1116            break;
1117        }
1118
1119        return canvas_interface->change_value(value_desc, point, lock_animation);
1120    }
1121
1122    return canvas_interface->change_value(value_desc,value,lock_animation);
1123}
1124
1125void
1126Duckmatic::connect_signals(const Duck::Handle &duck, const synfigapp::ValueDesc& value_desc, CanvasView &canvas_view)
1127{
1128    duck->signal_edited().connect(
1129        sigc::bind(
1130            sigc::mem_fun(
1131                *this,
1132                &studio::Duckmatic::on_duck_changed),
1133            value_desc));
1134    duck->signal_user_click(2).connect(
1135        sigc::bind(
1136            sigc::bind(
1137                sigc::bind(
1138                    sigc::mem_fun(
1139                        canvas_view,
1140                        &studio::CanvasView::popup_param_menu),
1141                    false),
1142                1.0f),
1143            value_desc));
1144}
1145
1146/*
1147-- ** -- DUCK BEZIER STOKE ADD/ERASE/FIND...  M E T H O D S----------------------------
1148*/
1149void
1150Duckmatic::add_duck(const etl::handle<Duck> &duck)
1151{
1152    //if(!duck_map.count(duck->get_guid()))
1153    {
1154        if(duck_data_share_map.count(duck->get_data_guid()))
1155        {
1156            duck->set_shared_point(duck_data_share_map[duck->get_data_guid()]);
1157        }
1158        else
1159        {
1160            etl::smart_ptr<synfig::Point> point(new Point(duck->get_point()));
1161            duck->set_shared_point(point);
1162            duck_data_share_map[duck->get_data_guid()]=point;
1163        }
1164
1165        duck_map.insert(duck);
1166    }
1167
1168    last_duck_guid=duck->get_guid();
1169}
1170
1171void
1172Duckmatic::add_bezier(const etl::handle<Bezier> &bezier)
1173{
1174    bezier_list_.push_back(bezier);
1175}
1176
1177void
1178Duckmatic::add_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
1179{
1180    assert(stroke_point_list);
1181
1182    std::list<etl::handle<Stroke> >::iterator iter;
1183
1184    for(iter=stroke_list_.begin();iter!=stroke_list_.end();++iter)
1185    {
1186        if((*iter)->stroke_data==stroke_point_list)
1187            return;
1188    }
1189
1190    etl::handle<Stroke> stroke(new Stroke());
1191
1192    stroke->stroke_data=stroke_point_list;
1193    stroke->color=color;
1194
1195    stroke_list_.push_back(stroke);
1196}
1197
1198void
1199Duckmatic::add_persistent_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
1200{
1201    add_stroke(stroke_point_list,color);
1202    persistent_stroke_list_.push_back(stroke_list_.back());
1203}
1204
1205void
1206Duckmatic::clear_persistent_strokes()
1207{
1208    persistent_stroke_list_.clear();
1209}
1210
1211void
1212Duckmatic::set_show_persistent_strokes(bool x)
1213{
1214    if(x!=show_persistent_strokes)
1215    {
1216        show_persistent_strokes=x;
1217        if(x)
1218            stroke_list_=persistent_stroke_list_;
1219        else
1220            stroke_list_.clear();
1221    }
1222}
1223
1224void
1225Duckmatic::erase_duck(const etl::handle<Duck> &duck)
1226{
1227    duck_map.erase(duck->get_guid());
1228}
1229
1230etl::handle<Duckmatic::Duck>
1231Duckmatic::find_similar_duck(etl::handle<Duck> duck)
1232{
1233    DuckMap::const_iterator iter(duck_map.find(duck->get_guid()));
1234    if(iter!=duck_map.end())
1235        return iter->second;
1236    return 0;
1237
1238/*  std::list<handle<Duck> >::reverse_iterator iter;
1239
1240    for(iter=duck_list_.rbegin();iter!=duck_list_.rend();++iter)
1241    {
1242        if(*iter!=duck && **iter==*duck)
1243        {
1244            //synfig::info("Found similar duck! (iter:%08x vs. duck:%08x)",iter->get(), duck.get());
1245            return *iter;
1246        }
1247    }
1248    return 0;
1249*/
1250}
1251
1252etl::handle<Duckmatic::Duck>
1253Duckmatic::add_similar_duck(etl::handle<Duck> duck)
1254{
1255    etl::handle<Duck> similar(find_similar_duck(duck));
1256    if(!similar)
1257    {
1258        add_duck(duck);
1259        return duck;
1260    }
1261    return similar;
1262}
1263
1264void
1265Duckmatic::erase_bezier(const etl::handle<Bezier> &bezier)
1266{
1267    std::list<handle<Bezier> >::iterator iter;
1268
1269    for(iter=bezier_list_.begin();iter!=bezier_list_.end();++iter)
1270    {
1271        if(*iter==bezier)
1272        {
1273            bezier_list_.erase(iter);
1274            return;
1275        }
1276    }
1277    synfig::warning("Unable to find bezier to erase!");
1278}
1279
1280etl::handle<Duckmatic::Duck>
1281Duckmatic::last_duck()const
1282{
1283    DuckMap::const_iterator iter(duck_map.find(last_duck_guid));
1284    if(iter!=duck_map.end())
1285        return iter->second;
1286    return 0;
1287}
1288
1289etl::handle<Duckmatic::Bezier>
1290Duckmatic::last_bezier()const
1291{
1292    return bezier_list_.back();
1293}
1294
1295etl::handle<Duckmatic::Duck>
1296Duckmatic::find_duck(synfig::Point point, synfig::Real radius, Duck::Type type)
1297{
1298    if(radius==0)radius=10000000;
1299
1300    if(type==Duck::TYPE_DEFAULT)
1301        type=get_type_mask();
1302
1303    Real closest(10000000);
1304    etl::handle<Duck> ret;
1305    std::vector< etl::handle<Duck> > ret_vector;
1306
1307    DuckMap::const_iterator iter;
1308
1309    for(iter=duck_map.begin();iter!=duck_map.end();++iter)
1310    {
1311        const Duck::Handle& duck(iter->second);
1312
1313        if(duck->get_ignore() ||
1314           (duck->get_type() && !(type & duck->get_type())))
1315            continue;
1316
1317        Real dist((duck->get_trans_point()-point).mag_squared());
1318
1319        bool equal;
1320        equal=fabs(dist-closest)<0.0000001?true:false;
1321        if(dist<closest || equal)
1322        {
1323            // if there are two ducks at the "same" position, keep track of them
1324            if(equal)
1325            {
1326                // if we haven't any duck stored keep track of last found
1327                if(!ret_vector.size())
1328                    ret_vector.push_back(ret);
1329                // and also keep track of the one on the same place
1330                ret_vector.push_back(duck);
1331            }
1332            // we have another closer duck then discard the stored
1333            else if (!equal && ret_vector.size())
1334                ret_vector.clear();
1335            closest=dist;
1336            ret=duck;
1337        }
1338    }
1339
1340    // Priorization of duck selection when are in the same place.
1341    bool found(false);
1342    if(ret_vector.size())
1343    {
1344        unsigned int i;
1345        for(i=0; i<ret_vector.size();i++)
1346            if(ret_vector[i]->get_type() & Duck::TYPE_WIDTHPOINT_POSITION)
1347            {
1348                ret=ret_vector[i];
1349                found=true;
1350                break;
1351            }
1352        if(!found)
1353            for(i=0; i<ret_vector.size();i++)
1354                if(ret_vector[i]->get_type() & Duck::TYPE_WIDTH)
1355                {
1356                    ret=ret_vector[i];
1357                    found=true;
1358                    break;
1359                }
1360        if(!found)
1361            for(i=0; i<ret_vector.size();i++)
1362                if(ret_vector[i]->get_type() & Duck::TYPE_RADIUS)
1363                {
1364                    ret=ret_vector[i];
1365                    found=true;
1366                    break;
1367                }
1368        if(!found)
1369            for(i=0; i<ret_vector.size();i++)
1370                if(ret_vector[i]->get_type() & Duck::TYPE_TANGENT)
1371                {
1372                    ret=ret_vector[i];
1373                    found=true;
1374                    break;
1375                }
1376        if(!found)
1377            for(i=0; i<ret_vector.size();i++)
1378                if(ret_vector[i]->get_type() & Duck::TYPE_POSITION)
1379                {
1380                    ret=ret_vector[i];
1381                    found=true;
1382                    break;
1383                }
1384    }
1385    if(radius==0 || closest<radius*radius)
1386        return ret;
1387
1388    return 0;
1389}
1390
1391etl::handle<Duckmatic::Bezier>
1392Duckmatic::find_bezier(synfig::Point point, synfig::Real radius,float* location)
1393{
1394    return find_bezier(point,radius,radius,location);
1395}
1396
1397etl::handle<Duckmatic::Bezier>
1398Duckmatic::find_bezier(synfig::Point pos, synfig::Real scale, synfig::Real radius, float* location)
1399{
1400    if(radius==0)radius=10000000;
1401    Real closest(10000000);
1402    etl::handle<Bezier> ret;
1403
1404    bezier<Point>   curve;
1405
1406    Real    d,step;
1407    float   time = 0;
1408    float   best_time = 0;
1409
1410    for(std::list<handle<Bezier> >::const_iterator iter=bezier_list().begin();iter!=bezier_list().end();++iter)
1411    {
1412        curve[0] = (*iter)->p1->get_trans_point();
1413        curve[1] = (*iter)->c1->get_trans_point();
1414        curve[2] = (*iter)->c2->get_trans_point();
1415        curve[3] = (*iter)->p2->get_trans_point();
1416        curve.sync();
1417
1418#if 0
1419        // I don't know why this doesn't work
1420        time=curve.find_closest(pos,6);
1421        d=((curve(time)-pos).mag_squared());
1422
1423#else
1424        //set the step size based on the size of the picture
1425        d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag() + (curve[3]-curve[2]).mag();
1426
1427        step = d/(2*scale); //want to make the distance between lines happy
1428
1429        step = max(step,0.01); //100 samples should be plenty
1430        step = min(step,0.1); //10 is minimum
1431
1432        d = find_closest(curve,pos,step,&closest,&time);
1433#endif
1434
1435        if(d < closest)
1436        {
1437            closest = d;
1438            ret = *iter;
1439            best_time=time;
1440        }
1441    }
1442
1443    if(closest < radius*radius)
1444    {
1445        if(location)
1446            *location = best_time;  // We need to square-root this because we were dealing with squared distances
1447
1448        return ret;
1449    }
1450
1451    return 0;
1452}
1453
1454
1455/*
1456-- ** -- Duckmatic sketch M E T H O D S----------------------------
1457*/
1458bool
1459Duckmatic::save_sketch(const synfig::String& filename)const
1460{
1461    ChangeLocale change_locale(LC_NUMERIC, "C");
1462    std::ofstream file(filename.c_str());
1463
1464    if(!file)return false;
1465
1466    file<<"SKETCH"<<endl;
1467
1468    std::list<etl::handle<Stroke> >::const_iterator iter;
1469
1470    for(iter=persistent_stroke_list_.begin();iter!=persistent_stroke_list_.end();++iter)
1471    {
1472        file<<"C "
1473            <<(*iter)->color.get_r()<<' '
1474            <<(*iter)->color.get_g()<<' '
1475            <<(*iter)->color.get_b()
1476        <<endl;
1477        std::list<synfig::Point>::const_iterator viter;
1478        for(viter=(*iter)->stroke_data->begin();viter!=(*iter)->stroke_data->end();++viter)
1479        {
1480            file<<"V "
1481                <<(*viter)[0]<<' '
1482                <<(*viter)[1]
1483            <<endl;
1484        }
1485    }
1486    if(!file)return false;
1487    sketch_filename_=filename;
1488    signal_sketch_saved_();
1489    return true;
1490}
1491
1492bool
1493Duckmatic::load_sketch(const synfig::String& filename)
1494{
1495    ChangeLocale change_locale(LC_NUMERIC, "C");
1496    std::ifstream file(filename.c_str());
1497
1498    if(!file)
1499        return false;
1500
1501    std::string line;
1502    getline(file,line);
1503
1504    if(line!="SKETCH")
1505    {
1506        synfig::error("Not a sketch");
1507        return false;
1508    }
1509
1510    etl::smart_ptr<std::list<synfig::Point> > stroke_data;
1511
1512    while(file)
1513    {
1514        getline(file,line);
1515
1516        if(line.empty())
1517            continue;
1518
1519        switch(line[0])
1520        {
1521        case 'C':
1522        case 'c':
1523            {
1524                stroke_data.spawn();
1525                float r,g,b;
1526                if(!strscanf(line,"C %f %f %f",&r, &g, &b))
1527                {
1528                    synfig::warning("Bad color line \"%s\"",line.c_str());
1529                    r=0;g=0;b=0;
1530                }
1531                add_persistent_stroke(stroke_data, synfig::Color(r,g,b));
1532            }
1533            break;
1534        case 'V':
1535        case 'v':
1536            if(!stroke_data)
1537            {
1538                stroke_data.spawn();
1539                add_persistent_stroke(stroke_data, synfig::Color(0,0,0));
1540            }
1541            float x,y;
1542            if(!strscanf(line,"V %f %f",&x, &y))
1543                synfig::warning("Bad vertex \"%s\"",line.c_str());
1544            else
1545                stroke_data->push_back(synfig::Vector(x,y));
1546            break;
1547        default:
1548            synfig::warning("Unexpected sketch token '%c'",line[0]);
1549            break;
1550        }
1551    }
1552
1553    sketch_filename_=filename;
1554    return true;
1555}
1556
1557
1558void
1559Duckmatic::add_ducks_layers(synfig::Canvas::Handle canvas, std::set<synfig::Layer::Handle>& selected_layer_set, etl::handle<CanvasView> canvas_view, synfig::TransformStack& transform_stack)
1560{
1561    int transforms(0);
1562    String layer_name;
1563
1564#define QUEUE_REBUILD_DUCKS     sigc::mem_fun(*canvas_view,&CanvasView::queue_rebuild_ducks)
1565
1566    if(!canvas)
1567    {
1568        synfig::warning("Duckmatic::add_ducks_layers(): Layer doesn't have canvas set");
1569        return;
1570    }
1571    for(Canvas::iterator iter(canvas->begin());iter!=canvas->end();++iter)
1572    {
1573        Layer::Handle layer(*iter);
1574
1575        if(selected_layer_set.count(layer))
1576        {
1577            if(!curr_transform_stack_set)
1578            {
1579                curr_transform_stack_set=true;
1580                curr_transform_stack=transform_stack;
1581            }
1582
1583            // This layer is currently selected.
1584            duck_changed_connections.push_back(layer->signal_changed().connect(QUEUE_REBUILD_DUCKS));
1585
1586            // do the bounding box thing
1587            synfig::Rect& bbox = canvas_view->get_bbox();
1588
1589            // special calculations for Layer_PasteCanvas
1590            etl::handle<Layer_PasteCanvas> layer_pastecanvas( etl::handle<Layer_PasteCanvas>::cast_dynamic(layer) );
1591            synfig::Rect layer_bounds = layer_pastecanvas
1592                                      ? layer_pastecanvas->get_bounding_rect_context_dependent(canvas_view->get_context_params())
1593                                      : layer->get_bounding_rect();
1594
1595            bbox|=transform_stack.perform(layer_bounds);
1596
1597            // Grab the layer's list of parameters
1598            Layer::ParamList paramlist(layer->get_param_list());
1599
1600            // Grab the layer vocabulary
1601            Layer::Vocab vocab=layer->get_param_vocab();
1602            Layer::Vocab::iterator iter;
1603
1604            for(iter=vocab.begin();iter!=vocab.end();iter++)
1605            {
1606                if(!iter->get_hidden() && !iter->get_invisible_duck())
1607                {
1608                    synfigapp::ValueDesc value_desc(layer,iter->get_name());
1609                    add_to_ducks(value_desc,canvas_view,transform_stack,&*iter);
1610                    if(value_desc.is_value_node())
1611                        duck_changed_connections.push_back(value_desc.get_value_node()->signal_changed().connect(QUEUE_REBUILD_DUCKS));
1612                }
1613            }
1614        }
1615
1616        layer_name=layer->get_name();
1617
1618        if(layer->active())
1619        {
1620            Transform::Handle trans(layer->get_transform());
1621            if(trans)
1622            {
1623                transform_stack.push(trans);
1624                transforms++;
1625            }
1626        }
1627
1628        // If this is a paste canvas layer, then we need to
1629        // descend into it
1630        if(etl::handle<Layer_PasteCanvas> layer_pastecanvas = etl::handle<Layer_PasteCanvas>::cast_dynamic(layer))
1631        {
1632            transform_stack.push_back(
1633                new Transform_Matrix(
1634                    layer->get_guid(),
1635                    layer_pastecanvas->get_summary_transformation().get_matrix()
1636                )
1637            );
1638
1639            Canvas::Handle child_canvas(layer->get_param("canvas").get(Canvas::Handle()));
1640            add_ducks_layers(child_canvas,selected_layer_set,canvas_view,transform_stack);
1641
1642            transform_stack.pop();
1643        }
1644    }
1645    // Remove all of the transforms we have added
1646    while(transforms--) { transform_stack.pop(); }
1647
1648#undef QUEUE_REBUILD_DUCKS
1649}
1650
1651/*
1652-- ** -- add_to_ducks GIANT  M E T H O D S-------------------------------------
1653-- ** -- -----------------------------------------------------------------------
1654-- ** -- S H O U L D  B E  S I M P L I F  I E D---------------------------------
1655-- ** -- -----------------------------------------------------------------------
1656---**-----------------------TODO-Must be simplified!(1500 lines length)-------
1657-- ** -- -----------------------------------------------------------------------
1658*/
1659bool
1660Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handle<CanvasView> canvas_view, const synfig::TransformStack& transform_stack, synfig::ParamDesc *param_desc)
1661{
1662    synfig::Type &type=value_desc.get_value_type();
1663#define REAL_COOKIE     reinterpret_cast<synfig::ParamDesc*>(28)
1664
1665    if (type == type_real)
1666    {
1667        if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
1668        {
1669            etl::handle<Duck> duck=new Duck();
1670            set_duck_value_desc(*duck, value_desc, transform_stack);
1671            duck->set_radius(true);
1672            duck->set_type(Duck::TYPE_RADIUS);
1673
1674            // put the duck on the right hand side of the center
1675            // Zoom parameter value (PasteCanvas and Zoom layers)
1676            // should be represented as exponent
1677            if ( param_desc && param_desc!=REAL_COOKIE && param_desc->get_exponential() )
1678            {
1679                duck->set_point(Point(exp(value_desc.get_value(get_time()).get(Real())), 0));
1680                duck->set_exponential(param_desc->get_exponential());
1681            } else {
1682                duck->set_point(Point(value_desc.get_value(get_time()).get(Real()), 0));
1683                duck->set_exponential(false);
1684            }
1685
1686            if(value_desc.is_value_node())
1687            {
1688                // If the ValueNode can be directly manipulated,
1689                // then set it as so.
1690                duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1691            }
1692            else
1693            {
1694                duck->set_editable(true);
1695            }
1696
1697            if(param_desc && param_desc!=REAL_COOKIE)
1698            {
1699                if(!param_desc->get_origin().empty())
1700                {
1701                    synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1702                    /*
1703                    duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1704                    */
1705                    add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1706
1707                    Layer::Handle layer=value_desc.get_layer();
1708                    if(etl::handle<Layer_PasteCanvas>::cast_dynamic(layer))
1709                    {
1710                        Vector focus(layer->get_param("focus").get(Vector()));
1711                        duck->set_origin(last_duck()->get_point() + focus);
1712                    }
1713                    else
1714                        duck->set_origin(last_duck());
1715                }
1716                duck->set_scalar(param_desc->get_scalar());
1717            }
1718
1719            duck->signal_edited().clear(); // value_desc.get_value_type() == type_real:
1720            duck->signal_edited().connect(
1721                sigc::bind(
1722                    sigc::mem_fun(
1723                        *this,
1724                        &studio::Duckmatic::on_duck_changed),
1725                    value_desc));
1726
1727            duck->signal_user_click(2).connect(
1728                sigc::bind(
1729                    sigc::bind(
1730                        sigc::bind(
1731                            sigc::mem_fun(
1732                                *canvas_view,
1733                                &studio::CanvasView::popup_param_menu),
1734                            false),
1735                        0.0f),
1736                    value_desc));
1737
1738            add_duck(duck);
1739
1740            return true;
1741        }
1742    }
1743    else
1744    if (type == type_angle)
1745    {
1746        if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
1747        {
1748            etl::handle<Duck> duck=new Duck();
1749            duck->set_type(Duck::TYPE_ANGLE);
1750            set_duck_value_desc(*duck, value_desc, transform_stack);
1751            synfig::Angle angle;
1752
1753            angle=value_desc.get_value(get_time()).get(Angle());
1754            duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1755            if(value_desc.is_value_node())
1756            {
1757                ValueNode::Handle value_node=value_desc.get_value_node();
1758                //duck->set_name(strprintf("%x",value_node.get()));
1759
1760                // If the ValueNode can be directly manipulated,
1761                // then set it as so.
1762                duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1763            }
1764            else
1765            {
1766                //angle=(value_desc.get_value().get(Angle()));
1767                //duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1768                //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1769                duck->set_editable(true);
1770            }
1771
1772            if(param_desc && param_desc!=REAL_COOKIE)
1773            {
1774                if(!param_desc->get_origin().empty())
1775                {
1776                    synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1777                    /*
1778                    duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1779                    */
1780                    add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1781                    duck->set_origin(last_duck());
1782                }
1783                duck->set_scalar(param_desc->get_scalar());
1784            }
1785
1786            duck->signal_edited().clear(); // value_desc.get_value_type() == type_angle:
1787            duck->signal_edited().connect(
1788                sigc::bind(
1789                    sigc::mem_fun(
1790                        *this,
1791                        &studio::Duckmatic::on_duck_changed),
1792                    value_desc));
1793
1794            duck->signal_user_click(2).connect(
1795                sigc::bind(
1796                    sigc::bind(
1797                        sigc::bind(
1798                            sigc::mem_fun(
1799                                *canvas_view,
1800                                &studio::CanvasView::popup_param_menu),
1801                            false),
1802                        0.0f),
1803                    value_desc));
1804
1805            add_duck(duck);
1806
1807            return true;
1808        }
1809    }
1810    else
1811    if (type == type_vector)
1812    {
1813        etl::handle<Layer_PasteCanvas> layer;
1814        if (value_desc.parent_is_layer())
1815            layer = etl::handle<Layer_PasteCanvas>::cast_dynamic(value_desc.get_layer());
1816        if (!layer) {
1817            etl::handle<Duck> duck=new Duck();
1818            set_duck_value_desc(*duck, value_desc, transform_stack);
1819            ValueNode_Composite::Handle blinepoint_value_node;
1820            int index;
1821            bool done(false);
1822            if(value_desc.parent_is_linkable_value_node()
1823               &&
1824               value_desc.get_parent_value_node()->get_type() == type_bline_point)
1825            {
1826                blinepoint_value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_parent_value_node());
1827                if(blinepoint_value_node)
1828                {
1829                    index=blinepoint_value_node->get_link_index_from_name("t2");
1830                    if(index==value_desc.get_index())
1831                    {
1832                        BLinePoint bp=(*blinepoint_value_node)(get_time()).get(BLinePoint());
1833                        Vector t2=bp.get_tangent2();
1834                        duck->set_point(t2);
1835                        done=true;
1836                    }
1837                }
1838            }
1839            if(!done)
1840                duck->set_point(value_desc.get_value(get_time()).get(Point()));
1841
1842            if(value_desc.is_value_node())
1843            {
1844                // if the vertex is converted to 'bone influence', add the bones' ducks
1845                if (ValueNode_BoneInfluence::Handle bone_influence_vertex_value_node =
1846                    ValueNode_BoneInfluence::Handle::cast_dynamic(value_desc.get_value_node()))
1847                    add_to_ducks(synfigapp::ValueDesc(bone_influence_vertex_value_node,
1848                                                      bone_influence_vertex_value_node->get_link_index_from_name("bone_weight_list")),
1849                                 canvas_view, transform_stack);
1850
1851                // If the ValueNode can be directly manipulated,
1852                // then set it as so.
1853                duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1854            }
1855            else
1856            {
1857                //duck->set_point(value_desc.get_value().get(Point()));
1858                //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1859                duck->set_editable(true);
1860            }
1861
1862            // If we were passed a parameter description
1863            if(param_desc)
1864            {
1865                if(!param_desc->get_connect().empty())
1866                {
1867                    synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_connect());
1868                    Duck::Handle connect_duck;
1869                    if(duck_map.find(calc_duck_guid(value_desc_origin, transform_stack))!=duck_map.end())
1870                    {
1871                        connect_duck=duck_map[calc_duck_guid(value_desc_origin, transform_stack)];
1872                    }
1873                    else
1874                    {
1875                        add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1876                        connect_duck=last_duck();
1877                    }
1878                    duck->set_connect_duck(connect_duck);
1879                }
1880                if(!param_desc->get_box().empty())
1881                {
1882                    synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_box());
1883                    add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1884                    duck->set_box_duck(last_duck());
1885                }
1886
1887                // If we have an origin
1888                if(!param_desc->get_origin().empty())
1889                {
1890                    synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1891                    /*
1892                    duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1893                    */
1894                    add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1895                    duck->set_origin(last_duck());
1896                    duck->set_type(Duck::TYPE_VERTEX);
1897                }
1898                else
1899                    duck->set_type(Duck::TYPE_POSITION);
1900
1901                duck->set_scalar(param_desc->get_scalar());
1902            }
1903            else
1904                duck->set_type(Duck::TYPE_POSITION);
1905
1906            duck->signal_edited().clear(); // value_desc.get_value_type() == type_vector:
1907            duck->signal_edited().connect(
1908                sigc::bind(
1909                    sigc::mem_fun(
1910                        *this,
1911                        &studio::Duckmatic::on_duck_changed),
1912                    value_desc));
1913
1914            duck->signal_user_click(2).connect(
1915                sigc::bind(
1916                    sigc::bind(
1917                        sigc::bind(
1918                            sigc::mem_fun(
1919                                *canvas_view,
1920                                &studio::CanvasView::popup_param_menu),
1921                            false),
1922                        1.0f),
1923                    value_desc));
1924
1925            add_duck(duck);
1926
1927            return true;
1928        }
1929    }
1930    else
1931    if (type == type_transformation)
1932    {
1933        if (value_desc.parent_is_layer() && param_desc != NULL)
1934        {
1935            etl::handle<Layer_PasteCanvas> layer = etl::handle<Layer_PasteCanvas>::cast_dynamic(value_desc.get_layer());
1936            if (layer)
1937            {
1938                synfigapp::ValueDesc alternative_value_desc(value_desc.get_layer(), "origin");
1939                Transformation transformation = value_desc.get_value(get_time()).get(Transformation());
1940
1941                bool editable = !value_desc.is_value_node()
1942                    || synfigapp::is_editable(value_desc.get_value_node());
1943                bool alternative_editable = !alternative_value_desc.is_value_node()
1944                    || synfigapp::is_editable(alternative_value_desc.get_value_node());
1945                alternative_editable = alternative_editable && editable;
1946                Point axis_x(1, transformation.angle);
1947                Point axis_y(1, transformation.angle + Angle::deg(90.f) + transformation.skew_angle);
1948
1949                Point screen_offset = transform_stack.perform(transformation.offset);
1950                Point screen_axis_x = transform_stack.perform(transformation.offset + axis_x) - screen_offset;
1951                Point screen_axis_y = transform_stack.perform(transformation.offset + axis_y) - screen_offset;
1952                Real scalar_x = screen_axis_x.mag();
1953                if (scalar_x > 0.0) scalar_x = 1.0/scalar_x;
1954                Real scalar_y = screen_axis_y.mag();
1955                if (scalar_y > 0.0) scalar_y = 1.0/scalar_y;
1956                scalar_x /= zoom;
1957                scalar_y /= zoom;
1958                Real pw = canvas_interface->get_canvas()->rend_desc().get_pw();
1959                Real ph = canvas_interface->get_canvas()->rend_desc().get_ph();
1960                scalar_x *= 75.0 * fabs(pw);
1961                scalar_y *= 75.0 * fabs(ph);
1962
1963                Duck::Handle duck;
1964
1965                // add offset duck
1966                duck=new Duck();
1967                set_duck_value_desc(*duck, value_desc, "offset", transform_stack);
1968                duck->set_point(transformation.offset);
1969                duck->set_editable(editable);
1970                duck->set_alternative_editable(alternative_editable);
1971                duck->set_type(Duck::TYPE_POSITION);
1972                duck->set_alternative_value_desc(alternative_value_desc);
1973                connect_signals(duck, duck->get_value_desc(), *canvas_view);
1974                add_duck(duck);
1975
1976                etl::handle<Duck> origin_duck = duck;
1977
1978                // add angle duck
1979                duck=new Duck();
1980                duck->set_type(Duck::TYPE_ANGLE);
1981                set_duck_value_desc(*duck, value_desc, "angle", transform_stack);
1982                duck->set_point(Point(0.8,transformation.angle));
1983                duck->set_scalar(scalar_x);
1984                duck->set_editable(editable);
1985                duck->set_origin(origin_duck);
1986                connect_signals(duck, duck->get_value_desc(), *canvas_view);
1987                add_duck(duck);
1988
1989                etl::handle<Duck> angle_duck = duck;
1990
1991                // add skew duck
1992                duck=new Duck();
1993                duck->set_type(Duck::TYPE_SKEW);
1994                set_duck_value_desc(*duck, value_desc, "skew_angle", transform_stack);
1995                duck->set_point(Point(0.8,transformation.skew_angle));
1996                duck->set_scalar(scalar_y);
1997                duck->set_editable(editable);
1998                duck->set_origin(origin_duck);
1999                duck->set_axis_x_angle(angle_duck, Angle::deg(90));
2000                duck->set_axis_y_angle(angle_duck, Angle::deg(180));
2001                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2002                add_duck(duck);
2003
2004                etl::handle<Duck> skew_duck = duck;
2005
2006                // add scale-x duck
2007                duck=new Duck();
2008                duck->set_type(Duck::TYPE_SCALE_X);
2009                set_duck_value_desc(*duck, value_desc.get_sub_value("scale").get_sub_value("x"), transform_stack);
2010                duck->set_point(Point(1,0));
2011                duck->set_scalar(scalar_x);
2012                duck->set_editable(editable);
2013                duck->set_origin(origin_duck);
2014                duck->set_linear(true, angle_duck);
2015                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2016                add_duck(duck);
2017
2018                etl::handle<Duck> scale_x_duck = duck;
2019
2020                // add scale-y duck
2021                duck=new Duck();
2022                duck->set_type(Duck::TYPE_SCALE_Y);
2023                set_duck_value_desc(*duck, value_desc.get_sub_value("scale").get_sub_value("y"), transform_stack);
2024                duck->set_point(Point(1,0));
2025                duck->set_scalar(scalar_y);
2026                duck->set_editable(editable);
2027                duck->set_origin(origin_duck);
2028                duck->set_linear(true, skew_duck);
2029                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2030                add_duck(duck);
2031
2032                etl::handle<Duck> scale_y_duck = duck;
2033
2034                // add scale duck
2035                duck=new Duck();
2036                duck->set_type(Duck::TYPE_SCALE);
2037                set_duck_value_desc(*duck, value_desc, "scale", transform_stack);
2038                duck->set_point(Point(1,1));
2039                duck->set_lock_aspect(true);
2040                duck->set_editable(editable);
2041                duck->set_origin(origin_duck);
2042                duck->set_axis_x_angle(scale_x_duck);
2043                duck->set_axis_x_mag(scale_x_duck);
2044                duck->set_axis_y_angle(scale_y_duck);
2045                duck->set_axis_y_mag(scale_y_duck);
2046                duck->set_track_axes(true);
2047                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2048                add_duck(duck);
2049
2050                return true;
2051            }
2052        }
2053    }
2054    else
2055    if (type == type_segment)
2056    {
2057        int index;
2058        etl::handle<Bezier> bezier(new Bezier());
2059        ValueNode_Composite::Handle value_node;
2060
2061        if(value_desc.is_value_node() &&
2062            (value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())))
2063        {
2064            index=value_node->get_link_index_from_name("p1");
2065            if(!add_to_ducks(synfigapp::ValueDesc(value_node,index),canvas_view,transform_stack))
2066                return false;
2067            bezier->p1=last_duck();
2068            bezier->p1->set_type(Duck::TYPE_VERTEX);
2069
2070            index=value_node->get_link_index_from_name("t1");
2071            if(!add_to_ducks(synfigapp::ValueDesc(value_node,index),canvas_view,transform_stack))
2072                return false;
2073            bezier->c1=last_duck();
2074            bezier->c1->set_type(Duck::TYPE_TANGENT);
2075            bezier->c1->set_origin(bezier->p1);
2076            bezier->c1->set_scalar(TANGENT_BEZIER_SCALE);
2077            bezier->c1->set_tangent(true);
2078
2079            index=value_node->get_link_index_from_name("p2");
2080            if(!add_to_ducks(synfigapp::ValueDesc(value_node,index),canvas_view,transform_stack))
2081                return false;
2082            bezier->p2=last_duck();
2083            bezier->p2->set_type(Duck::TYPE_VERTEX);
2084
2085            index=value_node->get_link_index_from_name("t2");
2086            if(!add_to_ducks(synfigapp::ValueDesc(value_node,index),canvas_view,transform_stack))
2087                return false;
2088            bezier->c2=last_duck();
2089            bezier->c2->set_type(Duck::TYPE_TANGENT);
2090            bezier->c2->set_origin(bezier->p2);
2091            bezier->c2->set_scalar(-TANGENT_BEZIER_SCALE);
2092            bezier->c2->set_tangent(true);
2093
2094            bezier->signal_user_click(2).connect(
2095                sigc::bind(
2096                    sigc::mem_fun(
2097                        *canvas_view,
2098                        &studio::CanvasView::popup_param_menu_bezier),
2099                    value_desc));
2100
2101            add_bezier(bezier);
2102        }
2103        else if(value_desc.get_value().is_valid())
2104        {
2105            Segment segment=value_desc.get_value().get(Segment());
2106            etl::handle<Duck> duck_p,duck_c;
2107            synfig::String name;
2108            if(param_desc)
2109                name=param_desc->get_local_name();
2110            else
2111                name=value_desc.get_guid_string();
2112
2113            duck_p=new Duck(segment.p1);
2114            duck_p->set_name(name+".P1");
2115            duck_p->set_type(Duck::TYPE_VERTEX);
2116            add_duck(duck_p);
2117
2118            duck_c=new Duck(segment.t1);
2119            duck_c->set_name(name+".T1");
2120            duck_c->set_type(Duck::TYPE_TANGENT);
2121            add_duck(duck_c);
2122            duck_c->set_origin(duck_p);
2123            duck_c->set_scalar(TANGENT_HANDLE_SCALE);
2124            duck_c->set_tangent(true);
2125
2126            bezier->p1=duck_p;
2127            bezier->c1=duck_c;
2128
2129            duck_p=new Duck(segment.p2);
2130            duck_p->set_name(name+".P2");
2131            duck_p->set_type(Duck::TYPE_VERTEX);
2132            add_duck(duck_p);
2133
2134            duck_c=new Duck(segment.t2);
2135            duck_c->set_type(Duck::TYPE_TANGENT);
2136            duck_c->set_name(name+".T2");
2137            add_duck(duck_c);
2138            duck_c->set_origin(duck_p);
2139            duck_c->set_scalar(-TANGENT_HANDLE_SCALE);
2140            duck_c->set_tangent(true);
2141
2142            bezier->p2=duck_p;
2143            bezier->c2=duck_c;
2144            add_bezier(bezier);
2145        }
2146
2147        return true;
2148    }
2149    else
2150    if (type == type_bline_point)
2151    {
2152        bool editable = !value_desc.is_value_node() || synfigapp::is_editable(value_desc.get_value_node());
2153        BLinePoint point = value_desc.get_value(get_time()).get(BLinePoint());
2154
2155        Duck::Handle duck;
2156
2157        // add vertex duck
2158        duck=new Duck();
2159        set_duck_value_desc(*duck, value_desc, "point", transform_stack);
2160        duck->set_point(point.get_vertex());
2161        duck->set_editable(editable);
2162        duck->set_type(Duck::TYPE_VERTEX);
2163        connect_signals(duck, duck->get_value_desc(), *canvas_view);
2164        add_duck(duck);
2165
2166        etl::handle<Duck> vertex_duck = duck;
2167
2168        // add tamgent1 duck
2169        duck=new Duck();
2170        duck->set_type(Duck::TYPE_TANGENT);
2171        set_duck_value_desc(*duck, value_desc, "t1", transform_stack);
2172        duck->set_point(point.get_tangent1());
2173        duck->set_editable(editable);
2174        duck->set_origin(vertex_duck);
2175        connect_signals(duck, duck->get_value_desc(), *canvas_view);
2176        add_duck(duck);
2177
2178        // add tamgent2 duck
2179        duck=new Duck();
2180        duck->set_type(Duck::TYPE_TANGENT);
2181        set_duck_value_desc(*duck, value_desc, "t2", transform_stack);
2182        duck->set_point(point.get_tangent2());
2183        duck->set_editable(editable);
2184        duck->set_origin(vertex_duck);
2185        duck->set_scalar(-1);
2186        connect_signals(duck, duck->get_value_desc(), *canvas_view);
2187        add_duck(duck);
2188
2189        return true;
2190    }
2191    else
2192    if (type == type_list)
2193    {
2194        // Check for BLine
2195        if (value_desc.is_value_node() &&
2196            ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node()))
2197        {
2198            ValueNode_BLine::Handle value_node;
2199            value_node=ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node());
2200
2201            int i,first=-1;
2202
2203            etl::handle<Bezier> bezier;
2204            etl::handle<Duck> first_duck, first_tangent2_duck;
2205
2206            for (i = 0; i < value_node->link_count(); i++)
2207            {
2208                float amount(value_node->list[i].amount_at_time(get_time()));
2209
2210                // skip vertices that aren't fully on
2211                if (amount < 0.9999f)
2212                    continue;
2213
2214                // remember the index of the first vertex we didn't skip
2215                if (first == -1)
2216                    first = i;
2217
2218                ValueNode::Handle sub_node = value_node->get_link(i);
2219                bool editable = synfigapp::is_editable(sub_node);
2220                BLinePoint bline_point((*value_node->get_link(i))(get_time()).get(BLinePoint()));
2221                synfigapp::ValueDesc sub_value_desc(value_node, i, value_desc);
2222
2223                // Now add the ducks:
2224
2225                Duck::Handle duck;
2226
2227                // ----Vertex Duck
2228
2229                duck=new Duck(bline_point.get_vertex());
2230                set_duck_value_desc(*duck, sub_value_desc, "point", transform_stack);
2231                duck->set_editable(editable);
2232                duck->set_type(Duck::TYPE_VERTEX);
2233                if(param_desc)
2234                {
2235                    if(!param_desc->get_origin().empty())
2236                    {
2237                        synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
2238                        add_to_ducks(value_desc_origin,canvas_view, transform_stack);
2239                        duck->set_origin(last_duck());
2240                    }
2241                }
2242                duck=add_similar_duck(duck);
2243                if(i==first) first_duck=duck;
2244                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2245
2246                Duck::Handle vertex_duck = duck;
2247
2248                // ----Width duck
2249
2250                Duck::Handle width;
2251
2252                // Add the width duck if it is a parameter with a hint (ie. "width") or if it isn't a parameter
2253                //if (!   ((param_desc && !param_desc->get_hint().empty()) || !param_desc)   )
2254                if (param_desc && param_desc->get_hint().empty())
2255                {
2256                    // if it's a parameter without a hint, then don't add the width duck
2257                    // (This prevents width ducks from being added to region layers, and possibly other cases)
2258                }
2259                else
2260                {
2261                    // add width duck
2262
2263                    duck=new Duck();
2264                    set_duck_value_desc(*duck, sub_value_desc, "width", transform_stack);
2265                    duck->set_radius(true);
2266                    duck->set_point(Point(bline_point.get_width(), 0));
2267                    duck->set_editable(editable);
2268                    duck->set_type(Duck::TYPE_WIDTH);
2269                    duck->set_origin(vertex_duck);
2270                    connect_signals(duck, duck->get_value_desc(), *canvas_view);
2271
2272                    // if the bline is a layer's parameter, scale the width duck by the layer's "width" parameter
2273                    if (param_desc)
2274                    {
2275                        ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_hint()).get_value(get_time()));
2276                        Real gv(value_desc.get_layer()->get_parent_canvas_grow_value());
2277                        if(value.same_type_as(synfig::Real()))
2278                            duck->set_scalar(exp(gv)*value.get(synfig::Real())*0.5f);
2279                        // if it doesn't have a "width" parameter, scale by 0.5f instead
2280                        else
2281                            duck->set_scalar(0.5f);
2282                    }
2283                    // otherwise just present the raw unscaled width
2284                    else
2285                        duck->set_scalar(0.5f);
2286
2287                    add_duck(duck);
2288                    width = duck;
2289                }
2290
2291                // each bezier uses t2 of one point and t1 of the next
2292                // the first time through this loop we won't have the t2 duck from the previous vertex
2293                // and so we don't make a bezier.  instead we skip on to t2 for this point
2294                Duck::Handle tangent1_duck;
2295                if(bezier)
2296                {
2297                    // Add the tangent1 duck
2298                    duck=new Duck(bline_point.get_tangent1());
2299                    set_duck_value_desc(*duck, sub_value_desc, "t1", transform_stack);
2300                    duck->set_editable(editable);
2301                    duck=add_similar_duck(duck);
2302
2303                    duck->set_origin(vertex_duck);
2304                    duck->set_scalar(-TANGENT_BEZIER_SCALE);
2305                    duck->set_tangent(true);
2306                    duck->set_shared_point(etl::smart_ptr<Point>());
2307                    duck->set_shared_angle(etl::smart_ptr<Angle>());
2308                    duck->set_shared_mag(etl::smart_ptr<Real>());
2309                    connect_signals(duck, duck->get_value_desc(), *canvas_view);
2310
2311                    // each bezier uses t2 of one point and t1 of the next
2312                    // we should already have a bezier, so add the t1 of this point to it
2313
2314                    bezier->p2=vertex_duck;
2315                    bezier->c2=duck;
2316
2317                    bezier->signal_user_click(2).connect(
2318                        sigc::bind(
2319                            sigc::mem_fun(
2320                                *canvas_view,
2321                                &studio::CanvasView::popup_param_menu_bezier),
2322                            synfigapp::ValueDesc(value_node,i)));
2323
2324                    add_bezier(bezier);
2325                    bezier=0;
2326                    tangent1_duck = duck;
2327                }
2328
2329                // don't start a new bezier for the last point in the line if we're not looped
2330                if ((i+1>=value_node->link_count() && !value_node->get_loop()))
2331                    continue;
2332
2333                bezier=new Bezier();
2334
2335                // Add the tangent2 duck
2336                Duck::Handle tangent2_duck;
2337                duck=new Duck(bline_point.get_tangent2());
2338                set_duck_value_desc(*duck, sub_value_desc, "t2", transform_stack);
2339                duck->set_editable(editable);
2340
2341                duck=add_similar_duck(duck);
2342                duck->set_origin(vertex_duck);
2343                duck->set_scalar(TANGENT_BEZIER_SCALE);
2344                duck->set_tangent(true);
2345                duck->set_shared_point(etl::smart_ptr<Point>());
2346                duck->set_shared_angle(etl::smart_ptr<Angle>());
2347                duck->set_shared_mag(etl::smart_ptr<Real>());
2348                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2349
2350                bezier->p1=vertex_duck;
2351                bezier->c1=duck;
2352                tangent2_duck = duck;
2353                if (i == first) first_tangent2_duck = tangent2_duck;
2354
2355                // link tangents
2356                if (tangent1_duck && tangent2_duck && !bline_point.get_split_tangent_both()) {
2357                    if (bline_point.get_merge_tangent_both())
2358                    {
2359                        etl::smart_ptr<synfig::Point> point(new Point(tangent1_duck->get_point()));
2360                        tangent1_duck->set_shared_point(point);
2361                        tangent2_duck->set_shared_point(point);
2362                    }
2363                    else
2364                    if (!bline_point.get_split_tangent_angle())
2365                    {
2366                        etl::smart_ptr<synfig::Angle> angle(new Angle(tangent1_duck->get_point().angle()));
2367                        tangent1_duck->set_shared_angle(angle);
2368                        tangent2_duck->set_shared_angle(angle);
2369                    }
2370                    else
2371                    if (!bline_point.get_split_tangent_radius())
2372                    {
2373                        etl::smart_ptr<synfig::Real> mag(new Real(tangent1_duck->get_point().mag()));
2374                        tangent1_duck->set_shared_mag(mag);
2375                        tangent2_duck->set_shared_mag(mag);
2376                    }
2377                }
2378            }
2379
2380            // Loop if necessary
2381            if(bezier && value_node->get_loop())
2382            {
2383                ValueNode::Handle sub_node = value_node->get_link(first);
2384                bool editable = synfigapp::is_editable(sub_node);
2385                bool is_bline_point = sub_node->get_type() == type_bline_point;
2386                BLinePoint bline_point;
2387                if (is_bline_point) bline_point = (*sub_node)(get_time()).get(BLinePoint());
2388
2389                ValueNode_BoneInfluence::Handle bone_influence_vertex_value_node(
2390                    ValueNode_BoneInfluence::Handle::cast_dynamic(value_node->get_link(first)));
2391                ValueNode_Composite::Handle composite_bone_link_value_node;
2392                synfig::TransformStack bone_transform_stack(transform_stack);
2393                if (bone_influence_vertex_value_node)
2394                {
2395                    // apply bones transformation to the ducks
2396                    composite_bone_link_value_node = ValueNode_Composite::Handle::cast_dynamic(
2397                        bone_influence_vertex_value_node->get_link("link") );
2398
2399                    if(param_desc)
2400                    {
2401                        if(!param_desc->get_origin().empty())
2402                        {
2403                            synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
2404                            add_to_ducks(value_desc_origin, canvas_view, transform_stack);
2405                            synfig::GUID guid(calc_duck_guid(value_desc_origin, transform_stack));
2406                            bone_transform_stack.push(new Transform_Origin(guid^synfig::GUID::hasher("origin"), last_duck()));
2407                        }
2408                    }
2409
2410                    Matrix transform(bone_influence_vertex_value_node->calculate_transform(get_time()));
2411                    synfig::GUID guid(bone_influence_vertex_value_node->get_link("bone_weight_list")->get_guid());
2412
2413                    bone_transform_stack.push(new Transform_Matrix(guid, transform));
2414                }
2415
2416                // Add the vertex duck
2417                Duck::Handle duck;
2418                Duck::Handle vertex_duck(first_duck);
2419                Duck::Handle tangent2_duck(first_tangent2_duck);
2420                synfigapp::ValueDesc sub_value_desc(value_node,first,value_desc);
2421
2422                // Add the tangent1 duck
2423                duck=new Duck(bline_point.get_tangent1());
2424                set_duck_value_desc(*duck, sub_value_desc, "t1", transform_stack);
2425                duck->set_editable(editable);
2426
2427                duck=add_similar_duck(duck);
2428                duck->set_origin(vertex_duck);
2429                duck->set_scalar(-TANGENT_BEZIER_SCALE);
2430                duck->set_tangent(true);
2431                duck->set_shared_point(etl::smart_ptr<Point>());
2432                duck->set_shared_angle(etl::smart_ptr<Angle>());
2433                duck->set_shared_mag(etl::smart_ptr<Real>());
2434                connect_signals(duck, duck->get_value_desc(), *canvas_view);
2435
2436                bezier->p2=vertex_duck;
2437                bezier->c2=duck;
2438
2439                bezier->signal_user_click(2).connect(
2440                    sigc::bind(
2441                        sigc::mem_fun(
2442                            *canvas_view,
2443                            &studio::CanvasView::popup_param_menu_bezier),
2444                        synfigapp::ValueDesc(value_node,first)));
2445
2446                add_bezier(bezier);
2447                bezier=0;
2448                Duck::Handle tangent1_duck = duck;
2449
2450                // link tangents
2451                if (tangent1_duck && tangent2_duck && !bline_point.get_split_tangent_both()) {
2452                    if (bline_point.get_merge_tangent_both())
2453                    {
2454                        etl::smart_ptr<synfig::Point> point(new Point(tangent1_duck->get_point()));
2455                        tangent1_duck->set_shared_point(point);
2456                        tangent2_duck->set_shared_point(point);
2457                    }
2458                    else
2459                    if (!bline_point.get_split_tangent_angle())
2460                    {
2461                        etl::smart_ptr<synfig::Angle> angle(new Angle(tangent1_duck->get_point().angle()));
2462                        tangent1_duck->set_shared_angle(angle);
2463                        tangent2_duck->set_shared_angle(angle);
2464                    }
2465                    else
2466                    if (!bline_point.get_split_tangent_radius())
2467                    {
2468                        etl::smart_ptr<synfig::Real> mag(new Real(tangent1_duck->get_point().mag()));
2469                        tangent1_duck->set_shared_mag(mag);
2470                        tangent2_duck->set_shared_mag(mag);
2471                    }
2472                }
2473            }
2474            return true;
2475        }
2476
2477        else // Check for StaticList
2478        if(value_desc.is_value_node() &&
2479            ValueNode_StaticList::Handle::cast_dynamic(value_desc.get_value_node()))
2480        {
2481            ValueNode_StaticList::Handle value_node;
2482            value_node=ValueNode_StaticList::Handle::cast_dynamic(value_desc.get_value_node());
2483            int i;
2484
2485            synfig::Type &contained_type(value_node->get_contained_type());
2486            if (contained_type == type_vector)
2487            {
2488                Bezier bezier;
2489                etl::handle<Duck> first_duck, duck;
2490                int first = -1;
2491                for(i=0;i<value_node->link_count();i++)
2492                {
2493                    if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
2494                        return false;
2495                    duck = last_duck();
2496
2497                    // remember the index of the first vertex we didn't skip
2498                    if (first == -1)
2499                    {
2500                        first = i;
2501                        first_duck = duck;
2502                    }
2503
2504                    if(param_desc && !param_desc->get_origin().empty())
2505                    {
2506                        synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
2507                        add_to_ducks(value_desc_origin,canvas_view, transform_stack);
2508                        duck->set_origin(last_duck());
2509/*
2510                        ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
2511                        if(value.same_type_as(synfig::Point()))
2512                            duck->set_origin(value.get(synfig::Point()));
2513*/
2514//                      if(!param_desc->get_origin().empty())
2515//                          last_duck()->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
2516                    }
2517                    duck->set_type(Duck::TYPE_VERTEX);
2518                    bezier.p1=bezier.p2;bezier.c1=bezier.c2;
2519                    bezier.p2=bezier.c2=duck;
2520
2521                    if (first != i)
2522                    {
2523                        handle<Bezier> bezier_(new Bezier());
2524                        bezier_->p1=bezier.p1;
2525                        bezier_->c1=bezier.c1;
2526                        bezier_->p2=bezier.p2;
2527                        bezier_->c2=bezier.c2;
2528                        add_bezier(bezier_);
2529                        last_bezier()->signal_user_click(2).connect(
2530                            sigc::bind(
2531                                sigc::mem_fun(
2532                                    *canvas_view,
2533                                    &studio::CanvasView::popup_param_menu_bezier),
2534                                synfigapp::ValueDesc(value_node,i)));
2535                    }
2536                }
2537
2538                if (value_node->get_loop() && first != -1 && first_duck != duck)
2539                {
2540                    duck = first_duck;
2541
2542                    bezier.p1=bezier.p2;bezier.c1=bezier.c2;
2543                    bezier.p2=bezier.c2=duck;
2544
2545                    handle<Bezier> bezier_(new Bezier());
2546                    bezier_->p1=bezier.p1;
2547                    bezier_->c1=bezier.c1;
2548                    bezier_->p2=bezier.p2;
2549                    bezier_->c2=bezier.c2;
2550                    add_bezier(bezier_);
2551                    last_bezier()->signal_user_click(2).connect(
2552                        sigc::bind(
2553                            sigc::mem_fun(
2554                                *canvas_view,
2555                                &studio::CanvasView::popup_param_menu_bezier),
2556                            synfigapp::ValueDesc(value_node,first)));
2557                }
2558            }
2559            else
2560            if (contained_type == type_segment)
2561            {
2562                for(i=0;i<value_node->link_count();i++)
2563                {
2564                    if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
2565                        return false;
2566                }
2567            }
2568            else
2569            if (contained_type == type_bone_object)
2570            {
2571                printf("%s:%d adding ducks\n", __FILE__, __LINE__);
2572                for(i=0;i<value_node->link_count();i++)
2573                    if(!add_to_ducks(synfigapp::ValueDesc(value_node,i,value_desc),canvas_view,transform_stack))
2574                        return false;
2575                printf("%s:%d adding ducks done\n\n", __FILE__, __LINE__);
2576            }
2577            else
2578            if (contained_type == type_bone_weight_pair)
2579            {
2580                for(i=0;i<value_node->link_count();i++)
2581                    if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
2582                        return false;
2583            }
2584            else
2585            if (value_node->get_contained_type() == types_namespace::TypePair<Bone, Bone>::instance)
2586            {
2587                bool edit_second = value_desc.parent_is_layer() && value_desc.get_layer()->active();
2588                for(i=0;i<value_node->link_count();i++)
2589                {
2590                    ValueNode_Composite::Handle value_node_composite =
2591                        ValueNode_Composite::Handle::cast_dynamic(
2592                            value_node->get_link(i) );
2593                    if (value_node_composite)
2594                    {
2595                        if (!add_to_ducks(
2596                            synfigapp::ValueDesc(
2597                                value_node_composite,
2598                                value_node_composite->get_link_index_from_name(edit_second ? "second" : "first"),
2599                                synfigapp::ValueDesc(value_node,i,value_desc) ),
2600                            canvas_view,
2601                            transform_stack ))
2602                                    return false;
2603                    }
2604                }
2605            }
2606            else
2607                return false;
2608        }
2609
2610        else // Check for WPList
2611        if(value_desc.is_value_node() &&
2612            ValueNode_WPList::Handle::cast_dynamic(value_desc.get_value_node()))
2613        {
2614            ValueNode_WPList::Handle value_node;
2615            bool homogeneous=true; // if we have an exported WPList without a layer consider it homogeneous
2616            value_node=ValueNode_WPList::Handle::cast_dynamic(value_desc.get_value_node());
2617            if(!value_node)
2618            {
2619                error("expected a ValueNode_WPList");
2620                assert(0);
2621            }
2622            ValueNode::Handle bline(value_node->get_bline());
2623            // it is not possible to place any widthpoint's duck if there is
2624            // not associated bline.
2625            if(!bline)
2626                return false;
2627            // Retrieve the homogeneous layer parameter
2628            Layer::Handle layer_parent;
2629            if(value_desc.parent_is_layer())
2630                layer_parent=value_desc.get_layer();
2631            if(layer_parent)
2632                {
2633                    String layer_name(layer_parent->get_name());
2634                    if(layer_name=="advanced_outline")
2635                        homogeneous=layer_parent->get_param("homogeneous").get(bool());
2636                }
2637            int i;
2638            for (i = 0; i < value_node->link_count(); i++)
2639            {
2640                float amount(value_node->list[i].amount_at_time(get_time()));
2641                // skip width points that aren't fully on
2642                if (amount < 0.9999f)
2643                    continue;
2644                WidthPoint width_point((*value_node->get_link(i))(get_time()).get(WidthPoint()));
2645                // try casting the width point to Composite - this tells us whether it is composite or not
2646                ValueNode_Composite::Handle composite_width_point_value_node(
2647                    ValueNode_Composite::Handle::cast_dynamic(value_node->get_link(i)));
2648                if(composite_width_point_value_node) // Add the position
2649                {
2650                    etl::handle<Duck> pduck=new Duck();
2651                    synfigapp::ValueDesc wpoint_value_desc(value_node, i); // The i-widthpoint on WPList
2652                    pduck->set_type(Duck::TYPE_WIDTHPOINT_POSITION);
2653                    set_duck_value_desc(*pduck, wpoint_value_desc, transform_stack);
2654                    // This is a quick hack to obtain the ducks position.
2655                    // The position by amount and the amount by position
2656                    // has to be written considering the bline length too
2657                    // optionally
2658                    ValueNode_BLineCalcVertex::LooseHandle bline_calc_vertex(ValueNode_BLineCalcVertex::create(Vector(0,0)));
2659                    bline_calc_vertex->set_link("bline", bline);
2660                    bline_calc_vertex->set_link("loop", ValueNode_Const::create(false));
2661                    bline_calc_vertex->set_link("amount", ValueNode_Const::create(width_point.get_norm_position(value_node->get_loop())));
2662                    bline_calc_vertex->set_link("homogeneous", ValueNode_Const::create(homogeneous));
2663                    pduck->set_point((*bline_calc_vertex)(get_time()).get(Vector()));
2664                    // hack end
2665                    pduck->set_editable(synfigapp::is_editable(wpoint_value_desc.get_value_node()));
2666                    pduck->signal_edited().clear();
2667                    pduck->signal_edited().connect(sigc::bind(sigc::mem_fun(*this, &studio::Duckmatic::on_duck_changed), wpoint_value_desc));
2668                    pduck->signal_user_click(2).clear();
2669                    pduck->signal_user_click(2).connect(
2670                        sigc::bind(
2671                            sigc::bind(
2672                                sigc::bind(
2673                                    sigc::mem_fun(
2674                                        *canvas_view,
2675                                        &studio::CanvasView::popup_param_menu),
2676                                    false),
2677                                1.0f),
2678                            wpoint_value_desc));
2679                    add_duck(pduck);
2680                    if(param_desc)
2681                    {
2682                        if(!param_desc->get_origin().empty())
2683                        {
2684                            synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
2685                            add_to_ducks(value_desc_origin,canvas_view, transform_stack);
2686                            pduck->set_origin(last_duck());
2687                        }
2688                    }
2689                    // add the width duck
2690                    int index=composite_width_point_value_node->get_link_index_from_name("width");
2691                    if (add_to_ducks(synfigapp::ValueDesc(composite_width_point_value_node,index),canvas_view,transform_stack))
2692                    {
2693                        etl::handle<Duck> wduck;
2694                        wduck=last_duck();
2695                        wduck->set_origin(pduck);
2696                        wduck->set_type(Duck::TYPE_WIDTH);
2697                        // if the composite comes from a layer get the layer's "width" parameter and scale the
2698                        // duck by that value.
2699                        if (param_desc)
2700                        {
2701                            ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),"width").get_value(get_time()));
2702                            Real gv(value_desc.get_layer()->get_parent_canvas_grow_value());
2703                            if(value.same_type_as(synfig::Real()))
2704                                wduck->set_scalar(exp(gv)*(value.get(synfig::Real())*0.5f));
2705                            // if it doesn't have a "width" parameter, scale by 0.5f instead
2706                            else
2707                                wduck->set_scalar(0.5f);
2708                        }
2709                        // otherwise just present the raw unscaled width
2710                        else
2711                            wduck->set_scalar(0.5f);
2712                    }
2713                    else
2714                        return false;
2715                }
2716            }
2717            return true;
2718        }
2719        else // Check for DynamicList
2720        if(value_desc.is_value_node() &&
2721            ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node()))
2722        {
2723            ValueNode_DynamicList::Handle value_node;
2724            value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node());
2725            int i;
2726
2727            if(value_node->get_contained_type()==type_vector)
2728            {
2729                Bezier bezier;
2730                etl::handle<Duck> first_duck, duck;
2731                int first = -1;
2732                for(i=0;i<value_node->link_count();i++)
2733                {
2734                    if(!value_node->list[i].status_at_time(get_time()))
2735                        continue;
2736                    if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
2737                        return false;
2738                    duck = last_duck();
2739
2740                    // remember the index of the first vertex we didn't skip
2741                    if (first == -1)
2742                    {
2743                        first = i;
2744                        first_duck = duck;
2745                    }
2746
2747                    if(param_desc && !param_desc->get_origin().empty())
2748                    {
2749                        synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
2750                        add_to_ducks(value_desc_origin,canvas_view, transform_stack);
2751                        duck->set_origin(last_duck());
2752/*
2753                        ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
2754                        if(value.same_type_as(synfig::Point()))
2755                            duck->set_origin(value.get(synfig::Point()));
2756*/
2757//                      if(!param_desc->get_origin().empty())
2758//                          last_duck()->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
2759                    }
2760                    duck->set_type(Duck::TYPE_VERTEX);
2761                    bezier.p1 = bezier.p2;
2762                    bezier.c1 = bezier.c2;
2763                    bezier.p2 = duck;
2764                    bezier.c2 = duck;
2765
2766                    if (first != i)
2767                    {
2768                        handle<Bezier> bezier_(new Bezier());
2769                        bezier_->p1=bezier.p1;
2770                        bezier_->c1=bezier.c1;
2771                        bezier_->p2=bezier.p2;
2772                        bezier_->c2=bezier.c2;
2773                        add_bezier(bezier_);
2774                        last_bezier()->signal_user_click(2).connect(
2775                            sigc::bind(
2776                                sigc::mem_fun(
2777                                    *canvas_view,
2778                                    &studio::CanvasView::popup_param_menu_bezier),
2779                                synfigapp::ValueDesc(value_node,i)));
2780                    }
2781                }
2782
2783                if (value_node->get_loop() && first != -1 && first_duck != duck)
2784                {
2785                    duck = first_duck;
2786
2787                    bezier.p1 = bezier.p2;
2788                    bezier.c1 = bezier.c2;
2789                    bezier.p2 = duck;
2790                    bezier.c2 = duck;
2791
2792                    handle<Bezier> bezier_(new Bezier());
2793                    bezier_->p1 = bezier.p1;
2794                    bezier_->c1 = bezier.c1;
2795                    bezier_->p2 = bezier.p2;
2796                    bezier_->c2 = bezier.c2;
2797                    add_bezier(bezier_);
2798                    last_bezier()->signal_user_click(2).connect(
2799                        sigc::bind(
2800                            sigc::mem_fun(
2801                                *canvas_view,
2802                                &studio::CanvasView::popup_param_menu_bezier),
2803                            synfigapp::ValueDesc(value_node,first)));
2804                }
2805            }
2806            else if(value_node->get_contained_type()==type_segment)
2807            {
2808                for(i=0;i<value_node->link_count();i++)
2809                {
2810                    if(!value_node->list[i].status_at_time(get_time()))
2811                        continue;
2812                    if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
2813                        return false;
2814                }
2815            }
2816            else
2817                return false;
2818        }
2819        else
2820        {
2821            // WRITEME
2822        }
2823
2824        return true;
2825    }
2826    else
2827    if (type == type_bone_object
2828     || type == type_bone_valuenode)
2829    {
2830        const synfigapp::ValueDesc &orig_value_desc = value_desc;
2831        ValueNode::Handle value_node(value_desc.get_value_node());
2832
2833        if (type == type_bone_valuenode)
2834        {
2835            assert(value_desc.parent_is_value_node());
2836            value_node = (*value_node)(get_time()).get(ValueNode_Bone::Handle());
2837        }
2838        else
2839            assert(value_desc.parent_is_linkable_value_node() || value_desc.parent_is_canvas());
2840
2841        Duck::Handle fake_duck;
2842        Duck::Handle tip_duck;
2843        synfig::TransformStack origin_transform_stack(transform_stack), bone_transform_stack;
2844        bool recursive(get_type_mask() & Duck::TYPE_BONE_RECURSIVE);
2845
2846        ValueNode_Bone::Handle bone_value_node;
2847        if (!(bone_value_node = ValueNode_Bone::Handle::cast_dynamic(value_node)))
2848        {
2849            error("expected a ValueNode_Bone");
2850            assert(0);
2851        }
2852
2853        synfig::GUID guid(bone_value_node->get_guid());
2854        Time time(get_time());
2855        Bone bone((*bone_value_node)(time).get(Bone()));
2856        bool invertible(true);
2857        Angle angle;
2858        Angle::deg parent_angle(0);
2859
2860        {
2861            Matrix transform;
2862            bool has_parent(!bone.is_root());
2863            if (has_parent)
2864            {
2865                Bone parent_bone((*bone.get_parent())(time).get(Bone()));
2866
2867                // add the parent's ducks too
2868                add_to_ducks(synfigapp::ValueDesc(bone_value_node, bone_value_node->get_link_index_from_name("parent"), value_desc),canvas_view,transform_stack);
2869
2870                transform = parent_bone.get_animated_matrix();
2871                origin_transform_stack.push(new Transform_Matrix(guid, transform));
2872                bone_transform_stack = origin_transform_stack;
2873                invertible = transform.is_invertible();
2874
2875                Vector scale(parent_bone.get_local_scale());
2876                bone_transform_stack.push(new Transform_Translate(guid, Point((scale[0])*bone.get_origin()[0],
2877                                                                              (scale[1])*bone.get_origin()[1])));
2878                origin_transform_stack.push(new Transform_Scale(guid, scale));
2879
2880#ifdef TRY_TO_ALIGN_WIDTH_DUCKS
2881                // this stuff doesn't work very well - we can find out
2882                // the cumulative angle and so place the duck on the
2883                // right of the circle, but recursive scales in the
2884                // parent can cause the radius to look wrong, and the
2885                // duck to appear off-center
2886                printf("%s:%d bone %s:\n", __FILE__, __LINE__, bone.get_name().c_str());
2887                while (true) {
2888                    printf("%s:%d parent_angle = %5.2f + %5.2f = %5.2f\n", __FILE__, __LINE__,
2889                           Angle::deg(parent_angle).get(), Angle::deg(parent_bone.get_angle()).get(),
2890                           Angle::deg(parent_angle + (parent_bone.get_angle())).get());
2891                    parent_angle += parent_bone.get_angle();
2892                    if (parent_bone.is_root()) break;
2893                    parent_bone = (*parent_bone.get_parent())(time).get(Bone());
2894                }
2895                printf("%s:%d finally %5.2f\n\n", __FILE__, __LINE__, Angle::deg(parent_angle).get());
2896#endif
2897            }
2898            else
2899            {
2900                bone_transform_stack = origin_transform_stack;
2901                bone_transform_stack.push(new Transform_Translate(guid, bone.get_origin()));
2902            }
2903        }
2904
2905        bone_transform_stack.push(new Transform_Rotate(guid, bone.get_angle()));
2906
2907        // origin
2908        {
2909            synfigapp::ValueDesc value_desc(bone_value_node, bone_value_node->get_link_index_from_name("origin"), orig_value_desc);
2910
2911            etl::handle<Duck> duck=new Duck();
2912            duck->set_type(Duck::TYPE_POSITION);
2913            set_duck_value_desc(*duck, value_desc, origin_transform_stack);
2914            duck->set_point(value_desc.get_value(time).get(Point()));
2915
2916            // if the ValueNode can be directly manipulated, then set it as so
2917            duck->set_editable(!invertible ? false :
2918                               !value_desc.is_value_node() ? true :
2919                               synfigapp::is_editable(value_desc.get_value_node()));
2920
2921            duck->signal_edited().clear();
2922            duck->signal_edited().connect(sigc::bind(sigc::mem_fun(*this, &studio::Duckmatic::on_duck_changed), value_desc));
2923            duck->signal_user_click(2).connect(sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(*canvas_view,
2924                                                                                              &studio::CanvasView::popup_param_menu),
2925                                                                                false), // bezier
2926                                                                     0.0f),             // location
2927                                                          value_desc));                 // value_desc
2928            add_duck(duck);
2929        }
2930
2931        // fake
2932        {
2933            synfigapp::ValueDesc value_desc(bone_value_node, bone_value_node->get_link_index_from_name("name"), orig_value_desc);
2934
2935            etl::handle<Duck> duck=new Duck();
2936            duck->set_type(Duck::TYPE_NONE);
2937            set_duck_value_desc(*duck, value_desc, bone_transform_stack);
2938            duck->set_point(Point(0, 0));
2939
2940            duck->set_ignore(true);
2941            add_duck(duck);
2942            fake_duck = last_duck();
2943        }
2944
2945        // angle
2946        {
2947            synfigapp::ValueDesc value_desc(bone_value_node, bone_value_node->get_link_index_from_name("angle"), orig_value_desc);
2948
2949            etl::handle<Duck> duck=new Duck();
2950            duck->set_type(Duck::TYPE_ANGLE);
2951            set_duck_value_desc(*duck, value_desc, bone_transform_stack);
2952
2953            angle = value_desc.get_value(time).get(Angle());
2954            Real length(bone.get_length() * (bone.get_scalex() * bone.get_scalelx()));
2955            duck->set_point(Point(length*0.9, 0));
2956
2957            // if the ValueNode can be directly manipulated, then set it as so
2958            duck->set_editable(!value_desc.is_value_node() ? true :
2959                               synfigapp::is_editable(value_desc.get_value_node()));
2960
2961            duck->signal_edited().clear();
2962            duck->signal_edited().connect(sigc::bind(sigc::mem_fun(*this, &studio::Duckmatic::on_duck_changed), value_desc));
2963            duck->signal_user_click(2).connect(sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(*canvas_view,
2964                                                                                              &studio::CanvasView::popup_param_menu),
2965                                                                                false), // bezier
2966                                                                     0.0f),             // location
2967                                                          value_desc));                 // value_desc
2968            duck->set_origin(fake_duck);
2969            add_duck(duck);
2970        }
2971
2972        // tip
2973        {
2974            synfigapp::ValueDesc value_desc(bone_value_node, bone_value_node->get_link_index_from_name(recursive ? "scalex" : "scalelx"), orig_value_desc);
2975
2976            etl::handle<Duck> duck=new Duck();
2977            duck->set_type(Duck::TYPE_VERTEX);
2978            set_duck_value_desc(*duck, value_desc, bone_transform_stack);
2979            //Real length = bone.get_length()*bone.get_scalex()*bone.get_scalelx();
2980            Real length = value_desc.get_value(time).get(Real());
2981            duck->set_point(Vector(length, 0.0));
2982
2983            // if the ValueNode can be directly manipulated, then set it as so
2984            duck->set_editable(!invertible ? false :
2985                               !value_desc.is_value_node() ? true :
2986                               synfigapp::is_editable(value_desc.get_value_node()));
2987
2988            duck->signal_edited().clear();
2989            duck->signal_edited().connect(sigc::bind(sigc::mem_fun(*this, &studio::Duckmatic::on_duck_changed), value_desc));
2990            duck->signal_user_click(2).connect(
2991                sigc::bind(
2992                    sigc::bind(
2993                        sigc::bind(
2994                            sigc::mem_fun(
2995                                *canvas_view,
2996                                &studio::CanvasView::popup_param_menu
2997                            ),
2998                            false // bezier
2999                        ),
3000                        0.0f // location
3001                    ),
3002                    value_desc
3003                )
3004            );
3005            duck->set_origin(fake_duck);
3006            add_duck(duck);
3007            tip_duck = last_duck();
3008        }
3009
3010        // origin width
3011        {
3012
3013            synfigapp::ValueDesc value_desc(bone_value_node, bone_value_node->get_link_index_from_name("width"), orig_value_desc);
3014
3015            etl::handle<Duck> duck=new Duck();
3016            duck->set_type(Duck::TYPE_WIDTH);
3017            set_duck_value_desc(*duck, value_desc, bone_transform_stack);
3018            duck->set_radius(true);
3019            duck->set_scalar(1);
3020            duck->set_point(Point(0, value_desc.get_value(time).get(Real())));
3021
3022            // if the ValueNode can be directly manipulated, then set it as so
3023            duck->set_editable(!invertible ? false :
3024                               !value_desc.is_value_node() ? true :
3025                               synfigapp::is_editable(value_desc.get_value_node()));
3026
3027            duck->signal_edited().clear();
3028            duck->signal_edited().connect(sigc::bind(sigc::mem_fun(*this, &studio::Duckmatic::on_duck_changed), value_desc));
3029            duck->signal_user_click(2).connect(sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(*canvas_view,
3030                            &studio::CanvasView::popup_param_menu),
3031                        false), // bezier
3032                    0.0f),              // location
3033                value_desc));                   // value_desc
3034            duck->set_origin(fake_duck);
3035            add_duck(duck);
3036        }
3037
3038        // tip width
3039        {
3040
3041            synfigapp::ValueDesc value_desc(bone_value_node, bone_value_node->get_link_index_from_name("tipwidth"), orig_value_desc);
3042
3043            etl::handle<Duck> duck=new Duck();
3044            duck->set_type(Duck::TYPE_WIDTH);
3045            set_duck_value_desc(*duck, value_desc, bone_transform_stack);
3046            duck->set_radius(true);
3047            duck->set_scalar(1);
3048            duck->set_point(Point(0, value_desc.get_value(time).get(Real())));
3049
3050            // if the ValueNode can be directly manipulated, then set it as so
3051            duck->set_editable(!invertible ? false :
3052                               !value_desc.is_value_node() ? true :
3053                               synfigapp::is_editable(value_desc.get_value_node()));
3054
3055            duck->signal_edited().clear();
3056            duck->signal_edited().connect(sigc::bind(sigc::mem_fun(*this, &studio::Duckmatic::on_duck_changed), value_desc));
3057            duck->signal_user_click(2).connect(sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(*canvas_view,
3058                            &studio::CanvasView::popup_param_menu),
3059                        false), // bezier
3060                    0.0f),              // location
3061                value_desc));                   // value_desc
3062            duck->set_origin(tip_duck);
3063            add_duck(duck);
3064        }
3065
3066        return true;
3067    }
3068    else
3069    if (type == type_bone_weight_pair)
3070    {
3071        ValueNode_BoneWeightPair::Handle value_node;
3072        if(value_desc.is_value_node() &&
3073           (value_node=ValueNode_BoneWeightPair::Handle::cast_dynamic(value_desc.get_value_node())))
3074            add_to_ducks(synfigapp::ValueDesc(value_node, value_node->get_link_index_from_name("bone"), value_desc), canvas_view, transform_stack);
3075    }
3076
3077    return false;
3078}
3079
3080
3081/*
3082-- ** -- DuckDrag_Translate M E T H O D S----------------------------
3083*/
3084void
3085DuckDrag_Translate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
3086{
3087        is_moving = false;
3088
3089        last_translate_=Vector(0,0);
3090        {
3091                drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
3092
3093                snap=Vector(0,0);
3094        }
3095
3096        const DuckList selected_ducks(duckmatic->get_selected_ducks());
3097        DuckList::const_iterator iter;
3098
3099        positions.clear();
3100        for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
3101        {
3102                Point p((*iter)->get_trans_point());
3103                positions.push_back(p);
3104        }
3105}
3106
3107bool
3108DuckDrag_Translate::end_duck_drag(Duckmatic* duckmatic)
3109{
3110        if(is_moving)
3111        {
3112                duckmatic->signal_edited_selected_ducks();
3113                return true;
3114        }
3115        else
3116        {
3117                duckmatic->signal_user_click_selected_ducks(0);
3118                return false;
3119        }
3120}
3121
3122void
3123DuckDrag_Translate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
3124{
3125        const DuckList selected_ducks(duckmatic->get_selected_ducks());
3126        DuckList::const_iterator iter;
3127
3128        synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_);
3129        int i;
3130        Time time(duckmatic->get_time());
3131
3132        // drag the vertex and position ducks first
3133        for (i=0,iter=selected_ducks.begin(); iter!=selected_ducks.end(); ++iter,i++)
3134                if((*iter)->get_type() == Duck::TYPE_VERTEX || (*iter)->get_type() == Duck::TYPE_POSITION)
3135                        (*iter)->set_trans_point(positions[i]+vect, time);
3136
3137        // then drag the others
3138        for (i=0,iter=selected_ducks.begin(); iter!=selected_ducks.end(); ++iter,i++)
3139                if ((*iter)->get_type() != Duck::TYPE_VERTEX && (*iter)->get_type() != Duck::TYPE_POSITION)
3140                        (*iter)->set_trans_point(positions[i]+vect, time);
3141
3142        last_translate_=vect;
3143
3144        if(last_translate_.mag()>0.0001)
3145                is_moving = true;
3146
3147        if (is_moving)
3148                duckmatic->signal_edited_selected_ducks(true);
3149
3150        // then patch up the tangents for the vertices we've moved
3151        duckmatic->update_ducks();
3152}
3153
3154/*
3155-- ** -- BezierDrag_Default M E T H O D S----------------------------
3156*/
3157void
3158BezierDrag_Default::begin_bezier_drag(Duckmatic* duckmatic, const synfig::Vector& offset, float bezier_click_pos)
3159{
3160        is_moving = false;
3161        drag_offset_=offset;
3162        click_pos_=bezier_click_pos;
3163
3164        etl::handle<Duck> c1(duckmatic->get_selected_bezier()->c1);
3165        etl::handle<Duck> c2(duckmatic->get_selected_bezier()->c2);
3166
3167        c1_initial = c1->get_trans_point();
3168        c2_initial = c2->get_trans_point();
3169        last_translate_ = synfig::Vector(0,0);
3170
3171        if (c1 == duckmatic->get_selected_bezier()->p1
3172                && c2 == duckmatic->get_selected_bezier()->p2)
3173        {
3174                // This is a polygon segment
3175                // We can't bend the curve, so drag it instead
3176                c1_ratio = 1.0;
3177                c2_ratio = 1.0;
3178
3179        }
3180        else
3181        {
3182                // This is a bline segment, so we can bend the curve
3183
3184                // Magic Bezier Drag Equations follow! (stolen from Inkscape)
3185                // "weight" describes how the influence of the drag should be
3186                // distributed among the handles;
3187                // 0 = front handle only, 1 = back handle only.
3188
3189                float t = bezier_click_pos;
3190                float weight;
3191                if (t <= 1.0/6.0 ) weight=0;
3192                else if (t <= 0.5 ) weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
3193                else if (t <= 5.0 / 6.0) weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
3194                else weight = 1;
3195
3196                c1_ratio = (1-weight)/(3*t*(1-t)*(1-t));
3197                c2_ratio = weight/(3*t*t*(1-t));
3198        }
3199}
3200
3201void
3202BezierDrag_Default::bezier_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
3203{
3204        synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_);
3205        Time time(duckmatic->get_time());
3206
3207        synfig::Vector c1_offset(vect[0]*c1_ratio, vect[1]*c1_ratio);
3208        synfig::Vector c2_offset(vect[0]*c2_ratio, vect[1]*c2_ratio);
3209
3210        etl::handle<Duck> c1(duckmatic->get_selected_bezier()->c1);
3211        etl::handle<Duck> c2(duckmatic->get_selected_bezier()->c2);
3212
3213        c1->set_trans_point(c1_initial+c1_offset, time);
3214        c2->set_trans_point(c2_initial+c2_offset, time);
3215
3216        last_translate_=vect;
3217        if(last_translate_.mag()>0.0001)
3218                is_moving = true;
3219
3220        if (is_moving) {
3221                duckmatic->signal_edited_duck(c1, true);
3222                duckmatic->signal_edited_duck(c2, true);
3223        }
3224
3225        duckmatic->update_ducks();
3226}
3227
3228bool
3229BezierDrag_Default::end_bezier_drag(Duckmatic* duckmatic)
3230{
3231        if(is_moving)
3232        {
3233                etl::handle<Duck> c1(duckmatic->get_selected_bezier()->c1);
3234                etl::handle<Duck> c2(duckmatic->get_selected_bezier()->c2);
3235
3236                duckmatic->signal_edited_duck(c1);
3237                duckmatic->signal_edited_duck(c2);
3238
3239                return true;
3240        }
3241        else
3242        {
3243                return false;
3244        }
3245}
3246
3247/*
3248-- ** -- Duckmatic::Push M E T H O D S----------------------------
3249*/
3250Duckmatic::Push::Push(Duckmatic *duckmatic_):
3251        duckmatic_(duckmatic_)
3252{
3253        duck_map=duckmatic_->duck_map;
3254        bezier_list_=duckmatic_->bezier_list_;
3255        duck_data_share_map=duckmatic_->duck_data_share_map;
3256        stroke_list_=duckmatic_->stroke_list_;
3257        duck_dragger_=duckmatic_->duck_dragger_;
3258        needs_restore=true;
3259}
3260
3261Duckmatic::Push::~Push()
3262{
3263        if(needs_restore)
3264                restore();
3265}
3266
3267void
3268Duckmatic::Push::restore()
3269{
3270        duckmatic_->duck_map=duck_map;
3271        duckmatic_->bezier_list_=bezier_list_;
3272        duckmatic_->duck_data_share_map=duck_data_share_map;
3273        duckmatic_->stroke_list_=stroke_list_;
3274        duckmatic_->duck_dragger_=duck_dragger_;
3275        needs_restore=false;
3276}
3277
3278/*
3279-- ** -- inline M E T H O D S----------------------------
3280*/
3281inline synfig::GUID calc_duck_guid(const synfigapp::ValueDesc& value_desc, const synfig::TransformStack& transform_stack)
3282{
3283        return value_desc.get_guid() % transform_stack.get_guid();
3284}
3285
3286//! sets duck name, value_desc, transform_stack and GUID
3287inline void set_duck_value_desc(Duck& duck, const synfigapp::ValueDesc& value_desc, const synfig::TransformStack& transform_stack)
3288{
3289        duck.set_name(value_desc.get_guid_string());
3290        duck.set_value_desc(value_desc);
3291        duck.set_transform_stack(transform_stack);
3292        duck.set_guid(calc_duck_guid(value_desc, transform_stack));
3293}
3294
3295//! sets duck name, value_desc and GUID
3296inline void set_duck_value_desc(Duck& duck, const synfigapp::ValueDesc& value_desc, const synfig::String& sub_name, const synfig::TransformStack& transform_stack)
3297{
3298        set_duck_value_desc(duck, value_desc.get_sub_value(sub_name), transform_stack);
3299}
Note: See TracBrowser for help on using the repository browser.