X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Fsrc%2Fgtkmm%2Fstate_normal.cpp;h=15a7b4305c3699a3f08533f1ddce8b3a0f5c8f10;hb=a0c4c834ff9eac521ea6e6efce297d4ece195bc2;hp=f2bb3b95c9d5a3db530b9a605577cbdad639cab3;hpb=adfc80c126f482d7ea2bac38001a2c4a7c7df88c;p=synfig.git diff --git a/synfig-studio/src/gtkmm/state_normal.cpp b/synfig-studio/src/gtkmm/state_normal.cpp index f2bb3b9..15a7b43 100644 --- a/synfig-studio/src/gtkmm/state_normal.cpp +++ b/synfig-studio/src/gtkmm/state_normal.cpp @@ -7,6 +7,7 @@ ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2009 Nikita Kitaev ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -30,20 +31,32 @@ # include #endif +#include +#include + +#include +#include +#include +#include +#include +#include + #include "state_normal.h" +#include "canvasview.h" #include "workarea.h" +#include "app.h" + +#include #include "event_mouse.h" #include "event_layerclick.h" #include "toolbox.h" #include "dialog_tooloptions.h" -#include -#include "widget_waypointmodel.h" -#include -#include -#include -#include "canvasview.h" -#include "general.h" +#include +#include "duck.h" +#include +#include +#include "general.h" #endif /* === U S I N G =========================================================== */ @@ -55,368 +68,459 @@ using namespace studio; /* === M A C R O S ========================================================= */ +#ifndef EPSILON +#define EPSILON 0.0000001 +#endif + +/* === G L O B A L S ======================================================= */ + +StateNormal studio::state_normal; + /* === C L A S S E S & S T R U C T S ======================================= */ -class studio::StateNormal_Context : public sigc::trackable +class DuckDrag_Combo : public DuckDrag_Base { - CanvasView *canvas_view; + synfig::Vector last_move; + synfig::Vector drag_offset; + synfig::Vector center; + synfig::Vector snap; - CanvasView* get_canvas_view() { return canvas_view; } - Canvas::Handle get_canvas() { return canvas_view->get_canvas(); } - WorkArea* get_work_area() { return canvas_view->get_work_area(); } - etl::handle get_canvas_interface() { return canvas_view->canvas_interface(); } + synfig::Angle original_angle; + synfig::Real original_mag; + + std::vector last_; + std::vector positions; + + + bool bad_drag; + bool move_only; public: - StateNormal_Context(CanvasView *canvas_view); - ~StateNormal_Context(); + etl::handle canvas_view_; + bool scale; + bool rotate; + bool constrain; + DuckDrag_Combo(); + void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin); + bool end_duck_drag(Duckmatic* duckmatic); + void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector); - Smach::event_result event_stop_handler(const Smach::event& x); + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} +}; - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_refresh_ducks_handler(const Smach::event& x); +class studio::StateNormal_Context : public sigc::trackable +{ + etl::handle canvas_view_; - Smach::event_result event_undo_handler(const Smach::event& x); + synfigapp::Settings& settings; - Smach::event_result event_redo_handler(const Smach::event& x); + sigc::connection keypress_connect; + sigc::connection keyrelease_connect; - Smach::event_result event_mouse_button_down_handler(const Smach::event& x); + etl::handle duck_dragger_; - Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x); + Gtk::Table options_table; - Smach::event_result event_refresh_tool_options(const Smach::event& x); + Gtk::CheckButton checkbutton_rotate; + Gtk::CheckButton checkbutton_scale; + Gtk::CheckButton checkbutton_constrain; + +public: - Smach::event_result event_layer_click(const Smach::event& x); + bool get_rotate_flag()const { return checkbutton_rotate.get_active(); } + void set_rotate_flag(bool x) { checkbutton_rotate.set_active(x); refresh_rotate_flag(); } + void refresh_rotate_flag() { if(duck_dragger_)duck_dragger_->rotate=get_rotate_flag(); } - void edit_several_waypoints(std::list value_desc_list); + bool get_scale_flag()const { return checkbutton_scale.get_active(); } + void set_scale_flag(bool x) { checkbutton_scale.set_active(x); refresh_scale_flag(); } + void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->scale=get_scale_flag(); } + bool get_constrain_flag()const { return checkbutton_constrain.get_active(); } + void set_constrain_flag(bool x) { checkbutton_constrain.set_active(x); refresh_constrain_flag(); } + void refresh_constrain_flag() { if(duck_dragger_)duck_dragger_->constrain=get_constrain_flag(); } + + Smach::event_result event_refresh_tool_options(const Smach::event& x); void refresh_tool_options(); -}; // END of class StateNormal_Context -/* === G L O B A L S ======================================================= */ + StateNormal_Context(CanvasView* canvas_view); -StateNormal studio::state_normal; + ~StateNormal_Context(); + + const etl::handle& get_canvas_view()const{return canvas_view_;} + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} + synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} + WorkArea * get_work_area()const{return canvas_view_->get_work_area();} + + void load_settings(); + void save_settings(); -/* === P R O C E D U R E S ================================================= */ + bool key_pressed(GdkEventKey *event); + bool key_released(GdkEventKey *event); + +}; // END of class StateNormal_Context /* === M E T H O D S ======================================================= */ StateNormal::StateNormal(): Smach::state("normal") { - insert(event_def(EVENT_STOP,&StateNormal_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateNormal_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateNormal_Context::event_refresh_ducks_handler)); - insert(event_def(EVENT_UNDO,&StateNormal_Context::event_undo_handler)); - insert(event_def(EVENT_REDO,&StateNormal_Context::event_redo_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateNormal_Context::event_mouse_button_down_handler)); - insert(event_def(EVENT_WORKAREA_MULTIPLE_DUCKS_CLICKED,&StateNormal_Context::event_multiple_ducks_clicked_handler)); insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateNormal_Context::event_refresh_tool_options)); - insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateNormal_Context::event_layer_click)); } StateNormal::~StateNormal() { } -StateNormal_Context::StateNormal_Context(CanvasView *canvas_view): - canvas_view(canvas_view) +void +StateNormal_Context::load_settings() { - // synfig::info("Entered Normal State"); -} + String value; + + if(settings.get_value("normal.rotate",value) && value=="1") + set_rotate_flag(true); + else + set_rotate_flag(false); + + if(settings.get_value("normal.scale",value) && value=="1") + set_scale_flag(true); + else + set_scale_flag(false); + + if(settings.get_value("normal.constrain",value) && value=="1") + set_constrain_flag(true); + else + set_constrain_flag(false); -StateNormal_Context::~StateNormal_Context() -{ - // synfig::info("Left Normal State"); } void -StateNormal_Context::refresh_tool_options() +StateNormal_Context::save_settings() { - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_name("normal"); + settings.set_value("normal.rotate",get_rotate_flag()?"1":"0"); + settings.set_value("normal.scale",get_scale_flag()?"1":"0"); + settings.set_value("normal.constrain",get_constrain_flag()?"1":"0"); } -Smach::event_result -StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/) +StateNormal_Context::StateNormal_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + settings(synfigapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_Combo()), + checkbutton_rotate(_("Rotate (Ctrl)")), + checkbutton_scale(_("Scale (Alt)")), + checkbutton_constrain(_("Constrain (Shift)")) { + duck_dragger_->canvas_view_=get_canvas_view(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Normal Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_rotate, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_scale, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_constrain, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + checkbutton_rotate.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_rotate_flag)); + checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_scale_flag)); + checkbutton_constrain.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_constrain_flag)); + + + options_table.show_all(); refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} + //App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->present(); -Smach::event_result -StateNormal_Context::event_stop_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received Stop Event"); - canvas_view->stop(); - return Smach::RESULT_ACCEPT; -} + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); -Smach::event_result -StateNormal_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received Refresh Event"); - canvas_view->rebuild_tables(); - canvas_view->work_area->queue_render_preview(); - return Smach::RESULT_ACCEPT; + keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_pressed),false); + keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_released),false); + +// get_canvas_view()->work_area->set_cursor(Gdk::CROSSHAIR); + get_canvas_view()->work_area->reset_cursor(); + + App::toolbox->refresh(); + + load_settings(); + refresh_scale_flag(); } -Smach::event_result -StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/) +bool +StateNormal_Context::key_pressed(GdkEventKey *event) { - // synfig::info("STATE NORMAL: Received Refresh Ducks"); - canvas_view->queue_rebuild_ducks(); - return Smach::RESULT_ACCEPT; + switch(event->keyval) + { + case GDK_Control_L: + case GDK_Control_R: + set_rotate_flag(true); + break; + case GDK_Alt_L: + case GDK_Alt_R: + set_scale_flag(true); + break; + case GDK_Shift_L: + case GDK_Shift_R: + set_constrain_flag(true); + break; + default: + break; + } + return false; //Pass on the event to other handlers, just in case } -Smach::event_result -StateNormal_Context::event_undo_handler(const Smach::event& /*x*/) +bool +StateNormal_Context::key_released(GdkEventKey *event) { - // synfig::info("STATE NORMAL: Received Undo Event"); - canvas_view->get_instance()->undo(); - return Smach::RESULT_ACCEPT; + switch(event->keyval) + { + case GDK_Control_L: + case GDK_Control_R: + set_rotate_flag(false); + break; + case GDK_Alt_L: + case GDK_Alt_R: + set_scale_flag(false); + break; + case GDK_Shift_L: + case GDK_Shift_R: + set_constrain_flag(false); + break; + default: + break; + } + return false; //Pass on the event to other handlers } -Smach::event_result -StateNormal_Context::event_redo_handler(const Smach::event& /*x*/) +void +StateNormal_Context::refresh_tool_options() { - // synfig::info("STATE NORMAL: Received Redo Event"); - canvas_view->get_instance()->redo(); - return Smach::RESULT_ACCEPT; + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Normal Tool")); + App::dialog_tool_options->set_name("normal"); } -Smach::event_result -StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x) + + +StateNormal_Context::~StateNormal_Context() { - // synfig::info("STATE NORMAL: Received mouse button down Event"); + save_settings(); - const EventMouse& event(*reinterpret_cast(&x)); + get_work_area()->clear_duck_dragger(); + get_canvas_view()->work_area->reset_cursor(); - switch(event.button) - { - case BUTTON_RIGHT: - canvas_view->popup_main_menu(); - return Smach::RESULT_ACCEPT; - default: - return Smach::RESULT_OK; - } + keypress_connect.disconnect(); + keyrelease_connect.disconnect(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); } + Smach::event_result -StateNormal_Context::event_layer_click(const Smach::event& x) +StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/) { - const EventLayerClick& event(*reinterpret_cast(&x)); - - if(event.layer) - { - // synfig::info("STATE NORMAL: Received layer click Event, \"%s\"",event.layer->get_name().c_str()); - } - else - { - // synfig::info("STATE NORMAL: Received layer click Event with an empty layer."); - } + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} - switch(event.button) - { - case BUTTON_LEFT: - if(!(event.modifier&Gdk::CONTROL_MASK)) - canvas_view->get_selection_manager()->clear_selected_layers(); - if(event.layer) - { - std::list layer_list(canvas_view->get_selection_manager()->get_selected_layers()); - std::set layers(layer_list.begin(),layer_list.end()); - if(layers.count(event.layer)) - { - layers.erase(event.layer); - layer_list=std::list(layers.begin(),layers.end()); - canvas_view->get_selection_manager()->clear_selected_layers(); - canvas_view->get_selection_manager()->set_selected_layers(layer_list); - } - else - { - canvas_view->get_selection_manager()->set_selected_layer(event.layer); - } - } - return Smach::RESULT_ACCEPT; - case BUTTON_RIGHT: - canvas_view->popup_layer_menu(event.layer); - return Smach::RESULT_ACCEPT; - default: - return Smach::RESULT_OK; - } +DuckDrag_Combo::DuckDrag_Combo(): + scale(false), + rotate(false), + constrain(false) // Lock aspect for scale; smooth move for translate +{ } -/* void -StateNormal_Context::edit_several_waypoints(std::list value_desc_list) +DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) { - Gtk::Dialog dialog( - "Edit Multiple Waypoints", // Title - true, // Modal - true // use_separator - ); - - Widget_WaypointModel widget_waypoint_model; - widget_waypoint_model.show(); + last_move=Vector(1,1); - dialog.get_vbox()->pack_start(widget_waypoint_model); + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + bad_drag=false; - dialog.add_button(Gtk::StockID("gtk-apply"),1); - dialog.add_button(Gtk::StockID("gtk-cancel"),0); - dialog.show(); + drag_offset=duckmatic->find_duck(offset)->get_trans_point(); - if(dialog.run()==0) - return; - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Set Waypoints")); + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset_; + snap=Vector(0,0); - std::list::iterator iter; - for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter) + // Calculate center + Point vmin(100000000,100000000); + Point vmax(-100000000,-100000000); + //std::set >::iterator iter; + positions.clear(); + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) { - synfigapp::ValueDesc value_desc(*iter); + Point p((*iter)->get_trans_point()); + vmin[0]=min(vmin[0],p[0]); + vmin[1]=min(vmin[1],p[1]); + vmax[0]=max(vmax[0],p[0]); + vmax[1]=max(vmax[1],p[1]); + positions.push_back(p); + } + center=(vmin+vmax)*0.5; + if((vmin-vmax).mag()<=EPSILON) + move_only=true; + else + move_only=false; - if(!value_desc.is_valid()) - continue; - ValueNode_Animated::Handle value_node; + synfig::Vector vect(offset-center); + original_angle=Angle::tan(vect[1],vect[0]); + original_mag=vect.mag(); +} - // If this value isn't a ValueNode_Animated, but - // it is somewhat constant, then go ahead and convert - // it to a ValueNode_Animated. - if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())) - { - ValueBase value; - if(value_desc.is_value_node()) - value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value(); - else - value=value_desc.get_value(); - value_node=ValueNode_Animated::create(value,get_canvas()->get_time()); +void +DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + if (!duckmatic) return; - synfigapp::Action::Handle action; + if(bad_drag) + return; - if(!value_desc.is_value_node()) - { - action=synfigapp::Action::create("ValueDescConnect"); - action->set_param("dest",value_desc); - action->set_param("src",ValueNode::Handle(value_node)); - } - else - { - action=synfigapp::Action::create("ValueNodeReplace"); - action->set_param("dest",value_desc.get_value_node()); - action->set_param("src",ValueNode::Handle(value_node)); - } + //Override axis lock set in workarea when holding down the shift key + if (!move_only && (scale || rotate)) + duckmatic->set_axis_lock(false); - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); + synfig::Vector vect; + if (move_only || (!scale && !rotate)) + vect= duckmatic->snap_point_to_grid(vector)-drag_offset+snap; + else + vect= duckmatic->snap_point_to_grid(vector)-center+snap; + last_move=vect; - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to convert to animated waypoint")); - group.cancel(); - return; - } + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + Time time(duckmatic->get_time()); + + int i; + if( move_only || (!scale && !rotate) ) + { + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if((*iter)->get_type()==Duck::TYPE_VERTEX || (*iter)->get_type()==Duck::TYPE_POSITION) + (*iter)->set_trans_point(positions[i]+vect, time); } - else + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) { - if(value_desc.is_value_node()) - value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()); + if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION) + (*iter)->set_trans_point(positions[i]+vect, time); } + } + if (rotate) + { + Angle::deg angle(Angle::tan(vect[1],vect[0])); + angle=original_angle-angle; + if (constrain) + { + float degrees = angle.get()/15; + angle= Angle::deg (degrees>0?std::floor(degrees)*15:std::ceil(degrees)*15); + } + Real mag(vect.mag()/original_mag); + Real sine(Angle::sin(angle).get()); + Real cosine(Angle::cos(angle).get()); - if(value_node) + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) { + if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue; - synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSetSmart")); - - if(!action) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to find WaypointSetSmart action")); - group.cancel(); - return; - } + Vector x(positions[i]-center),p; + p[0]=cosine*x[0]+sine*x[1]; + p[1]=-sine*x[0]+cosine*x[1]; + if(scale)p*=mag; + p+=center; + (*iter)->set_trans_point(p, time); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_node",ValueNode::Handle(value_node)); - action->set_param("time",get_canvas()->get_time()); - action->set_param("model",widget_waypoint_model.get_waypoint_model()); + Vector x(positions[i]-center),p; - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to set a specific waypoint")); - group.cancel(); - return; - } + p[0]=cosine*x[0]+sine*x[1]; + p[1]=-sine*x[0]+cosine*x[1]; + if(scale)p*=mag; + p+=center; + (*iter)->set_trans_point(p, time); } + } else if (scale) + { + if(!constrain) + { + if(abs(drag_offset[0]-center[0])>EPSILON) + vect[0]/=drag_offset[0]-center[0]; + else + vect[0]=1; + if(abs(drag_offset[1]-center[1])>EPSILON) + vect[1]/=drag_offset[1]-center[1]; + else + vect[1]=1; + } else { - //get_canvas_view()->get_ui_interface()->error(_("Unable to animate a specific valuedesc")); - //group.cancel(); - //return; + //vect[0]=vect[1]=vect.mag()*0.707106781; + Real amount(vect.mag()/(drag_offset-center).mag()); + vect[0]=vect[1]=amount; } - } -} -*/ - -Smach::event_result -StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received multiple duck click event"); + if(vect[0]-EPSILON) + vect[0]=1; + if(vect[1]-EPSILON) + vect[1]=1; - //const EventMouse& event(*reinterpret_cast(&x)); + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; - std::list value_desc_list; + Vector p(positions[i]-center); - // Create a list of value_descs associated with selection - const DuckList selected_ducks(get_work_area()->get_selected_ducks()); - DuckList::const_iterator iter; - for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter) - { - synfigapp::ValueDesc value_desc((*iter)->get_value_desc()); + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p, time); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; - if(!value_desc.is_valid()) - continue; + Vector p(positions[i]-center); - if(value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT && value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())) - { - value_desc_list.push_back( - synfigapp::ValueDesc( - ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()) - ,0 - ) - ); + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p, time); } - else - value_desc_list.push_back(value_desc); } - Gtk::Menu *menu=manage(new Gtk::Menu()); - menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), menu)); - - canvas_view->get_instance()->make_param_menu(menu,canvas_view->get_canvas(),value_desc_list); + // then patch up the tangents for the vertices we've moved + duckmatic->update_ducks(); - /* - synfigapp::Action::ParamList param_list; - param_list=get_canvas_interface()->generate_param_list(value_desc_list); + last_move=vect; +} - canvas_view->add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE); +bool +DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic) +{ + if(bad_drag)return false; - menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Edit Waypoints"), - sigc::bind( - sigc::mem_fun( - *this, - &studio::StateNormal_Context::edit_several_waypoints - ), - value_desc_list - ) - )); - */ - menu->popup(3,gtk_get_current_event_time()); + //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks")); - return Smach::RESULT_ACCEPT; + if((last_move-Vector(1,1)).mag()>0.0001) + { + duckmatic->signal_edited_selected_ducks(); + return true; + } + else + { + duckmatic->signal_user_click_selected_ducks(0); + return false; + } }