**
** \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
if(is_absolute_path(file_name))
external_canvas=open_canvas(file_name);
else
- external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPERATOR+file_name);
+ external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name);
if(!external_canvas)
throw Exception::FileNotFound(file_name);
return new_child_canvas(id);
}
- // If the first character is the seperator, then
+ // If the first character is the separator, then
// this references the root canvas.
if(id[0]==':')
return get_root()->surefind_canvas(string(id,1));
if(is_absolute_path(file_name))
external_canvas=open_canvas(file_name);
else
- external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPERATOR+file_name);
+ external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name);
if(!external_canvas)
throw Exception::FileNotFound(file_name);
throw Exception::IDNotFound("Child Canvas in Parent Canvas: (child)"+id);
}
- // If the first character is the seperator, then
+ // If the first character is the separator, then
// this references the root canvas.
if(id.find_first_of(':')==0)
return get_root()->find_canvas(string(id,1));
//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())
// 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());
{
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));
}
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<float,Layer::Handle> > 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")
+ {
+ 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++)
continue;
Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(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
}catch(int) { }
#endif
Layer::Handle new_layer(Layer::create("PasteCanvas"));
- dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_do_not_muck_with_time(true);
+ dynamic_cast<Layer_PasteCanvas*>(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);
dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_sub_canvas(sub_canvas);
- dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_do_not_muck_with_time(false);
+ dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(true);
layer=new_layer;
}
}
void
+Canvas::add_connection(Layer::LooseHandle layer, sigc::connection connection)
+{
+ connections_[layer].push_back(connection);
+}
+
+void
+Canvas::disconnect_connections(Layer::LooseHandle layer)
+{
+ std::vector<sigc::connection>::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_)