1 /* === S Y N F I G ========================================================= */
2 /*! \file duckmatic.cpp
3 ** \brief Template File
5 ** $Id: duckmatic.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
34 #include <ETL/hermite>
36 #include "duckmatic.h"
37 #include <synfigapp/value_desc.h>
38 #include <synfig/general.h>
39 #include <synfig/paramdesc.h>
40 #include <synfig/valuenode_timedswap.h>
41 #include <synfig/valuenode_animated.h>
42 #include <synfig/valuenode_composite.h>
43 #include <synfig/valuenode_scale.h>
44 #include <synfig/valuenode_bline.h>
46 #include <synfig/curve_helper.h>
48 #include <sigc++/retype_return.h>
49 #include <sigc++/retype.h>
50 #include <sigc++/hide.h>
51 #include <sigc++/bind.h>
53 #include "canvasview.h"
55 #include "onemoment.h"
59 /* === U S I N G =========================================================== */
63 using namespace synfig;
64 using namespace studio;
66 /* === M A C R O S ========================================================= */
68 /* === G L O B A L S ======================================================= */
70 /* === P R O C E D U R E S ================================================= */
72 /* === M E T H O D S ======================================================= */
74 /* === E N T R Y P O I N T ================================================= */
76 Duckmatic::Duckmatic():
77 type_mask(Duck::TYPE_ALL-Duck::TYPE_WIDTH),
80 grid_size(1.0/4.0,1.0/4.0),
81 show_persistant_strokes(true)
84 drag_offset_=Point(0,0);
88 Duckmatic::~Duckmatic()
91 //synfig::info("Duckmatic::~Duckmatic(): Deleted. Duck Count=%d",Duck::duck_count);
95 Duckmatic::clear_ducks()
97 duck_data_share_map.clear();
100 //duck_list_.clear();
101 bezier_list_.clear();
102 stroke_list_.clear();
104 if(show_persistant_strokes)
105 stroke_list_=persistant_stroke_list_;
108 //! Returns \a true if the given duck is currently selected
110 Duckmatic::duck_is_selected(const etl::handle<Duck> &duck)const
112 return duck && selected_ducks.count(duck->get_guid());
116 Duckmatic::set_grid_size(const synfig::Vector &s)
121 signal_grid_changed();
126 Duckmatic::set_grid_snap(bool x)
131 signal_grid_changed();
136 Duckmatic::set_guide_snap(bool x)
141 signal_grid_changed();
147 Duckmatic::GuideList::iterator
148 Duckmatic::find_guide_x(synfig::Point pos, float radius)
150 GuideList::iterator iter,best(guide_list_x_.end());
152 for(iter=guide_list_x_.begin();iter!=guide_list_x_.end();++iter)
154 float amount(abs(*iter-pos[0]));
164 Duckmatic::GuideList::iterator
165 Duckmatic::find_guide_y(synfig::Point pos, float radius)
167 GuideList::iterator iter,best(guide_list_y_.end());
169 for(iter=guide_list_y_.begin();iter!=guide_list_y_.end();++iter)
171 float amount(abs(*iter-pos[1]));
182 Duckmatic::clear_selected_ducks()
184 selected_ducks.clear();
185 signal_duck_selection_changed_();
188 etl::handle<Duckmatic::Duck>
189 Duckmatic::get_selected_duck()const
191 if(selected_ducks.empty() || duck_map.empty())
193 return duck_map.find(*selected_ducks.begin())->second;
197 Duckmatic::refresh_selected_ducks()
200 std::set<etl::handle<Duck> >::iterator iter;
201 std::set<etl::handle<Duck> > new_set;
202 if(duck_list().empty())
204 selected_duck_list.clear();
205 signal_duck_selection_changed_();
209 for(iter=selected_duck_list.begin();iter!=selected_duck_list.end();++iter)
211 etl::handle<Duck> similar(find_similar_duck(*iter));
214 new_set.insert(similar);
217 selected_duck_list=new_set;
219 GUIDSet old_set(selected_ducks);
220 GUIDSet::const_iterator iter;
222 for(iter=old_set.begin();iter!=old_set.end();++iter)
224 if(duck_map.count(*iter)==0)
225 selected_ducks.erase(*iter);
228 signal_duck_selection_changed_();
232 Duckmatic::is_duck_group_selectable(const etl::handle<Duck>& x)const
234 const Type type(get_type_mask());
236 if(( x->get_type() && (!(type & x->get_type())) ) )
240 if(x->get_value_desc().parent_is_layer_param() && type & Duck::TYPE_POSITION)
242 Layer::Handle layer(x->get_value_desc().get_layer());
243 String layer_name(layer->get_name());
245 layer_name=="outline" ||
246 layer_name=="region" ||
247 layer_name=="polygon" ||
248 layer_name=="curve_gradient"
252 (layer_name=="PasteCanvas"||
253 layer_name=="paste_canvas")
254 && !layer->get_param("children_lock").get(bool())
262 Duckmatic::select_all_ducks()
264 DuckMap::const_iterator iter;
265 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
266 if(is_duck_group_selectable(iter->second))
267 select_duck(iter->second);
271 Duckmatic::select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)
274 vmin[0]=std::min(tl[0],br[0]);
275 vmin[1]=std::min(tl[1],br[1]);
276 vmax[0]=std::max(tl[0],br[0]);
277 vmax[1]=std::max(tl[1],br[1]);
279 // Type type(get_type_mask());
281 DuckMap::const_iterator iter;
282 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
284 Point p(iter->second->get_trans_point());
285 if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1])
287 if(is_duck_group_selectable(iter->second))
288 select_duck(iter->second);
294 Duckmatic::count_selected_ducks()const
296 return selected_ducks.size();
300 Duckmatic::select_duck(const etl::handle<Duck> &duck)
304 selected_ducks.insert(duck->get_guid());
305 signal_duck_selection_changed_();
310 Duckmatic::get_selected_ducks()const
313 GUIDSet::const_iterator iter;
314 const Type type(get_type_mask());
316 for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
318 const DuckMap::const_iterator d_iter(duck_map.find(*iter));
320 if(d_iter==duck_map.end())
323 if(( d_iter->second->get_type() && (!(type & d_iter->second->get_type())) ) )
326 ret.push_back(d_iter->second);
332 Duckmatic::get_duck_list()const
335 DuckMap::const_iterator iter;
336 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
337 ret.push_back(iter->second);
342 Duckmatic::unselect_duck(const etl::handle<Duck> &duck)
344 if(duck && selected_ducks.count(duck->get_guid()))
346 selected_ducks.erase(duck->get_guid());
347 signal_duck_selection_changed_();
352 Duckmatic::toggle_select_duck(const etl::handle<Duck> &duck)
354 if(duck_is_selected(duck))
362 Duckmatic::translate_selected_ducks(const synfig::Vector& vector)
365 duck_dragger_->duck_drag(this,vector);
369 Duckmatic::start_duck_drag(const synfig::Vector& offset)
372 duck_dragger_->begin_duck_drag(this,offset);
374 //drag_offset_=offset;
375 drag_offset_=find_duck(offset)->get_trans_point();
379 Duckmatic::end_duck_drag()
382 return duck_dragger_->end_duck_drag(this);
387 Duckmatic::snap_point_to_grid(const Point& x, float radius)const
391 GuideList::const_iterator guide_x,guide_y;
392 bool has_guide_x(false), has_guide_y(false);
394 guide_x=find_guide_x(ret,radius);
395 if(guide_x!=guide_list_x_.end())
398 guide_y=find_guide_y(ret,radius);
399 if(guide_y!=guide_list_y_.end())
405 floor(ret[0]/get_grid_size()[0]+0.5)*get_grid_size()[0],
406 floor(ret[1]/get_grid_size()[1]+0.5)*get_grid_size()[1]
409 if(abs(snap[0]-ret[0])<=radius && (!has_guide_x || abs(snap[0]-ret[0])<=abs(*guide_x-ret[0])))
410 ret[0]=snap[0],has_guide_x=false;
411 if(abs(snap[1]-ret[1])<=radius && (!has_guide_y || abs(snap[1]-ret[1])<=abs(*guide_y-ret[1])))
412 ret[1]=snap[1],has_guide_y=false;
426 if(abs(ret[0])<abs(ret[1]))
437 DuckDrag_Translate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
439 last_translate_=Vector(0,0);
441 drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
446 const DuckList selected_ducks(duckmatic->get_selected_ducks());
447 DuckList::const_iterator iter;
450 for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
452 Point p((*iter)->get_trans_point());
453 positions.push_back(p);
458 DuckDrag_Translate::end_duck_drag(Duckmatic* duckmatic)
460 if(last_translate_.mag()>0.0001)
462 duckmatic->signal_edited_selected_ducks();
467 duckmatic->signal_user_click_selected_ducks(0);
473 DuckDrag_Translate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
475 const DuckList selected_ducks(duckmatic->get_selected_ducks());
476 DuckList::const_iterator iter;
478 synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_);
481 for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
483 if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
484 (*iter)->set_trans_point(positions[i]+vect);
486 for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
488 if((*iter)->get_type()==Duck::TYPE_VERTEX||(*iter)->get_type()==Duck::TYPE_POSITION)continue;
489 (*iter)->set_trans_point(positions[i]+vect);
491 last_translate_=vect;
504 Duckmatic::signal_edited_selected_ducks()
506 const DuckList ducks(get_selected_ducks());
507 DuckList::const_iterator iter;
509 synfig::GUIDSet old_set(selected_ducks);
511 // If we have more than 20 things to move, then display
512 // something to explain that it may take a moment
513 smart_ptr<OneMoment> wait; if(ducks.size()>20)wait.spawn();
515 // Go ahead and call everyone's signals
516 for(iter=ducks.begin();iter!=ducks.end();++iter)
518 if(!(*iter)->signal_edited()((*iter)->get_point()))
520 selected_ducks=old_set;
521 throw String("Bad edit");
524 selected_ducks=old_set;
528 Duckmatic::signal_user_click_selected_ducks(int button)
530 const DuckList ducks(get_selected_ducks());
531 DuckList::const_iterator iter;
533 for(iter=ducks.begin();iter!=ducks.end();++iter)
535 (*iter)->signal_user_click(button)();
544 Duckmatic::add_duck(const etl::handle<Duck> &duck)
546 //if(!duck_map.count(duck->get_guid()))
548 if(duck_data_share_map.count(duck->get_data_guid()))
550 duck->set_shared_point(duck_data_share_map[duck->get_data_guid()]);
554 etl::smart_ptr<synfig::Point> point(new Point(duck->get_point()));
555 duck->set_shared_point(point);
556 duck_data_share_map[duck->get_data_guid()]=point;
559 duck_map.insert(duck);
562 last_duck_guid=duck->get_guid();
566 Duckmatic::add_bezier(const etl::handle<Bezier> &bezier)
568 bezier_list_.push_back(bezier);
572 Duckmatic::add_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
574 assert(stroke_point_list);
576 std::list<etl::handle<Stroke> >::iterator iter;
578 for(iter=stroke_list_.begin();iter!=stroke_list_.end();++iter)
580 if((*iter)->stroke_data==stroke_point_list)
584 etl::handle<Stroke> stroke(new Stroke());
586 stroke->stroke_data=stroke_point_list;
589 stroke_list_.push_back(stroke);
593 Duckmatic::add_persistant_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
595 add_stroke(stroke_point_list,color);
596 persistant_stroke_list_.push_back(stroke_list_.back());
600 Duckmatic::clear_persistant_strokes()
602 persistant_stroke_list_.clear();
606 Duckmatic::set_show_persistant_strokes(bool x)
608 if(x!=show_persistant_strokes)
610 show_persistant_strokes=x;
612 stroke_list_=persistant_stroke_list_;
614 stroke_list_.clear();
619 Duckmatic::erase_duck(const etl::handle<Duck> &duck)
621 duck_map.erase(duck->get_guid());
624 etl::handle<Duckmatic::Duck>
625 Duckmatic::find_similar_duck(etl::handle<Duck> duck)
627 DuckMap::const_iterator iter(duck_map.find(duck->get_guid()));
628 if(iter!=duck_map.end())
632 /* std::list<handle<Duck> >::reverse_iterator iter;
634 for(iter=duck_list_.rbegin();iter!=duck_list_.rend();++iter)
636 if(*iter!=duck && **iter==*duck)
638 //synfig::info("Found similar duck! (iter:%08x vs. duck:%08x)",iter->get(), duck.get());
646 etl::handle<Duckmatic::Duck>
647 Duckmatic::add_similar_duck(etl::handle<Duck> duck)
649 etl::handle<Duck> similar(find_similar_duck(duck));
659 Duckmatic::erase_bezier(const etl::handle<Bezier> &bezier)
661 std::list<handle<Bezier> >::iterator iter;
663 for(iter=bezier_list_.begin();iter!=bezier_list_.end();++iter)
667 bezier_list_.erase(iter);
671 synfig::warning("Unable to find bezier to erase!");
674 etl::handle<Duckmatic::Duck>
675 Duckmatic::last_duck()const
677 DuckMap::const_iterator iter(duck_map.find(last_duck_guid));
678 if(iter!=duck_map.end())
683 etl::handle<Duckmatic::Bezier>
684 Duckmatic::last_bezier()const
686 return bezier_list_.back();
690 etl::handle<Duckmatic::Duck>
691 Duckmatic::find_duck(synfig::Point point, synfig::Real radius, Duck::Type type)
693 if(radius==0)radius=10000000;
695 if(type==Duck::TYPE_DEFAULT)
696 type=get_type_mask();
698 Real closest(10000000);
699 etl::handle<Duck> ret;
701 DuckMap::const_iterator iter;
703 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
705 const Duck::Handle& duck(iter->second);
707 if(!duck->get_editable())
709 Real dist((duck->get_trans_point()-point).mag_squared());
711 if(duck->get_type()&Duck::TYPE_VERTEX)
714 if(dist<=closest && !( duck->get_type() && (!(type & duck->get_type())) ) )
723 if(radius==0 || closest<radius*radius)
729 etl::handle<Duckmatic::Bezier>
730 Duckmatic::find_bezier(synfig::Point point, synfig::Real radius,float* location)
732 return find_bezier(point,radius,radius,location);
735 etl::handle<Duckmatic::Bezier>
736 Duckmatic::find_bezier(synfig::Point pos, synfig::Real scale, synfig::Real radius, float* location)
738 if(radius==0)radius=10000000;
739 Real closest(10000000);
740 etl::handle<Bezier> ret;
748 for(std::list<handle<Bezier> >::const_iterator iter=bezier_list().begin();iter!=bezier_list().end();++iter)
750 curve[0] = (*iter)->p1->get_trans_point();
751 curve[1] = (*iter)->c1->get_trans_point();
752 curve[2] = (*iter)->c2->get_trans_point();
753 curve[3] = (*iter)->p2->get_trans_point();
757 // I don't know why this doesn't work
758 time=curve.find_closest(pos,6);
759 d=((curve(time)-pos).mag_squared());
762 //set the step size based on the size of the picture
763 d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag() + (curve[3]-curve[2]).mag();
765 step = d/(2*scale); //want to make the distance between lines happy
767 step = max(step,0.01); //100 samples should be plenty
768 step = min(step,0.1); //10 is minimum
770 d = find_closest(curve,pos,step,&closest,&time);
781 if(closest < radius*radius)
784 *location = best_time; // We need to square-root this because we were dealing with squared distances
795 Duckmatic::save_sketch(const synfig::String& filename)const
797 std::ofstream file(filename.c_str());
799 if(!file)return false;
801 file<<"SKETCH"<<endl;
803 std::list<etl::handle<Stroke> >::const_iterator iter;
805 for(iter=persistant_stroke_list_.begin();iter!=persistant_stroke_list_.end();++iter)
808 <<(*iter)->color.get_r()<<' '
809 <<(*iter)->color.get_g()<<' '
810 <<(*iter)->color.get_b()
812 std::list<synfig::Point>::const_iterator viter;
813 for(viter=(*iter)->stroke_data->begin();viter!=(*iter)->stroke_data->end();++viter)
821 if(!file)return false;
822 sketch_filename_=filename;
823 signal_sketch_saved_();
828 Duckmatic::load_sketch(const synfig::String& filename)
830 std::ifstream file(filename.c_str());
840 synfig::error("Not a sketch");
845 etl::smart_ptr<std::list<synfig::Point> > stroke_data;
861 if(!strscanf(line,"C %f %f %f",&r, &g, &b))
863 synfig::warning("Bad color line \"%s\"",line.c_str());
866 add_persistant_stroke(stroke_data, synfig::Color(r,g,b));
874 add_persistant_stroke(stroke_data, synfig::Color(0,0,0));
877 if(!strscanf(line,"V %f %f",&x, &y))
878 synfig::warning("Bad vertex \"%s\"",line.c_str());
880 stroke_data->push_back(synfig::Vector(x,y));
883 synfig::warning("Unexpected sketch token '%c'",line[0]);
888 sketch_filename_=filename;
899 Duckmatic::Push::Push(Duckmatic *duckmatic_):
900 duckmatic_(duckmatic_)
902 duck_map=duckmatic_->duck_map;
903 bezier_list_=duckmatic_->bezier_list_;
904 duck_data_share_map=duckmatic_->duck_data_share_map;
905 stroke_list_=duckmatic_->stroke_list_;
906 duck_dragger_=duckmatic_->duck_dragger_;
910 Duckmatic::Push::~Push()
917 Duckmatic::Push::restore()
919 duckmatic_->duck_map=duck_map;
920 duckmatic_->bezier_list_=bezier_list_;
921 duckmatic_->duck_data_share_map=duck_data_share_map;
922 duckmatic_->stroke_list_=stroke_list_;
923 duckmatic_->duck_dragger_=duck_dragger_;
935 inline String guid_string(const synfigapp::ValueDesc& x)
937 if(x.parent_is_layer_param())
938 return strprintf("%s",x.get_layer()->get_guid().get_string().c_str())+x.get_param_name();
939 //if(x.is_value_node())
940 return strprintf("%s",x.get_value_node()->get_guid().get_string().c_str());
943 inline GUID calc_duck_guid(const synfigapp::ValueDesc& x,const synfig::TransformStack& transform_stack)
947 if(x.parent_is_layer_param())
949 ret=x.get_layer()->get_guid()^GUID::hasher(x.get_param_name());
953 ret=x.get_value_node()->get_guid();
956 ret^=transform_stack.get_guid();
962 Duckmatic::create_duck_from(const synfigapp::ValueDesc& value_desc,etl::handle<CanvasView> canvas_view, const synfig::TransformStack& transform_stack, int modifier, synfig::ParamDesc *param_desc)
964 GUID duck_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(modifier));
965 etl::handle<Duck> duck=new Duck();
972 Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handle<CanvasView> canvas_view, const synfig::TransformStack& transform_stack, synfig::ParamDesc *param_desc, int multiple)
974 ValueBase::Type type=value_desc.get_value_type();
975 #define REAL_COOKIE reinterpret_cast<synfig::ParamDesc*>(28)
978 case ValueBase::TYPE_REAL:
980 if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
982 etl::handle<Duck> duck=new Duck();
983 duck->set_transform_stack(transform_stack);
984 duck->set_radius(true);
985 duck->set_type(Duck::TYPE_RADIUS);
987 duck->set_point(Point(value_desc.get_value(get_time()).get(Real()),0));
988 duck->set_name(guid_string(value_desc));
989 if(value_desc.is_value_node())
991 // If the ValueNode can be directly manipulated,
992 // then set it as so.
993 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
997 duck->set_editable(true);
1000 if(param_desc && param_desc!=REAL_COOKIE)
1002 if(!param_desc->get_origin().empty())
1004 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1006 duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1008 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1009 duck->set_origin(last_duck());
1011 duck->set_scalar(param_desc->get_scalar());
1014 duck->signal_edited().clear();
1015 duck->signal_edited().connect(
1019 &studio::CanvasView::on_duck_changed
1024 duck->set_value_desc(value_desc);
1026 duck->signal_user_click(2).connect(
1031 &studio::CanvasView::popup_param_menu
1039 duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1047 case ValueBase::TYPE_ANGLE:
1049 if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
1051 etl::handle<Duck> duck=new Duck();
1052 duck->set_type(Duck::TYPE_ANGLE);
1053 duck->set_transform_stack(transform_stack);
1054 synfig::Angle angle;
1056 angle=value_desc.get_value(get_time()).get(Angle());
1057 duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1058 duck->set_name(guid_string(value_desc));
1059 if(value_desc.is_value_node())
1061 ValueNode::Handle value_node=value_desc.get_value_node();
1062 //duck->set_name(strprintf("%x",value_node.get()));
1064 // If the ValueNode can be directly manipulated,
1065 // then set it as so.
1066 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1070 //angle=(value_desc.get_value().get(Angle()));
1071 //duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1072 //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1073 duck->set_editable(true);
1076 if(param_desc && param_desc!=REAL_COOKIE)
1078 if(!param_desc->get_origin().empty())
1080 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1082 duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1084 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1085 duck->set_origin(last_duck());
1087 duck->set_scalar(param_desc->get_scalar());
1090 duck->signal_edited().clear();
1091 duck->signal_edited().connect(
1095 &studio::CanvasView::on_duck_changed
1100 duck->set_value_desc(value_desc);
1102 duck->signal_user_click(2).connect(
1107 &studio::CanvasView::popup_param_menu
1114 duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1122 case ValueBase::TYPE_VECTOR:
1124 etl::handle<Duck> duck=new Duck();
1125 duck->set_transform_stack(transform_stack);
1127 duck->set_point(value_desc.get_value(get_time()).get(Point()));
1128 duck->set_name(guid_string(value_desc));
1129 if(value_desc.is_value_node())
1131 //duck->set_name(strprintf("%x",value_desc.get_value_node().get()));
1133 // If the ValueNode can be directly manipulated,
1134 // then set it as so.
1135 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1139 //duck->set_point(value_desc.get_value().get(Point()));
1140 //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1141 duck->set_editable(true);
1144 // If we were passed a parameter description
1147 if(!param_desc->get_connect().empty())
1149 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_connect());
1150 Duck::Handle connect_duck;
1151 if(duck_map.find(calc_duck_guid(value_desc_origin,transform_stack)^GUID::hasher(0))!=duck_map.end())
1153 connect_duck=duck_map[calc_duck_guid(value_desc_origin,transform_stack)^GUID::hasher(0)];
1157 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1158 connect_duck=last_duck();
1160 duck->set_connect_duck(connect_duck);
1162 if(!param_desc->get_box().empty())
1164 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_box());
1165 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1166 duck->set_box_duck(last_duck());
1169 // If we have an origin
1170 if(!param_desc->get_origin().empty())
1172 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1174 duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1176 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1177 duck->set_origin(last_duck());
1178 duck->set_type(Duck::TYPE_VERTEX);
1181 duck->set_type(Duck::TYPE_POSITION);
1183 duck->set_scalar(param_desc->get_scalar());
1186 duck->set_type(Duck::TYPE_POSITION);
1189 duck->signal_edited().clear();
1190 duck->signal_edited().connect(
1194 &studio::CanvasView::on_duck_changed
1199 duck->set_value_desc(value_desc);
1201 duck->signal_user_click(2).connect(
1206 &studio::CanvasView::popup_param_menu
1213 duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1219 /* case ValueBase::TYPE_SEGMENT:
1221 etl::handle<Bezier> bezier(new Bezier());
1222 ValueNode_Composite::Handle value_node;
1224 if(value_desc.is_value_node() &&
1225 (value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
1228 if(!add_to_ducks(synfigapp::ValueDesc(value_node,0),canvas_view,transform_stack))
1230 bezier->p1=last_duck();
1231 bezier->p1->set_type(Duck::TYPE_VERTEX);
1232 if(!add_to_ducks(synfigapp::ValueDesc(value_node,1),canvas_view,transform_stack))
1234 bezier->c1=last_duck();
1235 bezier->c1->set_type(Duck::TYPE_TANGENT);
1236 bezier->c1->set_origin(bezier->p1);
1237 bezier->c1->set_scalar(0.33333333333333333);
1238 bezier->c1->set_tangent(true);
1241 if(!add_to_ducks(synfigapp::ValueDesc(value_node,2),canvas_view,transform_stack))
1243 bezier->p2=last_duck();
1244 bezier->p2->set_type(Duck::TYPE_VERTEX);
1245 if(!add_to_ducks(synfigapp::ValueDesc(value_node,3),canvas_view,transform_stack))
1247 bezier->c2=last_duck();
1248 bezier->c2->set_type(Duck::TYPE_TANGENT);
1249 bezier->c2->set_origin(bezier->p2);
1250 bezier->c2->set_scalar(-0.33333333333333333);
1251 bezier->c2->set_tangent(true);
1253 bezier->signal_user_click(2).connect(
1257 &studio::CanvasView::popup_param_menu_bezier
1265 else if(value_desc.get_value().is_valid())
1267 Segment segment=value_desc.get_value();
1268 etl::handle<Duck> duck_p,duck_c;
1269 synfig::String name;
1272 name=param_desc->get_local_name();
1276 name=guid_string(value_desc);
1279 duck_p=new class Duck(segment.p1);
1280 duck_p->set_name(name+".P1");
1281 duck_p->set_type(Duck::TYPE_VERTEX);
1284 duck_c=new class Duck(segment.t1);
1285 duck_c->set_name(name+".T1");
1286 duck_c->set_type(Duck::TYPE_TANGENT);
1288 duck_c->set_origin(duck_p);
1289 duck_c->set_scalar(0.33333333333333333);
1290 duck_c->set_tangent(true);
1295 duck_p=new class Duck(segment.p2);
1296 duck_p->set_name(name+".P2");
1297 duck_p->set_type(Duck::TYPE_VERTEX);
1300 duck_c=new class Duck(segment.t2);
1301 duck_c->set_type(Duck::TYPE_TANGENT);
1302 duck_c->set_name(name+".T2");
1304 duck_c->set_origin(duck_p);
1305 duck_c->set_scalar(-0.33333333333333333);
1306 duck_c->set_tangent(true);
1317 case ValueBase::TYPE_BLINEPOINT:
1320 if(value_desc.is_value_node() &&
1321 ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
1324 ValueNode_Composite::Handle value_node;
1325 value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node());
1328 if(!add_to_ducks(synfigapp::ValueDesc(value_node,0),canvas_view,transform_stack))
1330 etl::handle<Duck> vertex_duck(last_duck());
1331 vertex_duck->set_type(Duck::TYPE_VERTEX);
1332 if(!add_to_ducks(synfigapp::ValueDesc(value_node,4),canvas_view,transform_stack))
1334 etl::handle<Duck> t1_duck(last_duck());
1336 t1_duck->set_origin(vertex_duck);
1337 t1_duck->set_scalar(-0.33333333333333333);
1338 t1_duck->set_tangent(true);
1340 etl::handle<Duck> t2_duck;
1342 // If the tangents are split
1343 if((*value_node->get_link("split"))(get_time()).get(bool()))
1345 if(!add_to_ducks(synfigapp::ValueDesc(value_node,5),canvas_view,transform_stack))
1347 t2_duck=last_duck();
1348 t2_duck->set_origin(vertex_duck);
1349 t2_duck->set_scalar(0.33333333333333333);
1350 t2_duck->set_tangent(true);
1354 if(!add_to_ducks(synfigapp::ValueDesc(value_node,4),canvas_view,transform_stack))
1356 t2_duck=last_duck();
1357 t2_duck->set_origin(vertex_duck);
1358 t2_duck->set_scalar(0.33333333333333333);
1359 t2_duck->set_tangent(true);
1366 case ValueBase::TYPE_LIST:
1369 if(value_desc.is_value_node() &&
1370 ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node())
1373 ValueNode_BLine::Handle value_node;
1374 value_node=ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node());
1378 etl::handle<Bezier> bezier;
1379 etl::handle<Duck> first_duck;
1380 etl::handle<Duck> duck, tduck;
1382 for(i=0;i<value_node->link_count();i++)
1384 float amount(value_node->list[i].amount_at_time(get_time()));
1387 if(first==-1)first=i;
1389 BLinePoint bline_point((*value_node->get_link(i))(get_time()));
1391 ValueNode_Composite::Handle vertex_value_node(
1392 ValueNode_Composite::Handle::cast_dynamic(
1393 value_node->get_link(i)
1397 // Add the vertex duck
1398 if(vertex_value_node)
1400 if(add_to_ducks(synfigapp::ValueDesc(vertex_value_node,0),canvas_view,transform_stack))
1405 duck->set_type(Duck::TYPE_VERTEX);
1407 duck->signal_user_click(2).clear();
1408 duck->signal_user_click(2).connect(
1413 &studio::CanvasView::popup_param_menu
1417 synfigapp::ValueDesc(value_node,i)
1420 duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
1424 if(!param_desc->get_origin().empty())
1426 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1427 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1428 duck->set_origin(last_duck());
1430 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1431 if(value.same_as(synfig::Point()))
1432 duck->set_origin(value.get(synfig::Point()));
1442 duck=new Duck(bline_point.get_vertex());
1445 duck->set_transform_stack(transform_stack);
1446 duck->set_editable(false);
1447 //duck->set_name(strprintf("%x-vertex",value_node->get_link(i).get()));
1448 duck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".v");
1450 duck->set_type(Duck::TYPE_VERTEX);
1453 if(!param_desc->get_origin().empty())
1455 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1456 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1457 duck->set_origin(last_duck());
1459 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1460 if(value.same_as(synfig::Point()))
1461 duck->set_origin(value.get(synfig::Point()));
1465 duck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".v"));
1466 duck=add_similar_duck(duck);
1470 // Add the width duck only if we have a hint of scale
1471 if(param_desc && !param_desc->get_hint().empty())
1473 etl::handle<Duck> width;
1474 if(add_to_ducks(synfigapp::ValueDesc(vertex_value_node,1),canvas_view,transform_stack,REAL_COOKIE))
1477 width->set_origin(duck);
1478 width->set_type(Duck::TYPE_WIDTH);
1479 width->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".w");
1481 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_hint()).get_value(get_time()));
1482 if(value.same_as(synfig::Real()))
1483 width->set_scalar(value.get(synfig::Real())*0.5f);
1487 synfig::error("Unable to add width duck!");
1492 // Add the tangent1 duck
1493 if(vertex_value_node)
1495 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,4),canvas_view,transform_stack))
1501 tduck=new Duck(bline_point.get_tangent1());
1502 tduck->set_transform_stack(transform_stack);
1503 tduck->set_editable(false);
1504 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t1");
1505 // tduck->set_name(strprintf("%x-tangent1",value_node->get_link(i).get()));
1506 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1507 tduck=add_similar_duck(tduck);
1511 tduck->set_origin(duck);
1512 tduck->set_scalar(-0.33333333333333333);
1513 tduck->set_tangent(true);
1518 bezier->signal_user_click(2).connect(
1522 &studio::CanvasView::popup_param_menu_bezier
1524 synfigapp::ValueDesc(value_node,i)
1528 duck->signal_user_click(2).clear();
1529 duck->signal_user_click(2).connect(
1534 &studio::CanvasView::popup_param_menu
1538 synfigapp::ValueDesc(value_node,i)
1541 duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
1547 if(i+1>=value_node->link_count() && !value_node->get_loop())
1550 bezier=new Bezier();
1552 // Add the tangent2 duck
1553 if(vertex_value_node)
1555 int i=bline_point.get_split_tangent_flag()?5:4;
1556 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,i),canvas_view,transform_stack,0,2))
1562 if(bline_point.get_split_tangent_flag())
1564 tduck=new Duck(bline_point.get_tangent2());
1565 tduck->set_transform_stack(transform_stack);
1566 //tduck->set_name(strprintf("%x-tangent2",value_node->get_link(i).get()));
1567 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t2");
1568 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t2"));
1572 tduck=new Duck(bline_point.get_tangent1());
1573 tduck->set_transform_stack(transform_stack);
1574 //tduck->set_name(strprintf("%x-tangent1",value_node->get_link(i).get()));
1575 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t1");
1576 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1578 tduck->set_editable(false);
1579 tduck=add_similar_duck(tduck);
1583 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1584 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1585 duck->set_origin(last_duck());
1587 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1588 if(value.same_as(synfig::Point()))
1589 duck->set_origin(value.get(synfig::Point()));
1591 // if(!param_desc->get_origin().empty())
1592 // duck->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
1594 duck->signal_user_click(2).clear();
1595 duck->signal_user_click(2).connect(
1600 &studio::CanvasView::popup_param_menu
1604 synfigapp::ValueDesc(value_node,0)
1607 duck->set_value_desc(synfigapp::ValueDesc(value_node,0));
1611 tduck->set_origin(duck);
1612 tduck->set_scalar(0.33333333333333333);
1613 tduck->set_tangent(true);
1619 // Loop if necessary
1620 if(bezier && value_node->get_loop())
1622 BLinePoint bline_point((*value_node->get_link(first))(get_time()));
1624 ValueNode_Composite::Handle vertex_value_node(
1625 ValueNode_Composite::Handle::cast_dynamic(
1626 value_node->get_link(first)
1630 // Add the vertex duck
1633 if(vertex_value_node)
1635 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,0),canvas_view,transform_stack))
1640 if(!param_desc->get_origin().empty())
1641 duck->set_origin(value_desc.get_layer()->get_param(param_desc->get_origin()).get(synfig::Point()));
1643 duck->set_type(Duck::TYPE_VERTEX);
1647 duck=new Duck(bline_point.get_vertex());
1648 duck->set_transform_stack(transform_stack);
1651 if(!param_desc->get_origin().empty())
1652 duck->set_origin(value_desc.get_layer()->get_param(param_desc->get_origin()).get(synfig::Point()));
1654 duck->set_editable(false);
1655 duck->set_name(strprintf("%x-vertex",value_node->get_link(first).get()));
1656 duck->set_type(Duck::TYPE_VERTEX);
1657 duck=add_similar_duck(duck);
1661 // Add the tangent1 duck
1662 if(vertex_value_node)
1664 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,4),canvas_view,transform_stack))
1670 tduck=new Duck(bline_point.get_tangent1());
1671 tduck->set_transform_stack(transform_stack);
1672 tduck->set_editable(false);
1673 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,first))+".t1");
1674 //tduck->set_name(strprintf("%x-tangent1",value_node->get_link(first).get()));
1675 tduck=add_similar_duck(tduck);
1676 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1680 tduck->set_origin(duck);
1681 tduck->set_scalar(-0.33333333333333333);
1682 tduck->set_tangent(true);
1686 bezier->signal_user_click(2).connect(
1690 &studio::CanvasView::popup_param_menu_bezier
1692 synfigapp::ValueDesc(value_node,first)
1695 duck->signal_user_click(2).clear();
1696 duck->signal_user_click(2).connect(
1701 &studio::CanvasView::popup_param_menu
1705 synfigapp::ValueDesc(value_node,first)
1708 duck->set_value_desc(synfigapp::ValueDesc(value_node,first));
1716 else // Check for DynamicList
1717 if(value_desc.is_value_node() &&
1718 ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node())
1721 ValueNode_DynamicList::Handle value_node;
1722 value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node());
1725 if(value_node->get_contained_type()==ValueBase::TYPE_VECTOR)
1728 for(i=0;i<value_node->link_count();i++)
1730 if(!value_node->list[i].status_at_time(get_time()))
1732 if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
1734 etl::handle<Duck> duck(last_duck());
1738 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1739 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1740 duck->set_origin(last_duck());
1742 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1743 if(value.same_as(synfig::Point()))
1744 duck->set_origin(value.get(synfig::Point()));
1746 // if(!param_desc->get_origin().empty())
1747 // last_duck()->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
1749 duck->set_type(Duck::TYPE_VERTEX);
1750 bezier.p1=bezier.p2;bezier.c1=bezier.c2;
1751 bezier.p2=bezier.c2=duck;
1755 handle<Bezier> bezier_(new Bezier());
1756 bezier_->p1=bezier.p1;
1757 bezier_->c1=bezier.c1;
1758 bezier_->p2=bezier.p2;
1759 bezier_->c2=bezier.c2;
1760 add_bezier(bezier_);
1761 last_bezier()->signal_user_click(2).connect(
1765 &studio::CanvasView::popup_param_menu_bezier
1767 synfigapp::ValueDesc(value_node,i)
1773 /*else if(value_node->get_contained_type()==ValueBase::TYPE_SEGMENT)
1775 for(i=0;i<value_node->link_count();i++)
1777 if(!value_node->list[i].status_at_time(get_time()))
1779 if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))