X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Ftrunk%2Fsrc%2Fgtkmm%2Fstate_draw.cpp;h=9c551932122b82ce980700cffc1cd162da6a5c5d;hb=4ba22fb51d97f1ecce04dcc5e40569a4354c1bae;hp=e00baa38fa88663cf471af9d2a57b7968cad8311;hpb=6784db1651239a30b80f9b798663a55c1450242f;p=synfig.git diff --git a/synfig-studio/trunk/src/gtkmm/state_draw.cpp b/synfig-studio/trunk/src/gtkmm/state_draw.cpp index e00baa3..9c55193 100644 --- a/synfig-studio/trunk/src/gtkmm/state_draw.cpp +++ b/synfig-studio/trunk/src/gtkmm/state_draw.cpp @@ -62,6 +62,8 @@ #include #include +#include "general.h" + #endif /* === U S I N G =========================================================== */ @@ -97,7 +99,7 @@ class studio::StateDraw_Context : public sigc::trackable bool prev_workarea_layer_status_; int nested; - SigC::Connection process_queue_connection; + sigc::connection process_queue_connection; ValueNode_BLine::Handle last_stroke; synfig::String last_stroke_id; @@ -113,6 +115,7 @@ class studio::StateDraw_Context : public sigc::trackable Duckmatic::Type old_duckmask; void fill_last_stroke(); + Smach::event_result fill_last_stroke_and_unselect_other_layers(); Smach::event_result new_bline(std::list bline,bool loop_bline_flag,float radius); @@ -366,12 +369,15 @@ StateDraw_Context::increment_id() if(id[id.size()-1]<='9' && id[id.size()-1]>='0') { // figure out how many digits it is - for(digits=0;(int)id.size()-1>=digits && id[id.size()-1-digits]<='9' && id[id.size()-1-digits]>='0';digits++)while(false); + for (digits = 0; + (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0'; + digits++) + ; String str_number; str_number=String(id,id.size()-digits,id.size()); id=String(id,0,id.size()-digits); - synfig::info("---------------- \"%s\"",str_number.c_str()); + // synfig::info("---------------- \"%s\"",str_number.c_str()); number=atoi(str_number.c_str()); } @@ -404,8 +410,8 @@ StateDraw_Context::StateDraw_Context(CanvasView* canvas_view): checkbutton_auto_loop(_("Auto Loop")), checkbutton_auto_extend(_("Auto Extend")), checkbutton_auto_link(_("Auto Link")), - checkbutton_region(_("Create Region")), - checkbutton_outline(_("Create Outline")), + checkbutton_region(_("Create Region BLine")), + checkbutton_outline(_("Create Outline BLine")), checkbutton_auto_export(_("Auto Export")), button_fill_last_stroke(_("Fill Last Stroke")), adj_min_pressure(0,0,1,0.01,0.1), @@ -419,32 +425,30 @@ StateDraw_Context::StateDraw_Context(CanvasView* canvas_view): check_localerror(_("LocalError")) { - synfig::info("STATE SKETCH: entering state"); - nested=0; load_settings(); UpdateErrorBox(); - //options_table.attach(*manage(new Gtk::Label(_("Draw Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(entry_id, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_region, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_auto_loop, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_auto_extend, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_auto_link, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_auto_export, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_pressure_width, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(check_localerror, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Draw Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(entry_id, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_outline, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_region, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_auto_loop, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_auto_extend, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_auto_link, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_auto_export, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_pressure_width, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(check_localerror, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(check_min_pressure, 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_min_pressure, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(check_min_pressure, 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_min_pressure, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("Smooth"))), 0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_globalthres, 1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Smooth"))), 0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_globalthres, 1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("Feather"))), 0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_feather, 1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Feather"))), 0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_feather, 1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); //options_table.attach(button_fill_last_stroke, 0, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); @@ -521,10 +525,7 @@ StateDraw_Context::refresh_tool_options() )->signal_clicked().connect( sigc::mem_fun( *this, - &StateDraw_Context::fill_last_stroke - ) - ); - + &StateDraw_Context::fill_last_stroke)); } Smach::event_result @@ -588,9 +589,6 @@ StateDraw_Context::event_mouse_down_handler(const Smach::event& x) return Smach::RESULT_ACCEPT; } - case BUTTON_RIGHT: // Intercept the right-button click to short-circuit the pop-up menu - return Smach::RESULT_ACCEPT; - default: return Smach::RESULT_OK; } @@ -712,14 +710,16 @@ StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, } // If the start and end points are similar, then make them the same point - if(get_auto_loop_flag() && - bline.size()>2&&(bline.front().get_vertex()-bline.back().get_vertex()).mag()<=radius) + if (get_auto_loop_flag() && + bline.size() > 2 && + (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius) { loop_bline_flag=true; Vector tangent; Real width(0); - while(bline.size()>2&&(bline.front().get_vertex()-bline.back().get_vertex()).mag()<=radius) + while (bline.size() > 2 && + (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius) { tangent=bline.back().get_tangent1(); width=bline.back().get_width(); @@ -749,8 +749,15 @@ StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, } // If the bline only has one blinepoint, then there is nothing to do. - if(bline.size()<=1) + if(bline.size() < 2) + { + // hide the 'stroke' line we were drawing, unless the user + // explicitly requests that they are kept + if (!getenv("SYNFIG_KEEP_ABORTED_DRAW_LINES")) + refresh_ducks(); + return Smach::RESULT_OK; + } if(region_flag) return new_region(bline,radius); @@ -761,11 +768,13 @@ StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, Smach::event_result StateDraw_Context::new_bline(std::list bline,bool loop_bline_flag,float radius) { + synfigapp::SelectionManager::LayerList layer_list = get_canvas_view()->get_selection_manager()->get_selected_layers(); + // Create the action group synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch BLine")); - bool shift_offset = false; - Vector shift_offset_vector; + bool shift_origin = false; + Vector shift_origin_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; @@ -801,8 +810,8 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline (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(); + shift_origin=true; + shift_origin_vector=start_duck->get_origin(); } }while(0); @@ -822,6 +831,7 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline // don't extend looped blines if(finish_duck_value_node_bline&&!finish_duck_value_node_bline->get_loop()&& (finish_duck_index==0||finish_duck_index==finish_duck_value_node_bline->link_count()-1)) + { if(extend_start) { // we've started and finished drawing at the end of a bline. we can't @@ -831,9 +841,10 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline complete_loop=extend_finish=true; }else{ extend_finish=true; - shift_offset=true; - shift_offset_vector=finish_duck->get_origin(); + shift_origin=true; + shift_origin_vector=finish_duck->get_origin(); } + } }while(0); // if the new line's start didn't extend an existing line, @@ -845,10 +856,10 @@ StateDraw_Context::new_bline(std::list 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()) + if (shift_origin && shift_origin_vector != start_duck->get_origin()) break; - shift_offset = true; - shift_offset_vector = start_duck->get_origin(); + shift_origin = true; + shift_origin_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) @@ -870,10 +881,10 @@ StateDraw_Context::new_bline(std::list 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()) + if (shift_origin && shift_origin_vector != finish_duck->get_origin()) break; - shift_offset = true; - shift_offset_vector = finish_duck->get_origin(); + shift_origin = true; + shift_origin_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) @@ -911,14 +922,19 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline ) -new_vertex ); - if (shift_offset) - new_vertex=new_vertex-shift_offset_vector; + if (shift_origin) + new_vertex=new_vertex-shift_origin_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)); + + Canvas::Handle canvas(get_canvas_view()->get_canvas()); + Layer::Handle layer(get_canvas_view()->get_selection_manager()->get_selected_layer()); + if (layer) canvas=layer->get_canvas(); + value_node->set_member_canvas(canvas); } Smach::event_result result; @@ -989,8 +1005,7 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)-> set_link(0,finish_duck_value_desc.get_value_node()); - if(get_auto_export_flag()) { - printf("this is where we would export the new line\n"); + if(get_auto_export_flag()) if (!get_canvas_interface()->add_value_node(value_node,get_id())) { /* it's no big deal, is it? let's keep the shape anyway */ @@ -999,10 +1014,12 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline // increment_id(); // return Smach::RESULT_ERROR; } - } - // Create the layer + last_stroke=value_node; + last_stroke_id=get_id(); + { + // Create the layer(s) Layer::Handle layer; Canvas::Handle canvas(get_canvas_view()->get_canvas()); int depth(0); @@ -1015,6 +1032,20 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline canvas=layer->get_canvas(); } + // fill_last_stroke() will take care of clearing the selection if we're calling it + if(get_outline_flag() && get_region_flag()) + { + if (fill_last_stroke_and_unselect_other_layers() == Smach::RESULT_ERROR) + { + get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return Smach::RESULT_ERROR; + } + } + else + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + //int number(synfig::UniqueID().get_uid()); synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); @@ -1023,11 +1054,25 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline if(get_outline_flag()) { layer=get_canvas_interface()->add_layer_to("outline",canvas,depth); + if (!layer) + { + get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return Smach::RESULT_ERROR; + } layer->set_description(get_id()+_(" Outline")); } else { layer=get_canvas_interface()->add_layer_to("region",canvas,depth); + if (!layer) + { + get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return Smach::RESULT_ERROR; + } layer->set_description(get_id()+_(" Region")); } @@ -1040,11 +1085,11 @@ StateDraw_Context::new_bline(std::list 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) + if (shift_origin) get_canvas_interface()-> - change_value(synfigapp::ValueDesc(layer,"offset"),shift_offset_vector); + change_value(synfigapp::ValueDesc(layer,"origin"),shift_origin_vector); - synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect")); + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); assert(action); @@ -1064,20 +1109,180 @@ StateDraw_Context::new_bline(std::list bline,bool loop_bline //refresh_ducks(); return Smach::RESULT_ERROR; } - get_canvas_view()->get_selection_manager()->set_selected_layer(layer); + layer_list.push_back(layer); + get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); //refresh_ducks(); } - last_stroke=value_node; - last_stroke_id=get_id(); - - if(get_outline_flag() && get_region_flag()) - fill_last_stroke(); - increment_id(); return Smach::RESULT_ACCEPT; } +#ifdef _DEBUG +static void +debug_show_vertex_list(int iteration, std::list& vertex_list, + std::string title, int current) +{ + std::list::iterator i = vertex_list.begin(); + printf("\n%s\n ----- iter %d : ", title.c_str(), iteration); + int c = 0; + synfig::LinkableValueNode::Handle last = 0; + int start = -1; + int index; + int prev; + int dir = 0; + bool started = false; + for(;i!=vertex_list.end();i++,c++) + { + synfigapp::ValueDesc value_desc(*i); + + if (value_desc.parent_is_value_node()) { + if(value_desc.parent_is_linkable_value_node()) + { + index = value_desc.get_index(); + // printf("<%d>", index); + if (last == synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node())) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (start != -1) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (c == current) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (dir) + { + if (started) printf(", "); else started = true; + printf("%d--%d", start, prev); + } + else + { + if (started) printf(", "); else started = true; + printf("%d", start); + } + printf(", *%d*", index); + start = -1; + } + else if (dir == 0) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (index == start + 1) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + dir = 1; + prev = index; + } + else if (index == start - 1) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + dir = -1; + prev = index; + } + else + { + if (started) printf(", "); else started = true; + printf("%d", start); + start = index; + } + } + else if (index == prev + dir) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + prev = index; + } + else + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (started) printf(", "); else started = true; + if (prev != start) + printf("%d--%d", start, prev); + else + printf("%d", start); + // printf("\n%s:%d\n", __FILE__, __LINE__); + start = index; + dir = 0; + } + } + else + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (c == current) + { + if (started) printf(", "); else started = true; + printf("*%d*", index); + } + else + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + start = index; + dir = 0; + } + } + } + else + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (last) + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (start != -1) + { + if (started) printf(", "); else started = true; + if (dir != 0) + printf("%d--%d", start, prev); + else + printf("%d", start); + } + // printf("\n%s:%d\n", __FILE__, __LINE__); + printf(") "); + } + // printf("\n%s:%d\n", __FILE__, __LINE__); + last = synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node()); + printf("%d:(", synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node())->link_count()); + started = false; + // printf("\n%s:%d\n", __FILE__, __LINE__); + if (c == current) + { + start = -1; + printf("*%d*", index); + } + else + { + // printf("\n%s:%d\n", __FILE__, __LINE__); + start = index; + dir = 0; + } + // printf("\n%s:%d\n", __FILE__, __LINE__); + } + // printf("\n%s:%d\n", __FILE__, __LINE__); + } + else if (last) + if (last) printf("?!) "); + } + else + { + last = 0; + printf("? "); + } + } + if (last) + { + if (started) printf(", "); else started = true; + if (start != -1) + { + if (dir != 0) + printf("%d--%d", start, prev); + else + printf("%d", start); + } + printf(")"); + } + printf("\n"); +} +#else // _DEBUG +#define debug_show_vertex_list(a,b,c,d) +#endif // _DEBUG + Smach::event_result StateDraw_Context::new_region(std::list bline, synfig::Real radius) { @@ -1086,6 +1291,8 @@ StateDraw_Context::new_region(std::list bline, synfig::Real std::list vertex_list; + printf("new_region with %zd bline points\n", bline.size()); + // First we need to come up with a rough list of // BLinePoints that we are going to be using to // define our region. @@ -1101,7 +1308,6 @@ StateDraw_Context::new_region(std::list bline, synfig::Real return Smach::RESULT_OK; } - assert(duck->get_type()==Duck::TYPE_VERTEX); synfigapp::ValueDesc value_desc(duck->get_value_desc()); @@ -1126,192 +1332,423 @@ StateDraw_Context::new_region(std::list bline, synfig::Real } } - if(vertex_list.size()<=2) - { - synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__); - return Smach::RESULT_OK; - } - assert(vertex_list.back().is_valid()); + printf("vertex list with %zd bline points\n", vertex_list.size()); + // Remove any duplicates { } - // Now we need to clean the list of vertices up - // a bit. This includes inserting missing vertices - // and removing extraneous ones. - // We can do this in multiple passes. - int i=0; - for(bool done=false;!done && i<30;i++) + ValueNode_BLine::Handle value_node_bline; + + // Now we need to test for the trivial case, + // which is where all of the vertices + // come from one BLine. + if(vertex_list.front().parent_is_linkable_value_node()) { - // Set done to "true" for now. If - // any updates are performed, we will - // change it back to false. - done=true; + bool trivial_case(true); + ValueNode::Handle trivial_case_value_node; - std::list::iterator prev,iter,next; - prev=vertex_list.end();prev--; // Set prev to the last ValueDesc - next=vertex_list.begin(); - iter=next++; // Set iter to the first value desc, and next to the second + trivial_case_value_node=vertex_list.front().get_parent_value_node(); - for(;iter!=vertex_list.end();prev=iter,iter=next++) + std::list::iterator iter; + for(iter=vertex_list.begin();iter!=vertex_list.end();++iter) { - synfigapp::ValueDesc value_prev(*prev); - synfigapp::ValueDesc value_desc(*iter); - synfigapp::ValueDesc value_next((next==vertex_list.end())?vertex_list.front():*next); + if(trivial_case_value_node!=iter->get_parent_value_node()) + { + trivial_case=false; + break; + } + } - assert(value_desc.is_valid()); - assert(value_next.is_valid()); - assert(value_prev.is_valid()); + // \todo - re-enable this code + if(trivial_case && false) + { + synfig::info("all points are on the same bline, so just fill that line"); + value_node_bline=ValueNode_BLine::Handle::cast_dynamic(trivial_case_value_node); - //synfig::info("-------"); - //synfig::info(__FILE__":%d: value_prev 0x%08X:%d",__LINE__,value_prev.get_parent_value_node().get(),value_prev.get_index()); - //synfig::info(__FILE__":%d: value_desc 0x%08X:%d",__LINE__,value_desc.get_parent_value_node().get(),value_desc.get_index()); - //synfig::info(__FILE__":%d: value_next 0x%08X:%d",__LINE__,value_next.get_parent_value_node().get(),value_next.get_index()); + synfig::info("the line has %d vertices", value_node_bline->link_count()); - /* - if(value_prev.parent_is_value_node() && value_desc.parent_is_value_node() && value_next.parent_is_value_node()) + if(value_node_bline->link_count() <= 2) { - // Remove random extraneous vertices - if(value_prev.get_parent_value_node()==value_next.get_parent_value_node() && - value_prev.get_parent_value_node()!=value_desc.get_parent_value_node()) - { - DEBUGPOINT(); - vertex_list.erase(iter); - done=false; - break; - } + synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__); + return Smach::RESULT_OK; } - */ + } + } + + if(!value_node_bline) + if(vertex_list.size()<=2) + { + synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__); + return Smach::RESULT_OK; + } - // Remove duplicate vertices - if(value_prev.get_value_node()==value_desc.get_value_node() || - value_desc.get_value_node()==value_next.get_value_node()) + // Now we need to clean the list of vertices up + // a bit. This includes inserting missing vertices + // and removing extraneous ones. + // We can do this in multiple passes. + if(!value_node_bline) + { + debug_show_vertex_list(0, vertex_list, "before shifting stuff", -1); + // rearrange the list so that the first and last node are on different blines + std::list::iterator iter, start; + ValueNode::Handle last_value_node = vertex_list.back().get_parent_value_node(); + for(iter = vertex_list.begin(); iter!=vertex_list.end(); iter++) + if (iter->get_parent_value_node() != last_value_node) { - DEBUGPOINT(); - vertex_list.erase(iter); - done=false; + vertex_list.insert(vertex_list.end(), vertex_list.begin(), iter); + vertex_list.erase(vertex_list.begin(), iter); break; } - if(value_prev.get_value_node()==value_next.get_value_node()) + + debug_show_vertex_list(0, vertex_list, "before detecting direction and limits", -1); + // rearrange the list so that the first and last node are on different blines + iter = vertex_list.begin(); + while (iter!=vertex_list.end()) + { + // make a note of which bline we're looking at + ValueNode::Handle parent_value_node = iter->get_parent_value_node(); + start = iter; + int points_in_line = synfig::LinkableValueNode::Handle::cast_reinterpret(parent_value_node)->link_count(); + bool looped = (*parent_value_node)(get_time()).get_loop(); + int this_index, last_index = iter->get_index(); + int min_index = last_index, max_index = last_index; + bool whole; + int direction = 0; + + // printf("there are %d points in this line - first is index %d\n", points_in_line, last_index); + + // while we're looking at the same bline, keep going + iter++; + while (iter != vertex_list.end() && iter->get_parent_value_node() == parent_value_node) { - DEBUGPOINT(); - vertex_list.erase(prev); - done=false; - break; + this_index = iter->get_index(); + // printf("index went from %d to %d\n", last_index, this_index); + if (looped) + { + if (this_index - last_index > points_in_line/2) + while (this_index - last_index > points_in_line/2) + this_index -= points_in_line; + else if (last_index - this_index > points_in_line/2) + while (last_index - this_index > points_in_line/2) + this_index += points_in_line; + } + + if (this_index < min_index) min_index = this_index; + if (this_index > max_index) max_index = this_index; + + // printf("so let's imagine index went from %d to %d\n", last_index, this_index); + if (this_index > last_index) + direction++; + else if (this_index < last_index) + direction--; + + last_index = this_index; + iter++; } - if (value_desc.parent_is_value_node() && value_next.parent_is_value_node()) + // printf("min %d and max %d\n", min_index, max_index); + whole = max_index - min_index >= points_in_line; + min_index = (min_index % points_in_line + points_in_line) % points_in_line; + max_index = (max_index % points_in_line + points_in_line) % points_in_line; + // they drew around a shape more than once - what's the start/end point? does it matter? + if (whole) min_index = max_index = (min_index + max_index) / 2; + // printf("processed min %d max %d whole %d\n", min_index, max_index, whole); + + if (direction < 0) { - if (value_desc.get_parent_value_node() == value_next.get_parent_value_node()) + if (whole) { - if (next != vertex_list.end()) + // printf("whole (down) (%d) ", min_index); + for (int i = min_index; i >= 0; i--) { - // Fill in missing vertices - if(value_desc.get_index()= min_index; i--) + { + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); } } - // Ensure that connections between blines are properly connected - else if (value_desc.get_value_node() != value_next.get_value_node()) + else { - BLinePoint vertex(value_desc.get_value(get_time()).get(BLinePoint())); - BLinePoint vertex_next(value_next.get_value(get_time()).get(BLinePoint())); - - //synfig::info("--------"); - //synfig::info(__FILE__":%d: vertex: [%f, %f]",__LINE__,vertex.get_vertex()[0],vertex.get_vertex()[1]); - //synfig::info(__FILE__":%d: vertex_next: [%f, %f]",__LINE__,vertex_next.get_vertex()[0],vertex_next.get_vertex()[1]); - - if((vertex.get_vertex()-vertex_next.get_vertex()).mag_squared() %d) ", max_index, min_index); + for (int i = max_index; i != min_index; i--) { - DEBUGPOINT(); - ValueNode_Composite::Handle value_node; - ValueNode_Composite::Handle value_node_next; - value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node().clone()); - value_node_next=ValueNode_Composite::Handle::cast_dynamic(value_next.get_value_node().clone()); - if(!value_node || !value_node_next) - { - synfig::info(__FILE__":%d: Unable to properly connect blines.",__LINE__); - continue; - } - DEBUGPOINT(); - value_node->set_link(5,value_node_next->get_link(5)); - value_node->set_link(3,ValueNode_Const::create(true)); - - get_canvas_interface()->auto_export(value_node); - assert(value_node->is_exported()); - *iter=synfigapp::ValueDesc(get_canvas(),value_node->get_id()); - vertex_list.erase(next); - done=false; - break; + if (i == -1) i = points_in_line - 1; + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); } - else + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, min_index)); + } + } + else + { + if (whole) + { + // printf("whole (%d) ", min_index); + for (int i = min_index; i < points_in_line; i++) { - DEBUGPOINT(); - bool positive_trend(value_desc.get_index()>value_prev.get_index()); - - if(!positive_trend && value_desc.get_index()>0) - { - DEBUGPOINT(); - vertex_list.insert(next,synfigapp::ValueDesc(value_desc.get_parent_value_node(),value_desc.get_index()-1)); - done=false; - break; - } - if(positive_trend && value_desc.get_index()link_count()-1) - { - DEBUGPOINT(); - vertex_list.insert(next,synfigapp::ValueDesc(value_desc.get_parent_value_node(),value_desc.get_index()+1)); - done=false; - break; - } + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); + } + for (int i = 0; i <= min_index; i++) + { + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); } } + else + { + // printf("part (%d -> %d) ", min_index, max_index); + for (int i = min_index; i != max_index; i++) + { + if (i == points_in_line) i = 0; + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); + } + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, max_index)); + } } + // printf("\n"); + // debug_show_vertex_list(0, vertex_list, "after insert", -1); + vertex_list.erase(start, iter); + // debug_show_vertex_list(0, vertex_list, "after delete", -1); } - } - if(vertex_list.size()<=2) - { - synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__); - return Smach::RESULT_OK; - } + debug_show_vertex_list(0, vertex_list, "continuous vertices", -1); - ValueNode_BLine::Handle value_node_bline; + // \todo reenable or delete this section + int i=100; + for(bool done=false;!done && i<30;i++) + { + debug_show_vertex_list(i, vertex_list, "in big loop", -1); - // Now we need to test for the trivial case, - // which is where all of the vertices - // come from one BLine. - if(vertex_list.front().parent_is_linkable_value_node()) - { - bool trivial_case(true); - ValueNode::Handle trivial_case_value_node; + // Set done to "true" for now. If + // any updates are performed, we will + // change it back to false. + done=true; - trivial_case_value_node=vertex_list.front().get_parent_value_node(); + std::list::iterator prev,next; + prev=vertex_list.end();prev--; // Set prev to the last ValueDesc + next=vertex_list.begin(); + iter=next++; // Set iter to the first value desc, and next to the second - std::list::iterator iter; - for(iter=vertex_list.begin();iter!=vertex_list.end();++iter) - { - if(trivial_case_value_node!=iter->get_parent_value_node()) + int current = 0; + for(;iter!=vertex_list.end();prev=iter,iter++,next++,current++) { - trivial_case=false; - break; + // we need to be able to erase(next) and can't do that if next is end() + if (next == vertex_list.end()) next = vertex_list.begin(); + debug_show_vertex_list(i, vertex_list, "in loop around vertices", current); + synfigapp::ValueDesc value_prev(*prev); + synfigapp::ValueDesc value_desc(*iter); + synfigapp::ValueDesc value_next(*next); + + assert(value_desc.is_valid()); + assert(value_next.is_valid()); + assert(value_prev.is_valid()); + + // synfig::info("-------"); + // synfig::info(__FILE__":%d: value_prev 0x%08X:%d",__LINE__,value_prev.get_parent_value_node().get(),value_prev.get_index()); + // synfig::info(__FILE__":%d: value_desc 0x%08X:%d",__LINE__,value_desc.get_parent_value_node().get(),value_desc.get_index()); + // synfig::info(__FILE__":%d: value_next 0x%08X:%d",__LINE__,value_next.get_parent_value_node().get(),value_next.get_index()); + + /* + if(value_prev.parent_is_value_node() && value_desc.parent_is_value_node() && value_next.parent_is_value_node()) + { + // Remove random extraneous vertices + if(value_prev.get_parent_value_node()==value_next.get_parent_value_node() && + value_prev.get_parent_value_node()!=value_desc.get_parent_value_node()) + { + vertex_list.erase(iter); + done=false; + break; + } + } + */ + + // // Remove duplicate vertices + + // // if previous is the same as current or + // // current is the same as next, remove current + // if(value_prev.get_value_node()==value_desc.get_value_node() || + // value_desc.get_value_node()==value_next.get_value_node()) + // { + // vertex_list.erase(iter); + // done=false; + // printf("erased node - i = %d\n", i); + // break; + // } + + // // if previous is the same as next, remove previous? or next? + // if(value_prev.get_value_node()==value_next.get_value_node()) + // { + // vertex_list.erase(next); + // // vertex_list.erase(prev); + // done=false; + // printf("erased node - i = %d\n", i); + // break; + // } + + // if 'this' and 'next' both have parents + if (value_desc.parent_is_value_node() && value_next.parent_is_value_node()) + { + // if they are both on the same bline - this has been handled by new code above + if (value_desc.get_parent_value_node() == value_next.get_parent_value_node()) + { + // // if (next != vertex_list.end()) + // { + // printf("parent loop is %d and node loop is ??\n", + // (*(value_desc.get_parent_value_node()))(get_time()).get_loop() + // // value_desc.get_value_node().get_loop(), + // ); + // + // // Fill in missing vertices + // // \todo take loops into account: seeing (15, 2, 3, 4) probably means that (0, 1) is missing, not 14 through 3 + // if(value_desc.get_index() value_next.get_index(); index--) + // { + // printf("inserting down %d\n", index); + // vertex_list.insert(next, synfigapp::ValueDesc(value_desc.get_parent_value_node(), index)); + // } + // debug_show_vertex_list(i, vertex_list, "new list", current); + // done=false; + // break; + // } + // } + } + // 'this' and 'next' have different parents + else + { + ValueNode::Handle v1 = value_desc.get_value_node(); + ValueNode::Handle v2 = value_desc.get_parent_value_node(); + if (v1 == v2) + printf("same\n"); + else + printf("different\n"); + + if (value_desc.get_value_node() != value_next.get_value_node()) + { + // Ensure that connections between blines are properly connected + BLinePoint vertex(value_desc.get_value(get_time()).get(BLinePoint())); + BLinePoint vertex_next(value_next.get_value(get_time()).get(BLinePoint())); + + //synfig::info("--------"); + //synfig::info(__FILE__":%d: vertex: [%f, %f]",__LINE__,vertex.get_vertex()[0],vertex.get_vertex()[1]); + //synfig::info(__FILE__":%d: vertex_next: [%f, %f]",__LINE__,vertex_next.get_vertex()[0],vertex_next.get_vertex()[1]); + + // if this vertex is close to the next one, replace this vertex with a new one + // and erase the next one + printf("this point is %5.2f from the next point - compare with %5.2f\n", + (vertex.get_vertex()-vertex_next.get_vertex()).mag_squared(), + radius*radius); + if((vertex.get_vertex()-vertex_next.get_vertex()).mag_squared()set_link(5,value_node_next->get_link(5)); // Tangent 2 + value_node->set_link(3,ValueNode_Const::create(true)); // Split Tangents + + // get_canvas_interface()->auto_export(value_node); + printf("exporting\n"); + get_canvas_interface()->add_value_node(value_node,value_node->get_id() + strprintf("foo %d", rand())); + + assert(value_node->is_exported()); + // replace 'this' with the new valuenode + *iter=synfigapp::ValueDesc(get_canvas(),value_node->get_id()); + printf("erasing next\n"); + printf("erasing next point\n"); + vertex_list.erase(next); + done=false; + break; + } // this vertex isn't close to the next one + else if (value_prev.parent_is_value_node()) + { + printf("in two - it's far\n"); + // \todo this only makes sense if prev is on the same bline + printf("this is index %d\n", value_desc.get_index()); + printf("prev is index %d\n", value_prev.get_index()); + bool positive_trend(value_desc.get_index()>value_prev.get_index()); + + if(positive_trend) + { + printf("positive trend\n"); + printf("comparing index %d < link_count()-1 = %d-1 = %d\n", + value_desc.get_index(), + LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count(), + LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count()-1); + if (value_desc.get_index()link_count()-1) + { + printf("in two - b\n"); + printf("inserting node with index %d\n", value_desc.get_index()+1); + vertex_list.insert(next, + synfigapp::ValueDesc(value_desc.get_parent_value_node(), + value_desc.get_index()+1)); + done=false; + break; + } + } + else // !positive_trend + { + printf("negative trend\n"); + if(value_desc.get_index()>0) + { + printf("in two - a\n"); + printf("inserting node on this line with index %d\n", + value_desc.get_index()-1); + vertex_list.insert(next, + synfigapp::ValueDesc(value_desc.get_parent_value_node(), + value_desc.get_index()-1)); + done=false; + break; + } + } + } + } + } + } } } - if(trivial_case) - value_node_bline=ValueNode_BLine::Handle::cast_dynamic(trivial_case_value_node); + + if(vertex_list.size()<=2) + { + synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__); + return Smach::RESULT_OK; + } + + debug_show_vertex_list(i, vertex_list, "finished tidying list", -1); } // If we aren't the trivial case, @@ -1319,6 +1756,7 @@ StateDraw_Context::new_region(std::list bline, synfig::Real // BLine value node if(!value_node_bline) { + synfig::info("not all points are on the same bline"); value_node_bline=ValueNode_BLine::create(); std::list::iterator iter; @@ -1354,7 +1792,12 @@ StateDraw_Context::new_region(std::list bline, synfig::Real synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); layer=get_canvas_interface()->add_layer_to("region",canvas,depth); - assert(layer); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return Smach::RESULT_ERROR; + } layer->set_param("color",synfigapp::Main::get_background_color()); if(get_feather()) { @@ -1363,7 +1806,7 @@ StateDraw_Context::new_region(std::list bline, synfig::Real } get_canvas_interface()->signal_layer_param_changed()(layer,"color"); - synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect")); + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); assert(action); @@ -1415,7 +1858,7 @@ StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,st if (complete_loop) { - synfigapp::Action::Handle action(synfigapp::Action::create("value_node_dynamic_list_loop")); + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop")); assert(action); action->set_param("canvas",get_canvas()); @@ -1435,7 +1878,7 @@ StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,st { ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter)); - synfigapp::Action::Handle action(synfigapp::Action::create("value_node_dynamic_list_insert")); + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert")); assert(action); synfigapp::ValueDesc value_desc(value_node,0); @@ -1466,7 +1909,7 @@ StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std: if (complete_loop) { - synfigapp::Action::Handle action(synfigapp::Action::create("value_node_dynamic_list_loop")); + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop")); assert(action); action->set_param("canvas",get_canvas()); @@ -1486,7 +1929,7 @@ StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std: { ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter)); - synfigapp::Action::Handle action(synfigapp::Action::create("value_node_dynamic_list_insert")); + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert")); assert(action); synfigapp::ValueDesc value_desc(value_node,value_node->link_count()); @@ -1526,11 +1969,11 @@ StateDraw_Context::reverse_bline(std::list &bline) } } -void -StateDraw_Context::fill_last_stroke() +Smach::event_result +StateDraw_Context::fill_last_stroke_and_unselect_other_layers() { if(!last_stroke) - return; + return Smach::RESULT_OK; synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Fill Stroke")); @@ -1540,12 +1983,23 @@ StateDraw_Context::fill_last_stroke() synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - layer=get_canvas_interface()->add_layer("region"); - assert(layer); + Canvas::Handle canvas(get_canvas_view()->get_canvas()); + int depth(0); + + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + layer=get_canvas_interface()->add_layer_to("region", canvas, depth); + if (!layer) return Smach::RESULT_ERROR; layer->set_param("color",synfigapp::Main::get_background_color()); layer->set_description(last_stroke_id + _(" Region")); - synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect")); + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); assert(action); @@ -1561,7 +2015,19 @@ StateDraw_Context::fill_last_stroke() { get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); group.cancel(); - return; + return Smach::RESULT_OK; } get_canvas_view()->get_selection_manager()->set_selected_layer(layer); + return Smach::RESULT_OK; +} + +void +StateDraw_Context::fill_last_stroke() +{ + if(!last_stroke) + return; + + synfigapp::SelectionManager::LayerList layer_list = get_canvas_view()->get_selection_manager()->get_selected_layers(); + fill_last_stroke_and_unselect_other_layers(); + get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); }