From: dooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Date: Tue, 23 Oct 2007 19:55:53 +0000 (+0000)
Subject: Improvements to interaction with waypoints in time-shifted canvases.
X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=606a53ecae1c2993a50f9af49f65864d7bcab656;p=synfig.git

Improvements to interaction with waypoints in time-shifted canvases.


git-svn-id: http://svn.voria.com/code@947 1f10aa63-cdf2-0310-b900-c93c546f37ac
---

diff --git a/synfig-core/trunk/src/synfig/node.h b/synfig-core/trunk/src/synfig/node.h
index aeb5da1..ccdaaad 100644
--- a/synfig-core/trunk/src/synfig/node.h
+++ b/synfig-core/trunk/src/synfig/node.h
@@ -40,7 +40,7 @@
 // When a PasteCanvas layer has a non-zero 'time offset' parameter, should
 // the waypoints shown for the canvas be adjusted?  This currently only
 // partially works - see the TODO at the end of layer_pastecanvas.cpp
-// #define ADJUST_WAYPOINTS_FOR_TIME_OFFSET
+#define ADJUST_WAYPOINTS_FOR_TIME_OFFSET
 
 /* === T Y P E D E F S ===================================================== */
 
diff --git a/synfig-studio/trunk/src/gtkmm/cellrenderer_timetrack.cpp b/synfig-studio/trunk/src/gtkmm/cellrenderer_timetrack.cpp
index 7d2d6c0..af5b57c 100644
--- a/synfig-studio/trunk/src/gtkmm/cellrenderer_timetrack.cpp
+++ b/synfig-studio/trunk/src/gtkmm/cellrenderer_timetrack.cpp
@@ -124,6 +124,30 @@ CellRenderer_TimeTrack::is_selected(const Waypoint& waypoint)const
 	return selected==waypoint;
 }
 
