From 80031a8a28bb53f89ad750ec94a1b447b419d616 Mon Sep 17 00:00:00 2001 From: dooglus Date: Fri, 28 Mar 2008 08:51:12 +0000 Subject: [PATCH] Accept 1927294: Patch from Gerald Young to allow intuitive editing of the BLinePoint ValueNode's "Amount" parameter by dragging the duck in the workarea. git-svn-id: http://svn.voria.com/code@1929 1f10aa63-cdf2-0310-b900-c93c546f37ac --- synfig-core/trunk/src/synfig/valuenode_bline.cpp | 113 +++++++++++++++++++++ synfig-core/trunk/src/synfig/valuenode_bline.h | 3 + synfig-studio/trunk/src/gtkmm/canvasview.cpp | 16 +++ synfig-studio/trunk/src/gtkmm/duckmatic.cpp | 4 - synfig-studio/trunk/src/gtkmm/renderer_ducks.cpp | 90 +++++++++++++--- .../src/synfigapp/actions/valuedescblinelink.cpp | 2 + synfig-studio/trunk/src/synfigapp/instance.cpp | 2 + 7 files changed, 211 insertions(+), 19 deletions(-) diff --git a/synfig-core/trunk/src/synfig/valuenode_bline.cpp b/synfig-core/trunk/src/synfig/valuenode_bline.cpp index 366c301..49e9cb5 100644 --- a/synfig-core/trunk/src/synfig/valuenode_bline.cpp +++ b/synfig-core/trunk/src/synfig/valuenode_bline.cpp @@ -42,6 +42,7 @@ #include #include #include "segment.h" +#include "curve_helper.h" #endif @@ -163,6 +164,118 @@ synfig::convert_bline_to_width_list(const ValueBase& bline) 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 list(bline.get_list().begin(),bline.get_list().end()); + typedef std::vector::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 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 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 ======================================================= */ diff --git a/synfig-core/trunk/src/synfig/valuenode_bline.h b/synfig-core/trunk/src/synfig/valuenode_bline.h index a203fc8..c884908 100644 --- a/synfig-core/trunk/src/synfig/valuenode_bline.h +++ b/synfig-core/trunk/src/synfig/valuenode_bline.h @@ -49,6 +49,9 @@ ValueBase convert_bline_to_segment_list(const ValueBase &bline); //! 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 */ diff --git a/synfig-studio/trunk/src/gtkmm/canvasview.cpp b/synfig-studio/trunk/src/gtkmm/canvasview.cpp index ed139af..8c0f3b7 100644 --- a/synfig-studio/trunk/src/gtkmm/canvasview.cpp +++ b/synfig-studio/trunk/src/gtkmm/canvasview.cpp @@ -53,6 +53,8 @@ #include #include #include +#include +#include #include #include @@ -2583,6 +2585,20 @@ CanvasView::duck_change_param(const synfig::Point &value,synfig::Layer::Handle l 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: diff --git a/synfig-studio/trunk/src/gtkmm/duckmatic.cpp b/synfig-studio/trunk/src/gtkmm/duckmatic.cpp index cfdb9cd..7366ebc 100644 --- a/synfig-studio/trunk/src/gtkmm/duckmatic.cpp +++ b/synfig-studio/trunk/src/gtkmm/duckmatic.cpp @@ -1435,7 +1435,6 @@ Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handleset_value_desc(synfigapp::ValueDesc(value_node,i)); if(param_desc) { @@ -1565,7 +1564,6 @@ Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handleset_value_desc(synfigapp::ValueDesc(value_node,i)); add_bezier(bezier); bezier=0; @@ -1622,7 +1620,6 @@ Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handleset_value_desc(synfigapp::ValueDesc(value_node,i)); } @@ -1690,7 +1687,6 @@ Duckmatic::add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handleset_value_desc(synfigapp::ValueDesc(value_node,first)); add_bezier(bezier); bezier=0; diff --git a/synfig-studio/trunk/src/gtkmm/renderer_ducks.cpp b/synfig-studio/trunk/src/gtkmm/renderer_ducks.cpp index d5bc6ce..8c3dd3e 100644 --- a/synfig-studio/trunk/src/gtkmm/renderer_ducks.cpp +++ b/synfig-studio/trunk/src/gtkmm/renderer_ducks.cpp @@ -37,6 +37,8 @@ #include #include "widget_color.h" #include +#include +#include #include "app.h" #include "general.h" @@ -58,6 +60,45 @@ using namespace studio; /* === M E T H O D S ======================================================= */ +bool +restrict_blinevertex_duck(etl::handle duck, WorkArea& w_area, synfig::Point *point) +{ + synfig::Point sub_trans_origin(duck->get_sub_trans_origin()); + etl::handle 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() { } @@ -140,11 +181,22 @@ Renderer_Ducks::render_vfunc( // Render the beziers for(std::list >::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; @@ -211,6 +263,20 @@ Renderer_Ducks::render_vfunc( // Gdk::Rectangle area; Point sub_trans_point((*iter)->get_sub_trans_point()); Point sub_trans_origin((*iter)->get_sub_trans_origin()); + etl::handle 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()) @@ -221,23 +287,17 @@ Renderer_Ducks::render_vfunc( 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; diff --git a/synfig-studio/trunk/src/synfigapp/actions/valuedescblinelink.cpp b/synfig-studio/trunk/src/synfigapp/actions/valuedescblinelink.cpp index 1c21040..3c1487d 100644 --- a/synfig-studio/trunk/src/synfigapp/actions/valuedescblinelink.cpp +++ b/synfig-studio/trunk/src/synfigapp/actions/valuedescblinelink.cpp @@ -189,6 +189,8 @@ Action::ValueDescBLineLink::prepare() 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()); diff --git a/synfig-studio/trunk/src/synfigapp/instance.cpp b/synfig-studio/trunk/src/synfigapp/instance.cpp index cb2f681..bede03a 100644 --- a/synfig-studio/trunk/src/synfigapp/instance.cpp +++ b/synfig-studio/trunk/src/synfigapp/instance.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "general.h" @@ -67,6 +68,7 @@ synfigapp::is_editable(synfig::ValueNode::Handle value_node) || 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; -- 2.7.4