Fix 1679790: draw tool: extending transformed blines. Most of the required code...
[synfig.git] / synfig-studio / trunk / src / gtkmm / state_draw.cpp
index 76be3dc..8a0a1fe 100644 (file)
@@ -671,53 +671,24 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
        // Create the action group
        synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch BLine"));
 
-       //ValueNode_BLine::Handle value_node(ValueNode_BLine::create(synfig::ValueBase(bline,loop_bline_flag)));
-       ValueNode_BLine::Handle value_node;
-
-       {
-               std::list<synfig::BLinePoint> trans_bline;
-               std::list<synfig::BLinePoint>::iterator iter;
-               const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-
-               for(iter=bline.begin();iter!=bline.end();++iter)
-               {
-                       BLinePoint bline_point(*iter);
-                       Point new_vertex(transform.unperform(bline_point.get_vertex()));
-
-                       bline_point.set_tangent1(
-                               transform.unperform(
-                                       bline_point.get_tangent1()+bline_point.get_vertex()
-                               ) -new_vertex
-                       );
-
-                       bline_point.set_tangent2(
-                               transform.unperform(
-                                       bline_point.get_tangent2()+bline_point.get_vertex()
-                               ) -new_vertex
-                       );
-
-                       bline_point.set_vertex(new_vertex);
-
-                       trans_bline.push_back(bline_point);
-               }
-               value_node=ValueNode_BLine::create(synfig::ValueBase(trans_bline,loop_bline_flag));
-       }
+       bool shift_offset = false;
+       Vector shift_offset_vector;
+       bool join_start_no_extend=false,join_finish_no_extend=false;
+       synfigapp::ValueDesc start_duck_value_desc,finish_duck_value_desc;
+       bool extend_start=false,extend_finish=false,complete_loop=false;
+       bool extend_start_join_same=false,extend_start_join_different=false;
+       bool extend_finish_join_same=false,extend_finish_join_different=false;
+       int start_duck_index,finish_duck_index;
+       ValueNode_BLine::Handle start_duck_value_node_bline=NULL,finish_duck_value_node_bline=NULL;
 
        // Find any ducks at the start or end that we might attach to
        // (this used to only run if we aren't a loop - ie. !loop_bline_flag
        // but having loops auto-connect can be useful as well)
        if(get_auto_connect_flag())
        {
-               bool extend_start=false,extend_finish=false,complete_loop=false;
-               bool extend_start_join_same=false,extend_start_join_different=false,extend_finish_join_same=false,extend_finish_join_different=false;
-               int start_duck_index,finish_duck_index;
-
                etl::handle<Duck> start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX));
                etl::handle<Duck> finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX));
 
-               synfigapp::ValueDesc start_duck_value_desc,finish_duck_value_desc;
-               ValueNode_BLine::Handle start_duck_value_node_bline=NULL,finish_duck_value_node_bline=NULL;
-
                // check whether the start of the new line extends an
                // existing line.  this is only the case if the new
                // line isn't a self-contained loop, and if the new
@@ -733,7 +704,11 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                        // don't extend looped blines
                        if(start_duck_value_node_bline&&!start_duck_value_node_bline->get_loop()&&
                           (start_duck_index==0||start_duck_index==start_duck_value_node_bline->link_count()-1))
+                       {
                                extend_start=true;
+                               shift_offset=true;
+                               shift_offset_vector=start_duck->get_origin();
+                       }
                }while(0);
 
                // check whether the end of the new line extends an
@@ -758,8 +733,11 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                                        // of the same bline, only extend the one we started on
                                        if(start_duck_value_node_bline==finish_duck_value_node_bline)
                                                complete_loop=extend_finish=true;
-                               }else
+                               }else{
                                        extend_finish=true;
+                                       shift_offset=true;
+                                       shift_offset_vector=finish_duck->get_origin();
+                               }
                }while(0);
 
                // if the new line's start didn't extend an existing line,
@@ -771,6 +749,10 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                                start_duck_value_desc=synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_desc.get_value_node()),0);
                                // fall through
                        case synfig::ValueBase::TYPE_VECTOR:
