// 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 ===================================================== */
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)
{
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();
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(),
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)
//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...
{
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
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,
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
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)
//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");
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
//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...
{
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);
}
}
}
}
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
{
//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;
for(; j != jend && i != end;)
{
- double it = *i;
+ double it = *i+time_offset;
double jt = j->get_time();
double diff = (double)(it - jt);
{
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;
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);
}
}
}
//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);