#include <ETL/hermite>
#include <ETL/calculus>
#include "segment.h"
+#include "curve_helper.h"
#endif
return ValueBase(ret,bline.get_loop());
}
+Real
+synfig::find_closest_point(const ValueBase &bline, const Point &pos, Real &radius, bool loop, Point *out_point)
+{
+ Real d,step;
+ float time = 0;
+ float best_time = 0;
+ int best_index = -1;
+ synfig::Point best_point;
+
+ if(radius==0)radius=10000000;
+ Real closest(10000000);
+
+ int i=0;
+ std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
+ typedef std::vector<BLinePoint>::const_iterator iterT;
+ iterT iter, prev, first;
+ for(iter=list.begin(); iter!=list.end(); ++i, ++iter)
+ {
+ if( first == iterT() )
+ first = iter;
+
+ if( prev != iterT() )
+ {
+ bezier<Point> curve;
+
+ curve[0] = (*prev).get_vertex();
+ curve[1] = curve[0] + (*prev).get_tangent2()/3;
+ curve[3] = (*iter).get_vertex();
+ curve[2] = curve[3] - (*iter).get_tangent1()/3;
+ curve.sync();
+
+ #if 0
+ // I don't know why this doesn't work
+ time=curve.find_closest(pos,6);
+ d=((curve(time)-pos).mag_squared());
+
+ #else
+ //set the step size based on the size of the picture
+ d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag() + (curve[3]-curve[2]).mag();
+
+ step = d/(2*radius); //want to make the distance between lines happy
+
+ step = max(step,0.01); //100 samples should be plenty
+ step = min(step,0.1); //10 is minimum
+
+ d = find_closest(curve,pos,step,&closest,&time);
+ #endif
+
+ if(d < closest)
+ {
+ closest = d;
+ best_time = time;
+ best_index = i;
+ best_point = curve(best_time);
+ }
+
+ }
+
+ prev = iter;
+ }
+
+ // Loop if necessary
+ if( loop && ( first != iterT() ) && ( prev != iterT() ) )
+ {
+ bezier<Point> curve;
+
+ curve[0] = (*prev).get_vertex();
+ curve[1] = curve[0] + (*prev).get_tangent2()/3;
+ curve[3] = (*first).get_vertex();
+ curve[2] = curve[3] - (*first).get_tangent1()/3;
+ curve.sync();
+
+ #if 0
+ // I don't know why this doesn't work
+ time=curve.find_closest(pos,6);
+ d=((curve(time)-pos).mag_squared());
+
+ #else
+ //set the step size based on the size of the picture
+ d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag() + (curve[3]-curve[2]).mag();
+
+ step = d/(2*radius); //want to make the distance between lines happy
+
+ step = max(step,0.01); //100 samples should be plenty
+ step = min(step,0.1); //10 is minimum
+
+ d = find_closest(curve,pos,step,&closest,&time);
+ #endif
+
+ if(d < closest)
+ {
+ closest = d;
+ best_time = time;
+ best_index = i;
+ best_point = curve(best_time);
+ }
+ }
+
+ if(best_index != -1)
+ {
+ if(out_point)
+ *out_point = best_point;
+
+ int loop_adjust(loop ? 0 : -1);
+ int size = list.size();
+ Real amount = (best_index + best_time + loop_adjust) / (size + loop_adjust);
+ return amount;
+ }
+
+ return 0.0;
+
+}
/* === M E T H O D S ======================================================= */
//! Converts a list of bline points into a list of widths
ValueBase convert_bline_to_width_list(const ValueBase &bline);
+//! Finds the closest point to pos in bline
+Real find_closest_point(const ValueBase &bline, const Point &pos, Real &radius, bool loop, Point *out_point = 0);
+
/*! \class ValueNode_BLine
** \brief \writeme
*/
#include <synfig/valuenode_dynamiclist.h>
#include <synfig/valuenode_twotone.h>
#include <synfig/valuenode_stripes.h>
+#include <synfig/valuenode_blinecalcvertex.h>
+#include <synfig/valuenode_bline.h>
#include <synfig/layer.h>
#include <synfigapp/uimanager.h>
bool
CanvasView::on_duck_changed(const synfig::Point &value,const synfigapp::ValueDesc& value_desc)
{
+ if( ValueNode_BLineCalcVertex::Handle bline_vertex =
+ ValueNode_BLineCalcVertex::Handle::cast_dynamic(value_desc.get_value_node())
+ )
+ {
+ Real radius = 0.0;
+ Real amount = synfig::find_closest_point(
+ ( *bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline")) )( get_time() ),
+ value,
+ radius,
+ ( *bline_vertex->get_link(bline_vertex->get_link_index_from_name("loop")) )( get_time() ).get(bool())
+ );
+ return canvas_interface()->change_value(synfigapp::ValueDesc(bline_vertex,bline_vertex->get_link_index_from_name("amount")), amount);
+ }
+
switch(value_desc.get_value_type())
{
case ValueBase::TYPE_REAL:
false),
1.0f),
synfigapp::ValueDesc(value_node,i)));
- duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
if(param_desc)
{
false),
1.0f),
synfigapp::ValueDesc(value_node,i)));
- duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
add_bezier(bezier);
bezier=0;
false),
1.0f),
synfigapp::ValueDesc(value_node,i)));
- duck->set_value_desc(synfigapp::ValueDesc(value_node,i));
}
false),
1.0f),
synfigapp::ValueDesc(value_node,first)));
- duck->set_value_desc(synfigapp::ValueDesc(value_node,first));
add_bezier(bezier);
bezier=0;
#include <ETL/misc>
#include "widget_color.h"
#include <synfig/distance.h>
+#include <synfig/valuenode_blinecalcvertex.h>
+#include <synfig/valuenode_bline.h>
#include "app.h"
#include "general.h"
/* === M E T H O D S ======================================================= */
+bool
+restrict_blinevertex_duck(etl::handle<Duck> duck, WorkArea& w_area, synfig::Point *point)
+{
+ synfig::Point sub_trans_origin(duck->get_sub_trans_origin());
+ etl::handle<Duck> origin_duck = duck->get_origin_duck();
+ bool origin_changed = false;
+ if(origin_duck)
+ origin_changed = restrict_blinevertex_duck(origin_duck, w_area, &sub_trans_origin);
+
+ if( ValueNode_BLineCalcVertex::Handle bline_vertex =
+ ValueNode_BLineCalcVertex::Handle::cast_dynamic(duck->get_value_desc().get_value_node())
+ )
+ {
+ synfig::Point closest_point = duck->get_point();
+ synfig::Real radius = 0.0;
+ synfig::find_closest_point(
+ ( *bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline")) )( w_area.get_time() ),
+ duck->get_point(),
+ radius,
+ ( *bline_vertex->get_link(bline_vertex->get_link_index_from_name("loop")) )( w_area.get_time() ).get(bool()),
+ &closest_point
+ );
+
+ if(closest_point != duck->get_point())
+ {
+ *point = closest_point * duck->get_scalar() + sub_trans_origin;
+ return true;
+ }
+ }
+
+ if(origin_changed)
+ {
+ *point = duck->get_point() * duck->get_scalar() + sub_trans_origin;
+ return true;
+ }
+
+ return false;
+}
+
Renderer_Ducks::~Renderer_Ducks()
{
}
// Render the beziers
for(std::list<handle<Duckmatic::Bezier> >::const_iterator iter=bezier_list.begin();iter!=bezier_list.end();++iter)
{
+ Point sub_trans_p1((*iter)->p1->get_sub_trans_point());
+ Point sub_trans_p2((*iter)->p2->get_sub_trans_point());
+ Point sub_trans_c1((*iter)->c1->get_sub_trans_point());
+ Point sub_trans_c2((*iter)->c2->get_sub_trans_point());
+
+ WorkArea* w_area = get_work_area();
+ restrict_blinevertex_duck((*iter)->p1, *w_area, &sub_trans_p1);
+ restrict_blinevertex_duck((*iter)->p2, *w_area, &sub_trans_p2);
+ restrict_blinevertex_duck((*iter)->c1, *w_area, &sub_trans_c1);
+ restrict_blinevertex_duck((*iter)->c2, *w_area, &sub_trans_c2);
+
Point window_start(window_startx,window_starty);
- Point p1((*iter)->p1->get_trans_point()-window_start);
- Point p2((*iter)->p2->get_trans_point()-window_start);
- Point c1((*iter)->c1->get_trans_point()-window_start);
- Point c2((*iter)->c2->get_trans_point()-window_start);
+ Point p1((*iter)->p1->get_transform_stack().perform(sub_trans_p1)-window_start);
+ Point p2((*iter)->p2->get_transform_stack().perform(sub_trans_p2)-window_start);
+ Point c1((*iter)->c1->get_transform_stack().perform(sub_trans_c1)-window_start);
+ Point c2((*iter)->c2->get_transform_stack().perform(sub_trans_c2)-window_start);
p1[0]/=pw;p1[1]/=ph;
p2[0]/=pw;p2[1]/=ph;
c1[0]/=pw;c1[1]/=ph;
// Gdk::Rectangle area;
Point sub_trans_point((*iter)->get_sub_trans_point());
Point sub_trans_origin((*iter)->get_sub_trans_origin());
+ etl::handle<Duck> origin_duck = (*iter)->get_origin_duck();
+
+ bool has_connect(false);
+ if((*iter)->get_tangent() || (*iter)->get_type()&Duck::TYPE_ANGLE)
+ {
+ has_connect=true;
+ }
+ if((*iter)->get_connect_duck())
+ {
+ has_connect=true;
+ sub_trans_origin = (*iter)->get_connect_duck()->get_sub_trans_point();
+ origin_duck = (*iter)->get_connect_duck();
+ }
+
if (App::restrict_radius_ducks &&
(*iter)->is_radius())
sub_trans_point[1] = sub_trans_origin[1];
}
+ WorkArea* w_area = get_work_area();
+ restrict_blinevertex_duck((*iter), *w_area, &sub_trans_point);
+ if(origin_duck)
+ restrict_blinevertex_duck(origin_duck, *w_area, &sub_trans_origin);
+
Point point((*iter)->get_transform_stack().perform(sub_trans_point));
Point origin((*iter)->get_transform_stack().perform(sub_trans_origin));
point[0]=(point[0]-window_startx)/pw;
point[1]=(point[1]-window_starty)/ph;
- bool has_connect(false);
- if((*iter)->get_tangent() || (*iter)->get_type()&Duck::TYPE_ANGLE)
- {
- has_connect=true;
- }
- if((*iter)->get_connect_duck())
- {
- has_connect=true;
- origin=(*iter)->get_connect_duck()->get_trans_point();
- }
-
origin[0]=(origin[0]-window_startx)/pw;
origin[1]=(origin[1]-window_starty)/ph;
calculated_value_node = ValueNode_BLineCalcTangent::create(ValueBase::TYPE_VECTOR);
else if (link_name == "width")
calculated_value_node = ValueNode_BLineCalcWidth::create(ValueBase::TYPE_REAL);
+ else if (link_name == "point")
+ calculated_value_node = ValueNode_BLineCalcVertex::create(ValueBase::TYPE_VECTOR);
else
{
synfig::warning("can't link '%s'", link_name.c_str());
#include <synfig/valuenode_composite.h>
#include <synfig/valuenode_radialcomposite.h>
#include <synfig/valuenode_reference.h>
+#include <synfig/valuenode_blinecalcvertex.h>
#include <map>
#include "general.h"
|| ValueNode_Composite::Handle::cast_dynamic(value_node)
|| ValueNode_RadialComposite::Handle::cast_dynamic(value_node)
|| ValueNode_Reference::Handle::cast_dynamic(value_node)
+ || ValueNode_BLineCalcVertex::Handle::cast_dynamic(value_node)
)
return true;
return false;