+                               if (shift_offset && shift_offset_vector != start_duck->get_origin())
+                                       break;
+                               shift_offset = true;
+                               shift_offset_vector = start_duck->get_origin();
                                get_canvas_interface()->auto_export(start_duck_value_desc);
                                if (extend_finish)
                                        if(start_duck_value_node_bline&&start_duck_value_node_bline==finish_duck_value_node_bline)
@@ -778,8 +760,7 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                                        else
                                                extend_finish_join_different=true;
                                else
-                                       LinkableValueNode::Handle::cast_dynamic(value_node->list.front().value_node)->
-                                         set_link(0,start_duck_value_desc.get_value_node());
+                                       join_start_no_extend=true;
                                // fall through
                        default:break;
                        }
@@ -794,6 +775,10 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                                finish_duck_value_desc=synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_desc.get_value_node()),0);
                                // fall through
                        case synfig::ValueBase::TYPE_VECTOR:
+                               if (shift_offset && shift_offset_vector != finish_duck->get_origin())
+                                       break;
+                               shift_offset = true;
+                               shift_offset_vector = finish_duck->get_origin();
                                get_canvas_interface()->auto_export(finish_duck_value_desc);
                                if(extend_start)
                                        if(finish_duck_value_node_bline&&start_duck_value_node_bline==finish_duck_value_node_bline)
@@ -801,74 +786,115 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                                        else
                                                extend_start_join_different=true;
                                else
-                                       LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)->
-                                         set_link(0,finish_duck_value_desc.get_value_node());
+                                       join_finish_no_extend=true;
                                // fall through
                        default:break;
                        }
+       }
 
-               Smach::event_result result;
-               synfig::ValueNode_DynamicList::ListEntry source;
-               int target_index;
+       ValueNode_BLine::Handle value_node;
+       std::list<synfig::BLinePoint> trans_bline;
 
-               // the new line's start extends an existing line
-               if(extend_start)
+       {
+               std::list<synfig::BLinePoint>::iterator iter;
+               const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+
+               for(iter=bline.begin();iter!=bline.end();++iter)
                {
-                       if(complete_loop)bline.pop_back();
-                       bline.pop_front();
-                       if(start_duck_index==0)
-                       {       // We need to reverse the BLine first.
-                               reverse_bline(bline);
-                               result=extend_bline_from_begin(start_duck_value_node_bline,bline,complete_loop);
-                               source=start_duck_value_node_bline->list.front();
-                               target_index=bline.size()+finish_duck_index;
-                       }
-                       else
-                       {
-                               result=extend_bline_from_end(start_duck_value_node_bline,bline,complete_loop);
-                               source=start_duck_value_node_bline->list.back();
-                               target_index=finish_duck_index;
-                       }
+                       BLinePoint bline_point(*iter);
+                       Point new_vertex(transform.unperform(bline_point.get_vertex()));
+
+                       bline_point.set_tangent1(
+                               transform.unperform(
+                                       bline_point.get_tangent1()+bline_point.get_vertex()
+                               ) -new_vertex
+                       );
+
+                       bline_point.set_tangent2(
+                               transform.unperform(
+                                       bline_point.get_tangent2()+bline_point.get_vertex()
+                               ) -new_vertex
+                       );
+
+                       if (shift_offset)
+                               new_vertex=new_vertex-shift_offset_vector;
+
+                       bline_point.set_vertex(new_vertex);
+
+                       trans_bline.push_back(bline_point);
+               }
+               value_node=ValueNode_BLine::create(synfig::ValueBase(trans_bline,loop_bline_flag));
+       }
+
+       Smach::event_result result;
+       synfig::ValueNode_DynamicList::ListEntry source;
+       int target_index;
 
