1 /* === S Y N F I G ========================================================= */
3 ** \brief Canvas Class Member Definitions
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 ======================================================= */
25 #define SYNFIG_NO_ANGLE
37 #include "exception.h"
40 #include "layer_pastecanvas.h"
41 #include <sigc++/bind.h>
45 using namespace synfig;
49 namespace synfig { extern Canvas::Handle open_canvas(const String &filename); };
51 /* === M A C R O S ========================================================= */
59 synfig::error("%d canvases not yet deleted!",counter);
63 int _CanvasCounter::counter(0);
65 /* === G L O B A L S ======================================================= */
67 /* === P R O C E D U R E S ================================================= */
69 /* === M E T H O D S ======================================================= */
71 Canvas::Canvas(const string &id):
78 _CanvasCounter::counter++;
91 //if(is_inline() && parent_) assert(0);
92 _CanvasCounter::counter--;
101 return CanvasBase::end()-1;
104 Canvas::const_iterator
107 return CanvasBase::end()-1;
110 Canvas::reverse_iterator
113 return CanvasBase::rbegin()+1;
116 Canvas::const_reverse_iterator
117 Canvas::rbegin()const
119 return CanvasBase::rbegin()+1;
125 return CanvasBase::size()-1;
133 Layer::Handle layer(front());
134 //if(layer->count()>2)synfig::info("before layer->count()=%d",layer->count());
137 //if(layer->count()>1)synfig::info("after layer->count()=%d",layer->count());
139 //CanvasBase::clear();
141 // We need to keep a blank handle at the
142 // end of the image list, and acts at
143 // the bottom. Without it, the layers
144 // would just continue going when polled
146 CanvasBase::push_back(Layer::Handle());
154 return CanvasBase::size()<=1;
160 return *(CanvasBase::end()-1);
163 const Layer::Handle &
166 return *(CanvasBase::end()-1);
170 Canvas::get_context()const
175 const ValueNodeList &
176 Canvas::value_node_list()const
178 if(is_inline() && parent_)
179 return parent_->value_node_list();
180 return value_node_list_;
184 Canvas::keyframe_list()
186 if(is_inline() && parent_)
187 return parent_->keyframe_list();
188 return keyframe_list_;
192 Canvas::keyframe_list()const
194 if(is_inline() && parent_)
195 return parent_->keyframe_list();
196 return keyframe_list_;
200 Canvas::find_layer(const Point &pos)
202 return get_context().hit_check(pos);
206 valid_id(const String &x)
208 static const char bad_chars[]=" :#@$^&()*";
211 if(!x.empty() && x[0]>='0' && x[0]<='9')
214 for(i=0;i<sizeof(bad_chars);i++)
215 if(x.find_first_of(bad_chars[i])!=string::npos)
222 Canvas::set_id(const String &x)
224 if(is_inline() && parent_)
225 throw runtime_error("Inline Canvas cannot have an ID");
228 throw runtime_error("Invalid ID");
230 signal_id_changed_();
234 Canvas::set_name(const String &x)
237 signal_meta_data_changed()("name");
238 signal_meta_data_changed("name")();
242 Canvas::set_author(const String &x)
245 signal_meta_data_changed()("author");
246 signal_meta_data_changed("author")();
250 Canvas::set_description(const String &x)
253 signal_meta_data_changed()("description");
254 signal_meta_data_changed("description")();
258 Canvas::set_time(Time t)const
260 if(is_dirty_ || !get_time().is_equal(t))
265 synfig::info("is_dirty_=%d",is_dirty_);
266 synfig::info("get_time()=%f",(float)get_time());
267 synfig::info("t=%f",(float)t);
272 const_cast<Canvas&>(*this).cur_time_=t;
275 get_context().set_time(t);
281 Canvas::get_root()const
283 return parent_?parent_->get_root().get():const_cast<synfig::Canvas *>(this);
287 Canvas::get_depth(etl::handle<Layer> layer)const
291 for(iter=begin();iter!=end();++iter,i++)
300 Canvas::get_relative_id(etl::loose_handle<const Canvas> x)const
302 if(x->get_root()==this)
304 if(is_inline() && parent_)
305 return parent_->_get_relative_id(x);
306 return _get_relative_id(x);
310 Canvas::_get_relative_id(etl::loose_handle<const Canvas> x)const
312 if(is_inline() && parent_)
313 return parent_->_get_relative_id(x);
318 if(parent()==x.get())
323 const Canvas* canvas=this;
325 for(;!canvas->is_root();canvas=canvas->parent().get())
326 id=':'+canvas->get_id()+id;
328 if(x && get_root()!=x->get_root())
330 //String file_name=get_file_name();
331 //String file_path=x->get_file_path();
334 if(is_absolute_path(get_file_name()))
335 file_name=etl::relative_path(x->get_file_path(),get_file_name());
337 file_name=get_file_name();
339 // If the path of X is inside of file_name,
341 //if(file_name.size()>file_path.size())
342 // if(file_path==String(file_name,0,file_path.size()))
343 // file_name.erase(0,file_path.size()+1);
353 Canvas::find_value_node(const String &id)
356 ValueNode::Handle::cast_const(
357 const_cast<const Canvas*>(this)->find_value_node(id)
361 ValueNode::ConstHandle
362 Canvas::find_value_node(const String &id)const
364 if(is_inline() && parent_)
365 return parent_->find_value_node(id);
368 throw Exception::IDNotFound("Empty ID");
370 // If we do not have any resolution, then we assume that the
371 // request is for this immediate canvas
372 if(id.find_first_of(':')==string::npos && id.find_first_of('#')==string::npos)
373 return value_node_list_.find(id);
375 String canvas_id(id,0,id.rfind(':'));
376 String value_node_id(id,id.rfind(':')+1);
377 if(canvas_id.empty())
379 //synfig::warning("constfind:value_node_id: "+value_node_id);
380 //synfig::warning("constfind:canvas_id: "+canvas_id);
382 return find_canvas(canvas_id)->value_node_list_.find(value_node_id);
386 Canvas::surefind_value_node(const String &id)
388 if(is_inline() && parent_)
389 return parent_->surefind_value_node(id);
392 throw Exception::IDNotFound("Empty ID");
394 // If we do not have any resolution, then we assume that the
395 // request is for this immediate canvas
396 if(id.find_first_of(':')==string::npos && id.find_first_of('#')==string::npos)
397 return value_node_list_.surefind(id);
399 String canvas_id(id,0,id.rfind(':'));
400 String value_node_id(id,id.rfind(':')+1);
401 if(canvas_id.empty())
404 return surefind_canvas(canvas_id)->value_node_list_.surefind(value_node_id);
408 Canvas::add_value_node(ValueNode::Handle x, const String &id)
410 if(is_inline() && parent_)
411 return parent_->add_value_node(x,id);
412 // throw runtime_error("You cannot add a ValueNode to an inline Canvas");
416 throw runtime_error("ValueNode is already exported");
419 throw Exception::BadLinkName("Empty ID");
421 if(id.find_first_of(':',0)!=string::npos)
422 throw Exception::BadLinkName("Bad character");
427 if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id)))
428 throw Exception::IDNotFound("add_value_node()");
431 throw Exception::IDAlreadyExists(id);
433 catch(Exception::IDNotFound)
438 x->set_parent_canvas(this);
440 if(!value_node_list_.add(x))
442 synfig::error("Unable to add ValueNode");
443 throw std::runtime_error("Unable to add ValueNode");
453 Canvas::rename_value_node(ValueNode::Handle x, const String &id)
456 throw Exception::BadLinkName("Empty ID");
458 if(id.find_first_of(": ",0)!=string::npos)
459 throw Exception::BadLinkName("Bad character");
463 if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id)))
464 throw Exception::IDNotFound("rename_value_node");
465 throw Exception::IDAlreadyExists(id);
467 catch(Exception::IDNotFound)
477 Canvas::remove_value_node(ValueNode::Handle x)
479 if(is_inline() && parent_)
480 return parent_->remove_value_node(x);
481 // throw Exception::IDNotFound("Canvas::remove_value_node() was called from an inline canvas");
484 throw Exception::IDNotFound("Canvas::remove_value_node() was passed empty handle");
486 if(!value_node_list_.erase(x))
487 throw Exception::IDNotFound("Canvas::remove_value_node(): ValueNode was not found inside of this canvas");
489 //x->set_parent_canvas(0);
496 Canvas::surefind_canvas(const String &id)
498 if(is_inline() && parent_)
499 return parent_->surefind_canvas(id);
504 // If the ID contains a "#" character, then a filename is
505 // expected on the left side.
506 if(id.find_first_of('#')!=string::npos)
508 // If '#' is the first character, remove it
509 // and attempt to parse the ID again.
511 return surefind_canvas(String(id,1));
513 //! \todo This needs a lot more optimization
514 String file_name(id,0,id.find_first_of('#'));
515 String external_id(id,id.find_first_of('#')+1);
517 file_name=unix_to_local_path(file_name);
519 Canvas::Handle external_canvas;
521 // If the composition is already open, then use it.
522 if(externals_.count(file_name))
523 external_canvas=externals_[file_name];
526 if(is_absolute_path(file_name))
527 external_canvas=open_canvas(file_name);
529 external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name);
532 throw Exception::FileNotFound(file_name);
533 externals_[file_name]=external_canvas;
536 return Handle::cast_const(external_canvas.constant()->find_canvas(external_id));
539 // If we do not have any resolution, then we assume that the
540 // request is for this immediate canvas
541 if(id.find_first_of(':')==string::npos)
543 Children::iterator iter;
545 // Search for the image in the image list,
546 // and return it if it is found
547 for(iter=children().begin();iter!=children().end();iter++)
548 if(id==(*iter)->get_id())
551 // Create a new canvas and return it
552 //synfig::warning("Implicitly creating canvas named "+id);
553 return new_child_canvas(id);
556 // If the first character is the separator, then
557 // this references the root canvas.
559 return get_root()->surefind_canvas(string(id,1));
561 // Now we know that the requested Canvas is in a child
562 // of this canvas. We have to find that canvas and
563 // call "find_canvas" on it, and return the result.
565 String canvas_name=string(id,0,id.find_first_of(':'));
567 Canvas::Handle child_canvas=surefind_canvas(canvas_name);
569 return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1));
573 Canvas::find_canvas(const String &id)
576 Canvas::Handle::cast_const(
577 const_cast<const Canvas*>(this)->find_canvas(id)
582 Canvas::find_canvas(const String &id)const
584 if(is_inline() && parent_)return parent_->find_canvas(id);
589 // If the ID contains a "#" character, then a filename is
590 // expected on the left side.
591 if(id.find_first_of('#')!=string::npos)
593 // If '#' is the first character, remove it
594 // and attempt to parse the ID again.
596 return find_canvas(String(id,1));
598 //! \todo This needs a lot more optimization
599 String file_name(id,0,id.find_first_of('#'));
600 String external_id(id,id.find_first_of('#')+1);
602 file_name=unix_to_local_path(file_name);
604 Canvas::Handle external_canvas;
606 // If the composition is already open, then use it.
607 if(externals_.count(file_name))
608 external_canvas=externals_[file_name];
611 if(is_absolute_path(file_name))
612 external_canvas=open_canvas(file_name);
614 external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name);
617 throw Exception::FileNotFound(file_name);
618 externals_[file_name]=external_canvas;
621 return Handle::cast_const(external_canvas.constant()->find_canvas(external_id));
624 // If we do not have any resolution, then we assume that the
625 // request is for this immediate canvas
626 if(id.find_first_of(':')==string::npos)
628 Children::const_iterator iter;
630 // Search for the image in the image list,
631 // and return it if it is found
632 for(iter=children().begin();iter!=children().end();iter++)
633 if(id==(*iter)->get_id())
636 throw Exception::IDNotFound("Child Canvas in Parent Canvas: (child)"+id);
639 // If the first character is the separator, then
640 // this references the root canvas.
641 if(id.find_first_of(':')==0)
642 return get_root()->find_canvas(string(id,1));
644 // Now we know that the requested Canvas is in a child
645 // of this canvas. We have to find that canvas and
646 // call "find_canvas" on it, and return the result.
648 String canvas_name=string(id,0,id.find_first_of(':'));
650 Canvas::ConstHandle child_canvas=find_canvas(canvas_name);
652 return child_canvas->find_canvas(string(id,id.find_first_of(':')+1));
659 return new Canvas("Untitled");
663 Canvas::push_back(etl::handle<Layer> x)
666 // int i(x->count());
668 //if(x->count()!=i+1)synfig::info("push_back before %d, after %d",i,x->count());
672 Canvas::push_front(etl::handle<Layer> x)
675 // int i(x->count());
677 //if(x->count()!=i+1)synfig::error("push_front before %d, after %d",i,x->count());
681 Canvas::insert(iterator iter,etl::handle<Layer> x)
683 // int i(x->count());
684 CanvasBase::insert(iter,x);
686 /*if(x->count()!=i+1)
688 synfig::error(__FILE__":%d: Canvas::insert(): ***FAILURE*** before %d, after %d",__LINE__,i,x->count());
690 //throw runtime_error("Canvas Insertion Failed");
699 LooseHandle correct_canvas(this);
700 //while(correct_canvas->is_inline())correct_canvas=correct_canvas->parent();
701 Layer::LooseHandle loose_layer(x);
703 add_connection(loose_layer,
704 sigc::connection::connection(
705 x->signal_added_to_group().connect(
709 &Canvas::add_group_pair),
711 add_connection(loose_layer,
712 sigc::connection::connection(
713 x->signal_removed_from_group().connect(
717 &Canvas::remove_group_pair),
721 if(!x->get_group().empty())
722 add_group_pair(x->get_group(),x);
729 Canvas::push_back_simple(etl::handle<Layer> x)
731 CanvasBase::insert(end(),x);
736 Canvas::erase(Canvas::iterator iter)
738 if(!(*iter)->get_group().empty())
739 remove_group_pair((*iter)->get_group(),(*iter));
741 // HACK: We really shouldn't be wiping
742 // out these signals entirely. We should
743 // only be removing the specific connections
744 // that we made. At the moment, I'm too
745 // lazy to add the code to keep track
746 // of those connections, and no one else
747 // is using these signals, so I'll just
748 // leave these next two lines like they
749 // are for now - darco 07-30-2004
751 // so don't wipe them out entirely
752 // - dooglus 09-21-2007
753 disconnect_connections(*iter);
755 if(!op_flag_)remove_child(iter->get());
757 CanvasBase::erase(iter);
758 if(!op_flag_)changed();
762 Canvas::clone(const GUID& deriv_guid)const
769 name=get_id()+"_CLONE";
771 throw runtime_error("Cloning of non-inline canvases is not yet suported");
774 Handle canvas(new Canvas(name));
778 canvas->is_inline_=true;
780 //canvas->set_inline(parent());
783 canvas->set_guid(get_guid()^deriv_guid);
786 for(iter=begin();iter!=end();++iter)
788 Layer::Handle layer((*iter)->clone(deriv_guid));
791 assert(layer.count()==1);
793 canvas->push_back(layer);
794 if(!(layer.count()>1))
796 synfig::error("Canvas::clone(): Cloned layer insertion failure!");
797 synfig::error("Canvas::clone(): \tlayer.count()=%d",layer.count());
798 synfig::error("Canvas::clone(): \tlayer->get_name()=%s",layer->get_name().c_str());
799 synfig::error("Canvas::clone(): \tbefore size()=%d",presize);
800 synfig::error("Canvas::clone(): \tafter size()=%d",size());
802 assert(layer.count()>1);
806 synfig::error("Unable to clone layer");
810 canvas->signal_group_pair_removed().clear();
811 canvas->signal_group_pair_added().clear();
817 Canvas::set_inline(LooseHandle parent)
819 if(is_inline_ && parent_)
828 // Have the parent inherit all of the group stuff
830 std::map<String,std::set<etl::handle<Layer> > >::const_iterator iter;
832 for(iter=group_db_.begin();iter!=group_db_.end();++iter)
834 parent->group_db_[iter->first].insert(iter->second.begin(),iter->second.end());
837 rend_desc()=parent->rend_desc();
841 Canvas::create_inline(Handle parent)
844 //if(parent->is_inline())
845 // return create_inline(parent->parent());
847 Handle canvas(new Canvas("inline"));
848 canvas->set_inline(parent);
853 Canvas::new_child_canvas()
855 if(is_inline() && parent_)
856 return parent_->new_child_canvas();
857 // runtime_error("You cannot create a child Canvas in an inline Canvas");
859 // Create a new canvas
860 children().push_back(create());
861 Canvas::Handle canvas(children().back());
863 canvas->parent_=this;
865 canvas->rend_desc()=rend_desc();
871 Canvas::new_child_canvas(const String &id)
873 if(is_inline() && parent_)
874 return parent_->new_child_canvas(id);
875 // runtime_error("You cannot create a child Canvas in an inline Canvas");
877 // Create a new canvas
878 children().push_back(create());
879 Canvas::Handle canvas(children().back());
882 canvas->parent_=this;
883 canvas->rend_desc()=rend_desc();
889 Canvas::add_child_canvas(Canvas::Handle child_canvas, const synfig::String& id)
891 if(is_inline() && parent_)
892 return parent_->add_child_canvas(child_canvas,id);
894 if(child_canvas->parent() && !child_canvas->is_inline())
895 throw std::runtime_error("Cannot add child canvas because it belongs to someone else!");
898 throw runtime_error("Invalid ID");
903 throw Exception::IDAlreadyExists(id);
905 catch(Exception::IDNotFound)
907 if(child_canvas->is_inline())
908 child_canvas->is_inline_=false;
909 child_canvas->id_=id;
910 children().push_back(child_canvas);
911 child_canvas->parent_=this;
918 Canvas::remove_child_canvas(Canvas::Handle child_canvas)
920 if(is_inline() && parent_)
921 return parent_->remove_child_canvas(child_canvas);
923 if(child_canvas->parent_!=this)
924 throw runtime_error("Given child does not belong to me");
926 if(find(children().begin(),children().end(),child_canvas)==children().end())
927 throw Exception::IDNotFound(child_canvas->get_id());
929 children().remove(child_canvas);
931 child_canvas->parent_=0;
935 Canvas::set_file_name(const String &file_name)
938 parent()->set_file_name(file_name);
941 file_name_=file_name;
942 signal_file_name_changed_();
947 Canvas::signal_file_name_changed()
950 return signal_file_name_changed();
952 return signal_file_name_changed_;
956 Canvas::get_file_name()const
959 return parent()->get_file_name();
964 Canvas::get_file_path()const
967 return parent()->get_file_path();
968 return dirname(file_name_);
973 Canvas::get_meta_data(const String& key)const
975 if(!meta_data_.count(key))
977 return meta_data_.find(key)->second;
981 Canvas::set_meta_data(const String& key, const String& data)
983 if(meta_data_[key]!=data)
985 meta_data_[key]=data;
986 signal_meta_data_changed()(key);
987 signal_meta_data_changed(key)();
992 Canvas::erase_meta_data(const String& key)
994 if(meta_data_.count(key))
996 meta_data_.erase(key);
997 signal_meta_data_changed()(key);
998 signal_meta_data_changed(key)();
1003 Canvas::get_meta_data_keys()const
1005 std::list<String> ret;
1007 std::map<String,String>::const_iterator iter;
1009 for(iter=meta_data_.begin();!(iter==meta_data_.end());++iter)
1010 ret.push_back(iter->first);
1016 synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_motion_blur_in_parent)
1020 std::vector< std::pair<float,Layer::Handle> > sort_list;
1021 int i, motion_blur_i; // motion_blur_i is for resolving which layer comes first in the event of a z_depth tie
1022 float motion_blur_z_depth; // the z_depth of the least deep motion blur layer in this context
1023 bool seen_motion_blur_locally = false;
1024 bool motion_blurred; // the final result - is this layer blurred or not?
1026 // If the parent didn't cause us to already be motion blurred,
1027 // check whether there's a motion blur in this context,
1028 // and if so, calculate its z_depth.
1029 if (!seen_motion_blur_in_parent)
1030 for(iter=context,i=0;*iter;iter++,i++)
1032 Layer::Handle layer=*iter;
1034 // If the layer isn't active, don't worry about it
1035 if(!layer->active())
1038 // Any layer with an amount of zero is implicitly disabled.
1039 ValueBase value(layer->get_param("amount"));
1040 if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
1043 if(layer->get_name()=="MotionBlur")
1045 float z_depth(layer->get_z_depth()*1.0001+i);
1047 // If we've seen a motion blur before in this context...
1048 if (seen_motion_blur_locally)
1050 // ... then we're only interested in this one if it's less deep...
1051 if (z_depth < motion_blur_z_depth)
1053 motion_blur_z_depth = z_depth;
1057 // ... otherwise we're always interested in it.
1060 motion_blur_z_depth = z_depth;
1062 seen_motion_blur_locally = true;
1067 // Go ahead and start romping through the canvas to paste
1068 for(iter=context,i=0;*iter;iter++,i++)
1070 Layer::Handle layer=*iter;
1071 float z_depth(layer->get_z_depth()*1.0001+i);
1073 // If the layer isn't active, don't worry about it
1074 if(!layer->active())
1077 // Any layer with an amount of zero is implicitly disabled.
1078 ValueBase value(layer->get_param("amount"));
1079 if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
1082 Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
1084 // note: this used to include "&& paste_canvas->get_time_offset()==0", but then
1085 // time-shifted layers weren't being sorted by z-depth (bug #1806852)
1086 if(layer->get_name()=="PasteCanvas")
1088 // we need to blur the sub canvas if:
1089 // our parent is blurred,
1090 // or the child is lower than a local blur,
1091 // or the child is at the same z_depth as a local blur, but later in the context
1094 if (seen_motion_blur_in_parent) synfig::info("seen BLUR in parent\n");
1095 else if (seen_motion_blur_locally)
1096 if (z_depth > motion_blur_z_depth) synfig::info("paste is deeper than BLUR\n");
1097 else if (z_depth == motion_blur_z_depth) { synfig::info("paste is same depth as BLUR\n");
1098 if (i > motion_blur_i) synfig::info("paste is physically deeper than BLUR\n");
1099 else synfig::info("paste is less physically deep than BLUR\n");
1100 } else synfig::info("paste is less deep than BLUR\n");
1101 else synfig::info("no BLUR at all\n");
1104 motion_blurred = (seen_motion_blur_in_parent ||
1105 (seen_motion_blur_locally &&
1106 (z_depth > motion_blur_z_depth ||
1107 (z_depth == motion_blur_z_depth && i > motion_blur_i))));
1109 Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
1110 Canvas::Handle paste_sub_canvas = paste_canvas->get_sub_canvas();
1111 if(paste_sub_canvas)
1112 optimize_layers(paste_sub_canvas->get_context(),sub_canvas,motion_blurred);
1113 //#define SYNFIG_OPTIMIZE_PASTE_CANVAS 1
1115 #ifdef SYNFIG_OPTIMIZE_PASTE_CANVAS
1116 Canvas::iterator sub_iter;
1117 // Determine if we can just remove the paste canvas
1119 if(paste_canvas->get_blend_method()==Color::BLEND_COMPOSITE && paste_canvas->get_amount()==1.0f && paste_canvas->get_zoom()==0 && paste_canvas->get_time_offset()==0 && paste_canvas->get_origin()==Point(0,0))
1121 for(sub_iter=sub_canvas->begin();sub_iter!=sub_canvas->end();++sub_iter)
1123 Layer* layer=sub_iter->get();
1125 // any layers that deform end up breaking things
1126 // so do things the old way if we run into anything like this
1127 if(!dynamic_cast<Layer_NoDeform*>(layer))
1130 ValueBase value(layer->get_param("blend_method"));
1131 if(value.get_type()!=ValueBase::TYPE_INTEGER || value.get(int())!=(int)Color::BLEND_COMPOSITE)
1135 // It has turned out that we don't need a paste canvas
1136 // layer, so just go ahead and add all the layers onto
1137 // the current stack and be done with it
1138 while(sub_canvas->size())
1140 sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,sub_canvas->front()));
1141 //op_canvas->push_back_simple(sub_canvas->front());
1142 sub_canvas->pop_front();
1147 Layer::Handle new_layer(Layer::create("PasteCanvas"));
1148 dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(false);
1151 Layer::DynamicParamList dynamic_param_list(paste_canvas->dynamic_param_list());
1152 for(Layer::DynamicParamList::const_iterator iter(dynamic_param_list.begin()); iter != dynamic_param_list.end(); ++iter)
1153 new_layer->connect_dynamic_param(iter->first, iter->second);
1155 Layer::ParamList param_list(paste_canvas->get_param_list());
1156 //param_list.erase("canvas");
1157 new_layer->set_param_list(param_list);
1158 dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_sub_canvas(sub_canvas);
1159 dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(true);
1163 sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,layer));
1164 //op_canvas->push_back_simple(layer);
1168 stable_sort(sort_list.begin(),sort_list.end());
1169 std::vector< std::pair<float,Layer::Handle> >::iterator iter2;
1170 for(iter2=sort_list.begin();iter2!=sort_list.end();++iter2)
1171 op_canvas->push_back_simple(iter2->second);
1172 op_canvas->op_flag_=true;
1176 Canvas::get_times_vfunc(Node::time_set &set) const
1178 const_iterator i = begin(),
1181 for(; i != iend; ++i)
1183 const Node::time_set &tset = (*i)->get_times();
1184 set.insert(tset.begin(),tset.end());
1188 std::set<etl::handle<Layer> >
1189 Canvas::get_layers_in_group(const String&group)
1191 if(is_inline() && parent_)
1192 return parent_->get_layers_in_group(group);
1194 if(group_db_.count(group)==0)
1195 return std::set<etl::handle<Layer> >();
1196 return group_db_.find(group)->second;
1200 Canvas::get_groups()const
1202 if(is_inline() && parent_)
1203 return parent_->get_groups();
1205 std::set<String> ret;
1206 std::map<String,std::set<etl::handle<Layer> > >::const_iterator iter;
1207 for(iter=group_db_.begin();iter!=group_db_.end();++iter)
1208 ret.insert(iter->first);
1213 Canvas::get_group_count()const
1215 if(is_inline() && parent_)
1216 return parent_->get_group_count();
1218 return group_db_.size();
1222 Canvas::add_group_pair(String group, etl::handle<Layer> layer)
1224 group_db_[group].insert(layer);
1225 if(group_db_[group].size()==1)
1226 signal_group_added()(group);
1228 signal_group_changed()(group);
1230 signal_group_pair_added()(group,layer);
1232 if(is_inline() && parent_)
1233 return parent_->add_group_pair(group,layer);
1237 Canvas::remove_group_pair(String group, etl::handle<Layer> layer)
1239 group_db_[group].erase(layer);
1241 signal_group_pair_removed()(group,layer);
1243 if(group_db_[group].empty())
1245 group_db_.erase(group);
1246 signal_group_removed()(group);
1249 signal_group_changed()(group);
1251 if(is_inline() && parent_)
1252 return parent_->remove_group_pair(group,layer);
1256 Canvas::add_connection(Layer::LooseHandle layer, sigc::connection connection)
1258 connections_[layer].push_back(connection);
1262 Canvas::disconnect_connections(Layer::LooseHandle layer)
1264 std::vector<sigc::connection>::iterator iter;
1265 for(iter=connections_[layer].begin();iter!=connections_[layer].end();++iter)
1267 connections_[layer].clear();
1271 Canvas::rename_group(const String&old_name,const String&new_name)
1273 if(is_inline() && parent_)
1274 return parent_->rename_group(old_name,new_name);
1277 std::map<String,std::set<etl::handle<Layer> > >::iterator iter;
1278 iter=group_db_.find(old_name);
1279 if(iter!=group_db_.end())
1280 for(++iter;iter!=group_db_.end() && iter->first.find(old_name)==0;iter=group_db_.find(old_name),++iter)
1282 String name(iter->first,old_name.size(),String::npos);
1284 rename_group(iter->first,name);
1288 std::set<etl::handle<Layer> > layers(get_layers_in_group(old_name));
1289 std::set<etl::handle<Layer> >::iterator iter;
1291 for(iter=layers.begin();iter!=layers.end();++iter)
1293 (*iter)->remove_from_group(old_name);
1294 (*iter)->add_to_group(new_name);