X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcanvas.cpp;h=ede95013805a50094d765d636d533eadd4ba174e;hb=63e709f66d50c124cc0ece2325f4773ac4ae7b20;hp=e98b301fa107f1445f61a5c00d92d3f200f5a5e0;hpb=05903bd0db81b0db98639258d32cfcde302e4a9b;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/canvas.cpp b/synfig-core/trunk/src/synfig/canvas.cpp index e98b301..ede9501 100644 --- a/synfig-core/trunk/src/synfig/canvas.cpp +++ b/synfig-core/trunk/src/synfig/canvas.cpp @@ -6,6 +6,7 @@ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -68,8 +69,9 @@ int _CanvasCounter::counter(0); /* === M E T H O D S ======================================================= */ -Canvas::Canvas(const string &id): +Canvas::Canvas(const String &id): id_ (id), + version_ (CURRENT_CANVAS_VERSION), cur_time_ (0), is_inline_ (false), is_dirty_ (true), @@ -90,7 +92,6 @@ Canvas::~Canvas() { //if(is_inline() && parent_) assert(0); _CanvasCounter::counter--; - //DEBUGPOINT(); clear(); begin_delete(); } @@ -411,7 +412,6 @@ Canvas::add_value_node(ValueNode::Handle x, const String &id) return parent_->add_value_node(x,id); // throw runtime_error("You cannot add a ValueNode to an inline Canvas"); - //DEBUGPOINT(); if(x->is_exported()) throw runtime_error("ValueNode is already exported"); @@ -423,16 +423,13 @@ Canvas::add_value_node(ValueNode::Handle x, const String &id) try { - //DEBUGPOINT(); if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id))) throw Exception::IDNotFound("add_value_node()"); - //DEBUGPOINT(); throw Exception::IDAlreadyExists(id); } catch(Exception::IDNotFound) { - //DEBUGPOINT(); x->set_id(id); x->set_parent_canvas(this); @@ -442,7 +439,6 @@ Canvas::add_value_node(ValueNode::Handle x, const String &id) synfig::error("Unable to add ValueNode"); throw std::runtime_error("Unable to add ValueNode"); } - //DEBUGPOINT(); return; } @@ -662,7 +658,6 @@ Canvas::create() void Canvas::push_back(etl::handle x) { -// DEBUGPOINT(); // int i(x->count()); insert(end(),x); //if(x->count()!=i+1)synfig::info("push_back before %d, after %d",i,x->count()); @@ -671,7 +666,6 @@ Canvas::push_back(etl::handle x) void Canvas::push_front(etl::handle x) { -// DEBUGPOINT(); // int i(x->count()); insert(begin(),x); //if(x->count()!=i+1)synfig::error("push_front before %d, after %d",i,x->count()); @@ -700,24 +694,22 @@ Canvas::insert(iterator iter,etl::handle x) //while(correct_canvas->is_inline())correct_canvas=correct_canvas->parent(); Layer::LooseHandle loose_layer(x); - x->signal_added_to_group().connect( - sigc::bind( - sigc::mem_fun( - *correct_canvas, - &Canvas::add_group_pair - ), - loose_layer - ) - ); - x->signal_removed_from_group().connect( - sigc::bind( - sigc::mem_fun( - *correct_canvas, - &Canvas::remove_group_pair - ), - loose_layer - ) - ); + add_connection(loose_layer, + sigc::connection::connection( + x->signal_added_to_group().connect( + sigc::bind( + sigc::mem_fun( + *correct_canvas, + &Canvas::add_group_pair), + loose_layer)))); + add_connection(loose_layer, + sigc::connection::connection( + x->signal_removed_from_group().connect( + sigc::bind( + sigc::mem_fun( + *correct_canvas, + &Canvas::remove_group_pair), + loose_layer)))); if(!x->get_group().empty()) @@ -735,7 +727,7 @@ Canvas::push_back_simple(etl::handle x) } void -Canvas::erase(Canvas::iterator iter) +Canvas::erase(iterator iter) { if(!(*iter)->get_group().empty()) remove_group_pair((*iter)->get_group(),(*iter)); @@ -749,8 +741,10 @@ Canvas::erase(Canvas::iterator iter) // is using these signals, so I'll just // leave these next two lines like they // are for now - darco 07-30-2004 - (*iter)->signal_added_to_group().clear(); - (*iter)->signal_removed_from_group().clear(); + + // so don't wipe them out entirely + // - dooglus 09-21-2007 + disconnect_connections(*iter); if(!op_flag_)remove_child(iter->get()); @@ -768,7 +762,7 @@ Canvas::clone(const GUID& deriv_guid)const { name=get_id()+"_CLONE"; - throw runtime_error("Cloning of non-inline canvases is not yet suported"); + throw runtime_error("Cloning of non-inline canvases is not yet supported"); } Handle canvas(new Canvas(name)); @@ -776,7 +770,11 @@ Canvas::clone(const GUID& deriv_guid)const if(is_inline()) { canvas->is_inline_=true; - canvas->parent_=0; + // \todo this was setting parent_=0 - is there a reason for that? + // this was causing bug 1838132, where cloning an inline canvas that contains an imported image fails + // it was failing to ascertain the absolute pathname of the imported image, since it needs the pathname + // of the canvas to get that, which is stored in the parent canvas + canvas->parent_=parent(); //canvas->set_inline(parent()); } @@ -1012,13 +1010,62 @@ Canvas::get_meta_data_keys()const return ret; } +/* note - the "Motion Blur" and "Duplicate" layers need the dynamic + parameters of any PasteCanvas layers they loop over to be + maintained. When the variables in the following function + refer to "motion blur", they mean either of these two + layers. */ void -synfig::optimize_layers(Context context, Canvas::Handle op_canvas) +synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_motion_blur_in_parent) { Context iter; std::vector< std::pair > sort_list; - int i; + int i, motion_blur_i=0; // motion_blur_i is for resolving which layer comes first in the event of a z_depth tie + float motion_blur_z_depth=0; // the z_depth of the least deep motion blur layer in this context + bool seen_motion_blur_locally = false; + bool motion_blurred; // the final result - is this layer blurred or not? + + // If the parent didn't cause us to already be motion blurred, + // check whether there's a motion blur in this context, + // and if so, calculate its z_depth. + if (!seen_motion_blur_in_parent) + for(iter=context,i=0;*iter;iter++,i++) + { + Layer::Handle layer=*iter; + + // If the layer isn't active, don't worry about it + if(!layer->active()) + continue; + + // Any layer with an amount of zero is implicitly disabled. + ValueBase value(layer->get_param("amount")); + if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0) + continue; + + if(layer->get_name()=="MotionBlur" || layer->get_name()=="duplicate") + { + float z_depth(layer->get_z_depth()*1.0001+i); + + // If we've seen a motion blur before in this context... + if (seen_motion_blur_locally) + { + // ... then we're only interested in this one if it's less deep... + if (z_depth < motion_blur_z_depth) + { + motion_blur_z_depth = z_depth; + motion_blur_i = i; + } + } + // ... otherwise we're always interested in it. + else + { + motion_blur_z_depth = z_depth; + motion_blur_i = i; + seen_motion_blur_locally = true; + } + } + } // Go ahead and start romping through the canvas to paste for(iter=context,i=0;*iter;iter++,i++) @@ -1036,12 +1083,36 @@ synfig::optimize_layers(Context context, Canvas::Handle op_canvas) continue; Layer_PasteCanvas* paste_canvas(static_cast(layer.get())); - if(layer->get_name()=="PasteCanvas" && paste_canvas->get_time_offset()==0) + + // note: this used to include "&& paste_canvas->get_time_offset()==0", but then + // time-shifted layers weren't being sorted by z-depth (bug #1806852) + if(layer->get_name()=="PasteCanvas") { + // we need to blur the sub canvas if: + // our parent is blurred, + // or the child is lower than a local blur, + // or the child is at the same z_depth as a local blur, but later in the context + +#if 0 // DEBUG + if (seen_motion_blur_in_parent) synfig::info("seen BLUR in parent\n"); + else if (seen_motion_blur_locally) + if (z_depth > motion_blur_z_depth) synfig::info("paste is deeper than BLUR\n"); + else if (z_depth == motion_blur_z_depth) { synfig::info("paste is same depth as BLUR\n"); + if (i > motion_blur_i) synfig::info("paste is physically deeper than BLUR\n"); + else synfig::info("paste is less physically deep than BLUR\n"); + } else synfig::info("paste is less deep than BLUR\n"); + else synfig::info("no BLUR at all\n"); +#endif // DEBUG + + motion_blurred = (seen_motion_blur_in_parent || + (seen_motion_blur_locally && + (z_depth > motion_blur_z_depth || + (z_depth == motion_blur_z_depth && i > motion_blur_i)))); + Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas)); Canvas::Handle paste_sub_canvas = paste_canvas->get_sub_canvas(); if(paste_sub_canvas) - optimize_layers(paste_sub_canvas->get_context(),sub_canvas); + optimize_layers(paste_sub_canvas->get_context(),sub_canvas,motion_blurred); //#define SYNFIG_OPTIMIZE_PASTE_CANVAS 1 #ifdef SYNFIG_OPTIMIZE_PASTE_CANVAS @@ -1078,6 +1149,12 @@ synfig::optimize_layers(Context context, Canvas::Handle op_canvas) #endif Layer::Handle new_layer(Layer::create("PasteCanvas")); dynamic_cast(new_layer.get())->set_muck_with_time(false); + if (motion_blurred) + { + Layer::DynamicParamList dynamic_param_list(paste_canvas->dynamic_param_list()); + for(Layer::DynamicParamList::const_iterator iter(dynamic_param_list.begin()); iter != dynamic_param_list.end(); ++iter) + new_layer->connect_dynamic_param(iter->first, iter->second); + } Layer::ParamList param_list(paste_canvas->get_param_list()); //param_list.erase("canvas"); new_layer->set_param_list(param_list); @@ -1179,6 +1256,21 @@ Canvas::remove_group_pair(String group, etl::handle layer) } void +Canvas::add_connection(etl::loose_handle layer, sigc::connection connection) +{ + connections_[layer].push_back(connection); +} + +void +Canvas::disconnect_connections(etl::loose_handle layer) +{ + std::vector::iterator iter; + for(iter=connections_[layer].begin();iter!=connections_[layer].end();++iter) + iter->disconnect(); + connections_[layer].clear(); +} + +void Canvas::rename_group(const String&old_name,const String&new_name) { if(is_inline() && parent_)