-                       if(extend_start_join_different)
-                               LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                                 set_link(0,finish_duck_value_desc.get_value_node());
-                       else if(extend_start_join_same)
-                               LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                                 set_link(0,synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_node_bline->
-                                                                                                         list[target_index].value_node),0).get_value_node());
-                       return result;
+       // the new line's start extends an existing line
+       if(extend_start)
+       {
+               if(complete_loop)trans_bline.pop_back();
+               trans_bline.pop_front();
+               if(start_duck_index==0)
+               {       // We need to reverse the BLine first.
+                       reverse_bline(trans_bline);
+                       result=extend_bline_from_begin(start_duck_value_node_bline,trans_bline,complete_loop);
+                       source=start_duck_value_node_bline->list.front();
+                       target_index=trans_bline.size()+finish_duck_index;
+               }
+               else
+               {
+                       result=extend_bline_from_end(start_duck_value_node_bline,trans_bline,complete_loop);
+                       source=start_duck_value_node_bline->list.back();
+                       target_index=finish_duck_index;
                }
 
-               // the new line's end extends an existing line
-               if(extend_finish)
-               {       // SPECIAL CASE -- EXTENSION
-                       bline.pop_back();
-                       if(finish_duck_index==0)
-                       {
-                               result=extend_bline_from_begin(finish_duck_value_node_bline,bline,false);
-                               source=finish_duck_value_node_bline->list.front();
-                               target_index=bline.size()+start_duck_index;
-                       }
-                       else
-                       {       // We need to reverse the BLine first.
-                               reverse_bline(bline);
-                               result=extend_bline_from_end(finish_duck_value_node_bline,bline,false);
-                               source=finish_duck_value_node_bline->list.back();
-                               target_index=start_duck_index;
-                       }
+               if(extend_start_join_different)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link(0,finish_duck_value_desc.get_value_node());
+               else if(extend_start_join_same)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link(0,synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_node_bline->
+                                                                                                       list[target_index].value_node),0).get_value_node());
+               return result;
+       }
 
-                       if(extend_finish_join_different)
-                               LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                                 set_link(0,start_duck_value_desc.get_value_node());
-                       else if(extend_finish_join_same)
-                               LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                                 set_link(0,synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_node_bline->
-                                                                                                         list[target_index].value_node),0).get_value_node());
-                       return result;
+       // the new line's end extends an existing line
+       if(extend_finish)
+       {       // SPECIAL CASE -- EXTENSION
+               trans_bline.pop_back();
+               if(finish_duck_index==0)
+               {
+                       result=extend_bline_from_begin(finish_duck_value_node_bline,trans_bline,false);
+                       source=finish_duck_value_node_bline->list.front();
+                       target_index=trans_bline.size()+start_duck_index;
                }
+               else
+               {       // We need to reverse the BLine first.
+                       reverse_bline(trans_bline);
+                       result=extend_bline_from_end(finish_duck_value_node_bline,trans_bline,false);
+                       source=finish_duck_value_node_bline->list.back();
+                       target_index=start_duck_index;
+               }
+
+               if(extend_finish_join_different)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link(0,start_duck_value_desc.get_value_node());
+               else if(extend_finish_join_same)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link(0,synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_node_bline->
+                                                                                                       list[target_index].value_node),0).get_value_node());
+               return result;
        }
 
+       if (join_start_no_extend)
+               LinkableValueNode::Handle::cast_dynamic(value_node->list.front().value_node)->
+                 set_link(0,start_duck_value_desc.get_value_node());
+
+       if (join_finish_no_extend)
+               LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)->
+                 set_link(0,finish_duck_value_desc.get_value_node());
+
        // Create the layer
        {
                Layer::Handle layer;
@@ -901,7 +927,9 @@ StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline
                //layer->set_description(strprintf("Stroke %d",number));
                //get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
 
-
+               if (shift_offset)
+                       get_canvas_interface()->
+                         change_value(synfigapp::ValueDesc(layer,"offset"),shift_offset_vector);
 
                synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
 
@@ -1284,10 +1312,8 @@ StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,st
        }
 
        std::list<synfig::BLinePoint>::reverse_iterator iter;
-       iter=bline.rbegin();
-       for(;!(iter==bline.rend());++iter)
+       for(iter=bline.rbegin();!(iter==bline.rend());++iter)
        {
-               //iter->reverse();
                ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter));
 
                synfigapp::Action::Handle action(synfigapp::Action::create("value_node_dynamic_list_insert"));
@@ -1337,8 +1363,7 @@ StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std:
        }
 
        std::list<synfig::BLinePoint>::iterator iter;
-       iter=bline.begin();
-       for(;iter!=bline.end();++iter)
+       for(iter=bline.begin();iter!=bline.end();++iter)
        {
                ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter));