1 /* === S Y N F I G ========================================================= */
2 /*! \file duckmatic.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
35 #include <ETL/hermite>
37 #include "duckmatic.h"
38 #include <synfigapp/value_desc.h>
39 #include <synfig/general.h>
40 #include <synfig/paramdesc.h>
41 #include <synfig/valuenode_timedswap.h>
42 #include <synfig/valuenode_animated.h>
43 #include <synfig/valuenode_composite.h>
44 #include <synfig/valuenode_scale.h>
45 #include <synfig/valuenode_bline.h>
47 #include <synfig/curve_helper.h>
49 #include <sigc++/retype_return.h>
50 #include <sigc++/retype.h>
51 #include <sigc++/hide.h>
52 #include <sigc++/bind.h>
54 #include "canvasview.h"
56 #include "onemoment.h"
60 /* === U S I N G =========================================================== */
64 using namespace synfig;
65 using namespace studio;
67 /* === M A C R O S ========================================================= */
69 /* === G L O B A L S ======================================================= */
71 /* === P R O C E D U R E S ================================================= */
73 /* === M E T H O D S ======================================================= */
75 /* === E N T R Y P O I N T ================================================= */
77 Duckmatic::Duckmatic():
78 type_mask(Duck::TYPE_ALL-Duck::TYPE_WIDTH),
81 grid_size(1.0/4.0,1.0/4.0),
82 show_persistant_strokes(true)
85 drag_offset_=Point(0,0);
89 Duckmatic::~Duckmatic()
92 //synfig::info("Duckmatic::~Duckmatic(): Deleted. Duck Count=%d",Duck::duck_count);
96 Duckmatic::clear_ducks()
98 duck_data_share_map.clear();
101 //duck_list_.clear();
102 bezier_list_.clear();
103 stroke_list_.clear();
105 if(show_persistant_strokes)
106 stroke_list_=persistant_stroke_list_;
109 //! Returns \a true if the given duck is currently selected
111 Duckmatic::duck_is_selected(const etl::handle<Duck> &duck)const
113 return duck && selected_ducks.count(duck->get_guid());
117 Duckmatic::set_grid_size(const synfig::Vector &s)
122 signal_grid_changed();
127 Duckmatic::set_grid_snap(bool x)
132 signal_grid_changed();
137 Duckmatic::set_guide_snap(bool x)
142 signal_grid_changed();
148 Duckmatic::GuideList::iterator
149 Duckmatic::find_guide_x(synfig::Point pos, float radius)
151 GuideList::iterator iter,best(guide_list_x_.end());
153 for(iter=guide_list_x_.begin();iter!=guide_list_x_.end();++iter)
155 float amount(abs(*iter-pos[0]));
165 Duckmatic::GuideList::iterator
166 Duckmatic::find_guide_y(synfig::Point pos, float radius)
168 GuideList::iterator iter,best(guide_list_y_.end());
170 for(iter=guide_list_y_.begin();iter!=guide_list_y_.end();++iter)
172 float amount(abs(*iter-pos[1]));
183 Duckmatic::clear_selected_ducks()
185 selected_ducks.clear();
186 signal_duck_selection_changed_();
189 etl::handle<Duckmatic::Duck>
190 Duckmatic::get_selected_duck()const
192 if(selected_ducks.empty() || duck_map.empty())
194 return duck_map.find(*selected_ducks.begin())->second;
198 Duckmatic::refresh_selected_ducks()
201 std::set<etl::handle<Duck> >::iterator iter;
202 std::set<etl::handle<Duck> > new_set;
203 if(duck_list().empty())
205 selected_duck_list.clear();
206 signal_duck_selection_changed_();
210 for(iter=selected_duck_list.begin();iter!=selected_duck_list.end();++iter)
212 etl::handle<Duck> similar(find_similar_duck(*iter));
215 new_set.insert(similar);
218 selected_duck_list=new_set;
220 GUIDSet old_set(selected_ducks);
221 GUIDSet::const_iterator iter;
223 for(iter=old_set.begin();iter!=old_set.end();++iter)
225 if(duck_map.count(*iter)==0)
226 selected_ducks.erase(*iter);
229 signal_duck_selection_changed_();
233 Duckmatic::is_duck_group_selectable(const etl::handle<Duck>& x)const
235 const Type type(get_type_mask());
237 if(( x->get_type() && (!(type & x->get_type())) ) )
241 if(x->get_value_desc().parent_is_layer_param() && type & Duck::TYPE_POSITION)
243 Layer::Handle layer(x->get_value_desc().get_layer());
244 String layer_name(layer->get_name());
246 layer_name=="outline" ||
247 layer_name=="region" ||
248 layer_name=="polygon" ||
249 layer_name=="curve_gradient"
253 (layer_name=="PasteCanvas"||
254 layer_name=="paste_canvas")
255 && !layer->get_param("children_lock").get(bool())
263 Duckmatic::select_all_ducks()
265 DuckMap::const_iterator iter;
266 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
267 if(is_duck_group_selectable(iter->second))
268 select_duck(iter->second);
272 Duckmatic::select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br)
275 vmin[0]=std::min(tl[0],br[0]);
276 vmin[1]=std::min(tl[1],br[1]);
277 vmax[0]=std::max(tl[0],br[0]);
278 vmax[1]=std::max(tl[1],br[1]);
280 // Type type(get_type_mask());
282 DuckMap::const_iterator iter;
283 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
285 Point p(iter->second->get_trans_point());
286 if(p[0]<=vmax[0] && p[0]>=vmin[0] && p[1]<=vmax[1] && p[1]>=vmin[1])
288 if(is_duck_group_selectable(iter->second))
289 select_duck(iter->second);
295 Duckmatic::count_selected_ducks()const
297 return selected_ducks.size();
301 Duckmatic::select_duck(const etl::handle<Duck> &duck)
305 selected_ducks.insert(duck->get_guid());
306 signal_duck_selection_changed_();
311 Duckmatic::get_selected_ducks()const
314 GUIDSet::const_iterator iter;
315 const Type type(get_type_mask());
317 for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
319 const DuckMap::const_iterator d_iter(duck_map.find(*iter));
321 if(d_iter==duck_map.end())
324 if(( d_iter->second->get_type() && (!(type & d_iter->second->get_type())) ) )
327 ret.push_back(d_iter->second);
333 Duckmatic::get_duck_list()const
336 DuckMap::const_iterator iter;
337 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
338 ret.push_back(iter->second);
343 Duckmatic::unselect_duck(const etl::handle<Duck> &duck)
345 if(duck && selected_ducks.count(duck->get_guid()))
347 selected_ducks.erase(duck->get_guid());
348 signal_duck_selection_changed_();
353 Duckmatic::toggle_select_duck(const etl::handle<Duck> &duck)
355 if(duck_is_selected(duck))
363 Duckmatic::translate_selected_ducks(const synfig::Vector& vector)
366 duck_dragger_->duck_drag(this,vector);
370 Duckmatic::start_duck_drag(const synfig::Vector& offset)
373 duck_dragger_->begin_duck_drag(this,offset);
375 //drag_offset_=offset;
376 drag_offset_=find_duck(offset)->get_trans_point();
380 Duckmatic::end_duck_drag()
383 return duck_dragger_->end_duck_drag(this);
388 Duckmatic::snap_point_to_grid(const Point& x, float radius)const
392 GuideList::const_iterator guide_x,guide_y;
393 bool has_guide_x(false), has_guide_y(false);
395 guide_x=find_guide_x(ret,radius);
396 if(guide_x!=guide_list_x_.end())
399 guide_y=find_guide_y(ret,radius);
400 if(guide_y!=guide_list_y_.end())
406 floor(ret[0]/get_grid_size()[0]+0.5)*get_grid_size()[0],
407 floor(ret[1]/get_grid_size()[1]+0.5)*get_grid_size()[1]
410 if(abs(snap[0]-ret[0])<=radius && (!has_guide_x || abs(snap[0]-ret[0])<=abs(*guide_x-ret[0])))
411 ret[0]=snap[0],has_guide_x=false;
412 if(abs(snap[1]-ret[1])<=radius && (!has_guide_y || abs(snap[1]-ret[1])<=abs(*guide_y-ret[1])))
413 ret[1]=snap[1],has_guide_y=false;
427 if(abs(ret[0])<abs(ret[1]))
438 DuckDrag_Translate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
440 last_translate_=Vector(0,0);
442 drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
447 const DuckList selected_ducks(duckmatic->get_selected_ducks());
448 DuckList::const_iterator iter;
451 for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
453 Point p((*iter)->get_trans_point());
454 positions.push_back(p);
459 DuckDrag_Translate::end_duck_drag(Duckmatic* duckmatic)
461 if(last_translate_.mag()>0.0001)
463 duckmatic->signal_edited_selected_ducks();
468 duckmatic->signal_user_click_selected_ducks(0);
474 DuckDrag_Translate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
476 const DuckList selected_ducks(duckmatic->get_selected_ducks());
477 DuckList::const_iterator iter;
479 synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_);
482 for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
484 if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
485 (*iter)->set_trans_point(positions[i]+vect);
487 for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
489 if((*iter)->get_type()==Duck::TYPE_VERTEX||(*iter)->get_type()==Duck::TYPE_POSITION)continue;
490 (*iter)->set_trans_point(positions[i]+vect);
492 last_translate_=vect;
505 Duckmatic::signal_edited_selected_ducks()
507 const DuckList ducks(get_selected_ducks());
508 DuckList::const_iterator iter;
510 synfig::GUIDSet old_set(selected_ducks);
512 // If we have more than 20 things to move, then display
513 // something to explain that it may take a moment
514 smart_ptr<OneMoment> wait; if(ducks.size()>20)wait.spawn();
516 // Go ahead and call everyone's signals
517 for(iter=ducks.begin();iter!=ducks.end();++iter)
519 if(!(*iter)->signal_edited()((*iter)->get_point()))
521 selected_ducks=old_set;
522 throw String("Bad edit");
525 selected_ducks=old_set;
529 Duckmatic::signal_user_click_selected_ducks(int button)
531 const DuckList ducks(get_selected_ducks());
532 DuckList::const_iterator iter;
534 for(iter=ducks.begin();iter!=ducks.end();++iter)
536 (*iter)->signal_user_click(button)();
545 Duckmatic::add_duck(const etl::handle<Duck> &duck)
547 //if(!duck_map.count(duck->get_guid()))
549 if(duck_data_share_map.count(duck->get_data_guid()))
551 duck->set_shared_point(duck_data_share_map[duck->get_data_guid()]);
555 etl::smart_ptr<synfig::Point> point(new Point(duck->get_point()));
556 duck->set_shared_point(point);
557 duck_data_share_map[duck->get_data_guid()]=point;
560 duck_map.insert(duck);
563 last_duck_guid=duck->get_guid();
567 Duckmatic::add_bezier(const etl::handle<Bezier> &bezier)
569 bezier_list_.push_back(bezier);
573 Duckmatic::add_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
575 assert(stroke_point_list);
577 std::list<etl::handle<Stroke> >::iterator iter;
579 for(iter=stroke_list_.begin();iter!=stroke_list_.end();++iter)
581 if((*iter)->stroke_data==stroke_point_list)
585 etl::handle<Stroke> stroke(new Stroke());
587 stroke->stroke_data=stroke_point_list;
590 stroke_list_.push_back(stroke);
594 Duckmatic::add_persistant_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color)
596 add_stroke(stroke_point_list,color);
597 persistant_stroke_list_.push_back(stroke_list_.back());
601 Duckmatic::clear_persistant_strokes()
603 persistant_stroke_list_.clear();
607 Duckmatic::set_show_persistant_strokes(bool x)
609 if(x!=show_persistant_strokes)
611 show_persistant_strokes=x;
613 stroke_list_=persistant_stroke_list_;
615 stroke_list_.clear();
620 Duckmatic::erase_duck(const etl::handle<Duck> &duck)
622 duck_map.erase(duck->get_guid());
625 etl::handle<Duckmatic::Duck>
626 Duckmatic::find_similar_duck(etl::handle<Duck> duck)
628 DuckMap::const_iterator iter(duck_map.find(duck->get_guid()));
629 if(iter!=duck_map.end())
633 /* std::list<handle<Duck> >::reverse_iterator iter;
635 for(iter=duck_list_.rbegin();iter!=duck_list_.rend();++iter)
637 if(*iter!=duck && **iter==*duck)
639 //synfig::info("Found similar duck! (iter:%08x vs. duck:%08x)",iter->get(), duck.get());
647 etl::handle<Duckmatic::Duck>
648 Duckmatic::add_similar_duck(etl::handle<Duck> duck)
650 etl::handle<Duck> similar(find_similar_duck(duck));
660 Duckmatic::erase_bezier(const etl::handle<Bezier> &bezier)
662 std::list<handle<Bezier> >::iterator iter;
664 for(iter=bezier_list_.begin();iter!=bezier_list_.end();++iter)
668 bezier_list_.erase(iter);
672 synfig::warning("Unable to find bezier to erase!");
675 etl::handle<Duckmatic::Duck>
676 Duckmatic::last_duck()const
678 DuckMap::const_iterator iter(duck_map.find(last_duck_guid));
679 if(iter!=duck_map.end())
684 etl::handle<Duckmatic::Bezier>
685 Duckmatic::last_bezier()const
687 return bezier_list_.back();
691 etl::handle<Duckmatic::Duck>
692 Duckmatic::find_duck(synfig::Point point, synfig::Real radius, Duck::Type type)
694 if(radius==0)radius=10000000;
696 if(type==Duck::TYPE_DEFAULT)
697 type=get_type_mask();
699 Real closest(10000000);
700 etl::handle<Duck> ret;
702 DuckMap::const_iterator iter;
704 for(iter=duck_map.begin();iter!=duck_map.end();++iter)
706 const Duck::Handle& duck(iter->second);
708 if(!duck->get_editable())
710 Real dist((duck->get_trans_point()-point).mag_squared());
712 if(duck->get_type()&Duck::TYPE_VERTEX)
715 if(dist<=closest && !( duck->get_type() && (!(type & duck->get_type())) ) )
724 if(radius==0 || closest<radius*radius)
730 etl::handle<Duckmatic::Bezier>
731 Duckmatic::find_bezier(synfig::Point point, synfig::Real radius,float* location)
733 return find_bezier(point,radius,radius,location);
736 etl::handle<Duckmatic::Bezier>
737 Duckmatic::find_bezier(synfig::Point pos, synfig::Real scale, synfig::Real radius, float* location)
739 if(radius==0)radius=10000000;
740 Real closest(10000000);
741 etl::handle<Bezier> ret;
749 for(std::list<handle<Bezier> >::const_iterator iter=bezier_list().begin();iter!=bezier_list().end();++iter)
751 curve[0] = (*iter)->p1->get_trans_point();
752 curve[1] = (*iter)->c1->get_trans_point();
753 curve[2] = (*iter)->c2->get_trans_point();
754 curve[3] = (*iter)->p2->get_trans_point();
758 // I don't know why this doesn't work
759 time=curve.find_closest(pos,6);
760 d=((curve(time)-pos).mag_squared());
763 //set the step size based on the size of the picture
764 d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag() + (curve[3]-curve[2]).mag();
766 step = d/(2*scale); //want to make the distance between lines happy
768 step = max(step,0.01); //100 samples should be plenty
769 step = min(step,0.1); //10 is minimum
771 d = find_closest(curve,pos,step,&closest,&time);
782 if(closest < radius*radius)
785 *location = best_time; // We need to square-root this because we were dealing with squared distances
796 Duckmatic::save_sketch(const synfig::String& filename)const
798 std::ofstream file(filename.c_str());
800 if(!file)return false;
802 file<<"SKETCH"<<endl;
804 std::list<etl::handle<Stroke> >::const_iterator iter;
806 for(iter=persistant_stroke_list_.begin();iter!=persistant_stroke_list_.end();++iter)
809 <<(*iter)->color.get_r()<<' '
810 <<(*iter)->color.get_g()<<' '
811 <<(*iter)->color.get_b()
813 std::list<synfig::Point>::const_iterator viter;
814 for(viter=(*iter)->stroke_data->begin();viter!=(*iter)->stroke_data->end();++viter)
822 if(!file)return false;
823 sketch_filename_=filename;
824 signal_sketch_saved_();
829 Duckmatic::load_sketch(const synfig::String& filename)
831 std::ifstream file(filename.c_str());
841 synfig::error("Not a sketch");
846 etl::smart_ptr<std::list<synfig::Point> > stroke_data;
862 if(!strscanf(line,"C %f %f %f",&r, &g, &b))
864 synfig::warning("Bad color line \"%s\"",line.c_str());
867 add_persistant_stroke(stroke_data, synfig::Color(r,g,b));
875 add_persistant_stroke(stroke_data, synfig::Color(0,0,0));
878 if(!strscanf(line,"V %f %f",&x, &y))
879 synfig::warning("Bad vertex \"%s\"",line.c_str());
881 stroke_data->push_back(synfig::Vector(x,y));
884 synfig::warning("Unexpected sketch token '%c'",line[0]);
889 sketch_filename_=filename;
900 Duckmatic::Push::Push(Duckmatic *duckmatic_):
901 duckmatic_(duckmatic_)
903 duck_map=duckmatic_->duck_map;
904 bezier_list_=duckmatic_->bezier_list_;
905 duck_data_share_map=duckmatic_->duck_data_share_map;
906 stroke_list_=duckmatic_->stroke_list_;
907 duck_dragger_=duckmatic_->duck_dragger_;
911 Duckmatic::Push::~Push()
918 Duckmatic::Push::restore()
920 duckmatic_->duck_map=duck_map;
921 duckmatic_->bezier_list_=bezier_list_;
922 duckmatic_->duck_data_share_map=duck_data_share_map;
923 duckmatic_->stroke_list_=stroke_list_;
924 duckmatic_->duck_dragger_=duck_dragger_;
936 inline String guid_string(const synfigapp::ValueDesc& x)
938 if(x.parent_is_layer_param())
939 return strprintf("%s",x.get_layer()->get_guid().get_string().c_str())+x.get_param_name();
940 //if(x.is_value_node())
941 return strprintf("%s",x.get_value_node()->get_guid().get_string().c_str());
944 inline GUID calc_duck_guid(const synfigapp::ValueDesc& x,const synfig::TransformStack& transform_stack)
948 if(x.parent_is_layer_param())
950 ret=x.get_layer()->get_guid()^GUID::hasher(x.get_param_name());
954 ret=x.get_value_node()->get_guid();
957 ret^=transform_stack.get_guid();
963 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)
965 GUID duck_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(modifier));
966 etl::handle<Duck> duck=new Duck();
973 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)
975 ValueBase::Type type=value_desc.get_value_type();
976 #define REAL_COOKIE reinterpret_cast<synfig::ParamDesc*>(28)
979 case ValueBase::TYPE_REAL:
981 if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
983 etl::handle<Duck> duck=new Duck();
984 duck->set_transform_stack(transform_stack);
985 duck->set_radius(true);
986 duck->set_type(Duck::TYPE_RADIUS);
988 duck->set_point(Point(value_desc.get_value(get_time()).get(Real()),0));
989 duck->set_name(guid_string(value_desc));
990 if(value_desc.is_value_node())
992 // If the ValueNode can be directly manipulated,
993 // then set it as so.
994 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
998 duck->set_editable(true);
1001 if(param_desc && param_desc!=REAL_COOKIE)
1003 if(!param_desc->get_origin().empty())
1005 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1007 duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1009 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1010 duck->set_origin(last_duck());
1012 duck->set_scalar(param_desc->get_scalar());
1015 duck->signal_edited().clear();
1016 duck->signal_edited().connect(
1020 &studio::CanvasView::on_duck_changed
1025 duck->set_value_desc(value_desc);
1027 duck->signal_user_click(2).connect(
1032 &studio::CanvasView::popup_param_menu
1040 duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1048 case ValueBase::TYPE_ANGLE:
1050 if(!param_desc || param_desc==REAL_COOKIE || !param_desc->get_origin().empty())
1052 etl::handle<Duck> duck=new Duck();
1053 duck->set_type(Duck::TYPE_ANGLE);
1054 duck->set_transform_stack(transform_stack);
1055 synfig::Angle angle;
1057 angle=value_desc.get_value(get_time()).get(Angle());
1058 duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1059 duck->set_name(guid_string(value_desc));
1060 if(value_desc.is_value_node())
1062 ValueNode::Handle value_node=value_desc.get_value_node();
1063 //duck->set_name(strprintf("%x",value_node.get()));
1065 // If the ValueNode can be directly manipulated,
1066 // then set it as so.
1067 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1071 //angle=(value_desc.get_value().get(Angle()));
1072 //duck->set_point(Point(Angle::cos(angle).get(),Angle::sin(angle).get()));
1073 //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1074 duck->set_editable(true);
1077 if(param_desc && param_desc!=REAL_COOKIE)
1079 if(!param_desc->get_origin().empty())
1081 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1083 duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1085 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1086 duck->set_origin(last_duck());
1088 duck->set_scalar(param_desc->get_scalar());
1091 duck->signal_edited().clear();
1092 duck->signal_edited().connect(
1096 &studio::CanvasView::on_duck_changed
1101 duck->set_value_desc(value_desc);
1103 duck->signal_user_click(2).connect(
1108 &studio::CanvasView::popup_param_menu
1115 duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1123 case ValueBase::TYPE_VECTOR:
1125 etl::handle<Duck> duck=new Duck();
1126 duck->set_transform_stack(transform_stack);
1128 duck->set_point(value_desc.get_value(get_time()).get(Point()));
1129 duck->set_name(guid_string(value_desc));
1130 if(value_desc.is_value_node())
1132 //duck->set_name(strprintf("%x",value_desc.get_value_node().get()));
1134 // If the ValueNode can be directly manipulated,
1135 // then set it as so.
1136 duck->set_editable(synfigapp::is_editable(value_desc.get_value_node()));
1140 //duck->set_point(value_desc.get_value().get(Point()));
1141 //duck->set_name(strprintf("%x",value_desc.get_layer().get())+value_desc.get_param_name());
1142 duck->set_editable(true);
1145 // If we were passed a parameter description
1148 if(!param_desc->get_connect().empty())
1150 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_connect());
1151 Duck::Handle connect_duck;
1152 if(duck_map.find(calc_duck_guid(value_desc_origin,transform_stack)^GUID::hasher(0))!=duck_map.end())
1154 connect_duck=duck_map[calc_duck_guid(value_desc_origin,transform_stack)^GUID::hasher(0)];
1158 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1159 connect_duck=last_duck();
1161 duck->set_connect_duck(connect_duck);
1163 if(!param_desc->get_box().empty())
1165 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_box());
1166 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1167 duck->set_box_duck(last_duck());
1170 // If we have an origin
1171 if(!param_desc->get_origin().empty())
1173 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1175 duck->set_origin(value_desc_origin.get_value(get_time()).get(synfig::Point()));
1177 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1178 duck->set_origin(last_duck());
1179 duck->set_type(Duck::TYPE_VERTEX);
1182 duck->set_type(Duck::TYPE_POSITION);
1184 duck->set_scalar(param_desc->get_scalar());
1187 duck->set_type(Duck::TYPE_POSITION);
1190 duck->signal_edited().clear();
1191 duck->signal_edited().connect(
1195 &studio::CanvasView::on_duck_changed
1200 duck->set_value_desc(value_desc);
1202 duck->signal_user_click(2).connect(
1207 &studio::CanvasView::popup_param_menu
1214 duck->set_guid(calc_duck_guid(value_desc,transform_stack)^GUID::hasher(multiple));
1220 /* case ValueBase::TYPE_SEGMENT:
1222 etl::handle<Bezier> bezier(new Bezier());
1223 ValueNode_Composite::Handle value_node;
1225 if(value_desc.is_value_node() &&
1226 (value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
1229 if(!add_to_ducks(synfigapp::ValueDesc(value_node,0),canvas_view,transform_stack))
1231 bezier->p1=last_duck();
1232 bezier->p1->set_type(Duck::TYPE_VERTEX);
1233 if(!add_to_ducks(synfigapp::ValueDesc(value_node,1),canvas_view,transform_stack))
1235 bezier->c1=last_duck();
1236 bezier->c1->set_type(Duck::TYPE_TANGENT);
1237 bezier->c1->set_origin(bezier->p1);
1238 bezier->c1->set_scalar(0.33333333333333333);
1239 bezier->c1->set_tangent(true);
1242 if(!add_to_ducks(synfigapp::ValueDesc(value_node,2),canvas_view,transform_stack))
1244 bezier->p2=last_duck();
1245 bezier->p2->set_type(Duck::TYPE_VERTEX);
1246 if(!add_to_ducks(synfigapp::ValueDesc(value_node,3),canvas_view,transform_stack))
1248 bezier->c2=last_duck();
1249 bezier->c2->set_type(Duck::TYPE_TANGENT);
1250 bezier->c2->set_origin(bezier->p2);
1251 bezier->c2->set_scalar(-0.33333333333333333);
1252 bezier->c2->set_tangent(true);
1254 bezier->signal_user_click(2).connect(
1258 &studio::CanvasView::popup_param_menu_bezier
1266 else if(value_desc.get_value().is_valid())
1268 Segment segment=value_desc.get_value();
1269 etl::handle<Duck> duck_p,duck_c;
1270 synfig::String name;
1273 name=param_desc->get_local_name();
1277 name=guid_string(value_desc);
1280 duck_p=new class Duck(segment.p1);
1281 duck_p->set_name(name+".P1");
1282 duck_p->set_type(Duck::TYPE_VERTEX);
1285 duck_c=new class Duck(segment.t1);
1286 duck_c->set_name(name+".T1");
1287 duck_c->set_type(Duck::TYPE_TANGENT);
1289 duck_c->set_origin(duck_p);
1290 duck_c->set_scalar(0.33333333333333333);
1291 duck_c->set_tangent(true);
1296 duck_p=new class Duck(segment.p2);
1297 duck_p->set_name(name+".P2");
1298 duck_p->set_type(Duck::TYPE_VERTEX);
1301 duck_c=new class Duck(segment.t2);
1302 duck_c->set_type(Duck::TYPE_TANGENT);
1303 duck_c->set_name(name+".T2");
1305 duck_c->set_origin(duck_p);
1306 duck_c->set_scalar(-0.33333333333333333);
1307 duck_c->set_tangent(true);
1318 case ValueBase::TYPE_BLINEPOINT:
1321 if(value_desc.is_value_node() &&
1322 ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
1325 ValueNode_Composite::Handle value_node;
1326 value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node());
1329 if(!add_to_ducks(synfigapp::ValueDesc(value_node,0),canvas_view,transform_stack))
1331 etl::handle<Duck> vertex_duck(last_duck());
1332 vertex_duck->set_type(Duck::TYPE_VERTEX);
1333 if(!add_to_ducks(synfigapp::ValueDesc(value_node,4),canvas_view,transform_stack))
1335 etl::handle<Duck> t1_duck(last_duck());
1337 t1_duck->set_origin(vertex_duck);
1338 t1_duck->set_scalar(-0.33333333333333333);
1339 t1_duck->set_tangent(true);
1341 etl::handle<Duck> t2_duck;
1343 // If the tangents are split
1344 if((*value_node->get_link("split"))(get_time()).get(bool()))
1346 if(!add_to_ducks(synfigapp::ValueDesc(value_node,5),canvas_view,transform_stack))
1348 t2_duck=last_duck();
1349 t2_duck->set_origin(vertex_duck);
1350 t2_duck->set_scalar(0.33333333333333333);
1351 t2_duck->set_tangent(true);
1355 if(!add_to_ducks(synfigapp::ValueDesc(value_node,4),canvas_view,transform_stack))
1357 t2_duck=last_duck();
1358 t2_duck->set_origin(vertex_duck);
1359 t2_duck->set_scalar(0.33333333333333333);
1360 t2_duck->set_tangent(true);
1367 case ValueBase::TYPE_LIST:
1370 if(value_desc.is_value_node() &&
1371 ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node())
1374 ValueNode_BLine::Handle value_node;
1375 value_node=ValueNode_BLine::Handle::cast_dynamic(value_desc.get_value_node());
1379 etl::handle<Bezier> bezier;
1380 etl::handle<Duck> first_duck;
1381 etl::handle<Duck> duck, tduck;
1383 for(i=0;i<value_node->link_count();i++)
1385 float amount(value_node->list[i].amount_at_time(get_time()));
1388 if(first==-1)first=i;
1390 BLinePoint bline_point((*value_node->get_link(i))(get_time()));
1392 ValueNode_Composite::Handle vertex_value_node(
1393 ValueNode_Composite::Handle::cast_dynamic(
1394 value_node->get_link(i)
1398 // Add the vertex duck
1399 if(vertex_value_node)
1401 if(add_to_ducks(synfigapp::ValueDesc(vertex_value_node,0),canvas_view,transform_stack))
1406 duck->set_type(Duck::TYPE_VERTEX);
1408 duck->signal_user_click(2).clear();
1409 duck->signal_user_click(2).connect(
1414 &studio::CanvasView::popup_param_menu
1418 synfigapp::ValueDesc(value_node,i)
1421 duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
1425 if(!param_desc->get_origin().empty())
1427 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1428 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1429 duck->set_origin(last_duck());
1431 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1432 if(value.same_as(synfig::Point()))
1433 duck->set_origin(value.get(synfig::Point()));
1443 duck=new Duck(bline_point.get_vertex());
1446 duck->set_transform_stack(transform_stack);
1447 duck->set_editable(false);
1448 //duck->set_name(strprintf("%x-vertex",value_node->get_link(i).get()));
1449 duck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".v");
1451 duck->set_type(Duck::TYPE_VERTEX);
1454 if(!param_desc->get_origin().empty())
1456 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1457 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1458 duck->set_origin(last_duck());
1460 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1461 if(value.same_as(synfig::Point()))
1462 duck->set_origin(value.get(synfig::Point()));
1466 duck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".v"));
1467 duck=add_similar_duck(duck);
1471 // Add the width duck only if we have a hint of scale
1472 if(param_desc && !param_desc->get_hint().empty())
1474 etl::handle<Duck> width;
1475 if(add_to_ducks(synfigapp::ValueDesc(vertex_value_node,1),canvas_view,transform_stack,REAL_COOKIE))
1478 width->set_origin(duck);
1479 width->set_type(Duck::TYPE_WIDTH);
1480 width->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".w");
1482 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_hint()).get_value(get_time()));
1483 if(value.same_as(synfig::Real()))
1484 width->set_scalar(value.get(synfig::Real())*0.5f);
1488 synfig::error("Unable to add width duck!");
1493 // Add the tangent1 duck
1494 if(vertex_value_node)
1496 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,4),canvas_view,transform_stack))
1502 tduck=new Duck(bline_point.get_tangent1());
1503 tduck->set_transform_stack(transform_stack);
1504 tduck->set_editable(false);
1505 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t1");
1506 // tduck->set_name(strprintf("%x-tangent1",value_node->get_link(i).get()));
1507 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1508 tduck=add_similar_duck(tduck);
1512 tduck->set_origin(duck);
1513 tduck->set_scalar(-0.33333333333333333);
1514 tduck->set_tangent(true);
1519 bezier->signal_user_click(2).connect(
1523 &studio::CanvasView::popup_param_menu_bezier
1525 synfigapp::ValueDesc(value_node,i)
1529 duck->signal_user_click(2).clear();
1530 duck->signal_user_click(2).connect(
1535 &studio::CanvasView::popup_param_menu
1539 synfigapp::ValueDesc(value_node,i)
1542 duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
1548 if(i+1>=value_node->link_count() && !value_node->get_loop())
1551 bezier=new Bezier();
1553 // Add the tangent2 duck
1554 if(vertex_value_node)
1556 int i=bline_point.get_split_tangent_flag()?5:4;
1557 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,i),canvas_view,transform_stack,0,2))
1563 if(bline_point.get_split_tangent_flag())
1565 tduck=new Duck(bline_point.get_tangent2());
1566 tduck->set_transform_stack(transform_stack);
1567 //tduck->set_name(strprintf("%x-tangent2",value_node->get_link(i).get()));
1568 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t2");
1569 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t2"));
1573 tduck=new Duck(bline_point.get_tangent1());
1574 tduck->set_transform_stack(transform_stack);
1575 //tduck->set_name(strprintf("%x-tangent1",value_node->get_link(i).get()));
1576 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,i))+".t1");
1577 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1579 tduck->set_editable(false);
1580 tduck=add_similar_duck(tduck);
1584 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1585 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1586 duck->set_origin(last_duck());
1588 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1589 if(value.same_as(synfig::Point()))
1590 duck->set_origin(value.get(synfig::Point()));
1592 // if(!param_desc->get_origin().empty())
1593 // duck->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
1595 duck->signal_user_click(2).clear();
1596 duck->signal_user_click(2).connect(
1601 &studio::CanvasView::popup_param_menu
1605 synfigapp::ValueDesc(value_node,0)
1608 duck->set_value_desc(synfigapp::ValueDesc(value_node,0));
1612 tduck->set_origin(duck);
1613 tduck->set_scalar(0.33333333333333333);
1614 tduck->set_tangent(true);
1620 // Loop if necessary
1621 if(bezier && value_node->get_loop())
1623 BLinePoint bline_point((*value_node->get_link(first))(get_time()));
1625 ValueNode_Composite::Handle vertex_value_node(
1626 ValueNode_Composite::Handle::cast_dynamic(
1627 value_node->get_link(first)
1631 // Add the vertex duck
1634 if(vertex_value_node)
1636 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,0),canvas_view,transform_stack))
1641 if(!param_desc->get_origin().empty())
1642 duck->set_origin(value_desc.get_layer()->get_param(param_desc->get_origin()).get(synfig::Point()));
1644 duck->set_type(Duck::TYPE_VERTEX);
1648 duck=new Duck(bline_point.get_vertex());
1649 duck->set_transform_stack(transform_stack);
1652 if(!param_desc->get_origin().empty())
1653 duck->set_origin(value_desc.get_layer()->get_param(param_desc->get_origin()).get(synfig::Point()));
1655 duck->set_editable(false);
1656 duck->set_name(strprintf("%x-vertex",value_node->get_link(first).get()));
1657 duck->set_type(Duck::TYPE_VERTEX);
1658 duck=add_similar_duck(duck);
1662 // Add the tangent1 duck
1663 if(vertex_value_node)
1665 if(!add_to_ducks(synfigapp::ValueDesc(vertex_value_node,4),canvas_view,transform_stack))
1671 tduck=new Duck(bline_point.get_tangent1());
1672 tduck->set_transform_stack(transform_stack);
1673 tduck->set_editable(false);
1674 tduck->set_name(guid_string(synfigapp::ValueDesc(value_node,first))+".t1");
1675 //tduck->set_name(strprintf("%x-tangent1",value_node->get_link(first).get()));
1676 tduck=add_similar_duck(tduck);
1677 tduck->set_guid(calc_duck_guid(synfigapp::ValueDesc(value_node,i),transform_stack)^GUID::hasher(".t1"));
1681 tduck->set_origin(duck);
1682 tduck->set_scalar(-0.33333333333333333);
1683 tduck->set_tangent(true);
1687 bezier->signal_user_click(2).connect(
1691 &studio::CanvasView::popup_param_menu_bezier
1693 synfigapp::ValueDesc(value_node,first)
1696 duck->signal_user_click(2).clear();
1697 duck->signal_user_click(2).connect(
1702 &studio::CanvasView::popup_param_menu
1706 synfigapp::ValueDesc(value_node,first)
1709 duck->set_value_desc(synfigapp::ValueDesc(value_node,first));
1717 else // Check for DynamicList
1718 if(value_desc.is_value_node() &&
1719 ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node())
1722 ValueNode_DynamicList::Handle value_node;
1723 value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node());
1726 if(value_node->get_contained_type()==ValueBase::TYPE_VECTOR)
1729 for(i=0;i<value_node->link_count();i++)
1731 if(!value_node->list[i].status_at_time(get_time()))
1733 if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))
1735 etl::handle<Duck> duck(last_duck());
1739 synfigapp::ValueDesc value_desc_origin(value_desc.get_layer(),param_desc->get_origin());
1740 add_to_ducks(value_desc_origin,canvas_view, transform_stack);
1741 duck->set_origin(last_duck());
1743 ValueBase value(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()));
1744 if(value.same_as(synfig::Point()))
1745 duck->set_origin(value.get(synfig::Point()));
1747 // if(!param_desc->get_origin().empty())
1748 // last_duck()->set_origin(synfigapp::ValueDesc(value_desc.get_layer(),param_desc->get_origin()).get_value(get_time()).get(synfig::Point()));
1750 duck->set_type(Duck::TYPE_VERTEX);
1751 bezier.p1=bezier.p2;bezier.c1=bezier.c2;
1752 bezier.p2=bezier.c2=duck;
1756 handle<Bezier> bezier_(new Bezier());
1757 bezier_->p1=bezier.p1;
1758 bezier_->c1=bezier.c1;
1759 bezier_->p2=bezier.p2;
1760 bezier_->c2=bezier.c2;
1761 add_bezier(bezier_);
1762 last_bezier()->signal_user_click(2).connect(
1766 &studio::CanvasView::popup_param_menu_bezier
1768 synfigapp::ValueDesc(value_node,i)
1774 /*else if(value_node->get_contained_type()==ValueBase::TYPE_SEGMENT)
1776 for(i=0;i<value_node->link_count();i++)
1778 if(!value_node->list[i].status_at_time(get_time()))
1780 if(!add_to_ducks(synfigapp::ValueDesc(value_node,i),canvas_view,transform_stack))