+const synfig::Time get_time_offset_from_vdesc(const synfigapp::ValueDesc &v)
+{
+#ifdef ADJUST_WAYPOINTS_FOR_TIME_OFFSET
+	if(v.get_value_type() != synfig::ValueBase::TYPE_CANVAS)
+		return synfig::Time::zero();
+
+	synfig::Canvas::Handle canvasparam = v.get_value().get(Canvas::Handle());
+	if(!canvasparam)
+		return synfig::Time::zero();
+
+	if (!v.parent_is_layer_param())
+		return synfig::Time::zero();
+
+	synfig::Layer::Handle layer = v.get_layer();
+
+	if (layer->get_name()!="PasteCanvas")
+		return synfig::Time::zero();
+
+	return layer->get_param("time_offset").get(Time());
+#else // ADJUST_WAYPOINTS_FOR_TIME_OFFSET
+	return synfig::Time::zero();
+#endif
+}
+
 //kind of a hack... pointer is ugly
 const synfig::Node::time_set *get_times_from_vdesc(const synfigapp::ValueDesc &v)
 {
@@ -132,33 +156,7 @@ const synfig::Node::time_set *get_times_from_vdesc(const synfigapp::ValueDesc &v
 		synfig::Canvas::Handle canvasparam = v.get_value().get(Canvas::Handle());
 
 		if(canvasparam)
-		{
-#ifdef ADJUST_WAYPOINTS_FOR_TIME_OFFSET // see node.h
-			synfig::Time::value_type time_offset = 0;
-			if (v.parent_is_layer_param())
-			{
-				synfig::Layer::Handle layer = v.get_layer();
-				if (layer->get_name()=="PasteCanvas")
-					time_offset = layer->get_param("time_offset").get(Time());
-			}
-
-			const Node::time_set *times = &canvasparam->get_times();
-
-			if (time_offset)
-			{
-				//! \todo this is a memory leak - blame the 'kind of hack' above
-				Node::time_set *tmp = new Node::time_set;
-				Node::time_set::iterator i = times->begin(), end = times->end();
-				for (; i != end; ++i)
-					tmp->insert(*i - time_offset);
-				return tmp;
-			}
-
-			return times;
-#else // ADJUST_WAYPOINTS_FOR_TIME_OFFSET
 			return &canvasparam->get_times();
-#endif
-		}
 	}
 
 	ValueNode *base_value = v.get_value_node().get();
@@ -287,6 +285,7 @@ CellRenderer_TimeTrack::render_vfunc(
 
 		if(tset)
 		{
+			const synfig::Time time_offset = get_time_offset_from_vdesc(value_desc);
 			synfig::Node::time_set::const_iterator	i = tset->begin(), end = tset->end();
 
 			float 	lower = adjustment->get_lower(),
@@ -308,10 +307,9 @@ CellRenderer_TimeTrack::render_vfunc(
 			for(; i != end; ++i)
 			{
 				//find the coordinate in the drawable space...
-				Time t = i->get_time();
-
-				if(!t.is_valid())
-					continue;
+				Time t_orig = i->get_time();
+				if(!t_orig.is_valid()) continue;
+				Time t = t_orig - time_offset;
 
 				//if it found it... (might want to change comparison, and optimize
 				//					 sel_times.find to not produce an overall nlogn solution)
@@ -321,13 +319,13 @@ CellRenderer_TimeTrack::render_vfunc(
 				//if move dragging draw offset
 				//if copy dragging draw both...
 
-				if(valselected && sel_times.find(t) != sel_times.end())
+				if(valselected && sel_times.find(t_orig) != sel_times.end())
 				{
 					if(dragging) //skip if we're dragging because we'll render it later
 					{
 						if(mode & COPY_MASK) // draw both blue and red moved
 						{
-							drawredafter.push_back((t + diff).round(cfps));
+							drawredafter.push_back(t + diff.round(cfps));
 							gc->set_rgb_fg_color(Gdk::Color("#00EEEE"));
 						}else if(mode & DELETE_MASK) //it's just red...
 						{
@@ -335,7 +333,7 @@ CellRenderer_TimeTrack::render_vfunc(
 							selected=true;
 						}else //move - draw the red on top of the others...
 						{
-							drawredafter.push_back((t + diff).round(cfps));
+							drawredafter.push_back(t + diff.round(cfps));
 							continue;
 						}
 					}else
@@ -358,7 +356,7 @@ CellRenderer_TimeTrack::render_vfunc(
 					area.get_height()-2,
 					area.get_height()-2
 				);
-				render_time_point_to_window(window,area2,*i,selected);
+				render_time_point_to_window(window,area2,*i - time_offset,selected);
 
 				/*window->draw_arc(gc,true,
 				area.get_x() + x - area.get_height()/4,	area.get_y() + area.get_height()/8,
@@ -665,8 +663,9 @@ CellRenderer_TimeTrack::activate_vfunc(
 
 			synfigapp::ValueDesc valdesc = property_value_desc().get_value();
 			const Node::time_set *tset = get_times_from_vdesc(valdesc);
+			const synfig::Time time_offset = get_time_offset_from_vdesc(valdesc);
 
-			bool clickfound = tset && get_closest_time(*tset,actual_time,pixel_width*cell_area.get_height(),stime);
+			bool clickfound = tset && get_closest_time(*tset,actual_time+time_offset,pixel_width*cell_area.get_height(),stime);
 			bool selectmode = mode & SELECT_MASK;
 
 			//NOTE LATER ON WE SHOULD MAKE IT SO MULTIPLE VALUENODES CAN BE SELECTED AT ONCE
@@ -748,7 +747,7 @@ CellRenderer_TimeTrack::activate_vfunc(
 				synfigapp::ValueDesc valdesc = property_value_desc().get_value();
 				const Node::time_set *tset = get_times_from_vdesc(valdesc);
 
-				bool clickfound = tset && get_closest_time(*tset,actual_time,pixel_width*cell_area.get_height(),stime);
+				bool clickfound = tset && get_closest_time(*tset,actual_time+get_time_offset_from_vdesc(valdesc),pixel_width*cell_area.get_height(),stime);
 
 				etl::handle<synfig::Node> node;
 				if(valdesc.get_value(stime).get_type()==ValueBase::TYPE_CANVAS)
diff --git a/synfig-studio/trunk/src/synfigapp/timegather.cpp b/synfig-studio/trunk/src/synfigapp/timegather.cpp
index e7a05dc..7e2f34a 100644
--- a/synfig-studio/trunk/src/synfigapp/timegather.cpp
+++ b/synfig-studio/trunk/src/synfigapp/timegather.cpp
@@ -96,7 +96,7 @@ void synfigapp::timepoints_ref::insert(synfigapp::ValueDesc v, synfig::Activepoi
 
 //recursion functions
 void synfigapp::recurse_canvas(synfig::Canvas::Handle h, const std::set<Time> &tlist,
-								timepoints_ref &vals)
+								timepoints_ref &vals, synfig::Time time_offset)
 {
 
 	//synfig::info("Canvas...\n Recurse through layers");
@@ -107,15 +107,15 @@ void synfigapp::recurse_canvas(synfig::Canvas::Handle h, const std::set<Time> &t
 	for(; i != end; ++i)
 	{
 		const Node::time_set &tset = (*i)->get_times();
-		if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end()))
+		if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),time_offset))
 		{
-			recurse_layer(*i,tlist,vals);
+			recurse_layer(*i,tlist,vals,time_offset);
 		}
 	}
 }
 
 void synfigapp::recurse_layer(synfig::Layer::Handle h, const std::set<Time> &tlist,
-								timepoints_ref &vals)
+								timepoints_ref &vals, synfig::Time time_offset)
 {
 	// iterate through the layers
 	//check for special case of paste canvas
@@ -128,20 +128,10 @@ void synfigapp::recurse_layer(synfig::Layer::Handle h, const std::set<Time> &tli
 		//synfig::info("We are a paste canvas so go into that");
 		//recurse into the canvas
 		const synfig::Node::time_set &tset = p->get_sub_canvas()->get_times();
+		synfig::Time subcanvas_time_offset(time_offset + p->get_time_offset());
 
-		if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end()))
-		{
-			//we have to offset the times so it won't wreck havoc if the canvas is imported more than once...
-			// and so we get correct results when offsets are present
-			std::set<Time>	tlistoff;
-			std::set<Time>::iterator i = tlist.begin(), end = tlist.end();
-			for(; i != end; ++i)
-			{
-				tlistoff.insert(*i - p->get_time_offset());
-			}
-
-			recurse_canvas(p->get_sub_canvas(),tlist,vals);
-		}
+		if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),subcanvas_time_offset))
+			recurse_canvas(p->get_sub_canvas(),tlist,vals,subcanvas_time_offset);
 	}
 
 	//check all the valuenodes regardless...
@@ -152,9 +142,9 @@ void synfigapp::recurse_layer(synfig::Layer::Handle h, const std::set<Time> &tli
 	{
 		const synfig::Node::time_set &tset = i->second->get_times();
 
-		if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end()))
+		if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),time_offset))
 		{
-			recurse_valuedesc(ValueDesc(h,i->first),tlist,vals);
+			recurse_valuedesc(ValueDesc(h,i->first),tlist,vals,time_offset);
 		}
 	}
 }
@@ -174,7 +164,7 @@ static bool sorted(IT i,IT end, const CMP &cmp = CMP())
 }
 
 void synfigapp::recurse_valuedesc(synfigapp::ValueDesc h, const std::set<Time> &tlist,
-								timepoints_ref &vals)
+								timepoints_ref &vals, synfig::Time time_offset)
 {
 	//special cases for Animated, DynamicList, and Linkable
 
@@ -199,11 +189,11 @@ void synfigapp::recurse_valuedesc(synfigapp::ValueDesc h, const std::set<Time> &
 			{
 				//synfig::info("tpair t(%.3f) = %.3f", (float)*j, (float)(i->get_time()));
 
-				if(j->is_equal(i->get_time()))
+				if((*j+time_offset).is_equal(i->get_time()))
 				{
 					vals.insert(p,*i);
 					++i,++j;
-				}else if(*i < *j)
+				}else if(*i < *j+time_offset)
 				{
 					++i;
 				}else ++j;
@@ -234,7 +224,7 @@ void synfigapp::recurse_valuedesc(synfigapp::ValueDesc h, const std::set<Time> &
 
 			for(; j != jend && i != end;)
 			{
-				double it = *i;
+				double it = *i+time_offset;
 				double jt = j->get_time();
 				double diff = (double)(it - jt);
 
@@ -279,9 +269,9 @@ void synfigapp::recurse_valuedesc(synfigapp::ValueDesc h, const std::set<Time> &
 			{
 				const Node::time_set &tset = i->get_times();
 
-				if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end()))
+				if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),time_offset))
 				{
-					recurse_valuedesc(ValueDesc(p,index),tlist,vals);
+					recurse_valuedesc(ValueDesc(p,index),tlist,vals,time_offset);
 				}
 			}
 			return;
@@ -302,9 +292,9 @@ void synfigapp::recurse_valuedesc(synfigapp::ValueDesc h, const std::set<Time> &
 				ValueNode::Handle v = p->get_link(i);
 				const Node::time_set &tset = v->get_times();
 
-				if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end()))
+				if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),time_offset))
 				{
-					recurse_valuedesc(ValueDesc(p,i),tlist,vals);
+					recurse_valuedesc(ValueDesc(p,i),tlist,vals,time_offset);
 				}
 			}
 		}
diff --git a/synfig-studio/trunk/src/synfigapp/timegather.h b/synfig-studio/trunk/src/synfigapp/timegather.h
index 5db4afd..5792496 100644
--- a/synfig-studio/trunk/src/synfigapp/timegather.h
+++ b/synfig-studio/trunk/src/synfigapp/timegather.h
@@ -92,40 +92,36 @@ struct timepoints_ref
 //assumes they're sorted... (incremental advance)
 //checks the intersection of the two sets... might be something better in the stl
 template < typename I1, typename I2 >
-bool check_intersect(I1 b1, I1 end1, I2 b2, I2 end2)
+bool check_intersect(I1 b1, I1 end1, I2 b2, I2 end2, synfig::Time time_offset = 0)
 {
 	if(b1 == end1 || b2 == end2)
 		return false;
 
 	for(; b1 != end1 && b2 != end2;)
 	{
-		if(*b1 < *b2) ++b1;
-		else if(*b2 < *b1) ++b2;
+		if(*b1 < *b2 + time_offset) ++b1;
+		else if(*b2 + time_offset < *b1) ++b2;
 		else
 		{
-			assert(*b1 == *b2);
+			assert(*b1 == *b2 + time_offset);
 			return true;
 		}
 	}
 	return false;
 }
 
-//pointer kind of a hack, gets the accurate times from a value desc
-//	(deals with dynamic list member correctly... i.e. gathers activepoints)
-const synfig::Node::time_set *get_times_from_vdesc(const synfigapp::ValueDesc &v);
-
-//get's the closest time inside the set
+//gets the closest time inside the set
 bool get_closest_time(const synfig::Node::time_set &tset, const synfig::Time &t,
 						const synfig::Time &range, synfig::Time &out);
 
 //recursion functions based on time restrictions (can be expanded later)...
 //builds a list of relevant waypoints and activepoints inside the timepoints_ref structure
 void recurse_valuedesc(synfigapp::ValueDesc valdesc, const std::set<synfig::Time> &tlist,
-								timepoints_ref &vals);
+								timepoints_ref &vals, synfig::Time time = 0);
 void recurse_layer(synfig::Layer::Handle layer, const std::set<synfig::Time> &tlist,
-								timepoints_ref &vals);
+								timepoints_ref &vals, synfig::Time time = 0);
 void recurse_canvas(synfig::Canvas::Handle canvas, const std::set<synfig::Time> &tlist,
-								timepoints_ref &vals);
+								timepoints_ref &vals, synfig::Time time = 0);