From 45dc3b3e85f218337b52ec3a9b027678f6c6397a Mon Sep 17 00:00:00 2001 From: Nikita Kitaev Date: Fri, 16 Apr 2010 20:56:51 -0700 Subject: [PATCH] Move states into subfolder --- synfig-studio/src/gui/Makefile.am | 76 +- synfig-studio/src/gui/app.cpp | 36 +- synfig-studio/src/gui/canvasview.cpp | 8 +- synfig-studio/src/gui/state_bline.cpp | 1414 -------------- synfig-studio/src/gui/state_bline.h | 55 - synfig-studio/src/gui/state_circle.cpp | 1066 ----------- synfig-studio/src/gui/state_circle.h | 56 - synfig-studio/src/gui/state_draw.cpp | 2036 --------------------- synfig-studio/src/gui/state_draw.h | 56 - synfig-studio/src/gui/state_eyedrop.cpp | 146 -- synfig-studio/src/gui/state_eyedrop.h | 56 - synfig-studio/src/gui/state_fill.cpp | 182 -- synfig-studio/src/gui/state_fill.h | 56 - synfig-studio/src/gui/state_gradient.cpp | 546 ------ synfig-studio/src/gui/state_gradient.h | 56 - synfig-studio/src/gui/state_mirror.cpp | 336 ---- synfig-studio/src/gui/state_mirror.h | 55 - synfig-studio/src/gui/state_normal.cpp | 824 --------- synfig-studio/src/gui/state_normal.h | 57 - synfig-studio/src/gui/state_polygon.cpp | 945 ---------- synfig-studio/src/gui/state_polygon.h | 55 - synfig-studio/src/gui/state_rectangle.cpp | 875 --------- synfig-studio/src/gui/state_rectangle.h | 56 - synfig-studio/src/gui/state_rotate.cpp | 398 ---- synfig-studio/src/gui/state_rotate.h | 56 - synfig-studio/src/gui/state_scale.cpp | 389 ---- synfig-studio/src/gui/state_scale.h | 55 - synfig-studio/src/gui/state_sketch.cpp | 508 ----- synfig-studio/src/gui/state_sketch.h | 55 - synfig-studio/src/gui/state_smoothmove.cpp | 388 ---- synfig-studio/src/gui/state_smoothmove.h | 56 - synfig-studio/src/gui/state_star.cpp | 1091 ----------- synfig-studio/src/gui/state_star.h | 57 - synfig-studio/src/gui/state_stroke.cpp | 198 -- synfig-studio/src/gui/state_stroke.h | 80 - synfig-studio/src/gui/state_text.cpp | 460 ----- synfig-studio/src/gui/state_text.h | 57 - synfig-studio/src/gui/state_width.cpp | 606 ------ synfig-studio/src/gui/state_width.h | 56 - synfig-studio/src/gui/state_zoom.cpp | 263 --- synfig-studio/src/gui/state_zoom.h | 55 - synfig-studio/src/gui/states/state_bline.cpp | 1414 ++++++++++++++ synfig-studio/src/gui/states/state_bline.h | 55 + synfig-studio/src/gui/states/state_circle.cpp | 1066 +++++++++++ synfig-studio/src/gui/states/state_circle.h | 56 + synfig-studio/src/gui/states/state_draw.cpp | 2036 +++++++++++++++++++++ synfig-studio/src/gui/states/state_draw.h | 56 + synfig-studio/src/gui/states/state_eyedrop.cpp | 146 ++ synfig-studio/src/gui/states/state_eyedrop.h | 56 + synfig-studio/src/gui/states/state_fill.cpp | 182 ++ synfig-studio/src/gui/states/state_fill.h | 56 + synfig-studio/src/gui/states/state_gradient.cpp | 546 ++++++ synfig-studio/src/gui/states/state_gradient.h | 56 + synfig-studio/src/gui/states/state_mirror.cpp | 336 ++++ synfig-studio/src/gui/states/state_mirror.h | 55 + synfig-studio/src/gui/states/state_normal.cpp | 824 +++++++++ synfig-studio/src/gui/states/state_normal.h | 57 + synfig-studio/src/gui/states/state_polygon.cpp | 945 ++++++++++ synfig-studio/src/gui/states/state_polygon.h | 55 + synfig-studio/src/gui/states/state_rectangle.cpp | 875 +++++++++ synfig-studio/src/gui/states/state_rectangle.h | 56 + synfig-studio/src/gui/states/state_rotate.cpp | 398 ++++ synfig-studio/src/gui/states/state_rotate.h | 56 + synfig-studio/src/gui/states/state_scale.cpp | 389 ++++ synfig-studio/src/gui/states/state_scale.h | 55 + synfig-studio/src/gui/states/state_sketch.cpp | 508 +++++ synfig-studio/src/gui/states/state_sketch.h | 55 + synfig-studio/src/gui/states/state_smoothmove.cpp | 388 ++++ synfig-studio/src/gui/states/state_smoothmove.h | 56 + synfig-studio/src/gui/states/state_star.cpp | 1091 +++++++++++ synfig-studio/src/gui/states/state_star.h | 57 + synfig-studio/src/gui/states/state_stroke.cpp | 198 ++ synfig-studio/src/gui/states/state_stroke.h | 80 + synfig-studio/src/gui/states/state_text.cpp | 460 +++++ synfig-studio/src/gui/states/state_text.h | 57 + synfig-studio/src/gui/states/state_width.cpp | 606 ++++++ synfig-studio/src/gui/states/state_width.h | 56 + synfig-studio/src/gui/states/state_zoom.cpp | 263 +++ synfig-studio/src/gui/states/state_zoom.h | 55 + 79 files changed, 13816 insertions(+), 13816 deletions(-) delete mode 100644 synfig-studio/src/gui/state_bline.cpp delete mode 100644 synfig-studio/src/gui/state_bline.h delete mode 100644 synfig-studio/src/gui/state_circle.cpp delete mode 100644 synfig-studio/src/gui/state_circle.h delete mode 100644 synfig-studio/src/gui/state_draw.cpp delete mode 100644 synfig-studio/src/gui/state_draw.h delete mode 100644 synfig-studio/src/gui/state_eyedrop.cpp delete mode 100644 synfig-studio/src/gui/state_eyedrop.h delete mode 100644 synfig-studio/src/gui/state_fill.cpp delete mode 100644 synfig-studio/src/gui/state_fill.h delete mode 100644 synfig-studio/src/gui/state_gradient.cpp delete mode 100644 synfig-studio/src/gui/state_gradient.h delete mode 100644 synfig-studio/src/gui/state_mirror.cpp delete mode 100644 synfig-studio/src/gui/state_mirror.h delete mode 100644 synfig-studio/src/gui/state_normal.cpp delete mode 100644 synfig-studio/src/gui/state_normal.h delete mode 100644 synfig-studio/src/gui/state_polygon.cpp delete mode 100644 synfig-studio/src/gui/state_polygon.h delete mode 100644 synfig-studio/src/gui/state_rectangle.cpp delete mode 100644 synfig-studio/src/gui/state_rectangle.h delete mode 100644 synfig-studio/src/gui/state_rotate.cpp delete mode 100644 synfig-studio/src/gui/state_rotate.h delete mode 100644 synfig-studio/src/gui/state_scale.cpp delete mode 100644 synfig-studio/src/gui/state_scale.h delete mode 100644 synfig-studio/src/gui/state_sketch.cpp delete mode 100644 synfig-studio/src/gui/state_sketch.h delete mode 100644 synfig-studio/src/gui/state_smoothmove.cpp delete mode 100644 synfig-studio/src/gui/state_smoothmove.h delete mode 100644 synfig-studio/src/gui/state_star.cpp delete mode 100644 synfig-studio/src/gui/state_star.h delete mode 100644 synfig-studio/src/gui/state_stroke.cpp delete mode 100644 synfig-studio/src/gui/state_stroke.h delete mode 100644 synfig-studio/src/gui/state_text.cpp delete mode 100644 synfig-studio/src/gui/state_text.h delete mode 100644 synfig-studio/src/gui/state_width.cpp delete mode 100644 synfig-studio/src/gui/state_width.h delete mode 100644 synfig-studio/src/gui/state_zoom.cpp delete mode 100644 synfig-studio/src/gui/state_zoom.h create mode 100644 synfig-studio/src/gui/states/state_bline.cpp create mode 100644 synfig-studio/src/gui/states/state_bline.h create mode 100644 synfig-studio/src/gui/states/state_circle.cpp create mode 100644 synfig-studio/src/gui/states/state_circle.h create mode 100644 synfig-studio/src/gui/states/state_draw.cpp create mode 100644 synfig-studio/src/gui/states/state_draw.h create mode 100644 synfig-studio/src/gui/states/state_eyedrop.cpp create mode 100644 synfig-studio/src/gui/states/state_eyedrop.h create mode 100644 synfig-studio/src/gui/states/state_fill.cpp create mode 100644 synfig-studio/src/gui/states/state_fill.h create mode 100644 synfig-studio/src/gui/states/state_gradient.cpp create mode 100644 synfig-studio/src/gui/states/state_gradient.h create mode 100644 synfig-studio/src/gui/states/state_mirror.cpp create mode 100644 synfig-studio/src/gui/states/state_mirror.h create mode 100644 synfig-studio/src/gui/states/state_normal.cpp create mode 100644 synfig-studio/src/gui/states/state_normal.h create mode 100644 synfig-studio/src/gui/states/state_polygon.cpp create mode 100644 synfig-studio/src/gui/states/state_polygon.h create mode 100644 synfig-studio/src/gui/states/state_rectangle.cpp create mode 100644 synfig-studio/src/gui/states/state_rectangle.h create mode 100644 synfig-studio/src/gui/states/state_rotate.cpp create mode 100644 synfig-studio/src/gui/states/state_rotate.h create mode 100644 synfig-studio/src/gui/states/state_scale.cpp create mode 100644 synfig-studio/src/gui/states/state_scale.h create mode 100644 synfig-studio/src/gui/states/state_sketch.cpp create mode 100644 synfig-studio/src/gui/states/state_sketch.h create mode 100644 synfig-studio/src/gui/states/state_smoothmove.cpp create mode 100644 synfig-studio/src/gui/states/state_smoothmove.h create mode 100644 synfig-studio/src/gui/states/state_star.cpp create mode 100644 synfig-studio/src/gui/states/state_star.h create mode 100644 synfig-studio/src/gui/states/state_stroke.cpp create mode 100644 synfig-studio/src/gui/states/state_stroke.h create mode 100644 synfig-studio/src/gui/states/state_text.cpp create mode 100644 synfig-studio/src/gui/states/state_text.h create mode 100644 synfig-studio/src/gui/states/state_width.cpp create mode 100644 synfig-studio/src/gui/states/state_width.h create mode 100644 synfig-studio/src/gui/states/state_zoom.cpp create mode 100644 synfig-studio/src/gui/states/state_zoom.h diff --git a/synfig-studio/src/gui/Makefile.am b/synfig-studio/src/gui/Makefile.am index 0260a3c..f4442d3 100644 --- a/synfig-studio/src/gui/Makefile.am +++ b/synfig-studio/src/gui/Makefile.am @@ -156,46 +156,46 @@ WIDGET_CC = \ STATE_HH = \ - state_bline.h \ - state_circle.h \ - state_draw.h \ - state_eyedrop.h \ - state_fill.h \ - state_gradient.h \ - state_mirror.h \ - state_normal.h \ - state_polygon.h \ - state_rectangle.h \ - state_rotate.h \ - state_scale.h \ - state_sketch.h \ - state_smoothmove.h \ - state_star.h \ - state_stroke.h \ - state_text.h \ - state_width.h \ - state_zoom.h + states/state_bline.h \ + states/state_circle.h \ + states/state_draw.h \ + states/state_eyedrop.h \ + states/state_fill.h \ + states/state_gradient.h \ + states/state_mirror.h \ + states/state_normal.h \ + states/state_polygon.h \ + states/state_rectangle.h \ + states/state_rotate.h \ + states/state_scale.h \ + states/state_sketch.h \ + states/state_smoothmove.h \ + states/state_star.h \ + states/state_stroke.h \ + states/state_text.h \ + states/state_width.h \ + states/state_zoom.h STATE_CC = \ - state_bline.cpp \ - state_circle.cpp \ - state_draw.cpp \ - state_eyedrop.cpp \ - state_fill.cpp \ - state_gradient.cpp \ - state_mirror.cpp \ - state_normal.cpp \ - state_polygon.cpp \ - state_rectangle.cpp \ - state_rotate.cpp \ - state_scale.cpp \ - state_sketch.cpp \ - state_smoothmove.cpp \ - state_star.cpp \ - state_stroke.cpp \ - state_text.cpp \ - state_width.cpp \ - state_zoom.cpp + states/state_bline.cpp \ + states/state_circle.cpp \ + states/state_draw.cpp \ + states/state_eyedrop.cpp \ + states/state_fill.cpp \ + states/state_gradient.cpp \ + states/state_mirror.cpp \ + states/state_normal.cpp \ + states/state_polygon.cpp \ + states/state_rectangle.cpp \ + states/state_rotate.cpp \ + states/state_scale.cpp \ + states/state_sketch.cpp \ + states/state_smoothmove.cpp \ + states/state_star.cpp \ + states/state_stroke.cpp \ + states/state_text.cpp \ + states/state_width.cpp \ + states/state_zoom.cpp TREEVIEW_HH = \ diff --git a/synfig-studio/src/gui/app.cpp b/synfig-studio/src/gui/app.cpp index 719aec2..c27f7fc 100644 --- a/synfig-studio/src/gui/app.cpp +++ b/synfig-studio/src/gui/app.cpp @@ -78,24 +78,24 @@ #include "dockmanager.h" -#include "state_eyedrop.h" -#include "state_normal.h" -#include "state_mirror.h" -#include "state_draw.h" -#include "state_fill.h" -#include "state_bline.h" -#include "state_polygon.h" -#include "state_sketch.h" -#include "state_gradient.h" -#include "state_circle.h" -#include "state_rectangle.h" -#include "state_smoothmove.h" -#include "state_scale.h" -#include "state_star.h" -#include "state_text.h" -#include "state_width.h" -#include "state_rotate.h" -#include "state_zoom.h" +#include "states/state_eyedrop.h" +#include "states/state_normal.h" +#include "states/state_mirror.h" +#include "states/state_draw.h" +#include "states/state_fill.h" +#include "states/state_bline.h" +#include "states/state_polygon.h" +#include "states/state_sketch.h" +#include "states/state_gradient.h" +#include "states/state_circle.h" +#include "states/state_rectangle.h" +#include "states/state_smoothmove.h" +#include "states/state_scale.h" +#include "states/state_star.h" +#include "states/state_text.h" +#include "states/state_width.h" +#include "states/state_rotate.h" +#include "states/state_zoom.h" #include "devicetracker.h" #include "dialog_tooloptions.h" diff --git a/synfig-studio/src/gui/canvasview.cpp b/synfig-studio/src/gui/canvasview.cpp index b421bf9..8fdd889 100644 --- a/synfig-studio/src/gui/canvasview.cpp +++ b/synfig-studio/src/gui/canvasview.cpp @@ -83,10 +83,10 @@ #include "dialogs/dialog_color.h" #include "eventkey.h" -#include "state_polygon.h" -#include "state_bline.h" -#include "state_normal.h" -#include "state_eyedrop.h" +#include "states/state_polygon.h" +#include "states/state_bline.h" +#include "states/state_normal.h" +#include "states/state_eyedrop.h" #include "ducktransform_scale.h" #include "ducktransform_translate.h" diff --git a/synfig-studio/src/gui/state_bline.cpp b/synfig-studio/src/gui/state_bline.cpp deleted file mode 100644 index ee0ca20..0000000 --- a/synfig-studio/src/gui/state_bline.cpp +++ /dev/null @@ -1,1414 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_bline.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2007, 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include - -#include "state_bline.h" -#include "state_normal.h" -#include "canvasview.h" -#include "workarea.h" -#include "app.h" -#include -#include -#include -#include -#include "event_mouse.h" -#include "event_layerclick.h" -#include "toolbox.h" -#include "dialog_tooloptions.h" -#include -#include -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -// if defined, show the first duck as green while drawing -#define DISTINGUISH_FIRST_DUCK - -/* === G L O B A L S ======================================================= */ - -StateBLine studio::state_bline; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateBLine_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - bool prev_table_status; - bool loop_; - bool prev_workarea_layer_status_; - - int depth; - Canvas::Handle canvas; - - Gtk::Menu menu; - - Duckmatic::Push duckmatic_push; - - etl::handle curr_duck; - - etl::handle next_duck; - - std::list bline_point_list; - synfigapp::Settings& settings; - - bool on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node); - bool on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node); - bool on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node); - - - void popup_handle_menu(synfig::ValueNode_Const::Handle value_node); - void popup_vertex_menu(synfig::ValueNode_Const::Handle value_node); - void popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node); - - void bline_detach_handle(synfig::ValueNode_Const::Handle value_node); - void bline_attach_handle(synfig::ValueNode_Const::Handle value_node); - void bline_delete_vertex(synfig::ValueNode_Const::Handle value_node); - void bline_insert_vertex(synfig::ValueNode_Const::Handle value_node,float origin=0.5); - void loop_bline(); - void unloop_bline(); - - void refresh_ducks(bool x=true); - - Gtk::Table options_table; - Gtk::Entry entry_id; - Gtk::CheckButton checkbutton_layer_region; - Gtk::CheckButton checkbutton_layer_outline; - Gtk::CheckButton checkbutton_layer_curve_gradient; - Gtk::CheckButton checkbutton_layer_plant; - Gtk::CheckButton checkbutton_layer_link_origins; - Gtk::CheckButton checkbutton_auto_export; - Gtk::Button button_make; - Gtk::Button button_clear; - Gtk::Adjustment adj_feather; - Gtk::SpinButton spin_feather; - - - -public: - - int layers_to_create()const - { - return - get_layer_region_flag() + - get_layer_outline_flag() + - get_layer_curve_gradient_flag() + - get_layer_plant_flag(); - } - - void sanity_check() - { - if(layers_to_create()==0) - set_layer_region_flag(true); - } - - bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); } - void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); } - - bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } - void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } - - bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } - void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } - - bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } - void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } - - bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } - void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } - - bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } - void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } - - Real get_feather() const { return adj_feather.get_value(); } - void set_feather(Real x) { return adj_feather.set_value(x); } - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_mouse_release_handler(const Smach::event& x); - Smach::event_result event_mouse_motion_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - Smach::event_result event_hijack(const Smach::event& /*x*/) { return Smach::RESULT_ACCEPT; } - - void refresh_tool_options(); - - StateBLine_Context(CanvasView* canvas_view); - - ~StateBLine_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();} - const synfig::TransformStack& get_transform_stack()const { return canvas_view_->get_curr_transform_stack(); } - - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - //void on_user_click(synfig::Point point); - - bool run_(); - bool run(); - - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - -}; // END of class StateBLine_Context - - -/* === M E T H O D S ======================================================= */ - -StateBLine::StateBLine(): - Smach::state("bline") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED, &StateBLine_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_STOP, &StateBLine_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH, &StateBLine_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS, &StateBLine_Context::event_hijack)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN, &StateBLine_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP, &StateBLine_Context::event_mouse_release_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_MOTION, &StateBLine_Context::event_mouse_motion_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG, &StateBLine_Context::event_mouse_motion_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS, &StateBLine_Context::event_refresh_tool_options)); -} - -StateBLine::~StateBLine() -{ -} - -void -StateBLine_Context::load_settings() -{ - String value; - - if(settings.get_value("bline.layer_region",value) && value=="0") - set_layer_region_flag(false); - else - set_layer_region_flag(true); - - if(settings.get_value("bline.layer_outline",value) && value=="0") - set_layer_outline_flag(false); - else - set_layer_outline_flag(true); - - if(settings.get_value("bline.layer_curve_gradient",value) && value=="1") - set_layer_curve_gradient_flag(true); - else - set_layer_curve_gradient_flag(false); - - if(settings.get_value("bline.layer_plant",value) && value=="1") - set_layer_plant_flag(true); - else - set_layer_plant_flag(false); - - if(settings.get_value("bline.layer_link_origins",value) && value=="0") - set_layer_link_origins_flag(false); - else - set_layer_link_origins_flag(true); - - if(settings.get_value("bline.auto_export",value) && value=="1") - set_auto_export_flag(true); - else - set_auto_export_flag(false); - - if(settings.get_value("bline.id",value)) - set_id(value); - else - set_id("NewBLine"); - - if(settings.get_value("bline.feather",value)) - { - Real n = atof(value.c_str()); - set_feather(n); - } - - sanity_check(); -} - -void -StateBLine_Context::save_settings() -{ - sanity_check(); - settings.set_value("bline.layer_outline",get_layer_outline_flag()?"1":"0"); - settings.set_value("bline.layer_region",get_layer_region_flag()?"1":"0"); - settings.set_value("bline.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); - settings.set_value("bline.layer_plant",get_layer_plant_flag()?"1":"0"); - settings.set_value("bline.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); - settings.set_value("bline.auto_export",get_auto_export_flag()?"1":"0"); - settings.set_value("bline.id",get_id().c_str()); - settings.set_value("bline.feather",strprintf("%f",get_feather())); -} - -void -StateBLine_Context::reset() -{ - loop_=false; - bline_point_list.clear(); - refresh_ducks(); -} - -void -StateBLine_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="NewBLine"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - 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()); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - - -StateBLine_Context::StateBLine_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - loop_(false), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - duckmatic_push(get_work_area()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), - checkbutton_layer_region(_("Create Region BLine")), - checkbutton_layer_outline(_("Create Outline BLine")), - checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), - checkbutton_layer_plant(_("Create Plant BLine")), - checkbutton_layer_link_origins(_("Link Origins")), - checkbutton_auto_export(_("Auto Export")), - button_make(_("Make")), - button_clear(_("Clear")), - adj_feather(0,0,10000,0.01,0.1), - spin_feather(adj_feather,0.01,4) -{ - depth=-1; - egress_on_selection_change=true; - load_settings(); - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("BLine 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_layer_outline, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_region, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_plant, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_link_origins, 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(*manage(new Gtk::Label(_("Feather"))), 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_feather, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - //options_table.attach(button_make, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - //button_make.signal_pressed().connect(sigc::mem_fun(*this,&StateBLine_Context::run)); - options_table.show_all(); - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - // Hide the tables if they are showing - prev_table_status=get_canvas_view()->tables_are_visible(); - if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateBLine_Context::on_user_click)); - get_work_area()->set_cursor(Gdk::CROSSHAIR); - - App::toolbox->refresh(); -} - -void -StateBLine_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("BLine Tool")); - App::dialog_tool_options->set_name("bline"); - - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-execute"), - _("Make BLine and/or Region") - )->signal_clicked().connect( - sigc::hide_return(sigc::mem_fun( - *this, - &StateBLine_Context::run - )) - ); - - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-clear"), - _("Clear current BLine") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &StateBLine_Context::reset - ) - ); -} - -Smach::event_result -StateBLine_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateBLine_Context::~StateBLine_Context() -{ - run(); - - save_settings(); - App::dialog_tool_options->clear(); - - get_work_area()->reset_cursor(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - - // Enable the time bar - get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - if(prev_table_status)get_canvas_view()->show_tables(); - -// get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS); - - // Refresh the work area - get_work_area()->queue_draw(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateBLine_Context::event_stop_handler(const Smach::event& /*x*/) -{ -// synfig::info("STATE RotoBLine: Received Stop Event"); -// run(); - reset(); -// throw Smach::egress_exception(); -// get_canvas_view()->get_smach().pop_state(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateBLine_Context::event_refresh_handler(const Smach::event& /*x*/) -{ -// synfig::info("STATE RotoBLine: Received Refresh Event"); - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -bool -StateBLine_Context::run() -{ - sanity_check(); - - String err; - bool success(false); - for(int i=5;i>0 && !success;i--)try - { - success=run_(); - } - catch(String s) - { - err=s; - } - if(!success && !err.empty()) - { - get_canvas_view()->get_ui_interface()->error(err); - } - return success; -} - -bool -StateBLine_Context::run_() -{ - curr_duck=0; - next_duck=0; - - // Now we need to generate it - - if(bline_point_list.empty()) - { - return false; - } - if(bline_point_list.size()<2) - { - //get_canvas_view()->get_ui_interface()->error(_("You need at least two (2) points to create a BLine")); - return false; - } - - do - { - - // Create the action group - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New BLine")); - - std::vector new_list; - std::list::iterator iter; - const synfig::TransformStack& transform(get_transform_stack()); - - for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) - { - BLinePoint bline_point((*iter)->get_value().get(BLinePoint())); - 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); - - new_list.push_back(bline_point); - } - - ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); - assert(value_node_bline); - - ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector())); - assert(value_node_origin); - - // Set the looping flag - value_node_bline->set_loop(loop_); - - // Add the BLine to the canvas - if(get_auto_export_flag() && !get_canvas_interface()->add_value_node(value_node_bline,get_id())) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to add value node")); - group.cancel(); - increment_id(); - throw String(_("Unable to add value node")); - return false; - } - - Layer::Handle layer; - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - - if(layer) - { - if(depth<0) - depth=layer->get_depth(); - if(!canvas) - canvas=layer->get_canvas(); - } - else - depth=0; - - if(!canvas) - canvas=get_canvas_view()->get_canvas(); - - value_node_bline->set_member_canvas(canvas); - - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - - // count how many layers we're going to be creating - int layers_to_create = this->layers_to_create(); - - /////////////////////////////////////////////////////////////////////////// - // C U R V E G R A D I E N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_curve_gradient_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); - if (!layer) - { - group.cancel(); - throw String(_("Unable to create layer")); - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Gradient")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return false; - } - } - - // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return false; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // P L A N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_plant_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); - if (!layer) - { - group.cancel(); - throw String(_("Unable to create layer")); - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Plant")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return false; - } - } - - // only link the plant's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return false; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // R E G I O N - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_region_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); - if (!layer) - { - group.cancel(); - throw String(_("Unable to create layer")); - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Region")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - if(get_feather()) - { - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - } - - // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm - // using 2 separate ones. - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return false; - } - } - - // only link the region's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return false; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // O U T L I N E - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_outline_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); - if (!layer) - { - group.cancel(); - throw String(_("Unable to create layer")); - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Outline")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - if(get_feather()) - { - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - } - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return false; - } - } - - // only link the outline's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return false; - } - } - } - - egress_on_selection_change=false; - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - //if(finish_bline_dialog.get_region_flag() || finish_bline_dialog.get_bline_flag()) - // get_canvas_interface()->signal_dirty_preview()(); - - } while(0); - - reset(); - increment_id(); - return true; -} - -Smach::event_result -StateBLine_Context::event_mouse_motion_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - - if(curr_duck) - { - //synfig::info("Moved Duck"); - Point p(get_work_area()->snap_point_to_grid(event.pos)); - curr_duck->set_trans_point(p); - if(next_duck) - next_duck->set_trans_point(p); - get_work_area()->queue_draw(); - return Smach::RESULT_ACCEPT; - } - - return Smach::RESULT_OK; -} - -Smach::event_result -StateBLine_Context::event_mouse_release_handler(const Smach::event& /*x*/) -{ - if(curr_duck) - { - //synfig::info("Released current duck"); - curr_duck->signal_edited()(curr_duck->get_point()); - if(next_duck) - { - //synfig::info("grabbing next duck"); - curr_duck=next_duck; - next_duck=0; - } - return Smach::RESULT_ACCEPT; - } - return Smach::RESULT_OK; -} - -Smach::event_result -StateBLine_Context::event_mouse_click_handler(const Smach::event& x) -{ - // synfig::info("STATE BLINE: Received mouse button down Event"); - const EventMouse& event(*reinterpret_cast(&x)); - switch(event.button) - { - case BUTTON_LEFT: - { - // If we are already looped up, then don't try to add anything else - if(loop_) - return Smach::RESULT_OK; - - BLinePoint bline_point; - - bline_point.set_vertex(get_work_area()->snap_point_to_grid(event.pos)); - //bline_point.set_width(synfigapp::Main::get_bline_width()); - bline_point.set_width(1.0f); - bline_point.set_origin(0.5f); - bline_point.set_split_tangent_flag(false); - bline_point.set_tangent1(Vector(0,0)); - - // set the tangent - /* - if(bline_point_list.empty()) - { - bline_point.set_tangent1(Vector(1,1)); - } - else - { - const Vector t(event.pos-bline_point_list.back()->get_value().get(BLinePoint()).get_vertex()); - bline_point.set_tangent1(t); - } - - if(bline_point_list.size()>1) - { - std::list::iterator iter; - iter=bline_point_list.end(); - iter--;iter--; - BLinePoint prev(bline_point_list.back()->get_value().get(BLinePoint())); - prev.set_tangent1(event.pos-(*iter)->get_value().get(BLinePoint()).get_vertex()); - bline_point_list.back()->set_value(prev); - }; - */ - - bline_point_list.push_back(ValueNode_Const::create(bline_point)); - - refresh_ducks(); - return Smach::RESULT_ACCEPT; - } - - default: - return Smach::RESULT_OK; - } -} - -void -StateBLine_Context::refresh_ducks(bool button_down) -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); - - if(bline_point_list.empty()) - return; - - list::iterator iter; - - handle bezier; - handle duck,tduck; - BLinePoint bline_point; - - for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) - { - ValueNode_Const::Handle value_node(*iter); - bline_point=(value_node->get_value().get(BLinePoint())); - assert(value_node); - - - // First add the duck associated with this vertex - duck=new WorkArea::Duck(bline_point.get_vertex()); - duck->set_editable(true); -#ifdef DISTINGUISH_FIRST_DUCK - if (iter!=bline_point_list.begin()) - duck->set_type(Duck::TYPE_VERTEX); -#else - duck->set_type(Duck::TYPE_VERTEX); -#endif - duck->set_name(strprintf("%x-vertex",value_node.get())); - duck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),value_node) - ); - duck->signal_user_click(2).connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),value_node) - ); - duck->set_guid(value_node->get_guid()^synfig::GUID::hasher(0)); - - get_work_area()->add_duck(duck); - - // Add the tangent1 duck - tduck=new WorkArea::Duck(bline_point.get_tangent1()); - tduck->set_editable(true); - tduck->set_name(strprintf("%x-tangent1",value_node.get())); - tduck->set_origin(duck); - tduck->set_scalar(-0.33333333333333333); - tduck->set_tangent(true); - tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(3)); - tduck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node) - ); - tduck->signal_user_click(2).connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node) - ); - - // See if we need to add that duck to the previous bezier - if(bezier) - { - get_work_area()->add_duck(tduck); - bezier->p2=duck; - bezier->c2=tduck; - - bezier->signal_user_click(2).connect( - sigc::bind( - sigc::mem_fun( - *this, - &studio::StateBLine_Context::popup_bezier_menu - ), - value_node - ) - ); - - //get_work_area()->add_duck(bezier->c1); - //get_work_area()->add_duck(bezier->c2); - get_work_area()->add_bezier(bezier); - - bezier=0; - } - - // Now we see if we need to create a bezier - list::iterator next(iter); - next++; - - // If our next iterator is the end, then we don't need - // to add a bezier. - //if(next==bline_point_list.end() && !loop_) - // continue; - - bezier=new WorkArea::Bezier(); - - // Add the tangent2 duck - tduck=new WorkArea::Duck(bline_point.get_tangent2()); - tduck->set_editable(true); - tduck->set_origin(duck); - tduck->set_scalar(0.33333333333333333); - tduck->set_tangent(true); - if(bline_point.get_split_tangent_flag()) - { - tduck->set_name(strprintf("%x-tangent2",value_node.get())); - tduck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent2_change),value_node) - ); - } - else - { - tduck->set_name(strprintf("%x-tangent1",value_node.get())); - tduck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node) - ); - } - tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(4)); - tduck->signal_user_click(2).connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node) - ); - - // Setup the next bezier - bezier->p1=duck; - bezier->c1=tduck; - - get_work_area()->add_duck(tduck); - curr_duck=tduck; - } - - // Add the loop, if requested - if(bezier && loop_) - { - curr_duck=0; - BLinePoint bline_point(bline_point_list.front()->get_value().get(BLinePoint())); - - duck=new WorkArea::Duck(bline_point.get_vertex()); - duck->set_editable(true); -#ifndef DISTINGUISH_FIRST_DUCK - duck->set_type(Duck::TYPE_VERTEX); -#endif - duck->set_name(strprintf("%x-vertex",bline_point_list.front().get())); - duck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),bline_point_list.front()) - ); - duck->signal_user_click(2).connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),bline_point_list.front()) - ); - get_work_area()->add_duck(duck); - - // Add the tangent1 duck - tduck=new WorkArea::Duck(bline_point.get_tangent1()); - tduck->set_editable(true); - tduck->set_name(strprintf("%x-tangent1",bline_point_list.front().get())); - tduck->set_origin(duck); - tduck->set_scalar(-0.33333333333333333); - tduck->set_tangent(true); - tduck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),bline_point_list.front()) - ); - tduck->signal_user_click(2).connect( - sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),bline_point_list.front()) - ); - get_work_area()->add_duck(tduck); - - bezier->p2=duck; - bezier->c2=tduck; - - bezier->signal_user_click(2).connect( - sigc::bind( - sigc::mem_fun( - *this, - &studio::StateBLine_Context::popup_bezier_menu - ), - bline_point_list.front() - ) - ); - - //get_work_area()->add_duck(bezier->c1); - get_work_area()->add_bezier(bezier); - } - if(bezier && !loop_) - { - duck=new WorkArea::Duck(bline_point.get_vertex()); - duck->set_ignore(true); - duck->set_name("temp"); - - // Add the tangent1 duck - tduck=new WorkArea::Duck(Vector(0,0)); - tduck->set_ignore(true); - tduck->set_name("ttemp"); - tduck->set_origin(duck); - tduck->set_scalar(-0.33333333333333333); - - tduck->set_tangent(true); - bezier->p2=duck; - bezier->c2=tduck; - - get_work_area()->add_duck(bezier->p2); - //get_work_area()->add_duck(bezier->c2); - get_work_area()->add_bezier(bezier); - - duck->set_guid(synfig::GUID()); - tduck->set_guid(synfig::GUID()); - - next_duck=duck; - } - - if(!button_down) - { - if(curr_duck) - { - if(next_duck) - { - curr_duck=next_duck; - next_duck=0; - } - } - } - get_work_area()->queue_draw(); -} - - -bool -StateBLine_Context::on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node) -{ - BLinePoint bline_point(value_node->get_value().get(BLinePoint())); - bline_point.set_vertex(point); - value_node->set_value(bline_point); - //refresh_ducks(); - return true; -} - -bool -StateBLine_Context::on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node) -{ - BLinePoint bline_point(value_node->get_value().get(BLinePoint())); - bline_point.set_tangent1(point); - value_node->set_value(bline_point); - //refresh_ducks(); - return true; -} - -bool -StateBLine_Context::on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node) -{ - BLinePoint bline_point(value_node->get_value().get(BLinePoint())); - bline_point.set_tangent2(point); - value_node->set_value(bline_point); - //refresh_ducks(); - return true; -} - -void -StateBLine_Context::loop_bline() -{ - loop_=true; - - refresh_ducks(false); -} - -void -StateBLine_Context::unloop_bline() -{ - loop_=false; - - refresh_ducks(false); -} - -void -StateBLine_Context::popup_vertex_menu(synfig::ValueNode_Const::Handle value_node) -{ - menu.items().clear(); - - if(loop_) - { - menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unloop BLine"), - sigc::mem_fun(*this,&studio::StateBLine_Context::unloop_bline) - )); - } else { - menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Loop BLine"), - sigc::mem_fun(*this,&studio::StateBLine_Context::loop_bline) - )); - } - - menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Delete Vertex"), - sigc::bind( - sigc::mem_fun(*this,&studio::StateBLine_Context::bline_delete_vertex), - value_node - ) - )); - - menu.popup(0,0); -} - -void -StateBLine_Context::popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node) -{ - menu.items().clear(); - - menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Insert Vertex"), - sigc::bind( - sigc::bind( - sigc::mem_fun(*this,&studio::StateBLine_Context::bline_insert_vertex), - location - ), - value_node - ) - )); - - menu.popup(0,0); -} - -void -StateBLine_Context::bline_insert_vertex(synfig::ValueNode_Const::Handle value_node, float origin) -{ - list::iterator iter; - - for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) - if(*iter==value_node) - { - BLinePoint bline_point; - BLinePoint next_bline_point((*iter)->get_value().get(BLinePoint())); - BLinePoint prev_bline_point; - - list::iterator prev(iter); - if(iter==bline_point_list.begin()) - { - assert(loop_); - prev = bline_point_list.end(); - } - prev--; - - prev_bline_point=(*prev)->get_value().get(BLinePoint()); - - etl::hermite curve(prev_bline_point.get_vertex(), - next_bline_point.get_vertex(), - prev_bline_point.get_tangent2(), - next_bline_point.get_tangent1()); - etl::derivative< etl::hermite > deriv(curve); - - bline_point.set_vertex(curve(origin)); - bline_point.set_width((next_bline_point.get_width()-prev_bline_point.get_width())*origin+prev_bline_point.get_width()); - bline_point.set_tangent1(deriv(origin)*std::min(1.0f-origin,origin)); - bline_point.set_tangent2(bline_point.get_tangent1()); - bline_point.set_split_tangent_flag(false); - bline_point.set_origin(origin); - -/* - bline_point.set_vertex((next_bline_point.get_vertex()+prev_bline_point.get_vertex())*0.5); - bline_point.set_width((next_bline_point.get_width()+prev_bline_point.get_width())*0.5); - bline_point.set_origin(origin); - bline_point.set_split_tangent_flag(false); - bline_point.set_tangent1((next_bline_point.get_vertex()-prev_bline_point.get_vertex())*0.5); -*/ - - bline_point_list.insert(iter,ValueNode_Const::create(bline_point)); - break; - } - - if(iter==bline_point_list.end()) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to find where to insert vertex, internal error, please report this bug")); - } - - refresh_ducks(false); -} - -void -StateBLine_Context::bline_delete_vertex(synfig::ValueNode_Const::Handle value_node) -{ - list::iterator iter; - - for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) - if(*iter==value_node) - { - bline_point_list.erase(iter); - break; - } - if(iter==bline_point_list.end()) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to remove vertex, internal error, please report this bug")); - } - - refresh_ducks(false); -} - -void -StateBLine_Context::popup_handle_menu(synfig::ValueNode_Const::Handle value_node) -{ - menu.items().clear(); - - BLinePoint bline_point(value_node->get_value().get(BLinePoint())); - - if(bline_point.get_split_tangent_flag()) - menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Merge Tangents"), - sigc::bind( - sigc::mem_fun(*this,&studio::StateBLine_Context::bline_attach_handle), - value_node - ) - )); - else - menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Split Tangents"), - sigc::bind( - sigc::mem_fun(*this,&studio::StateBLine_Context::bline_detach_handle), - value_node - ) - )); - - menu.popup(0,0); -} - -void -StateBLine_Context::bline_detach_handle(synfig::ValueNode_Const::Handle value_node) -{ - BLinePoint bline_point(value_node->get_value().get(BLinePoint())); - bline_point.set_split_tangent_flag(true); - bline_point.set_tangent2(bline_point.get_tangent1()); - value_node->set_value(bline_point); - refresh_ducks(false); -} - -void -StateBLine_Context::bline_attach_handle(synfig::ValueNode_Const::Handle value_node) -{ - BLinePoint bline_point(value_node->get_value().get(BLinePoint())); - bline_point.set_tangent1((bline_point.get_tangent1()+bline_point.get_tangent2())*0.5); - bline_point.set_split_tangent_flag(false); - value_node->set_value(bline_point); - refresh_ducks(false); -} diff --git a/synfig-studio/src/gui/state_bline.h b/synfig-studio/src/gui/state_bline.h deleted file mode 100644 index 0f3ce0d..0000000 --- a/synfig-studio/src/gui/state_bline.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_bline.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H -#define __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateBLine_Context; - -class StateBLine : public Smach::state -{ -public: - StateBLine(); - ~StateBLine(); -}; // END of class StateBLine - -extern StateBLine state_bline; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_circle.cpp b/synfig-studio/src/gui/state_circle.cpp deleted file mode 100644 index 5ef611b..0000000 --- a/synfig-studio/src/gui/state_circle.cpp +++ /dev/null @@ -1,1066 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_circle.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include -#include - -#include "state_circle.h" -#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 "duck.h" -#include "widgets/widget_enum.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ -enum CircleFalloff -{ - CIRCLE_SQUARED =0, - CIRCLE_INTERPOLATION_LINEAR =1, - CIRCLE_COSINE =2, - CIRCLE_SIGMOND =3, - CIRCLE_SQRT =4, - CIRCLE_NUM_FALLOFF -}; - -/* === G L O B A L S ======================================================= */ - -StateCircle studio::state_circle; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateCircle_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - Duckmatic::Push duckmatic_push; - - Point point_holder; - - etl::handle point2_duck; - - void refresh_ducks(); - - bool prev_workarea_layer_status_; - - //Toolbox settings - synfigapp::Settings& settings; - - //Toolbox display - Gtk::Table options_table; - - Gtk::Entry entry_id; //what to name the layer - - Widget_Enum enum_falloff; -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - Widget_Enum enum_blend; -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - Gtk::Adjustment adj_feather; - Gtk::Adjustment adj_number_of_bline_points; - Gtk::Adjustment adj_bline_point_angle_offset; - Gtk::SpinButton spin_feather; - Gtk::SpinButton spin_number_of_bline_points; - Gtk::SpinButton spin_bline_point_angle_offset; - - Gtk::CheckButton checkbutton_invert; - Gtk::CheckButton checkbutton_layer_circle; - Gtk::CheckButton checkbutton_layer_region; - Gtk::CheckButton checkbutton_layer_outline; - Gtk::CheckButton checkbutton_layer_curve_gradient; - Gtk::CheckButton checkbutton_layer_plant; - Gtk::CheckButton checkbutton_layer_link_origins; - Gtk::CheckButton checkbutton_layer_origins_at_center; - -public: - - // this only counts the layers which will have their origins linked - int layers_to_create()const - { - return - (get_layer_circle_flag() && get_layer_origins_at_center_flag()) + - get_layer_region_flag() + - get_layer_outline_flag() + - get_layer_curve_gradient_flag() + - get_layer_plant_flag(); - } - - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - int get_falloff()const { return enum_falloff.get_value(); } - void set_falloff(int x) { return enum_falloff.set_value(x); } - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - int get_blend()const { return enum_blend.get_value(); } - void set_blend(int x) { return enum_blend.set_value(x); } -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - Real get_feather()const { return adj_feather.get_value(); } - void set_feather(Real f) { adj_feather.set_value(f); } - - Real get_number_of_bline_points()const { return adj_number_of_bline_points.get_value(); } - void set_number_of_bline_points(Real f) { adj_number_of_bline_points.set_value(f); } - - Real get_bline_point_angle_offset()const { return adj_bline_point_angle_offset.get_value(); } - void set_bline_point_angle_offset(Real f) { adj_bline_point_angle_offset.set_value(f); } - - bool get_invert()const { return checkbutton_invert.get_active(); } - void set_invert(bool i) { checkbutton_invert.set_active(i); } - - bool get_layer_circle_flag()const { return checkbutton_layer_circle.get_active(); } - void set_layer_circle_flag(bool x) { return checkbutton_layer_circle.set_active(x); } - - bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } - void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } - - bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } - void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } - - bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } - void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } - - bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } - void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } - - bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } - void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } - - bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); } - void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); } - - void refresh_tool_options(); //to refresh the toolbox - - //events - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - //constructor destructor - StateCircle_Context(CanvasView* canvas_view); - ~StateCircle_Context(); - - //Canvas interaction - 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();} - - //Modifying settings etc. - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - - void make_circle(const Point& p1, const Point& p2); - -}; // END of class StateCircle_Context - -/* === M E T H O D S ======================================================= */ - -StateCircle::StateCircle(): - Smach::state("circle") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateCircle_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_STOP,&StateCircle_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateCircle_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateCircle_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateCircle_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateCircle_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateCircle_Context::event_mouse_click_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateCircle_Context::event_refresh_tool_options)); -} - -StateCircle::~StateCircle() -{ -} - -void -StateCircle_Context::load_settings() -{ - String value; - - //parse the arguments yargh! - if(settings.get_value("circle.id",value)) - set_id(value); - else - set_id("Circle"); - - if(settings.get_value("circle.fallofftype",value) && value != "") - set_falloff(atoi(value.c_str())); - else - set_falloff(2); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - if(settings.get_value("circle.blend",value) && value != "") - set_blend(atoi(value.c_str())); - else - set_blend(0);//(int)Color::BLEND_COMPOSITE); //0 should be blend composites value -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - if(settings.get_value("circle.feather",value)) - set_feather(atof(value.c_str())); - else - set_feather(0); - - if(settings.get_value("circle.number_of_bline_points",value)) - set_number_of_bline_points(atof(value.c_str())); - else - set_number_of_bline_points(4); - - if(settings.get_value("circle.bline_point_angle_offset",value)) - set_bline_point_angle_offset(atof(value.c_str())); - else - set_bline_point_angle_offset(0); - - if(settings.get_value("circle.invert",value) && value != "0") - set_invert(true); - else - set_invert(false); - - if(settings.get_value("circle.layer_circle",value) && value=="0") - set_layer_circle_flag(false); - else - set_layer_circle_flag(true); - - if(settings.get_value("circle.layer_region",value) && value=="1") - set_layer_region_flag(true); - else - set_layer_region_flag(false); - - if(settings.get_value("circle.layer_outline",value) && value=="1") - set_layer_outline_flag(true); - else - set_layer_outline_flag(false); - - if(settings.get_value("circle.layer_curve_gradient",value) && value=="1") - set_layer_curve_gradient_flag(true); - else - set_layer_curve_gradient_flag(false); - - if(settings.get_value("circle.layer_plant",value) && value=="1") - set_layer_plant_flag(true); - else - set_layer_plant_flag(false); - - if(settings.get_value("circle.layer_link_origins",value) && value=="0") - set_layer_link_origins_flag(false); - else - set_layer_link_origins_flag(true); - - if(settings.get_value("circle.layer_origins_at_center",value) && value=="0") - set_layer_origins_at_center_flag(false); - else - set_layer_origins_at_center_flag(true); -} - -void -StateCircle_Context::save_settings() -{ - settings.set_value("circle.id",get_id()); - settings.set_value("circle.fallofftype",strprintf("%d",get_falloff())); -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - settings.set_value("circle.blend",strprintf("%d",get_blend())); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - settings.set_value("circle.feather",strprintf("%f",(float)get_feather())); - settings.set_value("circle.number_of_bline_points",strprintf("%d",(int)(get_number_of_bline_points() + 0.5))); - settings.set_value("circle.bline_point_angle_offset",strprintf("%f",(float)get_bline_point_angle_offset())); - settings.set_value("circle.invert",get_invert()?"1":"0"); - settings.set_value("circle.layer_circle",get_layer_circle_flag()?"1":"0"); - settings.set_value("circle.layer_outline",get_layer_outline_flag()?"1":"0"); - settings.set_value("circle.layer_region",get_layer_region_flag()?"1":"0"); - settings.set_value("circle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); - settings.set_value("circle.layer_plant",get_layer_plant_flag()?"1":"0"); - settings.set_value("circle.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); - settings.set_value("circle.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0"); -} - -void -StateCircle_Context::reset() -{ - refresh_ducks(); -} - -void -StateCircle_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Circle"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - String str_number; - str_number=String(id,id.size()-digits,id.size()); - id=String(id,0,id.size()-digits); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StateCircle_Context::StateCircle_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - duckmatic_push(get_work_area()), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), // value lower upper step page - adj_feather( 0, 0, 1, 0.01, 0.1), - adj_number_of_bline_points( 0, 2, 120, 1 , 1 ), - adj_bline_point_angle_offset( 0, -360, 360, 0.1 , 1 ), - spin_feather(adj_feather,0.1,3), - spin_number_of_bline_points(adj_number_of_bline_points,1,0), - spin_bline_point_angle_offset(adj_bline_point_angle_offset,1,1), - checkbutton_invert(_("Invert")), - checkbutton_layer_circle(_("Create Circle Layer")), - checkbutton_layer_region(_("Create Region BLine")), - checkbutton_layer_outline(_("Create Outline BLine")), - checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), - checkbutton_layer_plant(_("Create Plant BLine")), - checkbutton_layer_link_origins(_("Link Origins")), - checkbutton_layer_origins_at_center(_("BLine Origins at Center")) -{ - egress_on_selection_change=true; - - // Set up the tool options dialog - enum_falloff.set_param_desc(ParamDesc("falloff") - .set_local_name(_("Falloff")) - .set_description(_("Determines the falloff function for the feather")) - .set_hint("enum") - .add_enum_value(CIRCLE_INTERPOLATION_LINEAR,"linear",_("Linear")) - .add_enum_value(CIRCLE_SQUARED,"squared",_("Squared")) - .add_enum_value(CIRCLE_SQRT,"sqrt",_("Square Root")) - .add_enum_value(CIRCLE_SIGMOND,"sigmond",_("Sigmond")) - .add_enum_value(CIRCLE_COSINE,"cosine",_("Cosine"))); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method") - .set_local_name(_("Blend Method")) - .set_description(_("Defines the blend method to be used for circles"))); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - load_settings(); - - options_table.attach(*manage(new Gtk::Label(_("Circle 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_layer_circle, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_origins_at_center, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //invert flag - options_table.attach(checkbutton_invert, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Falloff:"))), 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(enum_falloff, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //feather stuff - options_table.attach(*manage(new Gtk::Label(_("Feather:"))), 0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_feather, 1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - options_table.attach(enum_blend, 0, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - options_table.attach(*manage(new Gtk::Label(_("BLine Points:"))), 0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_number_of_bline_points, 1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - -options_table.attach(*manage(new Gtk::Label(_("Point Angle Offset:"))), 0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_bline_point_angle_offset, 1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.show_all(); - - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - // Hide the tables if they are showing - //prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateCircle_Context::on_user_click)); - get_work_area()->set_cursor(Gdk::CROSSHAIR); - - App::toolbox->refresh(); -} - -void -StateCircle_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Circle Tool")); - App::dialog_tool_options->set_name("circle"); -} - -Smach::event_result -StateCircle_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateCircle_Context::~StateCircle_Context() -{ - save_settings(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - //if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_canvas_view()->queue_rebuild_ducks(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateCircle_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateCircle_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StateCircle_Context::make_circle(const Point& _p1, const Point& _p2) -{ - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Circle")); - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer; - - Canvas::Handle canvas; - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - - const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); - const Point p1(transform.unperform(_p1)); - const Point p2(transform.unperform(_p2)); - - Real radius((p2-p1).mag()); - int points = get_number_of_bline_points(); - Angle::deg offset(get_bline_point_angle_offset()); - Angle::deg angle(360.0/points); - Real tangent(4 * ((points == 2) - ? 1 - : ((2 * Angle::cos(angle/2).get() - Angle::cos(angle).get() - 1) / Angle::sin(angle).get()))); - Vector origin; - Real x, y; - - if (get_layer_origins_at_center_flag()) - { - x = y = 0; - origin = p1; - } - else - { - x = p1[0]; - y = p1[1]; - } - - std::vector new_list; - for (int i = 0; i < points; i++) - { - new_list.push_back(*(new BLinePoint)); - new_list[i].set_width(1); - new_list[i].set_vertex(Point(radius*Angle::cos(angle*i + offset).get() + x, - radius*Angle::sin(angle*i + offset).get() + y)); - new_list[i].set_tangent(Point(-radius*tangent*Angle::sin(angle*i + offset).get(), - radius*tangent*Angle::cos(angle*i + offset).get())); - } - - ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); - assert(value_node_bline); - - ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin)); - assert(value_node_origin); - - // Set the looping flag - value_node_bline->set_loop(true); - - if(!canvas) - canvas=get_canvas_view()->get_canvas(); - - value_node_bline->set_member_canvas(canvas); - - // count how many layers we're going to be creating - int layers_to_create = this->layers_to_create(); - - /////////////////////////////////////////////////////////////////////////// - // C I R C L E - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_circle_flag() && - get_falloff() >= 0 && get_falloff() < CIRCLE_NUM_FALLOFF) - { - layer=get_canvas_interface()->add_layer_to("circle",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - - layer->set_param("radius",(p2-p1).mag()); - get_canvas_interface()->signal_layer_param_changed()(layer,"radius"); - - layer->set_param("falloff",get_falloff()); - get_canvas_interface()->signal_layer_param_changed()(layer,"falloff"); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - layer->set_param("blend_method",get_blend()); - get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - layer->set_description(get_id()); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - // only link the circle's origin parameter if the option is selected, we're putting bline - // origins at their centers, and we're creating more than one layer - if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Circle layer")); - group.cancel(); - throw String(_("Unable to create Circle layer")); - return; - } - } - else - { - layer->set_param("origin",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // C U R V E G R A D I E N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_curve_gradient_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Gradient")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - layer->set_param("blend_method",get_blend()); - get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - - // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // P L A N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_plant_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Plant")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - layer->set_param("blend_method",get_blend()); - get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - - // only link the plant's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // R E G I O N - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_region_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Region")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - layer->set_param("blend_method",get_blend()); - get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm - // using 2 separate ones. - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - - // only link the region's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // O U T L I N E - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_outline_flag()) - { - Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Outline")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - layer->set_param("blend_method",get_blend()); - get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - - // only link the outline's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - egress_on_selection_change=false; - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - reset(); - increment_id(); -} - -Smach::event_result -StateCircle_Context::event_mouse_click_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) - { - point_holder=get_work_area()->snap_point_to_grid(event.pos); - etl::handle duck=new Duck(); - duck->set_point(point_holder); - duck->set_name("p1"); - duck->set_type(Duck::TYPE_POSITION); - duck->set_editable(false); - get_work_area()->add_duck(duck); - - point2_duck=new Duck(); - point2_duck->set_point(Vector(0,0)); - point2_duck->set_name("radius"); - point2_duck->set_origin(duck); - point2_duck->set_radius(true); - point2_duck->set_scalar(-1); - point2_duck->set_type(Duck::TYPE_RADIUS); - point2_duck->set_hover(true); - get_work_area()->add_duck(point2_duck); - - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) - { - if (!point2_duck) return Smach::RESULT_OK; - point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos)); - get_work_area()->queue_draw(); - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) - { - Point point(get_work_area()->snap_point_to_grid(event.pos)); - - if (App::restrict_radius_ducks) - { - if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0]; - if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1]; - } - - make_circle(point_holder, point); - get_work_area()->clear_ducks(); - return Smach::RESULT_ACCEPT; - } - - return Smach::RESULT_OK; -} - - -void -StateCircle_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); -} diff --git a/synfig-studio/src/gui/state_circle.h b/synfig-studio/src/gui/state_circle.h deleted file mode 100644 index b33ccf3..0000000 --- a/synfig-studio/src/gui/state_circle.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_circle.h -** \brief Circle creation state -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_CIRCLE_H -#define __SYNFIG_STUDIO_STATE_CIRCLE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateCircle_Context; - -class StateCircle : public Smach::state -{ -public: - StateCircle(); - ~StateCircle(); -}; // END of class StateCircle - -extern StateCircle state_circle; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_draw.cpp b/synfig-studio/src/gui/state_draw.cpp deleted file mode 100644 index 4482045..0000000 --- a/synfig-studio/src/gui/state_draw.cpp +++ /dev/null @@ -1,2036 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_draw.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2007 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 -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include - -#include "state_draw.h" -#include "state_stroke.h" -#include "state_normal.h" -#include "canvasview.h" -#include "workarea.h" -#include "app.h" -#include -#include -#include -#include -#include -#include "event_mouse.h" -#include "event_layerclick.h" -#include "toolbox.h" - -#include -#include - -#include -#include "dialog_tooloptions.h" - -#include -#include -#include -#include -#include -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateDraw studio::state_draw; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateDraw_Context : public sigc::trackable -{ - typedef etl::smart_ptr > StrokeData; - typedef etl::smart_ptr > WidthData; - - typedef list< pair > StrokeQueue; - - StrokeQueue stroke_queue; - - - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - bool prev_table_status; - bool loop_; - bool prev_workarea_layer_status_; - - int nested; - sigc::connection process_queue_connection; - - ValueNode_BLine::Handle last_stroke; - synfig::String last_stroke_id; - - Gtk::Menu menu; - - //Duckmatic::Push duckmatic_push; - - std::list< etl::smart_ptr > > stroke_list; - - void refresh_ducks(); - - 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); - - Smach::event_result new_region(std::list bline,synfig::Real radius); - - Smach::event_result extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop); - Smach::event_result extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop); - void reverse_bline(std::list &bline); - - synfigapp::Settings& settings; - - Gtk::Table options_table; - Gtk::Entry entry_id; - Gtk::CheckButton checkbutton_pressure_width; - Gtk::CheckButton checkbutton_round_ends; - Gtk::CheckButton checkbutton_auto_loop; // whether to loop new strokes which start and end in the same place - Gtk::CheckButton checkbutton_auto_extend; // whether to extend existing lines - Gtk::CheckButton checkbutton_auto_link; // whether to link new ducks to existing ducks - Gtk::CheckButton checkbutton_region; // whether to create regions - Gtk::CheckButton checkbutton_outline; // whether to create outlines - Gtk::CheckButton checkbutton_auto_export; - Gtk::Button button_fill_last_stroke; - - //pressure spinner and such - Gtk::Adjustment adj_min_pressure; - Gtk::SpinButton spin_min_pressure; - Gtk::CheckButton check_min_pressure; - - Gtk::Adjustment adj_feather; - Gtk::SpinButton spin_feather; - - Gtk::Adjustment adj_globalthres; - Gtk::SpinButton spin_globalthres; - - Gtk::Adjustment adj_localthres; - Gtk::CheckButton check_localerror; - void UpdateErrorBox(); //switches the stuff if need be :) - - //Added by Adrian - data drive HOOOOO - synfigapp::BLineConverter blineconv; - -public: - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - bool get_pressure_width_flag()const { return checkbutton_pressure_width.get_active(); } - void set_pressure_width_flag(bool x) { return checkbutton_pressure_width.set_active(x); } - - bool get_auto_loop_flag()const { return checkbutton_auto_loop.get_active(); } - void set_auto_loop_flag(bool x) { return checkbutton_auto_loop.set_active(x); } - - bool get_auto_extend_flag()const { return checkbutton_auto_extend.get_active(); } - void set_auto_extend_flag(bool x) { return checkbutton_auto_extend.set_active(x); } - - bool get_auto_link_flag()const { return checkbutton_auto_link.get_active(); } - void set_auto_link_flag(bool x) { return checkbutton_auto_link.set_active(x); } - - bool get_region_flag()const { return checkbutton_region.get_active(); } - void set_region_flag(bool x) { return checkbutton_region.set_active(x); } - - bool get_outline_flag()const { return checkbutton_outline.get_active(); } - void set_outline_flag(bool x) { return checkbutton_outline.set_active(x); } - - bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); } - void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); } - - Real get_min_pressure() const { return adj_min_pressure.get_value(); } - void set_min_pressure(Real x) { return adj_min_pressure.set_value(x); } - - Real get_feather() const { return adj_feather.get_value(); } - void set_feather(Real x) { return adj_feather.set_value(x); } - - Real get_gthres() const { return adj_globalthres.get_value(); } - void set_gthres(Real x) { return adj_globalthres.set_value(x); } - - Real get_lthres() const { return adj_localthres.get_value(); } - void set_lthres(Real x) { return adj_localthres.set_value(x); } - - bool get_local_error_flag() const { return check_localerror.get_active(); } - void set_local_error_flag(bool x) { check_localerror.set_active(x); } - - bool get_min_pressure_flag()const { return check_min_pressure.get_active(); } - void set_min_pressure_flag(bool x) { check_min_pressure.set_active(x); } - - void load_settings(); - void save_settings(); - void increment_id(); - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_mouse_down_handler(const Smach::event& x); - - Smach::event_result event_stroke(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - void refresh_tool_options(); - - Smach::event_result process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag=false); - - bool process_queue(); - - - StateDraw_Context(CanvasView* canvas_view); - - ~StateDraw_Context(); - - const etl::handle& get_canvas_view()const{return canvas_view_;} - etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} - synfig::Time get_time()const { return get_canvas_interface()->get_time(); } - synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} - WorkArea * get_work_area()const{return canvas_view_->get_work_area();} - - //void on_user_click(synfig::Point point); - -// bool run(); -}; // END of class StateDraw_Context - - -/* === M E T H O D S ======================================================= */ - -StateDraw::StateDraw(): - Smach::state("draw") -{ - insert(event_def(EVENT_STOP,&StateDraw_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateDraw_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateDraw_Context::event_mouse_down_handler)); - insert(event_def(EVENT_WORKAREA_STROKE,&StateDraw_Context::event_stroke)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateDraw_Context::event_refresh_tool_options)); -} - -StateDraw::~StateDraw() -{ -} - - -void -StateDraw_Context::load_settings() -{ - String value; - - if(settings.get_value("draw.id",value)) - set_id(value); - else - set_id("NewDrawing"); - - if(settings.get_value("draw.pressure_width",value) && value=="0") - set_pressure_width_flag(false); - else - set_pressure_width_flag(true); - - if(settings.get_value("draw.auto_loop",value) && value=="0") - set_auto_loop_flag(false); - else - set_auto_loop_flag(true); - - if(settings.get_value("draw.auto_extend",value) && value=="0") - set_auto_extend_flag(false); - else - set_auto_extend_flag(true); - - if(settings.get_value("draw.auto_link",value) && value=="0") - set_auto_link_flag(false); - else - set_auto_link_flag(true); - - if(settings.get_value("draw.region",value) && value=="0") - set_region_flag(false); - else - set_region_flag(true); - - if(settings.get_value("draw.outline",value) && value=="0") - set_outline_flag(false); - else - set_outline_flag(true); - - if(settings.get_value("draw.auto_export",value) && value=="1") - set_auto_export_flag(true); - else - set_auto_export_flag(false); - - if(settings.get_value("draw.min_pressure_on",value) && value=="0") - set_min_pressure_flag(false); - else - set_min_pressure_flag(true); - - if(settings.get_value("draw.min_pressure",value)) - { - Real n = atof(value.c_str()); - set_min_pressure(n); - }else - set_min_pressure(0); - - if(settings.get_value("draw.feather",value)) - { - Real n = atof(value.c_str()); - set_feather(n); - }else - set_feather(0); - - if(settings.get_value("draw.gthreshold",value)) - { - Real n = atof(value.c_str()); - set_gthres(n); - } - - if(settings.get_value("draw.lthreshold",value)) - { - Real n = atof(value.c_str()); - set_lthres(n); - } - - if(settings.get_value("draw.localize",value) && value == "1") - set_local_error_flag(true); - else - set_local_error_flag(false); -} - -void -StateDraw_Context::save_settings() -{ - settings.set_value("draw.id",get_id().c_str()); - settings.set_value("draw.pressure_width",get_pressure_width_flag()?"1":"0"); - settings.set_value("draw.auto_loop",get_auto_loop_flag()?"1":"0"); - settings.set_value("draw.auto_extend",get_auto_extend_flag()?"1":"0"); - settings.set_value("draw.auto_link",get_auto_link_flag()?"1":"0"); - settings.set_value("draw.region",get_region_flag()?"1":"0"); - settings.set_value("draw.outline",get_outline_flag()?"1":"0"); - settings.set_value("draw.auto_export",get_auto_export_flag()?"1":"0"); - settings.set_value("draw.min_pressure",strprintf("%f",get_min_pressure())); - settings.set_value("draw.feather",strprintf("%f",get_feather())); - settings.set_value("draw.min_pressure_on",get_min_pressure_flag()?"1":"0"); - settings.set_value("draw.gthreshold",strprintf("%f",get_gthres())); - settings.set_value("draw.lthreshold",strprintf("%f",get_lthres())); - settings.set_value("draw.localize",get_local_error_flag()?"1":"0"); -} - -void -StateDraw_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Drawing"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - 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()); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StateDraw_Context::StateDraw_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - loop_(false), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), - checkbutton_pressure_width(_("Pressure Width")), - checkbutton_auto_loop(_("Auto Loop")), - checkbutton_auto_extend(_("Auto Extend")), - checkbutton_auto_link(_("Auto Link")), - 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), - spin_min_pressure(adj_min_pressure,0.1,3), - check_min_pressure(_("Min Pressure")), - adj_feather(0,0,10000,0.01,0.1), - spin_feather(adj_feather,0.01,4), - adj_globalthres(.70f,0.01,10000,0.01,0.1), - spin_globalthres(adj_globalthres,0.01,3), - adj_localthres(20,1,100000,0.1,1), - check_localerror(_("LocalError")) - -{ - 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_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(*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(button_fill_last_stroke, 0, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - button_fill_last_stroke.signal_pressed().connect(sigc::mem_fun(*this,&StateDraw_Context::fill_last_stroke)); - check_localerror.signal_toggled().connect(sigc::mem_fun(*this,&StateDraw_Context::UpdateErrorBox)); - - options_table.show_all(); - refresh_tool_options(); - //App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->present(); - - - old_duckmask=get_work_area()->get_type_mask(); - get_work_area()->set_type_mask(Duck::TYPE_ALL-Duck::TYPE_TANGENT-Duck::TYPE_WIDTH); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // Turn off duck clicking - get_work_area()->set_allow_duck_clicks(false); - - // clear out the ducks - //get_work_area()->clear_ducks(); - - // Refresh the work area - //get_work_area()->queue_draw(); - - // Hide the tables if they are showing - prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateDraw_Context::on_user_click)); - - get_work_area()->set_cursor(Gdk::PENCIL); - - App::toolbox->refresh(); - - refresh_ducks(); -} - - -void StateDraw_Context::UpdateErrorBox() -{ - if(get_local_error_flag()) - { - spin_globalthres.set_adjustment(adj_localthres); - spin_globalthres.set_value(adj_localthres.get_value()); - spin_globalthres.set_increments(0.1,1); - }else - { - spin_globalthres.set_adjustment(adj_globalthres); - spin_globalthres.set_value(adj_globalthres.get_value()); - spin_globalthres.set_increments(0.01,.1); - } - - spin_globalthres.update(); -} - -void -StateDraw_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Draw Tool")); - App::dialog_tool_options->set_name("draw"); - - App::dialog_tool_options->add_button( - Gtk::StockID("synfig-fill"), - _("Fill Last Stroke") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &StateDraw_Context::fill_last_stroke)); -} - -Smach::event_result -StateDraw_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateDraw_Context::~StateDraw_Context() -{ - save_settings(); - - App::dialog_tool_options->clear(); - - get_work_area()->set_type_mask(old_duckmask); - - get_work_area()->reset_cursor(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - - // Restore duck clicking - get_work_area()->set_allow_duck_clicks(true); - - // Enable the time bar - get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateDraw_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateDraw_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateDraw_Context::event_mouse_down_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - switch(event.button) - { - case BUTTON_LEFT: - { - // Enter the stroke state to get the stroke - get_canvas_view()->get_smach().push_state(&state_stroke); - return Smach::RESULT_ACCEPT; - } - - default: - return Smach::RESULT_OK; - } -} - -#define SIMILAR_TANGENT_THRESHOLD (0.2) - -struct debugclass -{ - synfig::String x; - debugclass(const synfig::String &x):x(x) - { -// synfig::warning(">>>>>>>>>>>>>>>>>>> "+x); - } - ~debugclass() - { -// synfig::warning("<<<<<<<<<<<<<<<<<<< "+x); - } -}; - -struct DepthCounter -{ - int &i; - DepthCounter(int &i):i(i) { i++; } - ~DepthCounter() { i--; } -}; - -Smach::event_result -StateDraw_Context::event_stroke(const Smach::event& x) -{ -// debugclass debugger("StateDraw_Context::event_stroke(const Smach::event& x)"); - - const EventStroke& event(*reinterpret_cast(&x)); - - assert(event.stroke_data); - - get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color()); - - if(nested==0) - { - DirtyTrap dirty_trap(get_work_area()); - Smach::event_result result; - result=process_stroke(event.stroke_data,event.width_data,event.modifier&Gdk::CONTROL_MASK || event.modifier&Gdk::BUTTON2_MASK); - process_queue(); - return result; - } - - stroke_queue.push_back(pair(event.stroke_data,event.width_data)); - - return Smach::RESULT_ACCEPT; -} - -bool -StateDraw_Context::process_queue() -{ -// debugclass debugger("StateDraw_Context::process_queue()"); - if(nested) - return true; - DepthCounter depth_counter(nested); - while(!stroke_queue.empty()) - { - pair front(stroke_queue.front()); - process_stroke(front.first,front.second); - stroke_queue.pop_front(); - } - return false; -} - -Smach::event_result -StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag) -{ -// debugclass debugger("StateDraw_Context::process_stroke"); - DepthCounter depth_counter(nested); - - const float radius(synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc())+(abs(get_work_area()->get_pw())+abs(get_work_area()->get_ph()))*5); - - - // If we aren't using pressure width, - // then set all the width to 1 - if(!get_pressure_width_flag()) - { - std::list::iterator iter; - for(iter=width_data->begin();iter!=width_data->end();++iter) - { - *iter=1.0; - } - } - - //get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color()); - //stroke_list.push_back(event.stroke_data); - //refresh_ducks(); - - std::list bline; - bool loop_bline_flag(false); - - //Changed by Adrian - use resident class :) - //synfigapp::convert_stroke_to_bline(bline, *event.stroke_data,*event.width_data, synfigapp::Main::get_bline_width()); - blineconv.width = synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc()); - - if(get_local_error_flag()) - { - float pw = get_work_area()->get_pw(); - float ph = get_work_area()->get_ph(); - - blineconv.pixelwidth = sqrt(pw*pw+ph*ph); - blineconv.smoothness = get_lthres(); - }else - { - blineconv.pixelwidth = 1; - blineconv.smoothness = get_gthres(); - } - - blineconv(bline,*stroke_data,*width_data); - - //Postprocess to require minimum pressure - if(get_min_pressure_flag()) - { - synfigapp::BLineConverter::EnforceMinWidth(bline,get_min_pressure()); - } - - // 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) - { - loop_bline_flag=true; - Vector tangent; - Real width(0); - - while (bline.size() > 2 && - (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius) - { - tangent=bline.back().get_tangent1(); - width=bline.back().get_width(); - bline.pop_back(); - } - - if(abs(bline.front().get_tangent1().norm()*tangent.norm().perp())>SIMILAR_TANGENT_THRESHOLD) - { - // If the tangents are not similar, then - // split the tangents - bline.front().set_split_tangent_flag(true); - bline.front().set_tangent1(tangent); - } - else - { - // If the tangents are similar, then set the tangent - // to the average of the two - bline.front().set_tangent((tangent+bline.front().get_tangent1())*0.5f); - } - - // Add the widths of the two points - { - Real tmp_width(bline.front().get_width()+width); - tmp_width=tmp_width<=1?tmp_width:1; - bline.front().set_width(tmp_width); - } - } - - // If the bline only has one blinepoint, then there is nothing to do. - 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); - - return new_bline(bline,loop_bline_flag,radius); -} - -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_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; - 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 = 0,finish_duck_index = 0; // initialized to keep the compiler happy; shouldn't be needed though - 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 didn't just draw a loop - ie. !loop_bline_flag - // but having loops auto-connect can be useful as well) - if(get_auto_extend_flag() || get_auto_link_flag()) - { - etl::handle start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX)); - etl::handle finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX)); - - // 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 - // line starts at one of the ends of an existing line - if(start_duck)do - { - if(!(start_duck_value_desc=start_duck->get_value_desc()))break; - if(loop_bline_flag)break; // loops don't extend anything - if(!start_duck_value_desc.parent_is_value_node())break; - start_duck_index=start_duck_value_desc.get_index(); // which point on the line did we start drawing at - start_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(start_duck_value_desc.get_parent_value_node()); - if(!get_auto_extend_flag())break; - - // don't extend looped blines - if(start_duck_value_node_bline&&!start_duck_value_node_bline->get_loop()&& - // did we start drawing at either end of the line? - (start_duck_index==0||start_duck_index==start_duck_value_node_bline->link_count()-1)) - { - extend_start=true; - shift_origin=true; - shift_origin_vector=start_duck->get_origin(); - } - }while(0); - - // check whether the end 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 - // line ends at one of the ends of an existing line - if(finish_duck)do - { - if(!(finish_duck_value_desc=finish_duck->get_value_desc()))break; - if(loop_bline_flag)break; - if(!finish_duck_value_desc.parent_is_value_node())break; - finish_duck_index=finish_duck_value_desc.get_index(); - finish_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(finish_duck_value_desc.get_parent_value_node()); - if(!get_auto_extend_flag())break; - - // 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 - // extend both blines, so unless we started and finished at the 2 ends - // 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{ - extend_finish=true; - shift_origin=true; - shift_origin_vector=finish_duck->get_origin(); - } - } - }while(0); - - // if the new line's start didn't extend an existing line, - // check whether it needs to be linked to an existing duck - if(!extend_start&&get_auto_link_flag()&&start_duck&&start_duck_value_desc) - switch(start_duck_value_desc.get_value_type()) - { - case synfig::ValueBase::TYPE_BLINEPOINT: - 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_origin && shift_origin_vector != start_duck->get_origin()) - break; - 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) - extend_finish_join_same=true; - else - extend_finish_join_different=true; - else - join_start_no_extend=true; - // fall through - default:break; - } - - // if the new line's end didn't extend an existing line, - // check whether it needs to be linked to an existing duck - if(!extend_finish&&get_auto_link_flag()&&finish_duck&&finish_duck_value_desc) - switch(finish_duck_value_desc.get_value_type()) - { - case synfig::ValueBase::TYPE_BLINEPOINT: - 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_origin && shift_origin_vector != finish_duck->get_origin()) - break; - 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) - extend_start_join_same=true; - else - extend_start_join_different=true; - else - join_finish_no_extend=true; - // fall through - default:break; - } - } - - ValueNode_BLine::Handle value_node; - std::list trans_bline; - - { - std::list::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 - ); - - 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; - synfig::ValueNode_DynamicList::ListEntry source; - - // the new line's start extends an existing line - if(extend_start) - { - int target_offset = 0; - 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_offset=trans_bline.size(); - } - else - { - result=extend_bline_from_end(start_duck_value_node_bline,trans_bline,complete_loop); - source=start_duck_value_node_bline->list.back(); - } - - if(extend_start_join_different) - LinkableValueNode::Handle::cast_dynamic(source.value_node)-> - set_link("point",finish_duck_value_desc.get_value_node()); - else if(extend_start_join_same) - LinkableValueNode::Handle::cast_dynamic(source.value_node)-> - set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_node_bline-> - list[target_offset+finish_duck_index].value_node),0).get_value_node()); - return result; - } - - // the new line's end extends an existing line - if(extend_finish) - { - int target_offset = 0; - 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_offset=trans_bline.size(); - } - 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(); - } - - if(extend_finish_join_different) - LinkableValueNode::Handle::cast_dynamic(source.value_node)-> - set_link("point",start_duck_value_desc.get_value_node()); - else if(extend_finish_join_same) - LinkableValueNode::Handle::cast_dynamic(source.value_node)-> - set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_node_bline-> - list[target_offset+start_duck_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("point",start_duck_value_desc.get_value_node()); - - if (join_finish_no_extend) - LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)-> - set_link("point",finish_duck_value_desc.get_value_node()); - - 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 */ - // get_canvas_view()->get_ui_interface()->error(_("Unable to add value node")); - // group.cancel(); - // increment_id(); - // return Smach::RESULT_ERROR; - } - - 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); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - 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); - - // if they're both defined, we'll add the region later - 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")); - } - - if(get_feather()) - { - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - } - assert(layer); - //layer->set_description(strprintf("Stroke %d",number)); - //get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - if (shift_origin) - get_canvas_interface()-> - change_value(synfigapp::ValueDesc(layer,"origin"),shift_origin_vector); - - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - increment_id(); - //refresh_ducks(); - return Smach::RESULT_ERROR; - } - layer_list.push_back(layer); - get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); - //refresh_ducks(); - } - - 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) -{ - // Create the action group - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Define Region")); - - 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. - { - std::list::iterator iter; - for(iter=bline.begin();iter!=bline.end();++iter) - { - etl::handle duck(get_work_area()->find_duck(iter->get_vertex(),0,Duck::TYPE_VERTEX)); - - if(!duck) - { - synfig::info(__FILE__":%d: Nothing to enclose!",__LINE__); - return Smach::RESULT_OK; - } - - assert(duck->get_type()==Duck::TYPE_VERTEX); - - synfigapp::ValueDesc value_desc(duck->get_value_desc()); - - if(!value_desc) - { - synfig::info(__FILE__":%d: Got a hit, but no ValueDesc on this duck",__LINE__); - continue; - } - - switch(value_desc.get_value_type()) - { - case synfig::ValueBase::TYPE_BLINEPOINT: - //if(vertex_list.empty() || value_desc!=vertex_list.back()) - vertex_list.push_back(value_desc); - assert(vertex_list.back().is_valid()); - - break; - default: - break; - } - } - } - - assert(vertex_list.back().is_valid()); - - printf("vertex list with %zd bline points\n", vertex_list.size()); - - // Remove any duplicates - { - } - - 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()) - { - bool trivial_case(true); - ValueNode::Handle trivial_case_value_node; - - trivial_case_value_node=vertex_list.front().get_parent_value_node(); - - std::list::iterator iter; - for(iter=vertex_list.begin();iter!=vertex_list.end();++iter) - { - if(trivial_case_value_node!=iter->get_parent_value_node()) - { - trivial_case=false; - break; - } - } - - // \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("the line has %d vertices", value_node_bline->link_count()); - - if(value_node_bline->link_count() <= 2) - { - 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; - } - - // 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) - { - vertex_list.insert(vertex_list.end(), vertex_list.begin(), iter); - vertex_list.erase(vertex_list.begin(), iter); - break; - } - - 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) - { - 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++; - } - - // 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 (whole) - { - // printf("whole (down) (%d) ", min_index); - for (int i = min_index; i >= 0; i--) - { - // printf("%d ", i); - vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); - } - for (int i = points_in_line - 1; i >= min_index; i--) - { - // printf("%d ", i); - vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); - } - } - else - { - // printf("part (down) (%d -> %d) ", max_index, min_index); - for (int i = max_index; i != min_index; i--) - { - if (i == -1) i = points_in_line - 1; - // printf("%d ", i); - vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); - } - 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++) - { - // 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); - } - - debug_show_vertex_list(0, vertex_list, "continuous vertices", -1); - - // \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); - - // Set done to "true" for now. If - // any updates are performed, we will - // change it back to false. - done=true; - - 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 - - int current = 0; - for(;iter!=vertex_list.end();prev=iter,iter++,next++,current++) - { - // 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("t2",value_node_next->get_link("t2")); - value_node->set_link("split",ValueNode_Const::create(true)); - - // 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(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, - // then go ahead and create the new - // 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; - for(iter=vertex_list.begin();iter!=vertex_list.end();++iter) - { - // Ensure that the vertex is exported. - get_canvas_interface()->auto_export(*iter); - - value_node_bline->add(iter->get_value_node()); - //value_node_bline->add(ValueNode_BLine::ListEntry(iter->get_value_node())); - } - - value_node_bline->set_loop(true); - } - - get_canvas_interface()->auto_export(value_node_bline); - - // Now we create the region layer - // Create the layer - { - Layer::Handle layer; - Canvas::Handle canvas(get_canvas_view()->get_canvas()); - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - layer=get_canvas_interface()->add_layer_to("region",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return Smach::RESULT_ERROR; - } - - if(get_feather()) - { - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - } - get_canvas_interface()->signal_layer_param_changed()(layer,"color"); - - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - return Smach::RESULT_ERROR; - } - get_canvas_view()->get_selection_manager()->set_selected_layer(layer); - } - - return Smach::RESULT_ACCEPT; -} - -void -StateDraw_Context::refresh_ducks() -{ - get_canvas_view()->queue_rebuild_ducks(); -/* - get_work_area()->clear_ducks(); - - - std::list< etl::smart_ptr > >::iterator iter; - - for(iter=stroke_list.begin();iter!=stroke_list.end();++iter) - { - get_work_area()->add_stroke(*iter); - } - - get_work_area()->queue_draw(); -*/ -} - - -Smach::event_result -StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop) -{ - // Create the action group - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine")); - - if (complete_loop) - { - synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_node",ValueNode::Handle(value_node)); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline")); - group.cancel(); - return Smach::RESULT_ERROR; - } - } - - std::list::reverse_iterator iter; - for(iter=bline.rbegin();!(iter==bline.rend());++iter) - { - ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter)); - - synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert")); - - assert(action); - synfigapp::ValueDesc value_desc(value_node,0); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_desc",value_desc); - if(!action->set_param("item",ValueNode::Handle(composite))) - synfig::error("ACTION didn't like \"item\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to insert item")); - group.cancel(); - //refresh_ducks(); - return Smach::RESULT_ERROR; - } - } - last_stroke=value_node; - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop) -{ - // Create the action group - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine")); - - if (complete_loop) - { - synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_node",ValueNode::Handle(value_node)); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline")); - group.cancel(); - return Smach::RESULT_ERROR; - } - } - - std::list::iterator iter; - for(iter=bline.begin();iter!=bline.end();++iter) - { - ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter)); - - synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert")); - - assert(action); - synfigapp::ValueDesc value_desc(value_node,value_node->link_count()); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_desc",value_desc); - if(!action->set_param("item",ValueNode::Handle(composite))) - synfig::error("ACTION didn't like \"item\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to insert item")); - group.cancel(); - //refresh_ducks(); - return Smach::RESULT_ERROR; - } - } - last_stroke=value_node; - return Smach::RESULT_ACCEPT; -} - -void -StateDraw_Context::reverse_bline(std::list &bline) -{ - int i; - - std::list::iterator iter,eiter; - iter=bline.begin(); - eiter=bline.end(); - eiter--; - for(i=0;i<(int)bline.size()/2;++iter,--eiter,i++) - { - iter_swap(iter,eiter); - iter->reverse(); - eiter->reverse(); - } -} - -Smach::event_result -StateDraw_Context::fill_last_stroke_and_unselect_other_layers() -{ - if(!last_stroke) - return Smach::RESULT_OK; - - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Fill Stroke")); - - Layer::Handle layer; - - get_canvas_interface()->auto_export(last_stroke); - - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - 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_description(last_stroke_id + _(" Region")); - - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(last_stroke))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - 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); -} diff --git a/synfig-studio/src/gui/state_draw.h b/synfig-studio/src/gui/state_draw.h deleted file mode 100644 index 2c074a5..0000000 --- a/synfig-studio/src/gui/state_draw.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_draw.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_ROTOSCOPE_H -#define __SYNFIG_STUDIO_STATE_ROTOSCOPE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateDraw_Context; - -class StateDraw : public Smach::state -{ -public: - StateDraw(); - ~StateDraw(); -}; // END of class StateDraw - -extern StateDraw state_draw; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_eyedrop.cpp b/synfig-studio/src/gui/state_eyedrop.cpp deleted file mode 100644 index e7cf4bb..0000000 --- a/synfig-studio/src/gui/state_eyedrop.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_eyedrop.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "state_eyedrop.h" -#include "state_normal.h" -#include "workarea.h" -#include -#include "app.h" -#include "dialogs/dialog_color.h" -#include "event_mouse.h" -#include "event_layerclick.h" -#include "toolbox.h" -#include "canvasview.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateEyedrop_Context -{ - CanvasView *canvas_view; - CanvasView::IsWorking is_working; - -public: - StateEyedrop_Context(CanvasView *canvas_view); - ~StateEyedrop_Context(); - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x); - -}; // END of class StateEyedrop_Context - -/* === G L O B A L S ======================================================= */ - -StateEyedrop studio::state_eyedrop; - -/* === P R O C E D U R E S ================================================= */ - -/* === M E T H O D S ======================================================= */ - -StateEyedrop::StateEyedrop(): - Smach::state("eyedrop") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateEyedrop_Context::event_stop_handler)); - insert(event_def(EVENT_STOP,&StateEyedrop_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateEyedrop_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateEyedrop_Context::event_workarea_mouse_button_down_handler)); -} - -StateEyedrop::~StateEyedrop() -{ -} - -StateEyedrop_Context::StateEyedrop_Context(CanvasView *canvas_view): - canvas_view(canvas_view), - is_working(*canvas_view) -{ - synfig::info("Entered Eyedrop State"); - canvas_view->work_area->set_cursor(Gdk::Cursor(Gdk::CROSSHAIR)); - - App::toolbox->refresh(); -} - -StateEyedrop_Context::~StateEyedrop_Context() -{ - synfig::info("Left Eyedrop State"); - canvas_view->work_area->reset_cursor(); - App::toolbox->refresh(); -} - -Smach::event_result -StateEyedrop_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //synfig::info("STATE EYEDROP: Received Stop Event"); - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -// canvas_view->get_smach().pop_state(); -// return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateEyedrop_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - synfig::info("STATE EYEDROP: Received Refresh Event"); - canvas_view->work_area->queue_render_preview(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateEyedrop_Context::event_workarea_mouse_button_down_handler(const Smach::event& x) -{ - synfig::info("STATE EYEDROP: Received mouse button down Event"); - const EventMouse& event(*reinterpret_cast(&x)); - if(event.button==BUTTON_LEFT) - { - Color color(canvas_view->get_canvas()->get_context().get_color(event.pos)); - synfigapp::Main::set_outline_color(color); - studio::App::dialog_color->set_color(color); - return Smach::RESULT_ACCEPT; - } - return Smach::RESULT_OK; -} diff --git a/synfig-studio/src/gui/state_eyedrop.h b/synfig-studio/src/gui/state_eyedrop.h deleted file mode 100644 index 4a90021..0000000 --- a/synfig-studio/src/gui/state_eyedrop.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_eyedrop.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STATE_EYEDROP_H -#define __SYNFIG_STATE_EYEDROP_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateEyedrop_Context; - -class StateEyedrop : public Smach::state -{ -public: - StateEyedrop(); - ~StateEyedrop(); -}; // END of class StateEyedrop - -extern StateEyedrop state_eyedrop; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_fill.cpp b/synfig-studio/src/gui/state_fill.cpp deleted file mode 100644 index cf6c750..0000000 --- a/synfig-studio/src/gui/state_fill.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_fill.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "state_fill.h" -#include "state_normal.h" -#include "workarea.h" -#include -#include "app.h" -#include "dialogs/dialog_color.h" -#include "event_mouse.h" -#include "event_layerclick.h" -#include "toolbox.h" -#include "canvasview.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateFill_Context -{ - CanvasView *canvas_view; - CanvasView::IsWorking is_working; - -public: - StateFill_Context(CanvasView *canvas_view); - ~StateFill_Context(); - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_workarea_layer_clicked_handler(const Smach::event& x); - - - 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();} - - -}; // END of class StateFill_Context - -/* === G L O B A L S ======================================================= */ - -StateFill studio::state_fill; - -/* === P R O C E D U R E S ================================================= */ - -/* === M E T H O D S ======================================================= */ - -StateFill::StateFill(): - Smach::state("fill") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateFill_Context::event_stop_handler)); - insert(event_def(EVENT_STOP,&StateFill_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateFill_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateFill_Context::event_workarea_layer_clicked_handler)); -} - -StateFill::~StateFill() -{ -} - -StateFill_Context::StateFill_Context(CanvasView *canvas_view): - canvas_view(canvas_view), - is_working(*canvas_view) -{ - synfig::info("Entered Fill State"); - canvas_view->work_area->set_cursor(Gdk::CROSSHAIR); - - App::toolbox->refresh(); -} - -StateFill_Context::~StateFill_Context() -{ - synfig::info("Left Fill State"); - canvas_view->work_area->reset_cursor(); - App::toolbox->refresh(); -} - -Smach::event_result -StateFill_Context::event_stop_handler(const Smach::event& /*x*/) -{ - synfig::info("STATE FILL: Received Stop Event"); - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -// canvas_view->get_smach().pop_state(); -// return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateFill_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - synfig::info("STATE FILL: Received Refresh Event"); - canvas_view->work_area->queue_render_preview(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateFill_Context::event_workarea_layer_clicked_handler(const Smach::event& x) -{ - synfig::info("STATE FILL: Received layer clicked Event"); - const EventLayerClick& event(*reinterpret_cast(&x)); - - if(!event.layer) - { - get_canvas_view()->get_ui_interface()->warning(_("No layer here")); - return Smach::RESULT_ACCEPT; - } - - - //synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescSet")); - synfigapp::ValueDesc value_desc(event.layer,"color"); - - if(!get_canvas_interface()->change_value(value_desc,ValueBase(synfigapp::Main::get_fill_color()))) - { - get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color")); - return Smach::RESULT_ERROR; - } - /* - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_desc",value_desc); - action->set_param("time",get_canvas_interface()->get_time()); - //action->set_param("layer",event.layer); - //if(!action->set_param("param",String("color"))) - // synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("new_value",ValueBase(synfigapp::Main::get_fill_color()))) - synfig::error("LayerParamConnect didn't like \"fill_color\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color")); - return Smach::RESULT_ERROR; - } - get_canvas_view()->get_ui_interface()->task(_("Idle")); - */ - return Smach::RESULT_ACCEPT; -} diff --git a/synfig-studio/src/gui/state_fill.h b/synfig-studio/src/gui/state_fill.h deleted file mode 100644 index 349a1ce..0000000 --- a/synfig-studio/src/gui/state_fill.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_fill.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STATE_FILL_H -#define __SYNFIG_STATE_FILL_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateFill_Context; - -class StateFill : public Smach::state -{ -public: - StateFill(); - ~StateFill(); -}; // END of class StateFill - -extern StateFill state_fill; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_gradient.cpp b/synfig-studio/src/gui/state_gradient.cpp deleted file mode 100644 index 68f35c0..0000000 --- a/synfig-studio/src/gui/state_gradient.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_gradient.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include - -#include "state_gradient.h" -#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 "duck.h" - -#include "widgets/widget_enum.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -enum -{ - GRADIENT_INTERPOLATION_LINEAR=0, - GRADIENT_RADIAL=1, - GRADIENT_CONICAL=2, - GRADIENT_SPIRAL=3 -}; - -/* === G L O B A L S ======================================================= */ - -StateGradient studio::state_gradient; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateGradient_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - Duckmatic::Push duckmatic_push; - - synfigapp::Settings& settings; - - Point point_holder; - - etl::handle point2_duck; - - void refresh_ducks(); - - bool prev_workarea_layer_status_; - - Gtk::Table options_table; - Gtk::Entry entry_id; - Widget_Enum enum_type; -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - Widget_Enum enum_blend; -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - -public: - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - int get_type()const { return enum_type.get_value(); } - void set_type(int x) { return enum_type.set_value(x); } - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - int get_blend()const { return enum_blend.get_value(); } - void set_blend(int x) { return enum_blend.set_value(x); } -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - void refresh_tool_options(); - - StateGradient_Context(CanvasView* canvas_view); - - ~StateGradient_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 on_user_click(synfig::Point point); - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - - void make_gradient(const Point& p1, const Point& p2); - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - -}; // END of class StateGradient_Context - -/* === M E T H O D S ======================================================= */ - -StateGradient::StateGradient(): - Smach::state("gradient") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateGradient_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_STOP,&StateGradient_Context::event_stop_handler)); - insert(event_def(EVENT_TABLES_SHOW,&StateGradient_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateGradient_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateGradient_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateGradient_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateGradient_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateGradient_Context::event_mouse_click_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateGradient_Context::event_refresh_tool_options)); -} - -StateGradient::~StateGradient() -{ -} - -void -StateGradient_Context::load_settings() -{ - String value; - - if(settings.get_value("gradient.id",value)) - set_id(value); - else - set_id("Gradient"); - - if(settings.get_value("gradient.type",value)) - set_type(atoi(value.c_str())); - else - set_type(GRADIENT_INTERPOLATION_LINEAR); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - if(settings.get_value("gradient.blend",value)) - set_blend(atoi(value.c_str())); - else - set_blend(Color::BLEND_COMPOSITE); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS -} - -void -StateGradient_Context::save_settings() -{ - settings.set_value("gradient.id",get_id().c_str()); - settings.set_value("gradient.type",strprintf("%d",get_type())); -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - settings.set_value("gradient.blend",strprintf("%d",get_blend())); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS -} - -void -StateGradient_Context::reset() -{ - refresh_ducks(); -} - -void -StateGradient_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Gradient"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - String str_number; - str_number=String(id,id.size()-digits,id.size()); - id=String(id,0,id.size()-digits); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StateGradient_Context::StateGradient_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - duckmatic_push(get_work_area()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - entry_id() -{ - egress_on_selection_change=true; - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Gradient 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); - - enum_type.set_param_desc(ParamDesc("type") - .set_local_name(_("Gradient Type")) - .set_description(_("Determines the type of Gradient used")) - .set_hint("enum") - .add_enum_value(GRADIENT_INTERPOLATION_LINEAR,"linear",_("Linear")) - .add_enum_value(GRADIENT_RADIAL,"radial",_("Radial")) - .add_enum_value(GRADIENT_CONICAL,"conical",_("Conical")) - .add_enum_value(GRADIENT_SPIRAL,"spiral",_("Spiral"))); - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method") - .set_local_name(_("Blend Method")) - .set_description(_("The blend method the gradient will use"))); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - load_settings(); - - options_table.attach(enum_type, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - options_table.attach(enum_blend, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - options_table.show_all(); - refresh_tool_options(); - App::dialog_tool_options->present(); - - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - get_work_area()->set_cursor(Gdk::CROSSHAIR); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_work_area()->refresh_cursor(); - - // Hide the tables if they are showing - get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateGradient_Context::on_user_click)); - - App::toolbox->refresh(); -} - -void -StateGradient_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Gradient Tool")); - App::dialog_tool_options->set_name("gradient"); -} - -Smach::event_result -StateGradient_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateGradient_Context::~StateGradient_Context() -{ - save_settings(); - - // Restore layer clicking -// get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - get_work_area()->set_allow_layer_clicks(true); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - //if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_canvas_view()->queue_rebuild_ducks(); - - //get_canvas_view()->show_tables(); - - get_work_area()->refresh_cursor(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateGradient_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateGradient_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StateGradient_Context::make_gradient(const Point& _p1, const Point& _p2) -{ - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Gradient")); - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer; - - Canvas::Handle canvas(get_canvas_view()->get_canvas()); - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); - const Point p1(transform.unperform(_p1)); - const Point p2(transform.unperform(_p2)); - - switch(get_type()) - { - case GRADIENT_INTERPOLATION_LINEAR: - - layer=get_canvas_interface()->add_layer_to("linear_gradient",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer->set_param("p1",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"p1"); - layer->set_param("p2",p2); - get_canvas_interface()->signal_layer_param_changed()(layer,"p2"); - break; - case GRADIENT_RADIAL: - layer=get_canvas_interface()->add_layer_to("radial_gradient",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer->set_param("center",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"center"); - layer->set_param("radius",(p2-p1).mag()); - get_canvas_interface()->signal_layer_param_changed()(layer,"radius"); - break; - case GRADIENT_CONICAL: - layer=get_canvas_interface()->add_layer_to("conical_gradient",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer->set_param("center",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"center"); - { - Vector diff(p2-p1); - layer->set_param("angle",Angle::tan(diff[1],diff[0])); - get_canvas_interface()->signal_layer_param_changed()(layer,"angle"); - } - break; - case GRADIENT_SPIRAL: - layer=get_canvas_interface()->add_layer_to("spiral_gradient",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer->set_param("center",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"center"); - layer->set_param("radius",(p2-p1).mag()); - get_canvas_interface()->signal_layer_param_changed()(layer,"radius"); - { - Vector diff(p2-p1); - layer->set_param("angle",Angle::tan(diff[1],diff[0])); - get_canvas_interface()->signal_layer_param_changed()(layer,"angle"); - } - break; - - default: - return; - } - -#ifdef BLEND_METHOD_IN_TOOL_OPTIONS - layer->set_param("blend_method",get_blend()); - get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); -#endif // BLEND_METHOD_IN_TOOL_OPTIONS - - layer->set_description(get_id()); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - egress_on_selection_change=false; - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - layer_selection.push_back(layer); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - reset(); - increment_id(); -} - -Smach::event_result -StateGradient_Context::event_mouse_click_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) - { - point_holder=get_work_area()->snap_point_to_grid(event.pos); - etl::handle duck=new Duck(); - duck->set_point(point_holder); - duck->set_name("p1"); - duck->set_type(Duck::TYPE_POSITION); - get_work_area()->add_duck(duck); - - point2_duck=new Duck(); - point2_duck->set_point(point_holder); - point2_duck->set_name("p2"); - point2_duck->set_type(Duck::TYPE_POSITION); - get_work_area()->add_duck(point2_duck); - - handle bezier(new Duckmatic::Bezier()); - bezier->p1=bezier->c1=duck; - bezier->p2=bezier->c2=point2_duck; - get_work_area()->add_bezier(bezier); - - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) - { - if (!point2_duck) return Smach::RESULT_OK; - point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos)); - get_work_area()->queue_draw(); - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) - { - make_gradient(point_holder, get_work_area()->snap_point_to_grid(event.pos)); - get_work_area()->clear_ducks(); - return Smach::RESULT_ACCEPT; - } - - return Smach::RESULT_OK; -} - - -void -StateGradient_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); -} diff --git a/synfig-studio/src/gui/state_gradient.h b/synfig-studio/src/gui/state_gradient.h deleted file mode 100644 index 308b5ee..0000000 --- a/synfig-studio/src/gui/state_gradient.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_gradient.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_GRADIENT_H -#define __SYNFIG_STUDIO_STATE_GRADIENT_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateGradient_Context; - -class StateGradient : public Smach::state -{ -public: - StateGradient(); - ~StateGradient(); -}; // END of class StateGradient - -extern StateGradient state_gradient; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_mirror.cpp b/synfig-studio/src/gui/state_mirror.cpp deleted file mode 100644 index 59fc759..0000000 --- a/synfig-studio/src/gui/state_mirror.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_mirror.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** 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 -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include - -#include "state_mirror.h" -#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 "duck.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -enum Axis { - AXIS_X, - AXIS_Y -} ; - -/* === G L O B A L S ======================================================= */ - -StateMirror studio::state_mirror; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class DuckDrag_Mirror : public DuckDrag_Base -{ - synfig::Vector center; - - std::vector positions; - -public: - Axis axis; - - DuckDrag_Mirror(); - 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); -}; - -class studio::StateMirror_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - synfigapp::Settings& settings; - - sigc::connection keypress_connect; - sigc::connection keyrelease_connect; - - etl::handle duck_dragger_; - - Gtk::Table options_table; - - Gtk::RadioButton::Group radiobutton_group; - Gtk::RadioButton radiobutton_axis_x; - Gtk::RadioButton radiobutton_axis_y; - -public: - - Axis get_axis()const { return radiobutton_axis_x.get_active()?AXIS_X:AXIS_Y; } - void set_axis(Axis a) - { - if(a==AXIS_X) - radiobutton_axis_x.set_active(true); - else - radiobutton_axis_y.set_active(true); - - duck_dragger_->axis=get_axis(); - } - - void update_axes() - { - duck_dragger_->axis=get_axis(); - get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW); - } - - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - void refresh_tool_options(); - - StateMirror_Context(CanvasView* canvas_view); - - ~StateMirror_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(); - - bool key_event(GdkEventKey *event); -}; // END of class StateMirror_Context - -/* === M E T H O D S ======================================================= */ - -StateMirror::StateMirror(): - Smach::state("mirror") -{ - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateMirror_Context::event_refresh_tool_options)); - insert(event_def(EVENT_STOP,&StateMirror_Context::event_stop_handler)); -} - -StateMirror::~StateMirror() -{ -} - -void -StateMirror_Context::load_settings() -{ - String value; - - settings.get_value("mirror.axis",value); - set_axis((Axis)atoi(value.c_str())); -} - -void -StateMirror_Context::save_settings() -{ - settings.set_value("mirror.lock_aspect",strprintf("%d",(int)get_axis())); -} - -StateMirror_Context::StateMirror_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - settings(synfigapp::Main::get_selected_input_device()->settings()), - duck_dragger_(new DuckDrag_Mirror()), - radiobutton_axis_x(radiobutton_group,_("Horizontal")), - radiobutton_axis_y(radiobutton_group,_("Vertical")) -{ - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Mirror Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(radiobutton_axis_x, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(radiobutton_axis_y, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("(Shift key toggles axis)"))), 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - radiobutton_axis_x.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes)); - radiobutton_axis_y.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes)); - - options_table.show_all(); - refresh_tool_options(); - App::dialog_tool_options->present(); - - get_work_area()->set_allow_layer_clicks(true); - get_work_area()->set_duck_dragger(duck_dragger_); - - keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false); - keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false); - - get_work_area()->set_cursor(Gdk::SB_H_DOUBLE_ARROW); -// get_work_area()->reset_cursor(); - - App::toolbox->refresh(); - - set_axis(AXIS_X); - load_settings(); -} - -bool -StateMirror_Context::key_event(GdkEventKey *event) -{ - if (event->keyval==GDK_Shift_L || event->keyval==GDK_Shift_R ) - { - set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X); - get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW); - } - - return false; //Pass on the event to other handlers, just in case -} - -void -StateMirror_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Mirror Tool")); - App::dialog_tool_options->set_name("mirror"); -} - -Smach::event_result -StateMirror_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateMirror_Context::event_stop_handler(const Smach::event& /*x*/) -{ - throw &state_normal; - return Smach::RESULT_OK; -} - -StateMirror_Context::~StateMirror_Context() -{ - save_settings(); - - get_work_area()->clear_duck_dragger(); - get_work_area()->reset_cursor(); - - keypress_connect.disconnect(); - keyrelease_connect.disconnect(); - - App::dialog_tool_options->clear(); - - App::toolbox->refresh(); -} - -DuckDrag_Mirror::DuckDrag_Mirror(): - axis(AXIS_X) -{ -} - -#ifndef EPSILON -#define EPSILON 0.0000001 -#endif - -void -DuckDrag_Mirror::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& /*offset*/) -{ - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - positions.clear(); - int i; - for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) - { - Point p((*iter)->get_trans_point()); - positions.push_back(p); - } - -} - -void -DuckDrag_Mirror::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) -{ - center=vector; - int i; - - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - Time time(duckmatic->get_time()); - - // do the Vertex and Position ducks first - 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) - { - Vector p(positions[i]); - - if (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0]; - else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1]; - - (*iter)->set_trans_point(p); - } - - // then do the other ducks - 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) - { - // we don't need to mirror radius ducks - they're one-dimensional - if ((*iter)->is_radius()) - continue; - - Vector p(positions[i]); - - if (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0]; - else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1]; - - (*iter)->set_trans_point(p); - } -} - -bool -DuckDrag_Mirror::end_duck_drag(Duckmatic* duckmatic) -{ - duckmatic->signal_edited_selected_ducks(); - return true; -} diff --git a/synfig-studio/src/gui/state_mirror.h b/synfig-studio/src/gui/state_mirror.h deleted file mode 100644 index 4ac878e..0000000 --- a/synfig-studio/src/gui/state_mirror.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_mirror.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_MIRROR_H -#define __SYNFIG_STUDIO_STATE_MIRROR_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateMirror_Context; - -class StateMirror : public Smach::state -{ -public: - StateMirror(); - ~StateMirror(); -}; // END of class StateMirror - -extern StateMirror state_mirror; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_normal.cpp b/synfig-studio/src/gui/state_normal.cpp deleted file mode 100644 index c763022..0000000 --- a/synfig-studio/src/gui/state_normal.cpp +++ /dev/null @@ -1,824 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_normal.cpp -** \brief Template File -** -** $Id$ -** -** \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 -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# 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 "duck.h" -#include -#include - -#include "general.h" -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -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 DuckDrag_Combo : public DuckDrag_Base -{ - synfig::Vector last_move; - synfig::Vector drag_offset; - synfig::Vector center; - synfig::Vector snap; - - synfig::Angle original_angle; - synfig::Real original_mag; - - std::vector last_; - std::vector positions; - - - bool bad_drag; - bool move_only; - -public: - 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); - - etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} -}; - - -class studio::StateNormal_Context : public sigc::trackable -{ - etl::handle canvas_view_; - - synfigapp::Settings& settings; - - sigc::connection keypress_connect; - sigc::connection keyrelease_connect; - - etl::handle duck_dragger_; - - Gtk::Table options_table; - - Gtk::CheckButton checkbutton_rotate; - Gtk::CheckButton checkbutton_scale; - Gtk::CheckButton checkbutton_constrain; - -public: - - 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(); } - - 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(); } - - StateNormal_Context(CanvasView* canvas_view); - - ~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(); - - bool key_pressed(GdkEventKey *event); - bool key_released(GdkEventKey *event); - - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_refresh_ducks_handler(const Smach::event& x); - Smach::event_result event_undo_handler(const Smach::event& x); - Smach::event_result event_redo_handler(const Smach::event& x); - Smach::event_result event_mouse_button_down_handler(const Smach::event& x); - Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - void refresh_tool_options(); - Smach::event_result event_layer_click(const Smach::event& x); - - -}; // 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() -{ -} - -void -StateNormal_Context::load_settings() -{ - 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); - -} - -void -StateNormal_Context::save_settings() -{ - 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"); -} - -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(); - //App::dialog_tool_options->set_widget(options_table); - //App::dialog_tool_options->present(); - - get_work_area()->set_allow_layer_clicks(true); - get_work_area()->set_duck_dragger(duck_dragger_); - - 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); - - //these will segfault -// get_work_area()->set_cursor(Gdk::CROSSHAIR); -// get_work_area()->reset_cursor(); - - App::toolbox->refresh(); - - load_settings(); - refresh_scale_flag(); -} - -bool -StateNormal_Context::key_pressed(GdkEventKey *event) -{ - 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 -} - -bool -StateNormal_Context::key_released(GdkEventKey *event) -{ - 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 -} - -void -StateNormal_Context::refresh_tool_options() -{ - 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"); -} - - - -StateNormal_Context::~StateNormal_Context() -{ - save_settings(); - - get_work_area()->clear_duck_dragger(); - get_work_area()->reset_cursor(); - - keypress_connect.disconnect(); - keyrelease_connect.disconnect(); - - App::dialog_tool_options->clear(); - - App::toolbox->refresh(); -} - -DuckDrag_Combo::DuckDrag_Combo(): - scale(false), - rotate(false), - constrain(false) // Lock aspect for scale; smooth move for translate -{ -} - -void -DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) -{ - last_move=Vector(1,1); - - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - bad_drag=false; - - drag_offset=duckmatic->find_duck(offset)->get_trans_point(); - - //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); - //snap=offset-drag_offset_; - snap=Vector(0,0); - - // 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++) - { - 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; - - - synfig::Vector vect(offset-center); - original_angle=Angle::tan(vect[1],vect[0]); - original_mag=vect.mag(); -} - - -void -DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) -{ - if (!duckmatic) return; - - if(bad_drag) - return; - - //Override axis lock set in workarea when holding down the shift key - if (!move_only && (scale || rotate)) - duckmatic->set_axis_lock(false); - - 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; - - 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); - } - 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); - } - } - - 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()); - - 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; - - 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; - - 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); - } - } 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 - { - //vect[0]=vect[1]=vect.mag()*0.707106781; - Real amount(vect.mag()/(drag_offset-center).mag()); - vect[0]=vect[1]=amount; - } - - if(vect[0]-EPSILON) - vect[0]=1; - if(vect[1]-EPSILON) - vect[1]=1; - - 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; - - Vector p(positions[i]-center); - - 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; - - Vector p(positions[i]-center); - - p[0]*=vect[0]; - p[1]*=vect[1]; - p+=center; - (*iter)->set_trans_point(p, time); - } - } - - // then patch up the tangents for the vertices we've moved - duckmatic->update_ducks(); - - last_move=vect; -} - -bool -DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic) -{ - if(bad_drag)return false; - - //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks")); - - 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; - } -} - -Smach::event_result -StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -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; -} - -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; -} - -Smach::event_result -StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received Refresh Ducks"); - canvas_view_->queue_rebuild_ducks(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateNormal_Context::event_undo_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received Undo Event"); - canvas_view_->get_instance()->undo(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateNormal_Context::event_redo_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received Redo Event"); - canvas_view_->get_instance()->redo(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x) -{ - // synfig::info("STATE NORMAL: Received mouse button down Event"); - - const EventMouse& event(*reinterpret_cast(&x)); - - switch(event.button) - { - case BUTTON_RIGHT: - canvas_view_->popup_main_menu(); - return Smach::RESULT_ACCEPT; - default: - return Smach::RESULT_OK; - } -} - -Smach::event_result -StateNormal_Context::event_layer_click(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."); - } - - 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; - } -} - -/* -void -StateNormal_Context::edit_several_waypoints(std::list value_desc_list) -{ - Gtk::Dialog dialog( - "Edit Multiple Waypoints", // Title - true, // Modal - true // use_separator - ); - - Widget_WaypointModel widget_waypoint_model; - widget_waypoint_model.show(); - - dialog.get_vbox()->pack_start(widget_waypoint_model); - - - dialog.add_button(Gtk::StockID("gtk-apply"),1); - dialog.add_button(Gtk::StockID("gtk-cancel"),0); - dialog.show(); - - if(dialog.run()==0) - return; - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Set Waypoints")); - - std::list::iterator iter; - for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter) - { - synfigapp::ValueDesc value_desc(*iter); - - if(!value_desc.is_valid()) - continue; - - ValueNode_Animated::Handle value_node; - - // 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()); - - synfigapp::Action::Handle action; - - 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)); - } - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - - - 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; - } - } - else - { - if(value_desc.is_value_node()) - value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()); - } - - - if(value_node) - { - - 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; - } - - - 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()); - - 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; - } - } - else - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to animate a specific valuedesc")); - //group.cancel(); - //return; - } - - } -} -*/ - -Smach::event_result -StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& /*x*/) -{ - // synfig::info("STATE NORMAL: Received multiple duck click event"); - - //const EventMouse& event(*reinterpret_cast(&x)); - - std::list value_desc_list; - - // 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()); - - if(!value_desc.is_valid()) - continue; - - 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()) - ,ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()) - ->get_link_index_from_name("point") - ) - ); - } - 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); - - /* - synfigapp::Action::ParamList param_list; - param_list=get_canvas_interface()->generate_param_list(value_desc_list); - - canvas_view_->add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE); - - 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()); - - return Smach::RESULT_ACCEPT; -} - - diff --git a/synfig-studio/src/gui/state_normal.h b/synfig-studio/src/gui/state_normal.h deleted file mode 100644 index 01b040b..0000000 --- a/synfig-studio/src/gui/state_normal.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_normal.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** 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 -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_NORMAL_H -#define __SYNFIG_STUDIO_STATE_NORMAL_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateNormal_Context; - -class StateNormal : public Smach::state -{ -public: - StateNormal(); - ~StateNormal(); -}; // END of class StateNormal - -extern StateNormal state_normal; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_polygon.cpp b/synfig-studio/src/gui/state_polygon.cpp deleted file mode 100644 index 7c11c05..0000000 --- a/synfig-studio/src/gui/state_polygon.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_polygon.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2007, 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include -#include - -#include "state_polygon.h" -#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 "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StatePolygon studio::state_polygon; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StatePolygon_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - bool prev_table_status; - bool prev_workarea_layer_status_; - - Gtk::Menu menu; - - Duckmatic::Push duckmatic_push; - - std::list polygon_point_list; - synfigapp::Settings& settings; - - - bool on_polygon_duck_change(const synfig::Point &point, std::list::iterator iter); - - - void popup_handle_menu(synfigapp::ValueDesc value_desc); - - - void refresh_ducks(); - - Gtk::Table options_table; - Gtk::Entry entry_id; - Gtk::CheckButton checkbutton_invert; - Gtk::CheckButton checkbutton_layer_polygon; - Gtk::CheckButton checkbutton_layer_region; - Gtk::CheckButton checkbutton_layer_outline; - Gtk::CheckButton checkbutton_layer_curve_gradient; - Gtk::CheckButton checkbutton_layer_plant; - Gtk::CheckButton checkbutton_layer_link_origins; - Gtk::Button button_make; - Gtk::Adjustment adj_feather; - Gtk::SpinButton spin_feather; - -public: - - // this counts the layers we create - they all have origins we can link - int layers_to_create()const - { - return - get_layer_polygon_flag() + - get_layer_region_flag() + - get_layer_outline_flag() + - get_layer_curve_gradient_flag() + - get_layer_plant_flag(); - } - - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - bool get_invert()const { return checkbutton_invert.get_active(); } - void set_invert(bool i) { checkbutton_invert.set_active(i); } - - bool get_layer_polygon_flag()const { return checkbutton_layer_polygon.get_active(); } - void set_layer_polygon_flag(bool x) { return checkbutton_layer_polygon.set_active(x); } - - bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } - void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } - - bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } - void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } - - bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } - void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } - - bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } - void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } - - bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } - void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } - - Real get_feather() const { return adj_feather.get_value(); } - void set_feather(Real x) { return adj_feather.set_value(x); } - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - void refresh_tool_options(); - - StatePolygon_Context(CanvasView* canvas_view); - - ~StatePolygon_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 on_user_click(synfig::Point point); - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - - void run(); -}; // END of class StatePolygon_Context - -/* === M E T H O D S ======================================================= */ - -StatePolygon::StatePolygon(): - Smach::state("polygon") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StatePolygon_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_STOP,&StatePolygon_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StatePolygon_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StatePolygon_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StatePolygon_Context::event_mouse_click_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StatePolygon_Context::event_refresh_tool_options)); -} - -StatePolygon::~StatePolygon() -{ -} - -void -StatePolygon_Context::load_settings() -{ - String value; - - if(settings.get_value("polygon.id",value)) - set_id(value); - else - set_id("Polygon"); - - if(settings.get_value("polygon.invert",value) && value != "0") - set_invert(true); - else - set_invert(false); - - if(settings.get_value("polygon.layer_polygon",value) && value=="0") - set_layer_polygon_flag(false); - else - set_layer_polygon_flag(true); - - if(settings.get_value("polygon.layer_region",value) && value=="1") - set_layer_region_flag(true); - else - set_layer_region_flag(false); - - if(settings.get_value("polygon.layer_outline",value) && value=="1") - set_layer_outline_flag(true); - else - set_layer_outline_flag(false); - - if(settings.get_value("polygon.layer_curve_gradient",value) && value=="1") - set_layer_curve_gradient_flag(true); - else - set_layer_curve_gradient_flag(false); - - if(settings.get_value("polygon.layer_plant",value) && value=="1") - set_layer_plant_flag(true); - else - set_layer_plant_flag(false); - - if(settings.get_value("polygon.layer_link_origins",value) && value=="0") - set_layer_link_origins_flag(false); - else - set_layer_link_origins_flag(true); - - if(settings.get_value("polygon.feather",value)) - { - Real n = atof(value.c_str()); - set_feather(n); - } -} - -void -StatePolygon_Context::save_settings() -{ - settings.set_value("polygon.id",get_id().c_str()); - settings.set_value("polygon.invert",get_invert()?"1":"0"); - settings.set_value("polygon.layer_polygon",get_layer_polygon_flag()?"1":"0"); - settings.set_value("polygon.layer_outline",get_layer_outline_flag()?"1":"0"); - settings.set_value("polygon.layer_region",get_layer_region_flag()?"1":"0"); - settings.set_value("polygon.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); - settings.set_value("polygon.layer_plant",get_layer_plant_flag()?"1":"0"); - settings.set_value("polygon.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); - settings.set_value("polygon.feather",strprintf("%f",get_feather())); -} - -void -StatePolygon_Context::reset() -{ - polygon_point_list.clear(); - refresh_ducks(); -} - -void -StatePolygon_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Polygon"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - String str_number; - str_number=String(id,id.size()-digits,id.size()); - id=String(id,0,id.size()-digits); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StatePolygon_Context::StatePolygon_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - duckmatic_push(get_work_area()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), - checkbutton_invert(_("Invert")), - checkbutton_layer_polygon(_("Create Polygon Layer")), - checkbutton_layer_region(_("Create Region BLine")), - checkbutton_layer_outline(_("Create Outline BLine")), - checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), - checkbutton_layer_plant(_("Create Plant BLine")), - checkbutton_layer_link_origins(_("Link Origins")), - button_make(_("Make")), - adj_feather(0,0,10000,0.01,0.1), - spin_feather(adj_feather,0.01,4) -{ - egress_on_selection_change=true; - load_settings(); - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Polygon 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_layer_polygon, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //invert flag - options_table.attach(checkbutton_invert, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //feather stuff - options_table.attach(*manage(new Gtk::Label(_("Feather"))), 0, 1, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_feather, 1, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //options_table.attach(button_make, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - button_make.signal_pressed().connect(sigc::mem_fun(*this,&StatePolygon_Context::run)); - options_table.show_all(); - refresh_tool_options(); - App::dialog_tool_options->present(); - - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_work_area()->set_cursor(Gdk::CROSSHAIR); - - // Hide the tables if they are showing - prev_table_status=get_canvas_view()->tables_are_visible(); - if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_user_click)); - - App::toolbox->refresh(); -} - -void -StatePolygon_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - - App::dialog_tool_options->set_local_name(_("Polygon Tool")); - App::dialog_tool_options->set_name("polygon"); - - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-execute"), - _("Make Polygon") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &StatePolygon_Context::run - ) - ); - - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-clear"), - _("Clear current Polygon") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &StatePolygon_Context::reset - ) - ); -} - -Smach::event_result -StatePolygon_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StatePolygon_Context::~StatePolygon_Context() -{ - run(); - - save_settings(); - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - - App::dialog_tool_options->clear(); - - get_work_area()->reset_cursor(); - - // Enable the time bar - get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - App::toolbox->refresh(); -} - -Smach::event_result -StatePolygon_Context::event_stop_handler(const Smach::event& /*x*/) -{ - synfig::info("STATE RotoPolygon: Received Stop Event"); - //throw Smach::egress_exception(); - reset(); - return Smach::RESULT_ACCEPT; - -} - -Smach::event_result -StatePolygon_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - synfig::info("STATE RotoPolygon: Received Refresh Event"); - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StatePolygon_Context::run() -{ - if(polygon_point_list.empty()) - return; - - if(polygon_point_list.size()<3) - { - get_canvas_view()->get_ui_interface()->error("You need at least 3 points to create a polygon"); - return; - } - - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Polygon")); - - Layer::Handle layer; - - Canvas::Handle canvas; - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - - const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); - - std::vector new_list; - std::list::iterator iter; - int i; - for(i=0,iter=polygon_point_list.begin();iter!=polygon_point_list.end();++iter,++i) - { - *iter = transform.unperform(*iter); - new_list.push_back(*(new BLinePoint)); - new_list[i].set_width(1); - new_list[i].set_vertex(*iter); - new_list[i].set_tangent(Point(0,0)); - } - - ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); - assert(value_node_bline); - - ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector())); - assert(value_node_origin); - - // Set the looping flag - value_node_bline->set_loop(true); - - if(!canvas) - canvas=get_canvas_view()->get_canvas(); - - value_node_bline->set_member_canvas(canvas); - - // count how many layers we're going to be creating - int layers_to_create = this->layers_to_create(); - - /////////////////////////////////////////////////////////////////////////// - // P O L Y G O N - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_polygon_flag()) - { - layer=get_canvas_interface()->add_layer_to("polygon",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - if(get_feather()) - { - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - } - - layer->set_description(get_id()); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->disconnect_dynamic_param("vector_list"); - if(!layer->set_param("vector_list",polygon_point_list)) - { - group.cancel(); - get_canvas_view()->get_ui_interface()->error("Unable to set layer parameter"); - return; - } - - { - synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescConvert")); - synfigapp::ValueDesc value_desc(layer,"vector_list"); - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("value_desc",value_desc); - action->set_param("type","dynamic_list"); - action->set_param("time",get_canvas_interface()->get_time()); - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - group.cancel(); - get_canvas_view()->get_ui_interface()->error("Unable to execute action \"ValueDescConvert\""); - return; - } - } - - // only link the polygon's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create Polygon layer")); - group.cancel(); - throw String(_("Unable to create Polygon layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // C U R V E G R A D I E N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_curve_gradient_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Gradient")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - - // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // P L A N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_plant_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Plant")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - - // only link the plant's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // R E G I O N - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_region_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Region")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm - // using 2 separate ones. - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - - // only link the region's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // O U T L I N E - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_outline_flag()) - { - Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Outline")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - - // only link the outline's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - } - - egress_on_selection_change=false; - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - //post clean up stuff... - reset(); - increment_id(); -} - -Smach::event_result -StatePolygon_Context::event_mouse_click_handler(const Smach::event& x) -{ - synfig::info("STATE ROTOPOLYGON: Received mouse button down Event"); - const EventMouse& event(*reinterpret_cast(&x)); - switch(event.button) - { - case BUTTON_LEFT: - polygon_point_list.push_back(get_work_area()->snap_point_to_grid(event.pos)); - refresh_ducks(); - return Smach::RESULT_ACCEPT; - - default: - return Smach::RESULT_OK; - } -} - - -void -StatePolygon_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); - - if(polygon_point_list.empty()) return; - - std::list::iterator iter=polygon_point_list.begin(); - - etl::handle duck; - duck=new WorkArea::Duck(*iter); - duck->set_editable(true); - duck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter) - ); - duck->signal_user_click(0).connect(sigc::mem_fun(*this,&StatePolygon_Context::run)); - - get_work_area()->add_duck(duck); - - for(++iter;iter!=polygon_point_list.end();++iter) - { - etl::handle bezier(new WorkArea::Bezier()); - bezier->p1=bezier->c1=duck; - - duck=new WorkArea::Duck(*iter); - duck->set_editable(true); - duck->set_name(strprintf("%x",&*iter)); - duck->signal_edited().connect( - sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter) - ); - - get_work_area()->add_duck(duck); - - bezier->p2=bezier->c2=duck; - get_work_area()->add_bezier(bezier); - } - get_work_area()->queue_draw(); -} - - -bool -StatePolygon_Context::on_polygon_duck_change(const synfig::Point &point, std::list::iterator iter) -{ - *iter=point; - return true; -} diff --git a/synfig-studio/src/gui/state_polygon.h b/synfig-studio/src/gui/state_polygon.h deleted file mode 100644 index c633c4e..0000000 --- a/synfig-studio/src/gui/state_polygon.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_polygon.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H -#define __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StatePolygon_Context; - -class StatePolygon : public Smach::state -{ -public: - StatePolygon(); - ~StatePolygon(); -}; // END of class StatePolygon - -extern StatePolygon state_polygon; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_rectangle.cpp b/synfig-studio/src/gui/state_rectangle.cpp deleted file mode 100644 index 4f3eccb..0000000 --- a/synfig-studio/src/gui/state_rectangle.cpp +++ /dev/null @@ -1,875 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_rectangle.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include -#include - -#include "state_rectangle.h" -#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 "duck.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateRectangle studio::state_rectangle; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateRectangle_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - Duckmatic::Push duckmatic_push; - - Point point_holder; - - etl::handle point2_duck; - - void refresh_ducks(); - - bool prev_workarea_layer_status_; - - //Toolbox settings - synfigapp::Settings& settings; - - //Toolbox display - Gtk::Table options_table; - - Gtk::Entry entry_id; //what to name the layer - - Gtk::Adjustment adj_expand; - Gtk::Adjustment adj_feather; - Gtk::SpinButton spin_expand; - Gtk::SpinButton spin_feather; - - Gtk::CheckButton checkbutton_invert; - Gtk::CheckButton checkbutton_layer_rectangle; - Gtk::CheckButton checkbutton_layer_region; - Gtk::CheckButton checkbutton_layer_outline; - Gtk::CheckButton checkbutton_layer_curve_gradient; - Gtk::CheckButton checkbutton_layer_plant; - Gtk::CheckButton checkbutton_layer_link_origins; - -public: - - // this only counts the layers which use blines - they're the only - // ones we link the origins for - int layers_to_create()const - { - return - get_layer_region_flag() + - get_layer_outline_flag() + - get_layer_curve_gradient_flag() + - get_layer_plant_flag(); - } - - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - Real get_expand()const { return adj_expand.get_value(); } - void set_expand(Real f) { adj_expand.set_value(f); } - - Real get_feather()const { return adj_feather.get_value(); } - void set_feather(Real f) { adj_feather.set_value(f); } - - bool get_invert()const { return checkbutton_invert.get_active(); } - void set_invert(bool i) { checkbutton_invert.set_active(i); } - - bool get_layer_rectangle_flag()const { return checkbutton_layer_rectangle.get_active(); } - void set_layer_rectangle_flag(bool x) { return checkbutton_layer_rectangle.set_active(x); } - - bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } - void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } - - bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } - void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } - - bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } - void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } - - bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } - void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } - - bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } - void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } - - void refresh_tool_options(); //to refresh the toolbox - - //events - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - //constructor destructor - StateRectangle_Context(CanvasView* canvas_view); - ~StateRectangle_Context(); - - //Canvas interaction - 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();} - - //Modifying settings etc. - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - - void make_rectangle(const Point& p1, const Point& p2); - -}; // END of class StateGradient_Context - -/* === M E T H O D S ======================================================= */ - -StateRectangle::StateRectangle(): - Smach::state("rectangle") -{ - insert(event_def(EVENT_STOP,&StateRectangle_Context::event_stop_handler)); - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateRectangle_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_REFRESH,&StateRectangle_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateRectangle_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateRectangle_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateRectangle_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateRectangle_Context::event_mouse_click_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRectangle_Context::event_refresh_tool_options)); -} - -StateRectangle::~StateRectangle() -{ -} - -void -StateRectangle_Context::load_settings() -{ - String value; - - //parse the arguments yargh! - if(settings.get_value("rectangle.id",value)) - set_id(value); - else - set_id("Rectangle"); - - if(settings.get_value("rectangle.expand",value)) - set_expand(atof(value.c_str())); - else - set_expand(0); - - if(settings.get_value("rectangle.feather",value)) - set_feather(atof(value.c_str())); - else - set_feather(0); - - if(settings.get_value("rectangle.invert",value) && value != "0") - set_invert(true); - else - set_invert(false); - - if(settings.get_value("rectangle.layer_rectangle",value) && value=="0") - set_layer_rectangle_flag(false); - else - set_layer_rectangle_flag(true); - - if(settings.get_value("rectangle.layer_region",value) && value=="1") - set_layer_region_flag(true); - else - set_layer_region_flag(false); - - if(settings.get_value("rectangle.layer_outline",value) && value=="1") - set_layer_outline_flag(true); - else - set_layer_outline_flag(false); - - if(settings.get_value("rectangle.layer_curve_gradient",value) && value=="1") - set_layer_curve_gradient_flag(true); - else - set_layer_curve_gradient_flag(false); - - if(settings.get_value("rectangle.layer_plant",value) && value=="1") - set_layer_plant_flag(true); - else - set_layer_plant_flag(false); - - if(settings.get_value("rectangle.layer_link_origins",value) && value=="0") - set_layer_link_origins_flag(false); - else - set_layer_link_origins_flag(true); -} - -void -StateRectangle_Context::save_settings() -{ - settings.set_value("rectangle.id",get_id().c_str()); - settings.set_value("rectangle.expand",strprintf("%f",get_expand())); - settings.set_value("rectangle.feather",strprintf("%f",(float)get_feather())); - settings.set_value("rectangle.invert",get_invert()?"1":"0"); - settings.set_value("rectangle.layer_rectangle",get_layer_rectangle_flag()?"1":"0"); - settings.set_value("rectangle.layer_outline",get_layer_outline_flag()?"1":"0"); - settings.set_value("rectangle.layer_region",get_layer_region_flag()?"1":"0"); - settings.set_value("rectangle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); - settings.set_value("rectangle.layer_plant",get_layer_plant_flag()?"1":"0"); - settings.set_value("rectangle.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); -} - -void -StateRectangle_Context::reset() -{ - refresh_ducks(); -} - -void -StateRectangle_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Rectangle"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - String str_number; - str_number=String(id,id.size()-digits,id.size()); - id=String(id,0,id.size()-digits); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StateRectangle_Context::StateRectangle_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - duckmatic_push(get_work_area()), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), - adj_expand(0,0,1,0.01,0.1), - adj_feather(0,0,1,0.01,0.1), - spin_expand(adj_expand,0.1,3), - spin_feather(adj_feather,0.1,3), - checkbutton_invert(_("Invert")), - checkbutton_layer_rectangle(_("Create Rectangle Layer")), - checkbutton_layer_region(_("Create Region BLine")), - checkbutton_layer_outline(_("Create Outline BLine")), - checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), - checkbutton_layer_plant(_("Create Plant BLine")), - checkbutton_layer_link_origins(_("Link BLine Origins")) -{ - egress_on_selection_change=true; - load_settings(); - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Rectangle 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_layer_rectangle, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //invert flag - options_table.attach(checkbutton_invert, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //expand stuff - options_table.attach(*manage(new Gtk::Label(_("Expansion:"))), 0, 1, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_expand, 1, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //feather stuff - options_table.attach(*manage(new Gtk::Label(_("Feather:"))), 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_feather, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.show_all(); - - //App::dialog_tool_options->set_widget(options_table); - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_work_area()->set_cursor(Gdk::DOTBOX); - - // Hide the tables if they are showing - //prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateRectangle_Context::on_user_click)); - - App::toolbox->refresh(); -} - -void -StateRectangle_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Rectangle Tool")); - App::dialog_tool_options->set_name("rectangle"); -} - -Smach::event_result -StateRectangle_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateRectangle_Context::~StateRectangle_Context() -{ - save_settings(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - //if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_canvas_view()->queue_rebuild_ducks(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateRectangle_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateRectangle_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StateRectangle_Context::make_rectangle(const Point& _p1, const Point& _p2) -{ - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Rectangle")); - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer; - - Canvas::Handle canvas; - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - - const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); - const Point p1(transform.unperform(_p1)); - const Point p2(transform.unperform(_p2)); - Real x_min, x_max, y_min, y_max; - if (p1[0] < p2[0]) { x_min = p1[0]; x_max = p2[0]; } else { x_min = p2[0]; x_max = p1[0]; } - if (p1[1] < p2[1]) { y_min = p1[1]; y_max = p2[1]; } else { y_min = p2[1]; y_max = p1[1]; } - x_min -= get_expand(); x_max += get_expand(); y_min -= get_expand(); y_max += get_expand(); - - std::vector new_list; - for (int i = 0; i < 4; i++) - { - new_list.push_back(*(new BLinePoint)); - new_list[i].set_width(1); - new_list[i].set_vertex(Point((i==0||i==3)?x_min:x_max, - (i==0||i==1)?y_min:y_max)); - new_list[i].set_tangent(Point(0,0)); - } - - ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); - assert(value_node_bline); - - ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector())); - assert(value_node_origin); - - // Set the looping flag - value_node_bline->set_loop(true); - - if(!canvas) - canvas=get_canvas_view()->get_canvas(); - - value_node_bline->set_member_canvas(canvas); - - // count how many layers we're going to be creating - int layers_to_create = this->layers_to_create(); - - /////////////////////////////////////////////////////////////////////////// - // R E C T A N G L E - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_rectangle_flag()) - { - layer=get_canvas_interface()->add_layer_to("rectangle",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - - layer->set_param("point1",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"point1"); - - layer->set_param("point2",p2); - get_canvas_interface()->signal_layer_param_changed()(layer,"point2"); - - layer->set_param("expand",get_expand()); - get_canvas_interface()->signal_layer_param_changed()(layer,"expand"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - layer->set_description(get_id()); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - } - - /////////////////////////////////////////////////////////////////////////// - // C U R V E G R A D I E N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_curve_gradient_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Gradient")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - - // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // P L A N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_plant_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Plant")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - - // only link the plant's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // R E G I O N - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_region_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Region")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm - // using 2 separate ones. - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - - // only link the region's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - } - - /////////////////////////////////////////////////////////////////////////// - // O U T L I N E - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_outline_flag()) - { - Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Outline")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - - // only link the outline's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - } - - egress_on_selection_change=false; - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - //post clean up stuff... - reset(); - increment_id(); -} - -Smach::event_result -StateRectangle_Context::event_mouse_click_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) - { - point_holder=get_work_area()->snap_point_to_grid(event.pos); - etl::handle duck=new Duck(); - duck->set_point(point_holder); - duck->set_name("p1"); - duck->set_type(Duck::TYPE_POSITION); - get_work_area()->add_duck(duck); - - point2_duck=new Duck(); - point2_duck->set_point(point_holder); - point2_duck->set_name("p2"); - point2_duck->set_type(Duck::TYPE_POSITION); - point2_duck->set_box_duck(duck); - get_work_area()->add_duck(point2_duck); - - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) - { - if (!point2_duck) return Smach::RESULT_OK; - point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos)); - get_work_area()->queue_draw(); - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) - { - make_rectangle(point_holder, get_work_area()->snap_point_to_grid(event.pos)); - get_work_area()->clear_ducks(); - return Smach::RESULT_ACCEPT; - } - - return Smach::RESULT_OK; -} - - -void -StateRectangle_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); -} diff --git a/synfig-studio/src/gui/state_rectangle.h b/synfig-studio/src/gui/state_rectangle.h deleted file mode 100644 index 131dd40..0000000 --- a/synfig-studio/src/gui/state_rectangle.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_rectangle.h -** \brief Rectangle creation state -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_RECTANGLE_H -#define __SYNFIG_STUDIO_STATE_RECTANGLE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateRectangle_Context; - -class StateRectangle : public Smach::state -{ -public: - StateRectangle(); - ~StateRectangle(); -}; // END of class StateRectangle - -extern StateRectangle state_rectangle; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_rotate.cpp b/synfig-studio/src/gui/state_rotate.cpp deleted file mode 100644 index 5463a41..0000000 --- a/synfig-studio/src/gui/state_rotate.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_rotate.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include - -#include "state_rotate.h" -#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 "duck.h" -#include -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -#ifndef EPSILON -#define EPSILON 0.0000001 -#endif - -/* === G L O B A L S ======================================================= */ - -StateRotate studio::state_rotate; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class DuckDrag_Rotate : public DuckDrag_Base -{ - - synfig::Vector last_rotate; - synfig::Vector drag_offset; - synfig::Vector center; - synfig::Vector snap; - - Angle original_angle; - Real original_mag; - - std::vector positions; - - - bool bad_drag; - bool move_only; - -public: - etl::handle canvas_view_; - bool use_magnitude; - DuckDrag_Rotate(); - 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); - - etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} -}; - - -class studio::StateRotate_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - synfigapp::Settings& settings; - - etl::handle duck_dragger_; - - Gtk::Table options_table; - - Gtk::CheckButton checkbutton_scale; - -public: - - bool get_scale_flag()const { return checkbutton_scale.get_active(); } - void set_scale_flag(bool x) { return checkbutton_scale.set_active(x); refresh_scale_flag(); } - - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - void refresh_tool_options(); - - void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->use_magnitude=get_scale_flag(); } - - StateRotate_Context(CanvasView* canvas_view); - - ~StateRotate_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(); -}; // END of class StateRotate_Context - -/* === M E T H O D S ======================================================= */ - -StateRotate::StateRotate(): - Smach::state("rotate") -{ - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRotate_Context::event_refresh_tool_options)); - insert(event_def(EVENT_STOP,&StateRotate_Context::event_stop_handler)); -} - -StateRotate::~StateRotate() -{ -} - -void -StateRotate_Context::load_settings() -{ - String value; - - if(settings.get_value("rotate.scale",value) && value=="0") - set_scale_flag(false); - else - set_scale_flag(true); -} - -void -StateRotate_Context::save_settings() -{ - settings.set_value("rotate.scale",get_scale_flag()?"1":"0"); -} - -StateRotate_Context::StateRotate_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - settings(synfigapp::Main::get_selected_input_device()->settings()), - duck_dragger_(new DuckDrag_Rotate()), - checkbutton_scale(_("Allow Scale")) -{ - duck_dragger_->canvas_view_=get_canvas_view(); - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Rotate Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_scale, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateRotate_Context::refresh_scale_flag)); - - options_table.show_all(); - refresh_tool_options(); - //App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->present(); - - get_work_area()->set_allow_layer_clicks(true); - get_work_area()->set_duck_dragger(duck_dragger_); - - get_work_area()->set_cursor(Gdk::EXCHANGE); -// get_work_area()->reset_cursor(); - - App::toolbox->refresh(); - - load_settings(); - refresh_scale_flag(); -} - -void -StateRotate_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Rotate Tool")); - App::dialog_tool_options->set_name("rotate"); -} - -Smach::event_result -StateRotate_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateRotate_Context::event_stop_handler(const Smach::event& /*x*/) -{ - throw &state_normal; - return Smach::RESULT_OK; -} - -StateRotate_Context::~StateRotate_Context() -{ - save_settings(); - - get_work_area()->clear_duck_dragger(); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - App::toolbox->refresh(); -} - - - - -DuckDrag_Rotate::DuckDrag_Rotate() -{ - use_magnitude=true; -} - -void -DuckDrag_Rotate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) -{ - last_rotate=Vector(1,1); - - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - -/* - if(duckmatic->get_selected_ducks().size()<2) - { - bad_drag=true; - return; - } -*/ - bad_drag=false; - - drag_offset=duckmatic->find_duck(offset)->get_trans_point(); - - //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); - //snap=offset-drag_offset; - snap=Vector(0,0); - - // 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++) - { - 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; - - - synfig::Vector vect(offset-center); - original_angle=Angle::tan(vect[1],vect[0]); - original_mag=vect.mag(); -} - - -void -DuckDrag_Rotate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) -{ - if(bad_drag) - return; - - //std::set >::iterator iter; - synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center+snap); - - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - if(move_only) - { - int i; - 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; - - Vector p(positions[i]); - - p[0]+=vect[0]; - p[1]+=vect[1]; - (*iter)->set_trans_point(p); - } - 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; - - Vector p(positions[i]); - - p[0]+=vect[0]; - p[1]+=vect[1]; - (*iter)->set_trans_point(p); - } - return; - } - - Angle::tan angle(vect[1],vect[0]); - angle=original_angle-angle; - Real mag(vect.mag()/original_mag); - Real sine(Angle::sin(angle).get()); - Real cosine(Angle::cos(angle).get()); - - int i; - 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; - - Vector x(positions[i]-center),p; - - p[0]=cosine*x[0]+sine*x[1]; - p[1]=-sine*x[0]+cosine*x[1]; - if(use_magnitude)p*=mag; - p+=center; - (*iter)->set_trans_point(p); - } - 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; - - Vector x(positions[i]-center),p; - - p[0]=cosine*x[0]+sine*x[1]; - p[1]=-sine*x[0]+cosine*x[1]; - if(use_magnitude)p*=mag; - p+=center; - (*iter)->set_trans_point(p); - } - - last_rotate=vect; - //snap=Vector(0,0); -} - -bool -DuckDrag_Rotate::end_duck_drag(Duckmatic* duckmatic) -{ - if(bad_drag)return false; - if(move_only) - { - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Move Duck")); - duckmatic->signal_edited_selected_ducks(); - return true; - } - - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks")); - - if((last_rotate-Vector(1,1)).mag()>0.0001) - { - duckmatic->signal_edited_selected_ducks(); - return true; - } - else - { - duckmatic->signal_user_click_selected_ducks(0); - return false; - } -} diff --git a/synfig-studio/src/gui/state_rotate.h b/synfig-studio/src/gui/state_rotate.h deleted file mode 100644 index e2caafe..0000000 --- a/synfig-studio/src/gui/state_rotate.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_rotate.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_ROTATE_H -#define __SYNFIG_STUDIO_STATE_ROTATE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateRotate_Context; - -class StateRotate : public Smach::state -{ -public: - StateRotate(); - ~StateRotate(); -}; // END of class StateRotate - -extern StateRotate state_rotate; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_scale.cpp b/synfig-studio/src/gui/state_scale.cpp deleted file mode 100644 index edfb89b..0000000 --- a/synfig-studio/src/gui/state_scale.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_scale.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include - -#include "state_scale.h" -#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 "duck.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateScale studio::state_scale; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class DuckDrag_Scale : public DuckDrag_Base -{ - - synfig::Vector last_scale; - synfig::Vector drag_offset; - synfig::Vector center; - synfig::Vector snap; - - std::vector positions; - - bool move_only; - - bool bad_drag; -public: - bool lock_aspect; - DuckDrag_Scale(); - 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); -}; - - -class studio::StateScale_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - synfigapp::Settings& settings; - - etl::handle duck_dragger_; - - Gtk::Table options_table; - - - Gtk::CheckButton checkbutton_aspect_lock; - -public: - - bool get_aspect_lock_flag()const { return checkbutton_aspect_lock.get_active(); } - void set_aspect_lock_flag(bool x) { return checkbutton_aspect_lock.set_active(x); refresh_aspect_lock_flag(); } - - void refresh_aspect_lock_flag() { if(duck_dragger_)duck_dragger_->lock_aspect=get_aspect_lock_flag(); } - - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - void refresh_tool_options(); - - StateScale_Context(CanvasView* canvas_view); - - ~StateScale_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(); -}; // END of class StateScale_Context - -/* === M E T H O D S ======================================================= */ - -StateScale::StateScale(): - Smach::state("scale") -{ - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateScale_Context::event_refresh_tool_options)); - insert(event_def(EVENT_STOP,&StateScale_Context::event_stop_handler)); -} - -StateScale::~StateScale() -{ -} - -void -StateScale_Context::load_settings() -{ - String value; - - if(settings.get_value("scale.lock_aspect",value) && value=="0") - set_aspect_lock_flag(false); - else - set_aspect_lock_flag(true); -} - -void -StateScale_Context::save_settings() -{ - settings.set_value("scale.lock_aspect",get_aspect_lock_flag()?"1":"0"); -} - -StateScale_Context::StateScale_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - settings(synfigapp::Main::get_selected_input_device()->settings()), - duck_dragger_(new DuckDrag_Scale()), - checkbutton_aspect_lock(_("Lock Aspect Ratio")) -{ - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Scale Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_aspect_lock, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - checkbutton_aspect_lock.signal_toggled().connect(sigc::mem_fun(*this,&StateScale_Context::refresh_aspect_lock_flag)); - - options_table.show_all(); - refresh_tool_options(); - App::dialog_tool_options->present(); - - get_work_area()->set_allow_layer_clicks(true); - get_work_area()->set_duck_dragger(duck_dragger_); - - get_work_area()->set_cursor(Gdk::SIZING); -// get_work_area()->reset_cursor(); - - App::toolbox->refresh(); - - set_aspect_lock_flag(true); - load_settings(); -} - -void -StateScale_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Scale Tool")); - App::dialog_tool_options->set_name("scale"); -} - -Smach::event_result -StateScale_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateScale_Context::event_stop_handler(const Smach::event& /*x*/) -{ - throw &state_normal; - return Smach::RESULT_OK; -} - -StateScale_Context::~StateScale_Context() -{ - save_settings(); - - get_work_area()->clear_duck_dragger(); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - App::toolbox->refresh(); -} - - - - -DuckDrag_Scale::DuckDrag_Scale(): - lock_aspect(true) -{ -} - -#ifndef EPSILON -#define EPSILON 0.0000001 -#endif - -void -DuckDrag_Scale::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) -{ - last_scale=Vector(1,1); - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - //if(duckmatic->get_selected_ducks().size()<2) - //{ - // bad_drag=true; -// return; -// } - bad_drag=false; - - drag_offset=duckmatic->find_duck(offset)->get_trans_point(); - - //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); - //snap=offset-drag_offset; - snap=Vector(0,0); - - // 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++) - { - 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); - } - if((vmin-vmax).mag()<=EPSILON) - move_only=true; - else - move_only=false; - - center=(vmin+vmax)*0.5; -} - - -void -DuckDrag_Scale::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) -{ - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - if(bad_drag) - return; - - //std::set >::iterator iter; - synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center); - last_scale=vect; - - if(move_only) - { - int i; - 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; - - Vector p(positions[i]); - - p[0]+=vect[0]; - p[1]+=vect[1]; - (*iter)->set_trans_point(p); - } - 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; - - Vector p(positions[i]); - - p[0]+=vect[0]; - p[1]+=vect[1]; - (*iter)->set_trans_point(p); - } - return; - } - - if(!lock_aspect) - { - 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 - { - //vect[0]=vect[1]=vect.mag()*0.707106781; - Real amount(vect.mag()/(drag_offset-center).mag()); - vect[0]=vect[1]=amount; - } - - if(vect[0]-EPSILON) - vect[0]=1; - if(vect[1]-EPSILON) - vect[1]=1; - - int i; - 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; - - Vector p(positions[i]-center); - - p[0]*=vect[0]; - p[1]*=vect[1]; - p+=center; - (*iter)->set_trans_point(p); - } - 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; - - Vector p(positions[i]-center); - - p[0]*=vect[0]; - p[1]*=vect[1]; - p+=center; - (*iter)->set_trans_point(p); - } - - last_scale=vect; - //snap=Vector(0,0); -} - -bool -DuckDrag_Scale::end_duck_drag(Duckmatic* duckmatic) -{ - if(bad_drag)return false; - - if((last_scale-Vector(1,1)).mag()>0.0001) - { - duckmatic->signal_edited_selected_ducks(); - return true; - } - else - { - duckmatic->signal_user_click_selected_ducks(0); - return false; - } -} diff --git a/synfig-studio/src/gui/state_scale.h b/synfig-studio/src/gui/state_scale.h deleted file mode 100644 index f351c12..0000000 --- a/synfig-studio/src/gui/state_scale.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_scale.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_SCALE_H -#define __SYNFIG_STUDIO_STATE_SCALE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateScale_Context; - -class StateScale : public Smach::state -{ -public: - StateScale(); - ~StateScale(); -}; // END of class StateScale - -extern StateScale state_scale; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_sketch.cpp b/synfig-studio/src/gui/state_sketch.cpp deleted file mode 100644 index f8b77a3..0000000 --- a/synfig-studio/src/gui/state_sketch.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_sketch.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2007, 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include - -#include "state_sketch.h" -#include "state_normal.h" -#include "state_stroke.h" -#include "canvasview.h" -#include "workarea.h" -#include "app.h" -#include -#include -#include -#include -#include "event_mouse.h" -#include "event_layerclick.h" -#include "toolbox.h" - -#include -#include - -#include - -#include "dialog_tooloptions.h" - -#include -#include -#include -#include -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateSketch studio::state_sketch; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateSketch_Context : public sigc::trackable -{ - Glib::RefPtr action_group; - - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - bool prev_table_status; - bool prev_workarea_layer_status_; - - Gtk::Table options_table; - Gtk::Button button_clear_sketch; - Gtk::Button button_undo_stroke; - Gtk::Button button_save_sketch; - Gtk::Button button_load_sketch; - Gtk::CheckButton checkbutton_show_sketch; - - void clear_sketch(); - void save_sketch(); - void load_sketch(); - void undo_stroke(); - void toggle_show_sketch(); - -public: - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_mouse_down_handler(const Smach::event& x); - - Smach::event_result event_stroke(const Smach::event& x); - - Smach::event_result event_refresh_tool_options(const Smach::event& x); - Smach::event_result event_yield_tool_options(const Smach::event& x); - - void refresh_tool_options(); - void yield_tool_options(); - - StateSketch_Context(CanvasView* canvas_view); - - ~StateSketch_Context(); - - const etl::handle& get_canvas_view()const{return canvas_view_;} - etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} - synfig::Time get_time()const { return get_canvas_interface()->get_time(); } - synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} - WorkArea * get_work_area()const{return canvas_view_->get_work_area();} - -}; // END of class StateSketch_Context - - -/* === M E T H O D S ======================================================= */ - -StateSketch::StateSketch(): - Smach::state("sketch") -{ - insert(event_def(EVENT_STOP,&StateSketch_Context::event_stop_handler)); - //insert(event_def(EVENT_REFRESH,&StateSketch_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateSketch_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateSketch_Context::event_mouse_down_handler)); - insert(event_def(EVENT_WORKAREA_STROKE,&StateSketch_Context::event_stroke)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSketch_Context::event_refresh_tool_options)); - insert(event_def(EVENT_YIELD_TOOL_OPTIONS,&StateSketch_Context::event_yield_tool_options)); -} - -StateSketch::~StateSketch() -{ -} - -void -StateSketch_Context::save_sketch() -{ - synfig::String filename(basename(get_canvas()->get_file_name())+".sketch"); - - while(App::dialog_save_file(_("Save Sketch"), filename, SKETCH_DIR_PREFERENCE)) - { - // If the filename still has wildcards, then we should - // continue looking for the file we want - if(find(filename.begin(),filename.end(),'*')!=filename.end()) - continue; - - if(get_work_area()->save_sketch(filename)) - break; - - get_canvas_view()->get_ui_interface()->error(_("Unable to save sketch")); - } -} - -void -StateSketch_Context::load_sketch() -{ - synfig::String filename(basename(get_canvas()->get_file_name())+".sketch"); - - while(App::dialog_open_file(_("Load Sketch"), filename, SKETCH_DIR_PREFERENCE)) - { - // If the filename still has wildcards, then we should - // continue looking for the file we want - if(find(filename.begin(),filename.end(),'*')!=filename.end()) - continue; - - if(get_work_area()->load_sketch(filename)) - break; - - get_canvas_view()->get_ui_interface()->error(_("Unable to load sketch")); - } - get_work_area()->queue_draw(); -} - -void -StateSketch_Context::clear_sketch() -{ - get_work_area()->clear_persistent_strokes(); - - // if the sketch is currently shown, make sure it is updated - //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_? - if (checkbutton_show_sketch.get_active()) - { - get_work_area()->set_show_persistent_strokes(false); - get_work_area()->set_show_persistent_strokes(true); - get_canvas_view()->get_smach().process_event(EVENT_REFRESH); - } -} - -void -StateSketch_Context::undo_stroke() -{ - if(!get_work_area()->persistent_stroke_list().empty()) - { - get_work_area()->persistent_stroke_list().pop_back(); - - // if the sketch is currently shown, make sure it is updated - //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_? - if (checkbutton_show_sketch.get_active()) - { - get_work_area()->set_show_persistent_strokes(false); - get_work_area()->set_show_persistent_strokes(true); - get_canvas_view()->get_smach().process_event(EVENT_REFRESH); - } - } -} - -void -StateSketch_Context::toggle_show_sketch() -{ - get_work_area()->set_show_persistent_strokes(checkbutton_show_sketch.get_active()); - get_work_area()->queue_draw(); -} - -StateSketch_Context::StateSketch_Context(CanvasView* canvas_view): - action_group(Gtk::ActionGroup::create("action_group_state_sketch")), - canvas_view_(canvas_view), - is_working(*canvas_view), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - button_clear_sketch(_("Clear Sketch")), - button_undo_stroke(_("Undo Stroke")), - button_save_sketch(_("Save Sketch")), - button_load_sketch(_("Load Sketch")), - checkbutton_show_sketch(_("Show Sketch")) -{ - Glib::ustring ui_info = - "" - " " - " " - " " - " " - " " - " " - ""; - - action_group->add(Gtk::Action::create( - "sketch-undo", - Gtk::StockID("gtk-undo"), - _("Undo Last Stroke"), - _("Undo Last Stroke") - ), - sigc::mem_fun( - *this, - &studio::StateSketch_Context::undo_stroke - ) - ); - - action_group->add(Gtk::Action::create( - "sketch-clear", - Gtk::StockID("gtk-clear"), - _("Clear Sketch"), - _("Clear Sketch") - ), - sigc::mem_fun( - *this, - &studio::StateSketch_Context::clear_sketch - ) - ); - - action_group->add(Gtk::Action::create( - "sketch-save-as", - Gtk::StockID("gtk-save-as"), - _("Save Sketch As..."), - _("Save Sketch As...") - ), - sigc::mem_fun( - *this, - &studio::StateSketch_Context::save_sketch - ) - ); - - action_group->add(Gtk::Action::create( - "sketch-save-as", - Gtk::StockID("gtk-save-as"), - _("Save Sketch As..."), - _("Save Sketch As...") - ), - sigc::mem_fun( - *this, - &studio::StateSketch_Context::save_sketch - ) - ); - - action_group->add(Gtk::Action::create( - "sketch-open", - Gtk::StockID("gtk-open"), - _("Open a Sketch"), - _("Open a Sketch") - ), - sigc::mem_fun( - *this, - &studio::StateSketch_Context::load_sketch - ) - ); - - action_group->add( Gtk::Action::create("toolbar-sketch", "Sketch Toolbar") ); - - App::ui_manager()->add_ui_from_string(ui_info); - - checkbutton_show_sketch.set_active(get_work_area()->get_show_persistent_strokes()); - - button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch)); - button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke)); - button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch)); - button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch)); - checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch)); - - options_table.attach(*manage(new Gtk::Label(_("Sketch Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_show_sketch, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - //options_table.attach(button_undo_stroke, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - //options_table.attach(button_clear_sketch, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - //options_table.attach(button_save_sketch, 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - //options_table.attach(button_load_sketch, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.show_all(); - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - get_work_area()->set_cursor(Gdk::PENCIL); - - // Turn off duck clicking - get_work_area()->set_allow_duck_clicks(false); - - // clear out the ducks - //get_work_area()->clear_ducks(); - - // Refresh the work area - //get_work_area()->queue_draw(); - - // Hide the tables if they are showing - prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::on_user_click)); - - App::toolbox->refresh(); -} - -StateSketch_Context::~StateSketch_Context() -{ - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - - // Restore duck clicking - get_work_area()->set_allow_duck_clicks(true); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - //get_work_area()->queue_draw(); - - App::toolbox->refresh(); -} - -void -StateSketch_Context::yield_tool_options() -{ - App::dialog_tool_options->clear(); - App::ui_manager()->remove_action_group(action_group); -} - -void -StateSketch_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Sketch Tool")); - App::dialog_tool_options->set_name("sketch"); - - App::ui_manager()->insert_action_group(action_group); - App::dialog_tool_options->set_toolbar(*dynamic_cast(App::ui_manager()->get_widget("/toolbar-sketch"))); - - /* - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-undo"), - _("Undo Last Stroke") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &studio::StateSketch_Context::undo_stroke - ) - ); - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-clear"), - _("Clear Sketch") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &studio::StateSketch_Context::clear_sketch - ) - ); - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-save"), - _("Save Sketch to a File") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &studio::StateSketch_Context::save_sketch - ) - ); - - App::dialog_tool_options->add_button( - Gtk::StockID("gtk-open"), - _("Open a Sketch") - )->signal_clicked().connect( - sigc::mem_fun( - *this, - &studio::StateSketch_Context::load_sketch - ) - ); - */ - //button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch)); - //button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke)); - //button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch)); - //button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch)); - //checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch)); -} - -Smach::event_result -StateSketch_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateSketch_Context::event_yield_tool_options(const Smach::event& /*x*/) -{ - yield_tool_options(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateSketch_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateSketch_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateSketch_Context::event_mouse_down_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - switch(event.button) - { - case BUTTON_LEFT: - { - // Enter the stroke state to get the stroke - get_canvas_view()->get_smach().push_state(&state_stroke); - return Smach::RESULT_ACCEPT; - } - - default: - return Smach::RESULT_OK; - } -} - -Smach::event_result -StateSketch_Context::event_stroke(const Smach::event& x) -{ - const EventStroke& event(*reinterpret_cast(&x)); - - assert(event.stroke_data); - - get_work_area()->add_persistent_stroke(event.stroke_data,synfigapp::Main::get_outline_color()); - - return Smach::RESULT_ACCEPT; -} diff --git a/synfig-studio/src/gui/state_sketch.h b/synfig-studio/src/gui/state_sketch.h deleted file mode 100644 index 301c81d..0000000 --- a/synfig-studio/src/gui/state_sketch.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_sketch.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_SKETCH_H -#define __SYNFIG_STUDIO_STATE_SKETCH_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateSketch_Context; - -class StateSketch : public Smach::state -{ -public: - StateSketch(); - ~StateSketch(); -}; // END of class StateSketch - -extern StateSketch state_sketch; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_smoothmove.cpp b/synfig-studio/src/gui/state_smoothmove.cpp deleted file mode 100644 index f42df35..0000000 --- a/synfig-studio/src/gui/state_smoothmove.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_smoothmove.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 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 -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include -#include -#include - -#include "state_smoothmove.h" -#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 "duck.h" -#include "onemoment.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateSmoothMove studio::state_smooth_move; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class DuckDrag_SmoothMove : public DuckDrag_Base -{ - float radius; - - synfig::Vector last_translate_; - synfig::Vector drag_offset_; - synfig::Vector snap; - - std::vector last_; - std::vector positions; - -public: - DuckDrag_SmoothMove(); - 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); - - void set_radius(float x) { radius=x; } - float get_radius()const { return radius; } -}; - - -class studio::StateSmoothMove_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - //Duckmatic::Push duckmatic_push; - - synfigapp::Settings& settings; - - etl::handle duck_dragger_; - - Gtk::Table options_table; - - Gtk::Adjustment adj_radius; - Gtk::SpinButton spin_radius; - - float pressure; - -public: - float get_radius()const { return adj_radius.get_value(); } - void set_radius(float x) { return adj_radius.set_value(x); } - - void refresh_radius() { duck_dragger_->set_radius(get_radius()*pressure); } - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - void refresh_tool_options(); - - StateSmoothMove_Context(CanvasView* canvas_view); - - ~StateSmoothMove_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(); -}; // END of class StateSmoothMove_Context - -/* === M E T H O D S ======================================================= */ - -StateSmoothMove::StateSmoothMove(): - Smach::state("smooth_move") -{ - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSmoothMove_Context::event_refresh_tool_options)); - insert(event_def(EVENT_STOP,&StateSmoothMove_Context::event_stop_handler)); -} - -StateSmoothMove::~StateSmoothMove() -{ -} - -void -StateSmoothMove_Context::load_settings() -{ - String value; - - if(settings.get_value("smooth_move.radius",value)) - set_radius(atof(value.c_str())); - else - set_radius(1.0f); -} - -void -StateSmoothMove_Context::save_settings() -{ - settings.set_value("smooth_move.radius",strprintf("%f",get_radius())); -} - -StateSmoothMove_Context::StateSmoothMove_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), -// duckmatic_push(get_work_area()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - duck_dragger_(new DuckDrag_SmoothMove()), - adj_radius(1,0,100000,0.01,0.1), - spin_radius(adj_radius,0.1,3) -{ - pressure=1.0f; - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("SmoothMove Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("Radius"))), 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_radius, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - spin_radius.signal_value_changed().connect(sigc::mem_fun(*this,&StateSmoothMove_Context::refresh_radius)); - - options_table.show_all(); - refresh_tool_options(); - //App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->present(); - - get_work_area()->set_allow_layer_clicks(true); - get_work_area()->set_duck_dragger(duck_dragger_); - - App::toolbox->refresh(); - - get_work_area()->set_cursor(Gdk::FLEUR); - //get_work_area()->reset_cursor(); - - load_settings(); -} - -void -StateSmoothMove_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Smooth Move")); - App::dialog_tool_options->set_name("smooth_move"); -} - -Smach::event_result -StateSmoothMove_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateSmoothMove_Context::event_stop_handler(const Smach::event& /*x*/) -{ - throw &state_normal; - return Smach::RESULT_OK; -} - -StateSmoothMove_Context::~StateSmoothMove_Context() -{ - save_settings(); - - get_work_area()->clear_duck_dragger(); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - App::toolbox->refresh(); -} - - - - -DuckDrag_SmoothMove::DuckDrag_SmoothMove():radius(1.0f) -{ -} - -void -DuckDrag_SmoothMove::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) -{ - last_translate_=Vector(0,0); - drag_offset_=duckmatic->find_duck(offset)->get_trans_point(); - - //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); - //snap=offset-drag_offset_; - snap=Vector(0,0); - - last_.clear(); - positions.clear(); - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - int i; - for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) - { - last_.push_back(Vector(0,0)); - positions.push_back((*iter)->get_trans_point()); - } -} - -void -DuckDrag_SmoothMove::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) -{ - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_+snap); - - int i; - - Time time(duckmatic->get_time()); - - // process vertex and position ducks first - for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) - { - // skip this duck if it is NOT a vertex or a position - if (((*iter)->get_type() != Duck::TYPE_VERTEX && - (*iter)->get_type() != Duck::TYPE_POSITION)) - continue; - Point p(positions[i]); - - float dist(1.0f-(p-drag_offset_).mag()/get_radius()); - if(dist<0) - dist=0; - - last_[i]=vect*dist; - (*iter)->set_trans_point(p+last_[i], time); - } - - // then process non vertex and non position ducks - for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) - { - // skip this duck if it IS a vertex or a position - if (!((*iter)->get_type() != Duck::TYPE_VERTEX && - (*iter)->get_type() != Duck::TYPE_POSITION)) - continue; - Point p(positions[i]); - - float dist(1.0f-(p-drag_offset_).mag()/get_radius()); - if(dist<0) - dist=0; - - last_[i]=vect*dist; - (*iter)->set_trans_point(p+last_[i], time); - } - - // then patch up the tangents for the vertices we've moved - duckmatic->update_ducks(); - - last_translate_=vect; - //snap=Vector(0,0); -} - -bool -DuckDrag_SmoothMove::end_duck_drag(Duckmatic* duckmatic) -{ - //synfig::info("end_duck_drag(): Diff= %f",last_translate_.mag()); - if(last_translate_.mag()>0.0001) - { - const DuckList selected_ducks(duckmatic->get_selected_ducks()); - DuckList::const_iterator iter; - - int i; - - smart_ptr wait;if(selected_ducks.size()>20)wait.spawn(); - - for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) - { - if(last_[i].mag()>0.0001) - { - if ((*iter)->get_type() == Duck::TYPE_ANGLE) - { - if(!(*iter)->signal_edited_angle()((*iter)->get_rotations())) - { - throw String("Bad edit"); - } - } - else if (App::restrict_radius_ducks && - (*iter)->is_radius()) - { - Point point((*iter)->get_point()); - bool changed = false; - - if (point[0] < 0) - { - point[0] = 0; - changed = true; - } - if (point[1] < 0) - { - point[1] = 0; - changed = true; - } - - if (changed) (*iter)->set_point(point); - - if(!(*iter)->signal_edited()(point)) - { - throw String("Bad edit"); - } - } - else - { - if(!(*iter)->signal_edited()((*iter)->get_point())) - { - throw String("Bad edit"); - } - } - } - } - //duckmatic->get_selected_ducks()=new_set; - //duckmatic->refresh_selected_ducks(); - return true; - } - else - { - duckmatic->signal_user_click_selected_ducks(0); - return false; - } -} diff --git a/synfig-studio/src/gui/state_smoothmove.h b/synfig-studio/src/gui/state_smoothmove.h deleted file mode 100644 index 07442af..0000000 --- a/synfig-studio/src/gui/state_smoothmove.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_smoothmove.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H -#define __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateSmoothMove_Context; - -class StateSmoothMove : public Smach::state -{ -public: - StateSmoothMove(); - ~StateSmoothMove(); -}; // END of class StateSmoothMove - -extern StateSmoothMove state_smooth_move; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_star.cpp b/synfig-studio/src/gui/state_star.cpp deleted file mode 100644 index 3be4b53..0000000 --- a/synfig-studio/src/gui/state_star.cpp +++ /dev/null @@ -1,1091 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_star.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include -#include - -#include "state_star.h" -#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 "duck.h" -#include "widgets/widget_enum.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateStar studio::state_star; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateStar_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - Duckmatic::Push duckmatic_push; - - Point point_holder; - - etl::handle point2_duck; - - void refresh_ducks(); - - bool prev_workarea_layer_status_; - - //Toolbox settings - synfigapp::Settings& settings; - - //Toolbox display - Gtk::Table options_table; - - Gtk::Entry entry_id; //what to name the layer - - Gtk::Adjustment adj_feather; - Gtk::Adjustment adj_number_of_points; - Gtk::Adjustment adj_inner_tangent; - Gtk::Adjustment adj_outer_tangent; - Gtk::Adjustment adj_inner_width; - Gtk::Adjustment adj_outer_width; - Gtk::Adjustment adj_radius_ratio; - Gtk::Adjustment adj_angle_offset; - Gtk::SpinButton spin_feather; - Gtk::SpinButton spin_number_of_points; - Gtk::SpinButton spin_inner_tangent; - Gtk::SpinButton spin_outer_tangent; - Gtk::SpinButton spin_inner_width; - Gtk::SpinButton spin_outer_width; - Gtk::SpinButton spin_radius_ratio; - Gtk::SpinButton spin_angle_offset; - - Gtk::CheckButton checkbutton_invert; - Gtk::CheckButton checkbutton_regular_polygon; - Gtk::CheckButton checkbutton_layer_star; - Gtk::CheckButton checkbutton_layer_region; - Gtk::CheckButton checkbutton_layer_outline; - Gtk::CheckButton checkbutton_layer_curve_gradient; - Gtk::CheckButton checkbutton_layer_plant; - Gtk::CheckButton checkbutton_layer_link_origins; - Gtk::CheckButton checkbutton_layer_origins_at_center; - -public: - - // this only counts the layers which will have their origins linked - int layers_to_create()const - { - return - (get_layer_star_flag() && get_layer_origins_at_center_flag()) + - get_layer_region_flag() + - get_layer_outline_flag() + - get_layer_curve_gradient_flag() + - get_layer_plant_flag(); - } - - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - Real get_feather()const { return adj_feather.get_value(); } - void set_feather(Real f) { adj_feather.set_value(f); } - - Real get_number_of_points()const { return adj_number_of_points.get_value(); } - void set_number_of_points(Real f) { adj_number_of_points.set_value(f); } - - Real get_inner_tangent()const { return adj_inner_tangent.get_value(); } - void set_inner_tangent(Real f) { adj_inner_tangent.set_value(f); } - - Real get_outer_tangent()const { return adj_outer_tangent.get_value(); } - void set_outer_tangent(Real f) { adj_outer_tangent.set_value(f); } - - Real get_inner_width()const { return adj_inner_width.get_value(); } - void set_inner_width(Real f) { adj_inner_width.set_value(f); } - - Real get_outer_width()const { return adj_outer_width.get_value(); } - void set_outer_width(Real f) { adj_outer_width.set_value(f); } - - Real get_radius_ratio()const { return adj_radius_ratio.get_value(); } - void set_radius_ratio(Real f) { adj_radius_ratio.set_value(f); } - - Real get_angle_offset()const { return adj_angle_offset.get_value(); } - void set_angle_offset(Real f) { adj_angle_offset.set_value(f); } - - bool get_invert()const { return checkbutton_invert.get_active(); } - void set_invert(bool i) { checkbutton_invert.set_active(i); } - - bool get_regular_polygon()const { return checkbutton_regular_polygon.get_active(); } - void set_regular_polygon(bool i) { checkbutton_regular_polygon.set_active(i); } - - bool get_layer_star_flag()const { return checkbutton_layer_star.get_active(); } - void set_layer_star_flag(bool x) { return checkbutton_layer_star.set_active(x); } - - bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } - void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } - - bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } - void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } - - bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } - void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } - - bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } - void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } - - bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } - void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } - - bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); } - void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); } - - void refresh_tool_options(); //to refresh the toolbox - - //events - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - //constructor destructor - StateStar_Context(CanvasView* canvas_view); - ~StateStar_Context(); - - //Canvas interaction - 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();} - - //Modifying settings etc. - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - - void make_star(const Point& p1, const Point& p2); - -}; // END of class StateStar_Context - -/* === M E T H O D S ======================================================= */ - -StateStar::StateStar(): - Smach::state("star") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateStar_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_STOP,&StateStar_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateStar_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateStar_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStar_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStar_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStar_Context::event_mouse_click_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStar_Context::event_refresh_tool_options)); -} - -StateStar::~StateStar() -{ -} - -void -StateStar_Context::load_settings() -{ - String value; - - //parse the arguments yargh! - if(settings.get_value("star.id",value)) - set_id(value); - else - set_id("Star"); - - if(settings.get_value("star.feather",value)) - set_feather(atof(value.c_str())); - else - set_feather(0); - - if(settings.get_value("star.number_of_points",value)) - set_number_of_points(atof(value.c_str())); - else - set_number_of_points(5); - - if(settings.get_value("star.inner_tangent",value)) - set_inner_tangent(atof(value.c_str())); - else - set_inner_tangent(0); - - if(settings.get_value("star.outer_tangent",value)) - set_outer_tangent(atof(value.c_str())); - else - set_outer_tangent(0); - - if(settings.get_value("star.inner_width",value)) - set_inner_width(atof(value.c_str())); - else - set_inner_width(1); - - if(settings.get_value("star.outer_width",value)) - set_outer_width(atof(value.c_str())); - else - set_outer_width(1); - - if(settings.get_value("star.radius_ratio",value)) - set_radius_ratio(atof(value.c_str())); - else - set_radius_ratio(0.5); - - if(settings.get_value("star.angle_offset",value)) - set_angle_offset(atof(value.c_str())); - else - set_angle_offset(0); - - if(settings.get_value("star.invert",value) && value != "0") - set_invert(true); - else - set_invert(false); - - if(settings.get_value("star.regular_polygon",value) && value != "0") - set_regular_polygon(true); - else - set_regular_polygon(false); - - if(settings.get_value("star.layer_star",value) && value=="0") - set_layer_star_flag(false); - else - set_layer_star_flag(true); - - if(settings.get_value("star.layer_region",value) && value=="1") - set_layer_region_flag(true); - else - set_layer_region_flag(false); - - if(settings.get_value("star.layer_outline",value) && value=="1") - set_layer_outline_flag(true); - else - set_layer_outline_flag(false); - - if(settings.get_value("star.layer_curve_gradient",value) && value=="1") - set_layer_curve_gradient_flag(true); - else - set_layer_curve_gradient_flag(false); - - if(settings.get_value("star.layer_plant",value) && value=="1") - set_layer_plant_flag(true); - else - set_layer_plant_flag(false); - - if(settings.get_value("star.layer_link_origins",value) && value=="0") - set_layer_link_origins_flag(false); - else - set_layer_link_origins_flag(true); - - if(settings.get_value("star.layer_origins_at_center",value) && value=="0") - set_layer_origins_at_center_flag(false); - else - set_layer_origins_at_center_flag(true); -} - -void -StateStar_Context::save_settings() -{ - settings.set_value("star.id",get_id()); - settings.set_value("star.feather",strprintf("%f",(float)get_feather())); - settings.set_value("star.number_of_points",strprintf("%d",(int)(get_number_of_points() + 0.5))); - settings.set_value("star.inner_tangent",strprintf("%f",(float)get_inner_tangent())); - settings.set_value("star.outer_tangent",strprintf("%f",(float)get_outer_tangent())); - settings.set_value("star.inner_width",strprintf("%f",(float)get_inner_width())); - settings.set_value("star.outer_width",strprintf("%f",(float)get_outer_width())); - settings.set_value("star.radius_ratio",strprintf("%f",(float)get_radius_ratio())); - settings.set_value("star.angle_offset",strprintf("%f",(float)get_angle_offset())); - settings.set_value("star.invert",get_invert()?"1":"0"); - settings.set_value("star.regular_polygon",get_regular_polygon()?"1":"0"); - settings.set_value("star.layer_star",get_layer_star_flag()?"1":"0"); - settings.set_value("star.layer_outline",get_layer_outline_flag()?"1":"0"); - settings.set_value("star.layer_region",get_layer_region_flag()?"1":"0"); - settings.set_value("star.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); - settings.set_value("star.layer_plant",get_layer_plant_flag()?"1":"0"); - settings.set_value("star.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); - settings.set_value("star.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0"); -} - -void -StateStar_Context::reset() -{ - refresh_ducks(); -} - -void -StateStar_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Star"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - String str_number; - str_number=String(id,id.size()-digits,id.size()); - id=String(id,0,id.size()-digits); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StateStar_Context::StateStar_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - duckmatic_push(get_work_area()), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), // value lower upper step page - adj_feather( 0, 0, 1, 0.01, 0.1), - adj_number_of_points( 0, 2, 120, 1 , 1 ), - adj_inner_tangent( 0, -10, 10, 0.01, 0.1), - adj_outer_tangent( 0, -10, 10, 0.01, 0.1), - adj_inner_width( 0, -10, 10, 0.01, 0.1), - adj_outer_width( 0, -10, 10, 0.01, 0.1), - adj_radius_ratio( 0, -10, 10, 0.01, 0.1), - adj_angle_offset( 0, -360, 360, 0.1 , 1 ), - spin_feather(adj_feather,0.1,3), - spin_number_of_points(adj_number_of_points,1,0), - spin_inner_tangent(adj_inner_tangent,1,2), - spin_outer_tangent(adj_outer_tangent,1,2), - spin_inner_width(adj_inner_width,1,2), - spin_outer_width(adj_outer_width,1,2), - spin_radius_ratio(adj_radius_ratio,1,2), - spin_angle_offset(adj_angle_offset,1,1), - checkbutton_invert(_("Invert")), - checkbutton_regular_polygon(_("Regular Polygon")), - checkbutton_layer_star(_("Create Star Layer")), - checkbutton_layer_region(_("Create Region BLine")), - checkbutton_layer_outline(_("Create Outline BLine")), - checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), - checkbutton_layer_plant(_("Create Plant BLine")), - checkbutton_layer_link_origins(_("Link Origins")), - checkbutton_layer_origins_at_center(_("BLine Origins at Center")) -{ - egress_on_selection_change=true; - - load_settings(); - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Star 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_layer_star, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_layer_origins_at_center, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_invert, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_regular_polygon, 0, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Feather:"))), 0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_feather, 1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Number of Points:"))), 0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_number_of_points, 1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Inner Tangent:"))), 0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_inner_tangent, 1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Outer Tangent:"))), 0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_outer_tangent, 1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Inner Width:"))), 0, 1, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_inner_width, 1, 2, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Outer Width:"))), 0, 1, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_outer_width, 1, 2, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Radius Ratio:"))), 0, 1, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_radius_ratio, 1, 2, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Angle Offset:"))), 0, 1, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_angle_offset, 1, 2, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.show_all(); - - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - // Hide the tables if they are showing - //prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateStar_Context::on_user_click)); - get_work_area()->set_cursor(Gdk::STAR); - - App::toolbox->refresh(); -} - -void -StateStar_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Star Tool")); - App::dialog_tool_options->set_name("star"); -} - -Smach::event_result -StateStar_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateStar_Context::~StateStar_Context() -{ - save_settings(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - //if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - get_canvas_view()->queue_rebuild_ducks(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateStar_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateStar_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StateStar_Context::make_star(const Point& _p1, const Point& _p2) -{ - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Star")); - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer; - - Canvas::Handle canvas; - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - - const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); - const Point p1(transform.unperform(_p1)); - const Point p2(transform.unperform(_p2)); - - Real radius_ratio(get_radius_ratio()); - Real radius1((p2-p1).mag()); - Real radius2(radius1 * radius_ratio); - int points = get_number_of_points(); - Real inner_tangent = get_inner_tangent() * radius1; - Real outer_tangent = get_outer_tangent() * radius2; - Real inner_width = get_inner_width(); - Real outer_width = get_outer_width(); - Angle::deg offset(get_angle_offset()); - bool regular(get_regular_polygon()); - Angle::deg angle(360.0/points); - Vector origin; - Real x, y; - - if (get_layer_origins_at_center_flag()) - { - x = y = 0; - origin = p1; - } - else - { - x = p1[0]; - y = p1[1]; - } - - std::vector new_list; - int point(0); - for (int i = 0; i < points; i++) - { - new_list.push_back(*(new BLinePoint)); - new_list[point].set_width(outer_width); - new_list[point].set_vertex(Point(radius1*Angle::cos(angle*i + offset).get() + x, - radius1*Angle::sin(angle*i + offset).get() + y)); - new_list[point++].set_tangent(Point(-Angle::sin(angle*i + offset).get(), - Angle::cos(angle*i + offset).get()) * outer_tangent); - - if (!regular) - { - new_list.push_back(*(new BLinePoint)); - new_list[point].set_width(inner_width); - new_list[point].set_vertex(Point(radius2*Angle::cos(angle*i + angle/2 + offset).get() + x, - radius2*Angle::sin(angle*i + angle/2 + offset).get() + y)); - new_list[point++].set_tangent(Point(-Angle::sin(angle*i + angle/2 + offset).get(), - Angle::cos(angle*i + angle/2 + offset).get()) * inner_tangent); - } - } - - ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); - assert(value_node_bline); - - ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin)); - assert(value_node_origin); - - // Set the looping flag - value_node_bline->set_loop(true); - - if(!canvas) - canvas=get_canvas_view()->get_canvas(); - - value_node_bline->set_member_canvas(canvas); - - // count how many layers we're going to be creating - int layers_to_create = this->layers_to_create(); - - /////////////////////////////////////////////////////////////////////////// - // S T A R - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_star_flag()) - { - layer=get_canvas_interface()->add_layer_to("star",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - - layer->set_param("radius1",radius1); - get_canvas_interface()->signal_layer_param_changed()(layer,"radius1"); - - layer->set_param("radius2",radius2); - get_canvas_interface()->signal_layer_param_changed()(layer,"radius2"); - - layer->set_param("angle",offset); - get_canvas_interface()->signal_layer_param_changed()(layer,"angle"); - - layer->set_param("points",points); - get_canvas_interface()->signal_layer_param_changed()(layer,"points"); - - layer->set_param("regular_polygon",regular); - get_canvas_interface()->signal_layer_param_changed()(layer,"regular_polygon"); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - layer->set_description(get_id()); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - // only link the star's origin parameter if the option is selected, we're putting bline - // origins at their centers, and we're creating more than one layer - if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Star layer")); - group.cancel(); - throw String(_("Unable to create Star layer")); - return; - } - } - else - { - layer->set_param("origin",p1); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // C U R V E G R A D I E N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_curve_gradient_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Gradient")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - - // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Gradient layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // P L A N T - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_plant_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Plant")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - - // only link the plant's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Plant layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // R E G I O N - /////////////////////////////////////////////////////////////////////////// - - if(get_layer_region_flag()) - { - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Region")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm - // using 2 separate ones. - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - - // only link the region's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); - group.cancel(); - throw String(_("Unable to create Region layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - /////////////////////////////////////////////////////////////////////////// - // O U T L I N E - /////////////////////////////////////////////////////////////////////////// - - if (get_layer_outline_flag()) - { - Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - layer->set_description(get_id()+_(" Outline")); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - layer->set_param("feather",get_feather()); - get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); - - layer->set_param("invert",get_invert()); - get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); - - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("bline"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - - // only link the outline's origin parameter if the option is selected and we're creating more than one layer - if (get_layer_link_origins_flag() && layers_to_create > 1) - { - synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - action->set_param("layer",layer); - if(!action->set_param("param",String("origin"))) - synfig::error("LayerParamConnect didn't like \"param\""); - if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) - synfig::error("LayerParamConnect didn't like \"value_node\""); - - if(!get_canvas_interface()->get_instance()->perform_action(action)) - { - //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); - group.cancel(); - throw String(_("Unable to create Outline layer")); - return; - } - } - else - { - layer->set_param("origin",origin); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - } - } - - egress_on_selection_change=false; - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - reset(); - increment_id(); -} - -Smach::event_result -StateStar_Context::event_mouse_click_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) - { - point_holder=get_work_area()->snap_point_to_grid(event.pos); - etl::handle duck=new Duck(); - duck->set_point(point_holder); - duck->set_name("p1"); - duck->set_type(Duck::TYPE_POSITION); - duck->set_editable(false); - get_work_area()->add_duck(duck); - - point2_duck=new Duck(); - point2_duck->set_point(Vector(0,0)); - point2_duck->set_name("radius"); - point2_duck->set_origin(duck); - point2_duck->set_radius(true); - point2_duck->set_scalar(-1); - point2_duck->set_type(Duck::TYPE_RADIUS); - point2_duck->set_hover(true); - get_work_area()->add_duck(point2_duck); - - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) - { - if (!point2_duck) return Smach::RESULT_OK; - point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos)); - get_work_area()->queue_draw(); - return Smach::RESULT_ACCEPT; - } - - if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) - { - Point point(get_work_area()->snap_point_to_grid(event.pos)); - - if (App::restrict_radius_ducks) - { - if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0]; - if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1]; - } - - make_star(point_holder, point); - get_work_area()->clear_ducks(); - return Smach::RESULT_ACCEPT; - } - - return Smach::RESULT_OK; -} - - -void -StateStar_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); -} diff --git a/synfig-studio/src/gui/state_star.h b/synfig-studio/src/gui/state_star.h deleted file mode 100644 index 606f77d..0000000 --- a/synfig-studio/src/gui/state_star.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_star.h -** \brief Star creation state -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_STAR_H -#define __SYNFIG_STUDIO_STATE_STAR_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateStar_Context; - -class StateStar : public Smach::state -{ -public: - StateStar(); - ~StateStar(); -}; // END of class StateStar - -extern StateStar state_star; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_stroke.cpp b/synfig-studio/src/gui/state_stroke.cpp deleted file mode 100644 index a0f7eca..0000000 --- a/synfig-studio/src/gui/state_stroke.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_stroke.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2007 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include - -#include "state_stroke.h" -#include "canvasview.h" -#include "workarea.h" -#include "app.h" -#include -#include -#include -#include -#include "event_mouse.h" -#include "event_layerclick.h" -#include "toolbox.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateStroke studio::state_stroke; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateStroke_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - Duckmatic::Push duckmatic_push; - - etl::smart_ptr > stroke_data; - - etl::smart_ptr > width_data; - - Gdk::ModifierType modifier; - -public: - - Smach::event_result event_stop_handler(const Smach::event& x); - - Smach::event_result event_refresh_handler(const Smach::event& x); - - Smach::event_result event_mouse_up_handler(const Smach::event& x); - - Smach::event_result event_mouse_draw_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - StateStroke_Context(CanvasView* canvas_view); - - ~StateStroke_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();} - -}; // END of class StateStroke_Context - - -/* === M E T H O D S ======================================================= */ - -StateStroke::StateStroke(): - Smach::state("stroke") -{ - insert(event_def(EVENT_STOP,&StateStroke_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateStroke_Context::event_refresh_handler)); -// insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStroke_Context::event_mouse_down_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStroke_Context::event_mouse_up_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStroke_Context::event_mouse_draw_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStroke_Context::event_refresh_tool_options)); -} - -StateStroke::~StateStroke() -{ -} - - -StateStroke_Context::StateStroke_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - duckmatic_push(get_work_area()) -{ - width_data.spawn(); - stroke_data.spawn(); - - get_work_area()->add_stroke(stroke_data, synfigapp::Main::get_outline_color()); -} - -StateStroke_Context::~StateStroke_Context() -{ - duckmatic_push.restore(); - - App::toolbox->refresh(); - - // Send the stroke data to whatever previously called this state. - if(stroke_data->size()>=2) - get_canvas_view()->get_smach().process_event(EventStroke(stroke_data,width_data,modifier)); -} - -Smach::event_result -StateStroke_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateStroke_Context::event_stop_handler(const Smach::event& /*x*/) -{ - throw Smach::pop_exception(); -} - -Smach::event_result -StateStroke_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateStroke_Context::event_mouse_up_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - switch(event.button) - { - case BUTTON_LEFT: - { - modifier=event.modifier; - throw Smach::pop_exception(); - } - - default: - return Smach::RESULT_OK; - } -} - -Smach::event_result -StateStroke_Context::event_mouse_draw_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - switch(event.button) - { - case BUTTON_LEFT: - { - stroke_data->push_back(event.pos); - width_data->push_back(event.pressure); - get_work_area()->queue_draw(); - return Smach::RESULT_ACCEPT; - } - - default: - return Smach::RESULT_OK; - } -} diff --git a/synfig-studio/src/gui/state_stroke.h b/synfig-studio/src/gui/state_stroke.h deleted file mode 100644 index 0beade5..0000000 --- a/synfig-studio/src/gui/state_stroke.h +++ /dev/null @@ -1,80 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_stroke.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_STROKE_H -#define __SYNFIG_STUDIO_STATE_STROKE_H - -/* === H E A D E R S ======================================================= */ - -#include "canvasview.h" -#include "workarea.h" -#include -#include "duckmatic.h" -#include -#include -#include -#include "eventkey.h" -#include - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateStroke_Context; - -class StateStroke : public Smach::state -{ -public: - StateStroke(); - ~StateStroke(); -}; // END of class StateStroke - -extern StateStroke state_stroke; - -struct EventStroke : public Smach::event -{ - etl::smart_ptr > stroke_data; - etl::smart_ptr > width_data; - Gdk::ModifierType modifier; - - EventStroke(etl::smart_ptr > stroke_data, - etl::smart_ptr > width_data, - Gdk::ModifierType modifier=Gdk::ModifierType(0) - ): - Smach::event(EVENT_WORKAREA_STROKE), - stroke_data(stroke_data), - width_data(width_data), - modifier(modifier) - { } -}; // END of EventStroke - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_text.cpp b/synfig-studio/src/gui/state_text.cpp deleted file mode 100644 index 733f907..0000000 --- a/synfig-studio/src/gui/state_text.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_text.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include "state_text.h" -#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 "duck.h" -#include "widgets/widget_enum.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateText studio::state_text; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateText_Context -{ - etl::handle canvas_view; - CanvasView::IsWorking is_working; - - Duckmatic::Push duckmatic_push; - - void refresh_ducks(); - - bool prev_workarea_layer_status_; - - //Toolbox settings - synfigapp::Settings& settings; - - //Toolbox display - Gtk::Table options_table; - - Gtk::Entry entry_id; //what to name the layer - Gtk::Entry entry_family; - Widget_Vector widget_size; - Widget_Vector widget_orientation; - Gtk::CheckButton checkbutton_paragraph; - -public: - synfig::String get_id()const { return entry_id.get_text(); } - void set_id(const synfig::String& x) { return entry_id.set_text(x); } - - bool get_paragraph_flag()const { return checkbutton_paragraph.get_active(); } - void set_paragraph_flag(bool x) { return checkbutton_paragraph.set_active(x); } - - Vector get_size() { return widget_size.get_value(); } - void set_size(Vector s) { return widget_size.set_value(s); } - - Vector get_orientation() { return widget_orientation.get_value(); } - void set_orientation(Vector s) { return widget_orientation.set_value(s); } - - String get_family()const { return entry_family.get_text(); } - void set_family(String s) { return entry_family.set_text(s); } - - void refresh_tool_options(); //to refresh the toolbox - - //events - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_mouse_click_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x); - - //constructor destructor - StateText_Context(CanvasView *canvas_view); - ~StateText_Context(); - - const etl::handle& get_canvas_view()const{return canvas_view;} - etl::handle get_canvas_interface()const{return canvas_view->canvas_interface();} - WorkArea * get_work_area()const{return canvas_view->get_work_area();} - - //Modifying settings etc. - void load_settings(); - void save_settings(); - void reset(); - void increment_id(); - bool egress_on_selection_change; - Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) - { - if(egress_on_selection_change) - throw &state_normal; //throw Smach::egress_exception(); - return Smach::RESULT_OK; - } - - void make_text(const Point& point); - -}; // END of class StateText_Context - -/* === P R O C E D U R E S ================================================= */ - -/* === M E T H O D S ======================================================= */ - -StateText::StateText(): - Smach::state("text") -{ - insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateText_Context::event_layer_selection_changed_handler)); - insert(event_def(EVENT_STOP,&StateText_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateText_Context::event_refresh_handler)); - insert(event_def(EVENT_REFRESH_DUCKS,&StateText_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateText_Context::event_workarea_mouse_button_down_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateText_Context::event_refresh_tool_options)); -} - -StateText::~StateText() -{ -} - -void -StateText_Context::load_settings() -{ - String value; - Vector v; - - //parse the arguments yargh! - if(settings.get_value("text.id",value)) - set_id(value); - else - set_id("Text"); - - if(settings.get_value("text.paragraph",value) && value=="1") - set_paragraph_flag(true); - else - set_paragraph_flag(false); - - if(settings.get_value("text.size_x",value)) - v[0] = atof(value.c_str()); - else - v[0] = 0.25; - if(settings.get_value("text.size_y",value)) - v[1] = atof(value.c_str()); - else - v[1] = 0.25; - set_size(v); - - if(settings.get_value("text.orient_x",value)) - v[0] = atof(value.c_str()); - else - v[0] = 0.5; - if(settings.get_value("text.orient_y",value)) - v[1] = atof(value.c_str()); - else - v[1] = 0.5; - set_orientation(v); - - if(settings.get_value("text.family",value)) - set_family(value); - else - set_family("Sans Serif"); -} - -void -StateText_Context::save_settings() -{ - settings.set_value("text.id",get_id()); - settings.set_value("text.paragraph",get_paragraph_flag()?"1":"0"); - settings.set_value("text.size_x",strprintf("%f",(float)get_size()[0])); - settings.set_value("text.size_y",strprintf("%f",(float)get_size()[1])); - settings.set_value("text.orient_x",strprintf("%f",(float)get_orientation()[0])); - settings.set_value("text.orient_y",strprintf("%f",(float)get_orientation()[1])); - settings.set_value("text.family",get_family()); -} - -void -StateText_Context::reset() -{ - refresh_ducks(); -} - -void -StateText_Context::increment_id() -{ - String id(get_id()); - int number=1; - int digits=0; - - if(id.empty()) - id="Text"; - - // If there is a number - // already at the end of the - // id, then remove it. - 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++) - ; - - String str_number; - str_number=String(id,id.size()-digits,id.size()); - id=String(id,0,id.size()-digits); - - number=atoi(str_number.c_str()); - } - else - { - number=1; - digits=3; - } - - number++; - - // Add the number back onto the id - { - const String format(strprintf("%%0%dd",digits)); - id+=strprintf(format.c_str(),number); - } - - // Set the ID - set_id(id); -} - -StateText_Context::StateText_Context(CanvasView *canvas_view): - canvas_view(canvas_view), - is_working(*canvas_view), - duckmatic_push(get_work_area()), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), - settings(synfigapp::Main::get_selected_input_device()->settings()), - entry_id(), - checkbutton_paragraph(_("Multiline Editor")) -{ - egress_on_selection_change=true; - - widget_size.set_digits(2); - widget_size.set_canvas(canvas_view->get_canvas()); - - widget_orientation.set_digits(2); - - options_table.attach(*manage(new Gtk::Label(_("Text 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_paragraph, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("Size:"))), 0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(widget_size, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("Orientation:"))), 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(widget_orientation, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(*manage(new Gtk::Label(_("Family:"))), 0, 1, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(entry_family, 1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - load_settings(); - - options_table.show_all(); - - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - // Hide the tables if they are showing - //prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateText_Context::on_user_click)); - get_work_area()->set_cursor(Gdk::XTERM); - - App::toolbox->refresh(); -} - -void -StateText_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Text Tool")); - App::dialog_tool_options->set_name("text"); -} - -Smach::event_result -StateText_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateText_Context::~StateText_Context() -{ - save_settings(); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - get_work_area()->reset_cursor(); - - App::dialog_tool_options->clear(); - - get_work_area()->queue_draw(); - - get_canvas_view()->queue_rebuild_ducks(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateText_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateText_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StateText_Context::make_text(const Point& _point) -{ - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Text")); - synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); - - Layer::Handle layer; - - Canvas::Handle canvas(get_canvas_view()->get_canvas()); - int depth(0); - - // we are temporarily using the layer to hold something - layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); - if(layer) - { - depth=layer->get_depth(); - canvas=layer->get_canvas(); - } - - synfigapp::SelectionManager::LayerList layer_selection; - if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) - layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); - - const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); - const Point point(transform.unperform(_point)); - - String text; - if (get_paragraph_flag()) - App::dialog_paragraph(_("Text Paragraph"), _("Enter text here:"), text); - else - App::dialog_entry(_("Text Entry"), _("Enter text here:"), text); - - layer=get_canvas_interface()->add_layer_to("text",canvas,depth); - if (!layer) - { - get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); - group.cancel(); - return; - } - layer_selection.push_back(layer); - - layer->set_param("origin",point); - get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); - - layer->set_param("text",text); - get_canvas_interface()->signal_layer_param_changed()(layer,"text"); - - layer->set_param("size",get_size()); - get_canvas_interface()->signal_layer_param_changed()(layer,"size"); - - layer->set_param("orient",get_orientation()); - get_canvas_interface()->signal_layer_param_changed()(layer,"orient"); - - layer->set_param("family",get_family()); - get_canvas_interface()->signal_layer_param_changed()(layer,"family"); - - layer->set_description(get_id()); - get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); - - egress_on_selection_change=false; - get_canvas_interface()->get_selection_manager()->clear_selected_layers(); - get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); - egress_on_selection_change=true; - - reset(); - increment_id(); -} - -Smach::event_result -StateText_Context::event_workarea_mouse_button_down_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - if(event.button==BUTTON_LEFT) - { - make_text(get_work_area()->snap_point_to_grid(event.pos)); - - get_work_area()->clear_ducks(); - return Smach::RESULT_ACCEPT; - } - return Smach::RESULT_OK; -} - -void -StateText_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); -} diff --git a/synfig-studio/src/gui/state_text.h b/synfig-studio/src/gui/state_text.h deleted file mode 100644 index 4b05db5..0000000 --- a/synfig-studio/src/gui/state_text.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_text.h -** \brief Template Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STATE_TEXT_H -#define __SYNFIG_STATE_TEXT_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateText_Context; - -class StateText : public Smach::state -{ -public: - StateText(); - ~StateText(); -}; // END of class StateText - -extern StateText state_text; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_width.cpp b/synfig-studio/src/gui/state_width.cpp deleted file mode 100644 index 8c74daa..0000000 --- a/synfig-studio/src/gui/state_width.cpp +++ /dev/null @@ -1,606 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_width.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include - -#include -#include - -#include "state_width.h" -#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 "duck.h" - -//#include -#include - -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace synfigapp; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ - -StateWidth studio::state_width; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateWidth_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - //Point mouse_pos; - - handle center; - handle radius; - handle closestpoint; - - map,Real> changetable; - - etl::clock clocktime; - Real lastt; - - bool added; - - void refresh_ducks(); - - bool prev_workarea_layer_clicking; - bool prev_workarea_duck_clicking; - Duckmatic::Type old_duckmask; - - //Toolbox settings - synfigapp::Settings& settings; - - //Toolbox display - Gtk::Table options_table; - - Gtk::Adjustment adj_delta; - Gtk::SpinButton spin_delta; - - Gtk::Adjustment adj_radius; - Gtk::SpinButton spin_radius; - - Gtk::CheckButton check_relative; - - void AdjustWidth(handle c, float t, Real mult, bool invert); - -public: - - Real get_delta()const { return adj_delta.get_value(); } - void set_delta(Real f) { adj_delta.set_value(f); } - - Real get_radius()const { return adj_radius.get_value(); } - void set_radius(Real f) { adj_radius.set_value(f); } - - bool get_relative() const { return check_relative.get_active(); } - void set_relative(bool r) { check_relative.set_active(r); } - - void refresh_tool_options(); //to refresh the toolbox - - //events - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_mouse_handler(const Smach::event& x); - Smach::event_result event_refresh_tool_options(const Smach::event& x); - - //constructor destructor - StateWidth_Context(CanvasView* canvas_view); - ~StateWidth_Context(); - - //Canvas interaction - 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();} - - //Modifying settings etc. - void load_settings(); - void save_settings(); - void reset(); - -}; // END of class StateWidth_Context - -/* === M E T H O D S ======================================================= */ - -StateWidth::StateWidth(): - Smach::state("width") -{ - insert(event_def(EVENT_STOP,&StateWidth_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateWidth_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateWidth_Context::event_mouse_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateWidth_Context::event_mouse_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateWidth_Context::event_mouse_handler)); - insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateWidth_Context::event_refresh_tool_options)); -} - -StateWidth::~StateWidth() -{ -} - -void -StateWidth_Context::load_settings() -{ - String value; - - //parse the arguments yargh! - if(settings.get_value("width.delta",value)) - set_delta(atof(value.c_str())); - else - set_delta(6); - - if(settings.get_value("width.radius",value)) - set_radius(atof(value.c_str())); - else - set_radius(15); - - //defaults to false - if(settings.get_value("width.relative",value) && value == "1") - set_relative(true); - else - set_relative(false); -} - -void -StateWidth_Context::save_settings() -{ - settings.set_value("width.delta",strprintf("%f",get_delta())); - settings.set_value("width.radius",strprintf("%f",get_radius())); - settings.set_value("width.relative",get_relative()?"1":"0"); -} - -void -StateWidth_Context::reset() -{ - refresh_ducks(); -} - -StateWidth_Context::StateWidth_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - prev_workarea_layer_clicking(get_work_area()->get_allow_layer_clicks()), - prev_workarea_duck_clicking(get_work_area()->get_allow_duck_clicks()), - old_duckmask(get_work_area()->get_type_mask()), - - settings(synfigapp::Main::get_selected_input_device()->settings()), - - adj_delta(6,0,20,0.01,0.1), - spin_delta(adj_delta,0.01,3), - - adj_radius(200,0,1e50,1,10), - spin_radius(adj_radius,1,1), - - check_relative(_("Relative Growth")) -{ - load_settings(); - - // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Width Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - //expand stuff - options_table.attach(*manage(new Gtk::Label(_("Growth:"))), 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_delta, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(*manage(new Gtk::Label(_("Radius:"))), 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(spin_radius, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.attach(check_relative, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - options_table.show_all(); - - refresh_tool_options(); - App::dialog_tool_options->present(); - - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - //get_work_area()->clear_ducks(); - - // Refresh the work area - get_work_area()->queue_draw(); - - //Create the new ducks - added = false; - - if(!center) - { - center = new Duck(); - center->set_name("p1"); - center->set_type(Duck::TYPE_POSITION); - } - - if(!radius) - { - radius = new Duck(); - radius->set_origin(center); - radius->set_radius(true); - radius->set_type(Duck::TYPE_RADIUS); - radius->set_name("radius"); - } - - if(!closestpoint) - { - closestpoint = new Duck(); - closestpoint->set_name("closest"); - closestpoint->set_type(Duck::TYPE_POSITION); - } - - //Disable duck clicking for the maximum coolness :) - get_work_area()->set_allow_duck_clicks(false); - get_work_area()->set_type_mask((Duck::Type)((int)Duck::TYPE_WIDTH + (int)Duck::TYPE_RADIUS)); - - // Turn the mouse pointer to crosshairs - get_work_area()->set_cursor(Gdk::CROSSHAIR); - - // Hide the tables if they are showing - //prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateWidth_Context::on_user_click)); - - App::toolbox->refresh(); -} - -void -StateWidth_Context::refresh_tool_options() -{ - App::dialog_tool_options->clear(); - App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Width Tool")); - App::dialog_tool_options->set_name("width"); -} - -Smach::event_result -StateWidth_Context::event_refresh_tool_options(const Smach::event& /*x*/) -{ - refresh_tool_options(); - return Smach::RESULT_ACCEPT; -} - -StateWidth_Context::~StateWidth_Context() -{ - save_settings(); - - //remove ducks if need be - if(added) - { - get_work_area()->erase_duck(center); - get_work_area()->erase_duck(radius); - get_work_area()->erase_duck(closestpoint); - added = false; - } - - // Restore Duck clicking - get_work_area()->set_allow_duck_clicks(prev_workarea_duck_clicking); - - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_clicking); - - // Restore the mouse pointer - get_work_area()->reset_cursor(); - - // Restore duck masking - get_work_area()->set_type_mask(old_duckmask); - - // Tool options be rid of ye!! - App::dialog_tool_options->clear(); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - //if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - App::toolbox->refresh(); -} - -Smach::event_result -StateWidth_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateWidth_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - refresh_ducks(); - return Smach::RESULT_ACCEPT; -} - -void -StateWidth_Context::AdjustWidth(handle c, float t, Real mult, bool invert) -{ - //Leave the function if there is no curve - if(!c)return; - - Real amount1=0,amount2=0; - - //decide how much to change each width - /* - t \in [0,1] - - both pressure and multiply amount are in mult - (may want to change this to allow different types of falloff) - - rsq is the squared distance from the point on the curve (also part of the falloff) - - - */ - //may want to provide a different falloff function... - if(t <= 0.2) - amount1 = mult; - else if(t >= 0.8) - amount2 = mult; - else - { - t = (t-0.2)/0.6; - amount1 = (1-t)*mult; - amount2 = t*mult; - } - - if(invert) - { - amount1 *= -1; - amount2 *= -1; - } - - handle p1 = c->p1; - handle p2 = c->p2; - - handle w1,w2; - - //find w1,w2 - { - const DuckList dl = get_work_area()->get_duck_list(); - - DuckList::const_iterator i = dl.begin(); - - for(;i != dl.end(); ++i) - { - if((*i)->get_type() == Duck::TYPE_WIDTH) - { - if((*i)->get_origin_duck() == p1) - { - w1 = *i; - } - - if((*i)->get_origin_duck() == p2) - { - w2 = *i; - } - } - } - } - - if(amount1 != 0 && w1) - { - Real width = w1->get_point().mag(); - - width += amount1; - w1->set_point(Vector(width,0)); - - //log in the list of changes... - //to truly be changed after everything is said and done - changetable[w1] = width; - } - - if(amount2 != 0 && w2) - { - Real width = w2->get_point().mag(); - - width += amount2; - w2->set_point(Vector(width,0)); - - //log in the list of changes... - //to truly be changed after everything is said and done - changetable[w2] = width; - } -} - -Smach::event_result -StateWidth_Context::event_mouse_handler(const Smach::event& x) -{ - const EventMouse& event(*reinterpret_cast(&x)); - - //handle the click - if( (event.key == EVENT_WORKAREA_MOUSE_BUTTON_DOWN || event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG) - && event.button == BUTTON_LEFT ) - { - const Real pw = get_work_area()->get_pw(); - const Real ph = get_work_area()->get_ph(); - const Real scale = sqrt(pw*pw+ph*ph); - const Real rad = get_relative() ? scale * get_radius() : get_radius(); - - bool invert = (event.modifier&Gdk::CONTROL_MASK); - - const Real threshold = 0.08; - - float t = 0; - Real rsq = 0; - - Real dtime = 1/60.0; - - //if we're dragging get the difference in time between now and then - if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG) - { - dtime = min(1/15.0,clocktime()); - } - clocktime.reset(); - - //make way for new ducks - //get_work_area()->clear_ducks(); - - //update positions - //mouse_pos = event.pos; - - center->set_point(event.pos); - if(!added)get_work_area()->add_duck(center); - - radius->set_scalar(rad); - if(!added)get_work_area()->add_duck(radius); - - //the other duck is at the current duck - closestpoint->set_point(event.pos); - if(!added)get_work_area()->add_duck(closestpoint); - - //get the closest curve... - handle c; - if(event.pressure >= threshold) - c = get_work_area()->find_bezier(event.pos,scale*8,rad,&t); - - //run algorithm on event.pos to get 2nd placement - if(!c.empty()) - { - bezier curve; - Point p; - - curve[0] = c->p1->get_trans_point(); - curve[1] = c->c1->get_trans_point(); - curve[2] = c->c2->get_trans_point(); - curve[3] = c->p2->get_trans_point(); - - p = curve(t); - rsq = (p-event.pos).mag_squared(); - - const Real r = rad*rad; - - if(rsq < r) - { - closestpoint->set_point(curve(t)); - - //adjust the width... - //squared falloff for radius... [0,1] - - Real ri = (r - rsq)/r; - AdjustWidth(c,t,ri*event.pressure*get_delta()*dtime,invert); - } - } - - //the points have been added - added = true; - - //draw where it is yo! - get_work_area()->queue_draw(); - - return Smach::RESULT_ACCEPT; - } - - if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button == BUTTON_LEFT) - { - if(added) - { - get_work_area()->erase_duck(center); - get_work_area()->erase_duck(radius); - get_work_area()->erase_duck(closestpoint); - added = false; - } - - //Affect the width changes here... - map,Real>::iterator i = changetable.begin(); - - synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch Width")); - for(; i != changetable.end(); ++i) - { - //for each duck modify IT!!! - ValueDesc desc = i->first->get_value_desc(); - - if( desc.get_value_type() == ValueBase::TYPE_REAL ) - { - Action::Handle action(Action::create("ValueDescSet")); - assert(action); - - action->set_param("canvas",get_canvas()); - action->set_param("canvas_interface",get_canvas_interface()); - - action->set_param("value_desc",desc); - action->set_param("new_value",ValueBase(i->second)); - action->set_param("time",get_canvas_view()->get_time()); - - if(!action->is_ready() || !get_canvas_view()->get_instance()->perform_action(action)) - { - group.cancel(); - synfig::warning("Changing the width action has failed"); - return Smach::RESULT_ERROR; - } - } - } - - changetable.clear(); - - get_work_area()->queue_draw(); - - return Smach::RESULT_ACCEPT; - } - - return Smach::RESULT_OK; -} - - -void -StateWidth_Context::refresh_ducks() -{ - get_work_area()->clear_ducks(); - get_work_area()->queue_draw(); -} diff --git a/synfig-studio/src/gui/state_width.h b/synfig-studio/src/gui/state_width.h deleted file mode 100644 index f649140..0000000 --- a/synfig-studio/src/gui/state_width.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_width.h -** \brief Width creation state -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STUDIO_STATE_WIDTH_H -#define __SYNFIG_STUDIO_STATE_WIDTH_H - -/* === H E A D E R S ======================================================= */ - -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateWidth_Context; - -class StateWidth : public Smach::state -{ -public: - StateWidth(); - ~StateWidth(); -}; // END of class StateWidth - -extern StateWidth state_width; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/state_zoom.cpp b/synfig-studio/src/gui/state_zoom.cpp deleted file mode 100644 index 56363e6..0000000 --- a/synfig-studio/src/gui/state_zoom.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_zoom.cpp -** \brief Zoom Tool Implementation File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2008 Chris Moore -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include - - -#include "state_zoom.h" -#include "state_normal.h" -#include "event_mouse.h" -#include "canvasview.h" -#include "workarea.h" -#include "app.h" -#include "toolbox.h" -#include - -#include "general.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; -using namespace studio; - -/* === M A C R O S ========================================================= */ - -/* === G L O B A L S ======================================================= */ -StateZoom studio::state_zoom; - -const float ZOOMFACTOR = 1.25f; - -/* === C L A S S E S & S T R U C T S ======================================= */ - -class studio::StateZoom_Context : public sigc::trackable -{ - etl::handle canvas_view_; - CanvasView::IsWorking is_working; - - Point p1,p2; - - bool prev_workarea_layer_status_; - -public: - - //events - Smach::event_result event_stop_handler(const Smach::event& x); - Smach::event_result event_refresh_handler(const Smach::event& x); - Smach::event_result event_mouse_click_handler(const Smach::event& x); - - //constructor destructor - StateZoom_Context(CanvasView* canvas_view); - ~StateZoom_Context(); - - //Canvas interaction - 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 zoom(const Point& p1, const Point& p2); - -}; // END of class StateZoom_Context - -/* === M E T H O D S ======================================================= */ - -StateZoom::StateZoom(): - Smach::state("zoom") -{ - insert(event_def(EVENT_STOP,&StateZoom_Context::event_stop_handler)); - insert(event_def(EVENT_REFRESH,&StateZoom_Context::event_refresh_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateZoom_Context::event_mouse_click_handler)); - //insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateZoom_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_BOX,&StateZoom_Context::event_mouse_click_handler)); - //insert(event_def(EVENT_WORKAREA_BUTTON_CLICK,&StateZoom_Context::event_mouse_click_handler)); - insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateZoom_Context::event_mouse_click_handler)); -} - -StateZoom::~StateZoom() -{ -} - -StateZoom_Context::StateZoom_Context(CanvasView* canvas_view): - canvas_view_(canvas_view), - is_working(*canvas_view), - prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()) -{ - // Turn off layer clicking - get_work_area()->set_allow_layer_clicks(false); - - // clear out the ducks - get_work_area()->clear_ducks(); //??? - - // Refresh the work area - get_work_area()->queue_draw(); - - // Hide the tables if they are showing - //prev_table_status=get_canvas_view()->tables_are_visible(); - //if(prev_table_status)get_canvas_view()->hide_tables(); - - // Disable the time bar - //get_canvas_view()->set_sensitive_timebar(false); - - // Connect a signal - //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateZoom_Context::on_user_click)); - get_work_area()->set_cursor(Gdk::CROSSHAIR); - - App::toolbox->refresh(); -} - -StateZoom_Context::~StateZoom_Context() -{ - // Restore layer clicking - get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); - get_work_area()->reset_cursor(); - - // Enable the time bar - //get_canvas_view()->set_sensitive_timebar(true); - - // Bring back the tables if they were out before - //if(prev_table_status)get_canvas_view()->show_tables(); - - // Refresh the work area - get_work_area()->queue_draw(); - - App::toolbox->refresh(); - - get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS); -} - -Smach::event_result -StateZoom_Context::event_stop_handler(const Smach::event& /*x*/) -{ - //throw Smach::egress_exception(); - throw &state_normal; - return Smach::RESULT_OK; -} - -Smach::event_result -StateZoom_Context::event_refresh_handler(const Smach::event& /*x*/) -{ - return Smach::RESULT_ACCEPT; -} - -Smach::event_result -StateZoom_Context::event_mouse_click_handler(const Smach::event& x) -{ - if(x.key==EVENT_WORKAREA_BOX) - { - const EventBox& event(*reinterpret_cast(&x)); - - if(event.button==BUTTON_LEFT) - { - Point tl = get_work_area()->get_window_tl(); - Point br = get_work_area()->get_window_br(); - Vector window_span = br - tl, window_middle = (br+tl)/2; - Vector box_span = event.p2 - event.p1, box_middle = (event.p1+event.p2)/2; - Point newpos; - float zoom; - - if(event.modifier & Gdk::CONTROL_MASK) //zoom out... - { - if (window_span[0] == 0 || window_span[1] == 0) zoom = 1; - else zoom = max(abs(box_span[0]/window_span[0]), abs(box_span[1]/window_span[1])); - - // focus_point is -1 times the real position for some reason... - // center the window so the old contents fill the drawn box - newpos = -((window_middle - box_middle)/zoom + window_middle); - } - else // zoom in - { - if (box_span[0] == 0 || box_span[1] == 0) zoom = 1; - else zoom = min(abs(window_span[0]/box_span[0]), abs(window_span[1]/box_span[1])); - - // center the window at the center of the box - newpos = -(-get_work_area()->get_focus_point() + (box_middle - window_middle)); - } - - get_work_area()->set_focus_point(newpos); - get_work_area()->set_zoom(get_work_area()->get_zoom()*zoom); - - return Smach::RESULT_ACCEPT; - } - } - - if(x.key==EVENT_WORKAREA_MOUSE_BUTTON_UP) - { - const EventMouse& event(*reinterpret_cast(&x)); - - if(event.button==BUTTON_LEFT) - { - Point evpos; - - //make the event pos be in the same space... - // The weird ass inverted center normalized space... - { - const Point realcenter = (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2; - evpos = -(event.pos - realcenter) + get_work_area()->get_focus_point(); - } - - /* Zooming: - focus point must zoom about the point evpos... - - trans about an origin not 0: - p' = A(p - o) + o - */ - - Vector v = get_work_area()->get_focus_point() - evpos; - - if(event.modifier & Gdk::CONTROL_MASK) //zoom out... - { - v*=ZOOMFACTOR; - //get_work_area()->zoom_out(); - get_work_area()->set_focus_point(evpos + v); - get_work_area()->set_zoom(get_work_area()->get_zoom()/ZOOMFACTOR); - }else //zoom in - { - v/=ZOOMFACTOR; - //get_work_area()->zoom_in(); - get_work_area()->set_focus_point(evpos + v); - get_work_area()->set_zoom(get_work_area()->get_zoom()*ZOOMFACTOR); - } - - return Smach::RESULT_ACCEPT; - } - } - - return Smach::RESULT_OK; -} diff --git a/synfig-studio/src/gui/state_zoom.h b/synfig-studio/src/gui/state_zoom.h deleted file mode 100644 index e5e7260..0000000 --- a/synfig-studio/src/gui/state_zoom.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file state_zoom.h -** \brief Zoom tool Header -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** \endlegal -*/ -/* ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __SYNFIG_STATE_ZOOM_H -#define __SYNFIG_STATE_ZOOM_H - -/* === H E A D E R S ======================================================= */ -#include "smach.h" - - -/* === M A C R O S ========================================================= */ - -/* === T Y P E D E F S ===================================================== */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -namespace studio { - -class StateZoom_Context; - -class StateZoom : public Smach::state -{ -public: - StateZoom(); - ~StateZoom(); -}; // END of class StateZoom - -extern StateZoom state_zoom; - -}; // END of namespace studio - -/* === E N D =============================================================== */ - -#endif diff --git a/synfig-studio/src/gui/states/state_bline.cpp b/synfig-studio/src/gui/states/state_bline.cpp new file mode 100644 index 0000000..ee0ca20 --- /dev/null +++ b/synfig-studio/src/gui/states/state_bline.cpp @@ -0,0 +1,1414 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_bline.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include "state_bline.h" +#include "state_normal.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" +#include +#include +#include +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include "dialog_tooloptions.h" +#include +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +// if defined, show the first duck as green while drawing +#define DISTINGUISH_FIRST_DUCK + +/* === G L O B A L S ======================================================= */ + +StateBLine studio::state_bline; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateBLine_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + bool prev_table_status; + bool loop_; + bool prev_workarea_layer_status_; + + int depth; + Canvas::Handle canvas; + + Gtk::Menu menu; + + Duckmatic::Push duckmatic_push; + + etl::handle curr_duck; + + etl::handle next_duck; + + std::list bline_point_list; + synfigapp::Settings& settings; + + bool on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node); + bool on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node); + bool on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node); + + + void popup_handle_menu(synfig::ValueNode_Const::Handle value_node); + void popup_vertex_menu(synfig::ValueNode_Const::Handle value_node); + void popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node); + + void bline_detach_handle(synfig::ValueNode_Const::Handle value_node); + void bline_attach_handle(synfig::ValueNode_Const::Handle value_node); + void bline_delete_vertex(synfig::ValueNode_Const::Handle value_node); + void bline_insert_vertex(synfig::ValueNode_Const::Handle value_node,float origin=0.5); + void loop_bline(); + void unloop_bline(); + + void refresh_ducks(bool x=true); + + Gtk::Table options_table; + Gtk::Entry entry_id; + Gtk::CheckButton checkbutton_layer_region; + Gtk::CheckButton checkbutton_layer_outline; + Gtk::CheckButton checkbutton_layer_curve_gradient; + Gtk::CheckButton checkbutton_layer_plant; + Gtk::CheckButton checkbutton_layer_link_origins; + Gtk::CheckButton checkbutton_auto_export; + Gtk::Button button_make; + Gtk::Button button_clear; + Gtk::Adjustment adj_feather; + Gtk::SpinButton spin_feather; + + + +public: + + int layers_to_create()const + { + return + get_layer_region_flag() + + get_layer_outline_flag() + + get_layer_curve_gradient_flag() + + get_layer_plant_flag(); + } + + void sanity_check() + { + if(layers_to_create()==0) + set_layer_region_flag(true); + } + + bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); } + void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); } + + bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } + void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } + + bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } + void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } + + bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } + void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } + + bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } + void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } + + bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } + void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } + + Real get_feather() const { return adj_feather.get_value(); } + void set_feather(Real x) { return adj_feather.set_value(x); } + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_mouse_release_handler(const Smach::event& x); + Smach::event_result event_mouse_motion_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + Smach::event_result event_hijack(const Smach::event& /*x*/) { return Smach::RESULT_ACCEPT; } + + void refresh_tool_options(); + + StateBLine_Context(CanvasView* canvas_view); + + ~StateBLine_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();} + const synfig::TransformStack& get_transform_stack()const { return canvas_view_->get_curr_transform_stack(); } + + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + //void on_user_click(synfig::Point point); + + bool run_(); + bool run(); + + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + +}; // END of class StateBLine_Context + + +/* === M E T H O D S ======================================================= */ + +StateBLine::StateBLine(): + Smach::state("bline") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED, &StateBLine_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_STOP, &StateBLine_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH, &StateBLine_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS, &StateBLine_Context::event_hijack)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN, &StateBLine_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP, &StateBLine_Context::event_mouse_release_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_MOTION, &StateBLine_Context::event_mouse_motion_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG, &StateBLine_Context::event_mouse_motion_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS, &StateBLine_Context::event_refresh_tool_options)); +} + +StateBLine::~StateBLine() +{ +} + +void +StateBLine_Context::load_settings() +{ + String value; + + if(settings.get_value("bline.layer_region",value) && value=="0") + set_layer_region_flag(false); + else + set_layer_region_flag(true); + + if(settings.get_value("bline.layer_outline",value) && value=="0") + set_layer_outline_flag(false); + else + set_layer_outline_flag(true); + + if(settings.get_value("bline.layer_curve_gradient",value) && value=="1") + set_layer_curve_gradient_flag(true); + else + set_layer_curve_gradient_flag(false); + + if(settings.get_value("bline.layer_plant",value) && value=="1") + set_layer_plant_flag(true); + else + set_layer_plant_flag(false); + + if(settings.get_value("bline.layer_link_origins",value) && value=="0") + set_layer_link_origins_flag(false); + else + set_layer_link_origins_flag(true); + + if(settings.get_value("bline.auto_export",value) && value=="1") + set_auto_export_flag(true); + else + set_auto_export_flag(false); + + if(settings.get_value("bline.id",value)) + set_id(value); + else + set_id("NewBLine"); + + if(settings.get_value("bline.feather",value)) + { + Real n = atof(value.c_str()); + set_feather(n); + } + + sanity_check(); +} + +void +StateBLine_Context::save_settings() +{ + sanity_check(); + settings.set_value("bline.layer_outline",get_layer_outline_flag()?"1":"0"); + settings.set_value("bline.layer_region",get_layer_region_flag()?"1":"0"); + settings.set_value("bline.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); + settings.set_value("bline.layer_plant",get_layer_plant_flag()?"1":"0"); + settings.set_value("bline.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); + settings.set_value("bline.auto_export",get_auto_export_flag()?"1":"0"); + settings.set_value("bline.id",get_id().c_str()); + settings.set_value("bline.feather",strprintf("%f",get_feather())); +} + +void +StateBLine_Context::reset() +{ + loop_=false; + bline_point_list.clear(); + refresh_ducks(); +} + +void +StateBLine_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="NewBLine"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + 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()); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + + +StateBLine_Context::StateBLine_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + loop_(false), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + duckmatic_push(get_work_area()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), + checkbutton_layer_region(_("Create Region BLine")), + checkbutton_layer_outline(_("Create Outline BLine")), + checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), + checkbutton_layer_plant(_("Create Plant BLine")), + checkbutton_layer_link_origins(_("Link Origins")), + checkbutton_auto_export(_("Auto Export")), + button_make(_("Make")), + button_clear(_("Clear")), + adj_feather(0,0,10000,0.01,0.1), + spin_feather(adj_feather,0.01,4) +{ + depth=-1; + egress_on_selection_change=true; + load_settings(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("BLine 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_layer_outline, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_region, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_plant, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_link_origins, 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(*manage(new Gtk::Label(_("Feather"))), 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_feather, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + //options_table.attach(button_make, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + //button_make.signal_pressed().connect(sigc::mem_fun(*this,&StateBLine_Context::run)); + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + // Hide the tables if they are showing + prev_table_status=get_canvas_view()->tables_are_visible(); + if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateBLine_Context::on_user_click)); + get_work_area()->set_cursor(Gdk::CROSSHAIR); + + App::toolbox->refresh(); +} + +void +StateBLine_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("BLine Tool")); + App::dialog_tool_options->set_name("bline"); + + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-execute"), + _("Make BLine and/or Region") + )->signal_clicked().connect( + sigc::hide_return(sigc::mem_fun( + *this, + &StateBLine_Context::run + )) + ); + + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-clear"), + _("Clear current BLine") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &StateBLine_Context::reset + ) + ); +} + +Smach::event_result +StateBLine_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateBLine_Context::~StateBLine_Context() +{ + run(); + + save_settings(); + App::dialog_tool_options->clear(); + + get_work_area()->reset_cursor(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + + // Enable the time bar + get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + if(prev_table_status)get_canvas_view()->show_tables(); + +// get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS); + + // Refresh the work area + get_work_area()->queue_draw(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateBLine_Context::event_stop_handler(const Smach::event& /*x*/) +{ +// synfig::info("STATE RotoBLine: Received Stop Event"); +// run(); + reset(); +// throw Smach::egress_exception(); +// get_canvas_view()->get_smach().pop_state(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateBLine_Context::event_refresh_handler(const Smach::event& /*x*/) +{ +// synfig::info("STATE RotoBLine: Received Refresh Event"); + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +bool +StateBLine_Context::run() +{ + sanity_check(); + + String err; + bool success(false); + for(int i=5;i>0 && !success;i--)try + { + success=run_(); + } + catch(String s) + { + err=s; + } + if(!success && !err.empty()) + { + get_canvas_view()->get_ui_interface()->error(err); + } + return success; +} + +bool +StateBLine_Context::run_() +{ + curr_duck=0; + next_duck=0; + + // Now we need to generate it + + if(bline_point_list.empty()) + { + return false; + } + if(bline_point_list.size()<2) + { + //get_canvas_view()->get_ui_interface()->error(_("You need at least two (2) points to create a BLine")); + return false; + } + + do + { + + // Create the action group + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New BLine")); + + std::vector new_list; + std::list::iterator iter; + const synfig::TransformStack& transform(get_transform_stack()); + + for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) + { + BLinePoint bline_point((*iter)->get_value().get(BLinePoint())); + 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); + + new_list.push_back(bline_point); + } + + ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); + assert(value_node_bline); + + ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector())); + assert(value_node_origin); + + // Set the looping flag + value_node_bline->set_loop(loop_); + + // Add the BLine to the canvas + if(get_auto_export_flag() && !get_canvas_interface()->add_value_node(value_node_bline,get_id())) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to add value node")); + group.cancel(); + increment_id(); + throw String(_("Unable to add value node")); + return false; + } + + Layer::Handle layer; + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + + if(layer) + { + if(depth<0) + depth=layer->get_depth(); + if(!canvas) + canvas=layer->get_canvas(); + } + else + depth=0; + + if(!canvas) + canvas=get_canvas_view()->get_canvas(); + + value_node_bline->set_member_canvas(canvas); + + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + + // count how many layers we're going to be creating + int layers_to_create = this->layers_to_create(); + + /////////////////////////////////////////////////////////////////////////// + // C U R V E G R A D I E N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_curve_gradient_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); + if (!layer) + { + group.cancel(); + throw String(_("Unable to create layer")); + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Gradient")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return false; + } + } + + // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return false; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // P L A N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_plant_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); + if (!layer) + { + group.cancel(); + throw String(_("Unable to create layer")); + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Plant")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return false; + } + } + + // only link the plant's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return false; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // R E G I O N + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_region_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); + if (!layer) + { + group.cancel(); + throw String(_("Unable to create layer")); + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Region")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + if(get_feather()) + { + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + } + + // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm + // using 2 separate ones. + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return false; + } + } + + // only link the region's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return false; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // O U T L I N E + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_outline_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); + if (!layer) + { + group.cancel(); + throw String(_("Unable to create layer")); + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Outline")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + if(get_feather()) + { + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + } + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return false; + } + } + + // only link the outline's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return false; + } + } + } + + egress_on_selection_change=false; + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + //if(finish_bline_dialog.get_region_flag() || finish_bline_dialog.get_bline_flag()) + // get_canvas_interface()->signal_dirty_preview()(); + + } while(0); + + reset(); + increment_id(); + return true; +} + +Smach::event_result +StateBLine_Context::event_mouse_motion_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + + if(curr_duck) + { + //synfig::info("Moved Duck"); + Point p(get_work_area()->snap_point_to_grid(event.pos)); + curr_duck->set_trans_point(p); + if(next_duck) + next_duck->set_trans_point(p); + get_work_area()->queue_draw(); + return Smach::RESULT_ACCEPT; + } + + return Smach::RESULT_OK; +} + +Smach::event_result +StateBLine_Context::event_mouse_release_handler(const Smach::event& /*x*/) +{ + if(curr_duck) + { + //synfig::info("Released current duck"); + curr_duck->signal_edited()(curr_duck->get_point()); + if(next_duck) + { + //synfig::info("grabbing next duck"); + curr_duck=next_duck; + next_duck=0; + } + return Smach::RESULT_ACCEPT; + } + return Smach::RESULT_OK; +} + +Smach::event_result +StateBLine_Context::event_mouse_click_handler(const Smach::event& x) +{ + // synfig::info("STATE BLINE: Received mouse button down Event"); + const EventMouse& event(*reinterpret_cast(&x)); + switch(event.button) + { + case BUTTON_LEFT: + { + // If we are already looped up, then don't try to add anything else + if(loop_) + return Smach::RESULT_OK; + + BLinePoint bline_point; + + bline_point.set_vertex(get_work_area()->snap_point_to_grid(event.pos)); + //bline_point.set_width(synfigapp::Main::get_bline_width()); + bline_point.set_width(1.0f); + bline_point.set_origin(0.5f); + bline_point.set_split_tangent_flag(false); + bline_point.set_tangent1(Vector(0,0)); + + // set the tangent + /* + if(bline_point_list.empty()) + { + bline_point.set_tangent1(Vector(1,1)); + } + else + { + const Vector t(event.pos-bline_point_list.back()->get_value().get(BLinePoint()).get_vertex()); + bline_point.set_tangent1(t); + } + + if(bline_point_list.size()>1) + { + std::list::iterator iter; + iter=bline_point_list.end(); + iter--;iter--; + BLinePoint prev(bline_point_list.back()->get_value().get(BLinePoint())); + prev.set_tangent1(event.pos-(*iter)->get_value().get(BLinePoint()).get_vertex()); + bline_point_list.back()->set_value(prev); + }; + */ + + bline_point_list.push_back(ValueNode_Const::create(bline_point)); + + refresh_ducks(); + return Smach::RESULT_ACCEPT; + } + + default: + return Smach::RESULT_OK; + } +} + +void +StateBLine_Context::refresh_ducks(bool button_down) +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); + + if(bline_point_list.empty()) + return; + + list::iterator iter; + + handle bezier; + handle duck,tduck; + BLinePoint bline_point; + + for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) + { + ValueNode_Const::Handle value_node(*iter); + bline_point=(value_node->get_value().get(BLinePoint())); + assert(value_node); + + + // First add the duck associated with this vertex + duck=new WorkArea::Duck(bline_point.get_vertex()); + duck->set_editable(true); +#ifdef DISTINGUISH_FIRST_DUCK + if (iter!=bline_point_list.begin()) + duck->set_type(Duck::TYPE_VERTEX); +#else + duck->set_type(Duck::TYPE_VERTEX); +#endif + duck->set_name(strprintf("%x-vertex",value_node.get())); + duck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),value_node) + ); + duck->signal_user_click(2).connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),value_node) + ); + duck->set_guid(value_node->get_guid()^synfig::GUID::hasher(0)); + + get_work_area()->add_duck(duck); + + // Add the tangent1 duck + tduck=new WorkArea::Duck(bline_point.get_tangent1()); + tduck->set_editable(true); + tduck->set_name(strprintf("%x-tangent1",value_node.get())); + tduck->set_origin(duck); + tduck->set_scalar(-0.33333333333333333); + tduck->set_tangent(true); + tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(3)); + tduck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node) + ); + tduck->signal_user_click(2).connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node) + ); + + // See if we need to add that duck to the previous bezier + if(bezier) + { + get_work_area()->add_duck(tduck); + bezier->p2=duck; + bezier->c2=tduck; + + bezier->signal_user_click(2).connect( + sigc::bind( + sigc::mem_fun( + *this, + &studio::StateBLine_Context::popup_bezier_menu + ), + value_node + ) + ); + + //get_work_area()->add_duck(bezier->c1); + //get_work_area()->add_duck(bezier->c2); + get_work_area()->add_bezier(bezier); + + bezier=0; + } + + // Now we see if we need to create a bezier + list::iterator next(iter); + next++; + + // If our next iterator is the end, then we don't need + // to add a bezier. + //if(next==bline_point_list.end() && !loop_) + // continue; + + bezier=new WorkArea::Bezier(); + + // Add the tangent2 duck + tduck=new WorkArea::Duck(bline_point.get_tangent2()); + tduck->set_editable(true); + tduck->set_origin(duck); + tduck->set_scalar(0.33333333333333333); + tduck->set_tangent(true); + if(bline_point.get_split_tangent_flag()) + { + tduck->set_name(strprintf("%x-tangent2",value_node.get())); + tduck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent2_change),value_node) + ); + } + else + { + tduck->set_name(strprintf("%x-tangent1",value_node.get())); + tduck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node) + ); + } + tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(4)); + tduck->signal_user_click(2).connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node) + ); + + // Setup the next bezier + bezier->p1=duck; + bezier->c1=tduck; + + get_work_area()->add_duck(tduck); + curr_duck=tduck; + } + + // Add the loop, if requested + if(bezier && loop_) + { + curr_duck=0; + BLinePoint bline_point(bline_point_list.front()->get_value().get(BLinePoint())); + + duck=new WorkArea::Duck(bline_point.get_vertex()); + duck->set_editable(true); +#ifndef DISTINGUISH_FIRST_DUCK + duck->set_type(Duck::TYPE_VERTEX); +#endif + duck->set_name(strprintf("%x-vertex",bline_point_list.front().get())); + duck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),bline_point_list.front()) + ); + duck->signal_user_click(2).connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),bline_point_list.front()) + ); + get_work_area()->add_duck(duck); + + // Add the tangent1 duck + tduck=new WorkArea::Duck(bline_point.get_tangent1()); + tduck->set_editable(true); + tduck->set_name(strprintf("%x-tangent1",bline_point_list.front().get())); + tduck->set_origin(duck); + tduck->set_scalar(-0.33333333333333333); + tduck->set_tangent(true); + tduck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),bline_point_list.front()) + ); + tduck->signal_user_click(2).connect( + sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),bline_point_list.front()) + ); + get_work_area()->add_duck(tduck); + + bezier->p2=duck; + bezier->c2=tduck; + + bezier->signal_user_click(2).connect( + sigc::bind( + sigc::mem_fun( + *this, + &studio::StateBLine_Context::popup_bezier_menu + ), + bline_point_list.front() + ) + ); + + //get_work_area()->add_duck(bezier->c1); + get_work_area()->add_bezier(bezier); + } + if(bezier && !loop_) + { + duck=new WorkArea::Duck(bline_point.get_vertex()); + duck->set_ignore(true); + duck->set_name("temp"); + + // Add the tangent1 duck + tduck=new WorkArea::Duck(Vector(0,0)); + tduck->set_ignore(true); + tduck->set_name("ttemp"); + tduck->set_origin(duck); + tduck->set_scalar(-0.33333333333333333); + + tduck->set_tangent(true); + bezier->p2=duck; + bezier->c2=tduck; + + get_work_area()->add_duck(bezier->p2); + //get_work_area()->add_duck(bezier->c2); + get_work_area()->add_bezier(bezier); + + duck->set_guid(synfig::GUID()); + tduck->set_guid(synfig::GUID()); + + next_duck=duck; + } + + if(!button_down) + { + if(curr_duck) + { + if(next_duck) + { + curr_duck=next_duck; + next_duck=0; + } + } + } + get_work_area()->queue_draw(); +} + + +bool +StateBLine_Context::on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node) +{ + BLinePoint bline_point(value_node->get_value().get(BLinePoint())); + bline_point.set_vertex(point); + value_node->set_value(bline_point); + //refresh_ducks(); + return true; +} + +bool +StateBLine_Context::on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node) +{ + BLinePoint bline_point(value_node->get_value().get(BLinePoint())); + bline_point.set_tangent1(point); + value_node->set_value(bline_point); + //refresh_ducks(); + return true; +} + +bool +StateBLine_Context::on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node) +{ + BLinePoint bline_point(value_node->get_value().get(BLinePoint())); + bline_point.set_tangent2(point); + value_node->set_value(bline_point); + //refresh_ducks(); + return true; +} + +void +StateBLine_Context::loop_bline() +{ + loop_=true; + + refresh_ducks(false); +} + +void +StateBLine_Context::unloop_bline() +{ + loop_=false; + + refresh_ducks(false); +} + +void +StateBLine_Context::popup_vertex_menu(synfig::ValueNode_Const::Handle value_node) +{ + menu.items().clear(); + + if(loop_) + { + menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unloop BLine"), + sigc::mem_fun(*this,&studio::StateBLine_Context::unloop_bline) + )); + } else { + menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Loop BLine"), + sigc::mem_fun(*this,&studio::StateBLine_Context::loop_bline) + )); + } + + menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Delete Vertex"), + sigc::bind( + sigc::mem_fun(*this,&studio::StateBLine_Context::bline_delete_vertex), + value_node + ) + )); + + menu.popup(0,0); +} + +void +StateBLine_Context::popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node) +{ + menu.items().clear(); + + menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Insert Vertex"), + sigc::bind( + sigc::bind( + sigc::mem_fun(*this,&studio::StateBLine_Context::bline_insert_vertex), + location + ), + value_node + ) + )); + + menu.popup(0,0); +} + +void +StateBLine_Context::bline_insert_vertex(synfig::ValueNode_Const::Handle value_node, float origin) +{ + list::iterator iter; + + for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) + if(*iter==value_node) + { + BLinePoint bline_point; + BLinePoint next_bline_point((*iter)->get_value().get(BLinePoint())); + BLinePoint prev_bline_point; + + list::iterator prev(iter); + if(iter==bline_point_list.begin()) + { + assert(loop_); + prev = bline_point_list.end(); + } + prev--; + + prev_bline_point=(*prev)->get_value().get(BLinePoint()); + + etl::hermite curve(prev_bline_point.get_vertex(), + next_bline_point.get_vertex(), + prev_bline_point.get_tangent2(), + next_bline_point.get_tangent1()); + etl::derivative< etl::hermite > deriv(curve); + + bline_point.set_vertex(curve(origin)); + bline_point.set_width((next_bline_point.get_width()-prev_bline_point.get_width())*origin+prev_bline_point.get_width()); + bline_point.set_tangent1(deriv(origin)*std::min(1.0f-origin,origin)); + bline_point.set_tangent2(bline_point.get_tangent1()); + bline_point.set_split_tangent_flag(false); + bline_point.set_origin(origin); + +/* + bline_point.set_vertex((next_bline_point.get_vertex()+prev_bline_point.get_vertex())*0.5); + bline_point.set_width((next_bline_point.get_width()+prev_bline_point.get_width())*0.5); + bline_point.set_origin(origin); + bline_point.set_split_tangent_flag(false); + bline_point.set_tangent1((next_bline_point.get_vertex()-prev_bline_point.get_vertex())*0.5); +*/ + + bline_point_list.insert(iter,ValueNode_Const::create(bline_point)); + break; + } + + if(iter==bline_point_list.end()) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to find where to insert vertex, internal error, please report this bug")); + } + + refresh_ducks(false); +} + +void +StateBLine_Context::bline_delete_vertex(synfig::ValueNode_Const::Handle value_node) +{ + list::iterator iter; + + for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter) + if(*iter==value_node) + { + bline_point_list.erase(iter); + break; + } + if(iter==bline_point_list.end()) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to remove vertex, internal error, please report this bug")); + } + + refresh_ducks(false); +} + +void +StateBLine_Context::popup_handle_menu(synfig::ValueNode_Const::Handle value_node) +{ + menu.items().clear(); + + BLinePoint bline_point(value_node->get_value().get(BLinePoint())); + + if(bline_point.get_split_tangent_flag()) + menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Merge Tangents"), + sigc::bind( + sigc::mem_fun(*this,&studio::StateBLine_Context::bline_attach_handle), + value_node + ) + )); + else + menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Split Tangents"), + sigc::bind( + sigc::mem_fun(*this,&studio::StateBLine_Context::bline_detach_handle), + value_node + ) + )); + + menu.popup(0,0); +} + +void +StateBLine_Context::bline_detach_handle(synfig::ValueNode_Const::Handle value_node) +{ + BLinePoint bline_point(value_node->get_value().get(BLinePoint())); + bline_point.set_split_tangent_flag(true); + bline_point.set_tangent2(bline_point.get_tangent1()); + value_node->set_value(bline_point); + refresh_ducks(false); +} + +void +StateBLine_Context::bline_attach_handle(synfig::ValueNode_Const::Handle value_node) +{ + BLinePoint bline_point(value_node->get_value().get(BLinePoint())); + bline_point.set_tangent1((bline_point.get_tangent1()+bline_point.get_tangent2())*0.5); + bline_point.set_split_tangent_flag(false); + value_node->set_value(bline_point); + refresh_ducks(false); +} diff --git a/synfig-studio/src/gui/states/state_bline.h b/synfig-studio/src/gui/states/state_bline.h new file mode 100644 index 0000000..0f3ce0d --- /dev/null +++ b/synfig-studio/src/gui/states/state_bline.h @@ -0,0 +1,55 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_bline.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H +#define __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateBLine_Context; + +class StateBLine : public Smach::state +{ +public: + StateBLine(); + ~StateBLine(); +}; // END of class StateBLine + +extern StateBLine state_bline; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_circle.cpp b/synfig-studio/src/gui/states/state_circle.cpp new file mode 100644 index 0000000..5ef611b --- /dev/null +++ b/synfig-studio/src/gui/states/state_circle.cpp @@ -0,0 +1,1066 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_circle.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include "state_circle.h" +#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 "duck.h" +#include "widgets/widget_enum.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ +enum CircleFalloff +{ + CIRCLE_SQUARED =0, + CIRCLE_INTERPOLATION_LINEAR =1, + CIRCLE_COSINE =2, + CIRCLE_SIGMOND =3, + CIRCLE_SQRT =4, + CIRCLE_NUM_FALLOFF +}; + +/* === G L O B A L S ======================================================= */ + +StateCircle studio::state_circle; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateCircle_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + Duckmatic::Push duckmatic_push; + + Point point_holder; + + etl::handle point2_duck; + + void refresh_ducks(); + + bool prev_workarea_layer_status_; + + //Toolbox settings + synfigapp::Settings& settings; + + //Toolbox display + Gtk::Table options_table; + + Gtk::Entry entry_id; //what to name the layer + + Widget_Enum enum_falloff; +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + Widget_Enum enum_blend; +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + Gtk::Adjustment adj_feather; + Gtk::Adjustment adj_number_of_bline_points; + Gtk::Adjustment adj_bline_point_angle_offset; + Gtk::SpinButton spin_feather; + Gtk::SpinButton spin_number_of_bline_points; + Gtk::SpinButton spin_bline_point_angle_offset; + + Gtk::CheckButton checkbutton_invert; + Gtk::CheckButton checkbutton_layer_circle; + Gtk::CheckButton checkbutton_layer_region; + Gtk::CheckButton checkbutton_layer_outline; + Gtk::CheckButton checkbutton_layer_curve_gradient; + Gtk::CheckButton checkbutton_layer_plant; + Gtk::CheckButton checkbutton_layer_link_origins; + Gtk::CheckButton checkbutton_layer_origins_at_center; + +public: + + // this only counts the layers which will have their origins linked + int layers_to_create()const + { + return + (get_layer_circle_flag() && get_layer_origins_at_center_flag()) + + get_layer_region_flag() + + get_layer_outline_flag() + + get_layer_curve_gradient_flag() + + get_layer_plant_flag(); + } + + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + int get_falloff()const { return enum_falloff.get_value(); } + void set_falloff(int x) { return enum_falloff.set_value(x); } + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + int get_blend()const { return enum_blend.get_value(); } + void set_blend(int x) { return enum_blend.set_value(x); } +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + Real get_feather()const { return adj_feather.get_value(); } + void set_feather(Real f) { adj_feather.set_value(f); } + + Real get_number_of_bline_points()const { return adj_number_of_bline_points.get_value(); } + void set_number_of_bline_points(Real f) { adj_number_of_bline_points.set_value(f); } + + Real get_bline_point_angle_offset()const { return adj_bline_point_angle_offset.get_value(); } + void set_bline_point_angle_offset(Real f) { adj_bline_point_angle_offset.set_value(f); } + + bool get_invert()const { return checkbutton_invert.get_active(); } + void set_invert(bool i) { checkbutton_invert.set_active(i); } + + bool get_layer_circle_flag()const { return checkbutton_layer_circle.get_active(); } + void set_layer_circle_flag(bool x) { return checkbutton_layer_circle.set_active(x); } + + bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } + void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } + + bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } + void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } + + bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } + void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } + + bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } + void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } + + bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } + void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } + + bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); } + void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); } + + void refresh_tool_options(); //to refresh the toolbox + + //events + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + //constructor destructor + StateCircle_Context(CanvasView* canvas_view); + ~StateCircle_Context(); + + //Canvas interaction + 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();} + + //Modifying settings etc. + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + + void make_circle(const Point& p1, const Point& p2); + +}; // END of class StateCircle_Context + +/* === M E T H O D S ======================================================= */ + +StateCircle::StateCircle(): + Smach::state("circle") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateCircle_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_STOP,&StateCircle_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateCircle_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateCircle_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateCircle_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateCircle_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateCircle_Context::event_mouse_click_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateCircle_Context::event_refresh_tool_options)); +} + +StateCircle::~StateCircle() +{ +} + +void +StateCircle_Context::load_settings() +{ + String value; + + //parse the arguments yargh! + if(settings.get_value("circle.id",value)) + set_id(value); + else + set_id("Circle"); + + if(settings.get_value("circle.fallofftype",value) && value != "") + set_falloff(atoi(value.c_str())); + else + set_falloff(2); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + if(settings.get_value("circle.blend",value) && value != "") + set_blend(atoi(value.c_str())); + else + set_blend(0);//(int)Color::BLEND_COMPOSITE); //0 should be blend composites value +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + if(settings.get_value("circle.feather",value)) + set_feather(atof(value.c_str())); + else + set_feather(0); + + if(settings.get_value("circle.number_of_bline_points",value)) + set_number_of_bline_points(atof(value.c_str())); + else + set_number_of_bline_points(4); + + if(settings.get_value("circle.bline_point_angle_offset",value)) + set_bline_point_angle_offset(atof(value.c_str())); + else + set_bline_point_angle_offset(0); + + if(settings.get_value("circle.invert",value) && value != "0") + set_invert(true); + else + set_invert(false); + + if(settings.get_value("circle.layer_circle",value) && value=="0") + set_layer_circle_flag(false); + else + set_layer_circle_flag(true); + + if(settings.get_value("circle.layer_region",value) && value=="1") + set_layer_region_flag(true); + else + set_layer_region_flag(false); + + if(settings.get_value("circle.layer_outline",value) && value=="1") + set_layer_outline_flag(true); + else + set_layer_outline_flag(false); + + if(settings.get_value("circle.layer_curve_gradient",value) && value=="1") + set_layer_curve_gradient_flag(true); + else + set_layer_curve_gradient_flag(false); + + if(settings.get_value("circle.layer_plant",value) && value=="1") + set_layer_plant_flag(true); + else + set_layer_plant_flag(false); + + if(settings.get_value("circle.layer_link_origins",value) && value=="0") + set_layer_link_origins_flag(false); + else + set_layer_link_origins_flag(true); + + if(settings.get_value("circle.layer_origins_at_center",value) && value=="0") + set_layer_origins_at_center_flag(false); + else + set_layer_origins_at_center_flag(true); +} + +void +StateCircle_Context::save_settings() +{ + settings.set_value("circle.id",get_id()); + settings.set_value("circle.fallofftype",strprintf("%d",get_falloff())); +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + settings.set_value("circle.blend",strprintf("%d",get_blend())); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + settings.set_value("circle.feather",strprintf("%f",(float)get_feather())); + settings.set_value("circle.number_of_bline_points",strprintf("%d",(int)(get_number_of_bline_points() + 0.5))); + settings.set_value("circle.bline_point_angle_offset",strprintf("%f",(float)get_bline_point_angle_offset())); + settings.set_value("circle.invert",get_invert()?"1":"0"); + settings.set_value("circle.layer_circle",get_layer_circle_flag()?"1":"0"); + settings.set_value("circle.layer_outline",get_layer_outline_flag()?"1":"0"); + settings.set_value("circle.layer_region",get_layer_region_flag()?"1":"0"); + settings.set_value("circle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); + settings.set_value("circle.layer_plant",get_layer_plant_flag()?"1":"0"); + settings.set_value("circle.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); + settings.set_value("circle.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0"); +} + +void +StateCircle_Context::reset() +{ + refresh_ducks(); +} + +void +StateCircle_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Circle"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + String str_number; + str_number=String(id,id.size()-digits,id.size()); + id=String(id,0,id.size()-digits); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StateCircle_Context::StateCircle_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + duckmatic_push(get_work_area()), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), // value lower upper step page + adj_feather( 0, 0, 1, 0.01, 0.1), + adj_number_of_bline_points( 0, 2, 120, 1 , 1 ), + adj_bline_point_angle_offset( 0, -360, 360, 0.1 , 1 ), + spin_feather(adj_feather,0.1,3), + spin_number_of_bline_points(adj_number_of_bline_points,1,0), + spin_bline_point_angle_offset(adj_bline_point_angle_offset,1,1), + checkbutton_invert(_("Invert")), + checkbutton_layer_circle(_("Create Circle Layer")), + checkbutton_layer_region(_("Create Region BLine")), + checkbutton_layer_outline(_("Create Outline BLine")), + checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), + checkbutton_layer_plant(_("Create Plant BLine")), + checkbutton_layer_link_origins(_("Link Origins")), + checkbutton_layer_origins_at_center(_("BLine Origins at Center")) +{ + egress_on_selection_change=true; + + // Set up the tool options dialog + enum_falloff.set_param_desc(ParamDesc("falloff") + .set_local_name(_("Falloff")) + .set_description(_("Determines the falloff function for the feather")) + .set_hint("enum") + .add_enum_value(CIRCLE_INTERPOLATION_LINEAR,"linear",_("Linear")) + .add_enum_value(CIRCLE_SQUARED,"squared",_("Squared")) + .add_enum_value(CIRCLE_SQRT,"sqrt",_("Square Root")) + .add_enum_value(CIRCLE_SIGMOND,"sigmond",_("Sigmond")) + .add_enum_value(CIRCLE_COSINE,"cosine",_("Cosine"))); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method") + .set_local_name(_("Blend Method")) + .set_description(_("Defines the blend method to be used for circles"))); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + load_settings(); + + options_table.attach(*manage(new Gtk::Label(_("Circle 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_layer_circle, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_origins_at_center, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //invert flag + options_table.attach(checkbutton_invert, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Falloff:"))), 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(enum_falloff, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //feather stuff + options_table.attach(*manage(new Gtk::Label(_("Feather:"))), 0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_feather, 1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + options_table.attach(enum_blend, 0, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + options_table.attach(*manage(new Gtk::Label(_("BLine Points:"))), 0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_number_of_bline_points, 1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + +options_table.attach(*manage(new Gtk::Label(_("Point Angle Offset:"))), 0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_bline_point_angle_offset, 1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.show_all(); + + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + // Hide the tables if they are showing + //prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateCircle_Context::on_user_click)); + get_work_area()->set_cursor(Gdk::CROSSHAIR); + + App::toolbox->refresh(); +} + +void +StateCircle_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Circle Tool")); + App::dialog_tool_options->set_name("circle"); +} + +Smach::event_result +StateCircle_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateCircle_Context::~StateCircle_Context() +{ + save_settings(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + //if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_canvas_view()->queue_rebuild_ducks(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateCircle_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateCircle_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StateCircle_Context::make_circle(const Point& _p1, const Point& _p2) +{ + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Circle")); + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer; + + Canvas::Handle canvas; + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + + const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); + const Point p1(transform.unperform(_p1)); + const Point p2(transform.unperform(_p2)); + + Real radius((p2-p1).mag()); + int points = get_number_of_bline_points(); + Angle::deg offset(get_bline_point_angle_offset()); + Angle::deg angle(360.0/points); + Real tangent(4 * ((points == 2) + ? 1 + : ((2 * Angle::cos(angle/2).get() - Angle::cos(angle).get() - 1) / Angle::sin(angle).get()))); + Vector origin; + Real x, y; + + if (get_layer_origins_at_center_flag()) + { + x = y = 0; + origin = p1; + } + else + { + x = p1[0]; + y = p1[1]; + } + + std::vector new_list; + for (int i = 0; i < points; i++) + { + new_list.push_back(*(new BLinePoint)); + new_list[i].set_width(1); + new_list[i].set_vertex(Point(radius*Angle::cos(angle*i + offset).get() + x, + radius*Angle::sin(angle*i + offset).get() + y)); + new_list[i].set_tangent(Point(-radius*tangent*Angle::sin(angle*i + offset).get(), + radius*tangent*Angle::cos(angle*i + offset).get())); + } + + ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); + assert(value_node_bline); + + ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin)); + assert(value_node_origin); + + // Set the looping flag + value_node_bline->set_loop(true); + + if(!canvas) + canvas=get_canvas_view()->get_canvas(); + + value_node_bline->set_member_canvas(canvas); + + // count how many layers we're going to be creating + int layers_to_create = this->layers_to_create(); + + /////////////////////////////////////////////////////////////////////////// + // C I R C L E + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_circle_flag() && + get_falloff() >= 0 && get_falloff() < CIRCLE_NUM_FALLOFF) + { + layer=get_canvas_interface()->add_layer_to("circle",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + + layer->set_param("radius",(p2-p1).mag()); + get_canvas_interface()->signal_layer_param_changed()(layer,"radius"); + + layer->set_param("falloff",get_falloff()); + get_canvas_interface()->signal_layer_param_changed()(layer,"falloff"); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + layer->set_param("blend_method",get_blend()); + get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + layer->set_description(get_id()); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + // only link the circle's origin parameter if the option is selected, we're putting bline + // origins at their centers, and we're creating more than one layer + if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Circle layer")); + group.cancel(); + throw String(_("Unable to create Circle layer")); + return; + } + } + else + { + layer->set_param("origin",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // C U R V E G R A D I E N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_curve_gradient_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Gradient")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + layer->set_param("blend_method",get_blend()); + get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + + // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // P L A N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_plant_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Plant")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + layer->set_param("blend_method",get_blend()); + get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + + // only link the plant's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // R E G I O N + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_region_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Region")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + layer->set_param("blend_method",get_blend()); + get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm + // using 2 separate ones. + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + + // only link the region's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // O U T L I N E + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_outline_flag()) + { + Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Outline")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + layer->set_param("blend_method",get_blend()); + get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + + // only link the outline's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + egress_on_selection_change=false; + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + reset(); + increment_id(); +} + +Smach::event_result +StateCircle_Context::event_mouse_click_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) + { + point_holder=get_work_area()->snap_point_to_grid(event.pos); + etl::handle duck=new Duck(); + duck->set_point(point_holder); + duck->set_name("p1"); + duck->set_type(Duck::TYPE_POSITION); + duck->set_editable(false); + get_work_area()->add_duck(duck); + + point2_duck=new Duck(); + point2_duck->set_point(Vector(0,0)); + point2_duck->set_name("radius"); + point2_duck->set_origin(duck); + point2_duck->set_radius(true); + point2_duck->set_scalar(-1); + point2_duck->set_type(Duck::TYPE_RADIUS); + point2_duck->set_hover(true); + get_work_area()->add_duck(point2_duck); + + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) + { + if (!point2_duck) return Smach::RESULT_OK; + point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos)); + get_work_area()->queue_draw(); + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) + { + Point point(get_work_area()->snap_point_to_grid(event.pos)); + + if (App::restrict_radius_ducks) + { + if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0]; + if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1]; + } + + make_circle(point_holder, point); + get_work_area()->clear_ducks(); + return Smach::RESULT_ACCEPT; + } + + return Smach::RESULT_OK; +} + + +void +StateCircle_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); +} diff --git a/synfig-studio/src/gui/states/state_circle.h b/synfig-studio/src/gui/states/state_circle.h new file mode 100644 index 0000000..b33ccf3 --- /dev/null +++ b/synfig-studio/src/gui/states/state_circle.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_circle.h +** \brief Circle creation state +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_CIRCLE_H +#define __SYNFIG_STUDIO_STATE_CIRCLE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateCircle_Context; + +class StateCircle : public Smach::state +{ +public: + StateCircle(); + ~StateCircle(); +}; // END of class StateCircle + +extern StateCircle state_circle; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_draw.cpp b/synfig-studio/src/gui/states/state_draw.cpp new file mode 100644 index 0000000..4482045 --- /dev/null +++ b/synfig-studio/src/gui/states/state_draw.cpp @@ -0,0 +1,2036 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_draw.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 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 +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include "state_draw.h" +#include "state_stroke.h" +#include "state_normal.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" +#include +#include +#include +#include +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" + +#include +#include + +#include +#include "dialog_tooloptions.h" + +#include +#include +#include +#include +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateDraw studio::state_draw; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateDraw_Context : public sigc::trackable +{ + typedef etl::smart_ptr > StrokeData; + typedef etl::smart_ptr > WidthData; + + typedef list< pair > StrokeQueue; + + StrokeQueue stroke_queue; + + + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + bool prev_table_status; + bool loop_; + bool prev_workarea_layer_status_; + + int nested; + sigc::connection process_queue_connection; + + ValueNode_BLine::Handle last_stroke; + synfig::String last_stroke_id; + + Gtk::Menu menu; + + //Duckmatic::Push duckmatic_push; + + std::list< etl::smart_ptr > > stroke_list; + + void refresh_ducks(); + + 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); + + Smach::event_result new_region(std::list bline,synfig::Real radius); + + Smach::event_result extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop); + Smach::event_result extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop); + void reverse_bline(std::list &bline); + + synfigapp::Settings& settings; + + Gtk::Table options_table; + Gtk::Entry entry_id; + Gtk::CheckButton checkbutton_pressure_width; + Gtk::CheckButton checkbutton_round_ends; + Gtk::CheckButton checkbutton_auto_loop; // whether to loop new strokes which start and end in the same place + Gtk::CheckButton checkbutton_auto_extend; // whether to extend existing lines + Gtk::CheckButton checkbutton_auto_link; // whether to link new ducks to existing ducks + Gtk::CheckButton checkbutton_region; // whether to create regions + Gtk::CheckButton checkbutton_outline; // whether to create outlines + Gtk::CheckButton checkbutton_auto_export; + Gtk::Button button_fill_last_stroke; + + //pressure spinner and such + Gtk::Adjustment adj_min_pressure; + Gtk::SpinButton spin_min_pressure; + Gtk::CheckButton check_min_pressure; + + Gtk::Adjustment adj_feather; + Gtk::SpinButton spin_feather; + + Gtk::Adjustment adj_globalthres; + Gtk::SpinButton spin_globalthres; + + Gtk::Adjustment adj_localthres; + Gtk::CheckButton check_localerror; + void UpdateErrorBox(); //switches the stuff if need be :) + + //Added by Adrian - data drive HOOOOO + synfigapp::BLineConverter blineconv; + +public: + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + bool get_pressure_width_flag()const { return checkbutton_pressure_width.get_active(); } + void set_pressure_width_flag(bool x) { return checkbutton_pressure_width.set_active(x); } + + bool get_auto_loop_flag()const { return checkbutton_auto_loop.get_active(); } + void set_auto_loop_flag(bool x) { return checkbutton_auto_loop.set_active(x); } + + bool get_auto_extend_flag()const { return checkbutton_auto_extend.get_active(); } + void set_auto_extend_flag(bool x) { return checkbutton_auto_extend.set_active(x); } + + bool get_auto_link_flag()const { return checkbutton_auto_link.get_active(); } + void set_auto_link_flag(bool x) { return checkbutton_auto_link.set_active(x); } + + bool get_region_flag()const { return checkbutton_region.get_active(); } + void set_region_flag(bool x) { return checkbutton_region.set_active(x); } + + bool get_outline_flag()const { return checkbutton_outline.get_active(); } + void set_outline_flag(bool x) { return checkbutton_outline.set_active(x); } + + bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); } + void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); } + + Real get_min_pressure() const { return adj_min_pressure.get_value(); } + void set_min_pressure(Real x) { return adj_min_pressure.set_value(x); } + + Real get_feather() const { return adj_feather.get_value(); } + void set_feather(Real x) { return adj_feather.set_value(x); } + + Real get_gthres() const { return adj_globalthres.get_value(); } + void set_gthres(Real x) { return adj_globalthres.set_value(x); } + + Real get_lthres() const { return adj_localthres.get_value(); } + void set_lthres(Real x) { return adj_localthres.set_value(x); } + + bool get_local_error_flag() const { return check_localerror.get_active(); } + void set_local_error_flag(bool x) { check_localerror.set_active(x); } + + bool get_min_pressure_flag()const { return check_min_pressure.get_active(); } + void set_min_pressure_flag(bool x) { check_min_pressure.set_active(x); } + + void load_settings(); + void save_settings(); + void increment_id(); + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_mouse_down_handler(const Smach::event& x); + + Smach::event_result event_stroke(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + void refresh_tool_options(); + + Smach::event_result process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag=false); + + bool process_queue(); + + + StateDraw_Context(CanvasView* canvas_view); + + ~StateDraw_Context(); + + const etl::handle& get_canvas_view()const{return canvas_view_;} + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} + synfig::Time get_time()const { return get_canvas_interface()->get_time(); } + synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} + WorkArea * get_work_area()const{return canvas_view_->get_work_area();} + + //void on_user_click(synfig::Point point); + +// bool run(); +}; // END of class StateDraw_Context + + +/* === M E T H O D S ======================================================= */ + +StateDraw::StateDraw(): + Smach::state("draw") +{ + insert(event_def(EVENT_STOP,&StateDraw_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateDraw_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateDraw_Context::event_mouse_down_handler)); + insert(event_def(EVENT_WORKAREA_STROKE,&StateDraw_Context::event_stroke)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateDraw_Context::event_refresh_tool_options)); +} + +StateDraw::~StateDraw() +{ +} + + +void +StateDraw_Context::load_settings() +{ + String value; + + if(settings.get_value("draw.id",value)) + set_id(value); + else + set_id("NewDrawing"); + + if(settings.get_value("draw.pressure_width",value) && value=="0") + set_pressure_width_flag(false); + else + set_pressure_width_flag(true); + + if(settings.get_value("draw.auto_loop",value) && value=="0") + set_auto_loop_flag(false); + else + set_auto_loop_flag(true); + + if(settings.get_value("draw.auto_extend",value) && value=="0") + set_auto_extend_flag(false); + else + set_auto_extend_flag(true); + + if(settings.get_value("draw.auto_link",value) && value=="0") + set_auto_link_flag(false); + else + set_auto_link_flag(true); + + if(settings.get_value("draw.region",value) && value=="0") + set_region_flag(false); + else + set_region_flag(true); + + if(settings.get_value("draw.outline",value) && value=="0") + set_outline_flag(false); + else + set_outline_flag(true); + + if(settings.get_value("draw.auto_export",value) && value=="1") + set_auto_export_flag(true); + else + set_auto_export_flag(false); + + if(settings.get_value("draw.min_pressure_on",value) && value=="0") + set_min_pressure_flag(false); + else + set_min_pressure_flag(true); + + if(settings.get_value("draw.min_pressure",value)) + { + Real n = atof(value.c_str()); + set_min_pressure(n); + }else + set_min_pressure(0); + + if(settings.get_value("draw.feather",value)) + { + Real n = atof(value.c_str()); + set_feather(n); + }else + set_feather(0); + + if(settings.get_value("draw.gthreshold",value)) + { + Real n = atof(value.c_str()); + set_gthres(n); + } + + if(settings.get_value("draw.lthreshold",value)) + { + Real n = atof(value.c_str()); + set_lthres(n); + } + + if(settings.get_value("draw.localize",value) && value == "1") + set_local_error_flag(true); + else + set_local_error_flag(false); +} + +void +StateDraw_Context::save_settings() +{ + settings.set_value("draw.id",get_id().c_str()); + settings.set_value("draw.pressure_width",get_pressure_width_flag()?"1":"0"); + settings.set_value("draw.auto_loop",get_auto_loop_flag()?"1":"0"); + settings.set_value("draw.auto_extend",get_auto_extend_flag()?"1":"0"); + settings.set_value("draw.auto_link",get_auto_link_flag()?"1":"0"); + settings.set_value("draw.region",get_region_flag()?"1":"0"); + settings.set_value("draw.outline",get_outline_flag()?"1":"0"); + settings.set_value("draw.auto_export",get_auto_export_flag()?"1":"0"); + settings.set_value("draw.min_pressure",strprintf("%f",get_min_pressure())); + settings.set_value("draw.feather",strprintf("%f",get_feather())); + settings.set_value("draw.min_pressure_on",get_min_pressure_flag()?"1":"0"); + settings.set_value("draw.gthreshold",strprintf("%f",get_gthres())); + settings.set_value("draw.lthreshold",strprintf("%f",get_lthres())); + settings.set_value("draw.localize",get_local_error_flag()?"1":"0"); +} + +void +StateDraw_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Drawing"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + 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()); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StateDraw_Context::StateDraw_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + loop_(false), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), + checkbutton_pressure_width(_("Pressure Width")), + checkbutton_auto_loop(_("Auto Loop")), + checkbutton_auto_extend(_("Auto Extend")), + checkbutton_auto_link(_("Auto Link")), + 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), + spin_min_pressure(adj_min_pressure,0.1,3), + check_min_pressure(_("Min Pressure")), + adj_feather(0,0,10000,0.01,0.1), + spin_feather(adj_feather,0.01,4), + adj_globalthres(.70f,0.01,10000,0.01,0.1), + spin_globalthres(adj_globalthres,0.01,3), + adj_localthres(20,1,100000,0.1,1), + check_localerror(_("LocalError")) + +{ + 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_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(*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(button_fill_last_stroke, 0, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + button_fill_last_stroke.signal_pressed().connect(sigc::mem_fun(*this,&StateDraw_Context::fill_last_stroke)); + check_localerror.signal_toggled().connect(sigc::mem_fun(*this,&StateDraw_Context::UpdateErrorBox)); + + options_table.show_all(); + refresh_tool_options(); + //App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->present(); + + + old_duckmask=get_work_area()->get_type_mask(); + get_work_area()->set_type_mask(Duck::TYPE_ALL-Duck::TYPE_TANGENT-Duck::TYPE_WIDTH); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // Turn off duck clicking + get_work_area()->set_allow_duck_clicks(false); + + // clear out the ducks + //get_work_area()->clear_ducks(); + + // Refresh the work area + //get_work_area()->queue_draw(); + + // Hide the tables if they are showing + prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateDraw_Context::on_user_click)); + + get_work_area()->set_cursor(Gdk::PENCIL); + + App::toolbox->refresh(); + + refresh_ducks(); +} + + +void StateDraw_Context::UpdateErrorBox() +{ + if(get_local_error_flag()) + { + spin_globalthres.set_adjustment(adj_localthres); + spin_globalthres.set_value(adj_localthres.get_value()); + spin_globalthres.set_increments(0.1,1); + }else + { + spin_globalthres.set_adjustment(adj_globalthres); + spin_globalthres.set_value(adj_globalthres.get_value()); + spin_globalthres.set_increments(0.01,.1); + } + + spin_globalthres.update(); +} + +void +StateDraw_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Draw Tool")); + App::dialog_tool_options->set_name("draw"); + + App::dialog_tool_options->add_button( + Gtk::StockID("synfig-fill"), + _("Fill Last Stroke") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &StateDraw_Context::fill_last_stroke)); +} + +Smach::event_result +StateDraw_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateDraw_Context::~StateDraw_Context() +{ + save_settings(); + + App::dialog_tool_options->clear(); + + get_work_area()->set_type_mask(old_duckmask); + + get_work_area()->reset_cursor(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + + // Restore duck clicking + get_work_area()->set_allow_duck_clicks(true); + + // Enable the time bar + get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateDraw_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateDraw_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateDraw_Context::event_mouse_down_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + switch(event.button) + { + case BUTTON_LEFT: + { + // Enter the stroke state to get the stroke + get_canvas_view()->get_smach().push_state(&state_stroke); + return Smach::RESULT_ACCEPT; + } + + default: + return Smach::RESULT_OK; + } +} + +#define SIMILAR_TANGENT_THRESHOLD (0.2) + +struct debugclass +{ + synfig::String x; + debugclass(const synfig::String &x):x(x) + { +// synfig::warning(">>>>>>>>>>>>>>>>>>> "+x); + } + ~debugclass() + { +// synfig::warning("<<<<<<<<<<<<<<<<<<< "+x); + } +}; + +struct DepthCounter +{ + int &i; + DepthCounter(int &i):i(i) { i++; } + ~DepthCounter() { i--; } +}; + +Smach::event_result +StateDraw_Context::event_stroke(const Smach::event& x) +{ +// debugclass debugger("StateDraw_Context::event_stroke(const Smach::event& x)"); + + const EventStroke& event(*reinterpret_cast(&x)); + + assert(event.stroke_data); + + get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color()); + + if(nested==0) + { + DirtyTrap dirty_trap(get_work_area()); + Smach::event_result result; + result=process_stroke(event.stroke_data,event.width_data,event.modifier&Gdk::CONTROL_MASK || event.modifier&Gdk::BUTTON2_MASK); + process_queue(); + return result; + } + + stroke_queue.push_back(pair(event.stroke_data,event.width_data)); + + return Smach::RESULT_ACCEPT; +} + +bool +StateDraw_Context::process_queue() +{ +// debugclass debugger("StateDraw_Context::process_queue()"); + if(nested) + return true; + DepthCounter depth_counter(nested); + while(!stroke_queue.empty()) + { + pair front(stroke_queue.front()); + process_stroke(front.first,front.second); + stroke_queue.pop_front(); + } + return false; +} + +Smach::event_result +StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag) +{ +// debugclass debugger("StateDraw_Context::process_stroke"); + DepthCounter depth_counter(nested); + + const float radius(synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc())+(abs(get_work_area()->get_pw())+abs(get_work_area()->get_ph()))*5); + + + // If we aren't using pressure width, + // then set all the width to 1 + if(!get_pressure_width_flag()) + { + std::list::iterator iter; + for(iter=width_data->begin();iter!=width_data->end();++iter) + { + *iter=1.0; + } + } + + //get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color()); + //stroke_list.push_back(event.stroke_data); + //refresh_ducks(); + + std::list bline; + bool loop_bline_flag(false); + + //Changed by Adrian - use resident class :) + //synfigapp::convert_stroke_to_bline(bline, *event.stroke_data,*event.width_data, synfigapp::Main::get_bline_width()); + blineconv.width = synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc()); + + if(get_local_error_flag()) + { + float pw = get_work_area()->get_pw(); + float ph = get_work_area()->get_ph(); + + blineconv.pixelwidth = sqrt(pw*pw+ph*ph); + blineconv.smoothness = get_lthres(); + }else + { + blineconv.pixelwidth = 1; + blineconv.smoothness = get_gthres(); + } + + blineconv(bline,*stroke_data,*width_data); + + //Postprocess to require minimum pressure + if(get_min_pressure_flag()) + { + synfigapp::BLineConverter::EnforceMinWidth(bline,get_min_pressure()); + } + + // 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) + { + loop_bline_flag=true; + Vector tangent; + Real width(0); + + while (bline.size() > 2 && + (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius) + { + tangent=bline.back().get_tangent1(); + width=bline.back().get_width(); + bline.pop_back(); + } + + if(abs(bline.front().get_tangent1().norm()*tangent.norm().perp())>SIMILAR_TANGENT_THRESHOLD) + { + // If the tangents are not similar, then + // split the tangents + bline.front().set_split_tangent_flag(true); + bline.front().set_tangent1(tangent); + } + else + { + // If the tangents are similar, then set the tangent + // to the average of the two + bline.front().set_tangent((tangent+bline.front().get_tangent1())*0.5f); + } + + // Add the widths of the two points + { + Real tmp_width(bline.front().get_width()+width); + tmp_width=tmp_width<=1?tmp_width:1; + bline.front().set_width(tmp_width); + } + } + + // If the bline only has one blinepoint, then there is nothing to do. + 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); + + return new_bline(bline,loop_bline_flag,radius); +} + +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_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; + 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 = 0,finish_duck_index = 0; // initialized to keep the compiler happy; shouldn't be needed though + 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 didn't just draw a loop - ie. !loop_bline_flag + // but having loops auto-connect can be useful as well) + if(get_auto_extend_flag() || get_auto_link_flag()) + { + etl::handle start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX)); + etl::handle finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX)); + + // 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 + // line starts at one of the ends of an existing line + if(start_duck)do + { + if(!(start_duck_value_desc=start_duck->get_value_desc()))break; + if(loop_bline_flag)break; // loops don't extend anything + if(!start_duck_value_desc.parent_is_value_node())break; + start_duck_index=start_duck_value_desc.get_index(); // which point on the line did we start drawing at + start_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(start_duck_value_desc.get_parent_value_node()); + if(!get_auto_extend_flag())break; + + // don't extend looped blines + if(start_duck_value_node_bline&&!start_duck_value_node_bline->get_loop()&& + // did we start drawing at either end of the line? + (start_duck_index==0||start_duck_index==start_duck_value_node_bline->link_count()-1)) + { + extend_start=true; + shift_origin=true; + shift_origin_vector=start_duck->get_origin(); + } + }while(0); + + // check whether the end 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 + // line ends at one of the ends of an existing line + if(finish_duck)do + { + if(!(finish_duck_value_desc=finish_duck->get_value_desc()))break; + if(loop_bline_flag)break; + if(!finish_duck_value_desc.parent_is_value_node())break; + finish_duck_index=finish_duck_value_desc.get_index(); + finish_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(finish_duck_value_desc.get_parent_value_node()); + if(!get_auto_extend_flag())break; + + // 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 + // extend both blines, so unless we started and finished at the 2 ends + // 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{ + extend_finish=true; + shift_origin=true; + shift_origin_vector=finish_duck->get_origin(); + } + } + }while(0); + + // if the new line's start didn't extend an existing line, + // check whether it needs to be linked to an existing duck + if(!extend_start&&get_auto_link_flag()&&start_duck&&start_duck_value_desc) + switch(start_duck_value_desc.get_value_type()) + { + case synfig::ValueBase::TYPE_BLINEPOINT: + 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_origin && shift_origin_vector != start_duck->get_origin()) + break; + 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) + extend_finish_join_same=true; + else + extend_finish_join_different=true; + else + join_start_no_extend=true; + // fall through + default:break; + } + + // if the new line's end didn't extend an existing line, + // check whether it needs to be linked to an existing duck + if(!extend_finish&&get_auto_link_flag()&&finish_duck&&finish_duck_value_desc) + switch(finish_duck_value_desc.get_value_type()) + { + case synfig::ValueBase::TYPE_BLINEPOINT: + 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_origin && shift_origin_vector != finish_duck->get_origin()) + break; + 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) + extend_start_join_same=true; + else + extend_start_join_different=true; + else + join_finish_no_extend=true; + // fall through + default:break; + } + } + + ValueNode_BLine::Handle value_node; + std::list trans_bline; + + { + std::list::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 + ); + + 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; + synfig::ValueNode_DynamicList::ListEntry source; + + // the new line's start extends an existing line + if(extend_start) + { + int target_offset = 0; + 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_offset=trans_bline.size(); + } + else + { + result=extend_bline_from_end(start_duck_value_node_bline,trans_bline,complete_loop); + source=start_duck_value_node_bline->list.back(); + } + + if(extend_start_join_different) + LinkableValueNode::Handle::cast_dynamic(source.value_node)-> + set_link("point",finish_duck_value_desc.get_value_node()); + else if(extend_start_join_same) + LinkableValueNode::Handle::cast_dynamic(source.value_node)-> + set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_node_bline-> + list[target_offset+finish_duck_index].value_node),0).get_value_node()); + return result; + } + + // the new line's end extends an existing line + if(extend_finish) + { + int target_offset = 0; + 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_offset=trans_bline.size(); + } + 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(); + } + + if(extend_finish_join_different) + LinkableValueNode::Handle::cast_dynamic(source.value_node)-> + set_link("point",start_duck_value_desc.get_value_node()); + else if(extend_finish_join_same) + LinkableValueNode::Handle::cast_dynamic(source.value_node)-> + set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_node_bline-> + list[target_offset+start_duck_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("point",start_duck_value_desc.get_value_node()); + + if (join_finish_no_extend) + LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)-> + set_link("point",finish_duck_value_desc.get_value_node()); + + 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 */ + // get_canvas_view()->get_ui_interface()->error(_("Unable to add value node")); + // group.cancel(); + // increment_id(); + // return Smach::RESULT_ERROR; + } + + 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); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + 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); + + // if they're both defined, we'll add the region later + 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")); + } + + if(get_feather()) + { + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + } + assert(layer); + //layer->set_description(strprintf("Stroke %d",number)); + //get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + if (shift_origin) + get_canvas_interface()-> + change_value(synfigapp::ValueDesc(layer,"origin"),shift_origin_vector); + + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + increment_id(); + //refresh_ducks(); + return Smach::RESULT_ERROR; + } + layer_list.push_back(layer); + get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list); + //refresh_ducks(); + } + + 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) +{ + // Create the action group + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Define Region")); + + 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. + { + std::list::iterator iter; + for(iter=bline.begin();iter!=bline.end();++iter) + { + etl::handle duck(get_work_area()->find_duck(iter->get_vertex(),0,Duck::TYPE_VERTEX)); + + if(!duck) + { + synfig::info(__FILE__":%d: Nothing to enclose!",__LINE__); + return Smach::RESULT_OK; + } + + assert(duck->get_type()==Duck::TYPE_VERTEX); + + synfigapp::ValueDesc value_desc(duck->get_value_desc()); + + if(!value_desc) + { + synfig::info(__FILE__":%d: Got a hit, but no ValueDesc on this duck",__LINE__); + continue; + } + + switch(value_desc.get_value_type()) + { + case synfig::ValueBase::TYPE_BLINEPOINT: + //if(vertex_list.empty() || value_desc!=vertex_list.back()) + vertex_list.push_back(value_desc); + assert(vertex_list.back().is_valid()); + + break; + default: + break; + } + } + } + + assert(vertex_list.back().is_valid()); + + printf("vertex list with %zd bline points\n", vertex_list.size()); + + // Remove any duplicates + { + } + + 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()) + { + bool trivial_case(true); + ValueNode::Handle trivial_case_value_node; + + trivial_case_value_node=vertex_list.front().get_parent_value_node(); + + std::list::iterator iter; + for(iter=vertex_list.begin();iter!=vertex_list.end();++iter) + { + if(trivial_case_value_node!=iter->get_parent_value_node()) + { + trivial_case=false; + break; + } + } + + // \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("the line has %d vertices", value_node_bline->link_count()); + + if(value_node_bline->link_count() <= 2) + { + 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; + } + + // 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) + { + vertex_list.insert(vertex_list.end(), vertex_list.begin(), iter); + vertex_list.erase(vertex_list.begin(), iter); + break; + } + + 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) + { + 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++; + } + + // 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 (whole) + { + // printf("whole (down) (%d) ", min_index); + for (int i = min_index; i >= 0; i--) + { + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); + } + for (int i = points_in_line - 1; i >= min_index; i--) + { + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); + } + } + else + { + // printf("part (down) (%d -> %d) ", max_index, min_index); + for (int i = max_index; i != min_index; i--) + { + if (i == -1) i = points_in_line - 1; + // printf("%d ", i); + vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i)); + } + 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++) + { + // 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); + } + + debug_show_vertex_list(0, vertex_list, "continuous vertices", -1); + + // \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); + + // Set done to "true" for now. If + // any updates are performed, we will + // change it back to false. + done=true; + + 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 + + int current = 0; + for(;iter!=vertex_list.end();prev=iter,iter++,next++,current++) + { + // 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("t2",value_node_next->get_link("t2")); + value_node->set_link("split",ValueNode_Const::create(true)); + + // 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(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, + // then go ahead and create the new + // 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; + for(iter=vertex_list.begin();iter!=vertex_list.end();++iter) + { + // Ensure that the vertex is exported. + get_canvas_interface()->auto_export(*iter); + + value_node_bline->add(iter->get_value_node()); + //value_node_bline->add(ValueNode_BLine::ListEntry(iter->get_value_node())); + } + + value_node_bline->set_loop(true); + } + + get_canvas_interface()->auto_export(value_node_bline); + + // Now we create the region layer + // Create the layer + { + Layer::Handle layer; + Canvas::Handle canvas(get_canvas_view()->get_canvas()); + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + layer=get_canvas_interface()->add_layer_to("region",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return Smach::RESULT_ERROR; + } + + if(get_feather()) + { + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + } + get_canvas_interface()->signal_layer_param_changed()(layer,"color"); + + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + return Smach::RESULT_ERROR; + } + get_canvas_view()->get_selection_manager()->set_selected_layer(layer); + } + + return Smach::RESULT_ACCEPT; +} + +void +StateDraw_Context::refresh_ducks() +{ + get_canvas_view()->queue_rebuild_ducks(); +/* + get_work_area()->clear_ducks(); + + + std::list< etl::smart_ptr > >::iterator iter; + + for(iter=stroke_list.begin();iter!=stroke_list.end();++iter) + { + get_work_area()->add_stroke(*iter); + } + + get_work_area()->queue_draw(); +*/ +} + + +Smach::event_result +StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop) +{ + // Create the action group + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine")); + + if (complete_loop) + { + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_node",ValueNode::Handle(value_node)); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline")); + group.cancel(); + return Smach::RESULT_ERROR; + } + } + + std::list::reverse_iterator iter; + for(iter=bline.rbegin();!(iter==bline.rend());++iter) + { + ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter)); + + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert")); + + assert(action); + synfigapp::ValueDesc value_desc(value_node,0); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_desc",value_desc); + if(!action->set_param("item",ValueNode::Handle(composite))) + synfig::error("ACTION didn't like \"item\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to insert item")); + group.cancel(); + //refresh_ducks(); + return Smach::RESULT_ERROR; + } + } + last_stroke=value_node; + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list bline,bool complete_loop) +{ + // Create the action group + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine")); + + if (complete_loop) + { + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_node",ValueNode::Handle(value_node)); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline")); + group.cancel(); + return Smach::RESULT_ERROR; + } + } + + std::list::iterator iter; + for(iter=bline.begin();iter!=bline.end();++iter) + { + ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter)); + + synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert")); + + assert(action); + synfigapp::ValueDesc value_desc(value_node,value_node->link_count()); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_desc",value_desc); + if(!action->set_param("item",ValueNode::Handle(composite))) + synfig::error("ACTION didn't like \"item\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to insert item")); + group.cancel(); + //refresh_ducks(); + return Smach::RESULT_ERROR; + } + } + last_stroke=value_node; + return Smach::RESULT_ACCEPT; +} + +void +StateDraw_Context::reverse_bline(std::list &bline) +{ + int i; + + std::list::iterator iter,eiter; + iter=bline.begin(); + eiter=bline.end(); + eiter--; + for(i=0;i<(int)bline.size()/2;++iter,--eiter,i++) + { + iter_swap(iter,eiter); + iter->reverse(); + eiter->reverse(); + } +} + +Smach::event_result +StateDraw_Context::fill_last_stroke_and_unselect_other_layers() +{ + if(!last_stroke) + return Smach::RESULT_OK; + + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Fill Stroke")); + + Layer::Handle layer; + + get_canvas_interface()->auto_export(last_stroke); + + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + 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_description(last_stroke_id + _(" Region")); + + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(last_stroke))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + 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); +} diff --git a/synfig-studio/src/gui/states/state_draw.h b/synfig-studio/src/gui/states/state_draw.h new file mode 100644 index 0000000..2c074a5 --- /dev/null +++ b/synfig-studio/src/gui/states/state_draw.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_draw.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_ROTOSCOPE_H +#define __SYNFIG_STUDIO_STATE_ROTOSCOPE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateDraw_Context; + +class StateDraw : public Smach::state +{ +public: + StateDraw(); + ~StateDraw(); +}; // END of class StateDraw + +extern StateDraw state_draw; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_eyedrop.cpp b/synfig-studio/src/gui/states/state_eyedrop.cpp new file mode 100644 index 0000000..e7cf4bb --- /dev/null +++ b/synfig-studio/src/gui/states/state_eyedrop.cpp @@ -0,0 +1,146 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_eyedrop.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "state_eyedrop.h" +#include "state_normal.h" +#include "workarea.h" +#include +#include "app.h" +#include "dialogs/dialog_color.h" +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include "canvasview.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateEyedrop_Context +{ + CanvasView *canvas_view; + CanvasView::IsWorking is_working; + +public: + StateEyedrop_Context(CanvasView *canvas_view); + ~StateEyedrop_Context(); + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x); + +}; // END of class StateEyedrop_Context + +/* === G L O B A L S ======================================================= */ + +StateEyedrop studio::state_eyedrop; + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +StateEyedrop::StateEyedrop(): + Smach::state("eyedrop") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateEyedrop_Context::event_stop_handler)); + insert(event_def(EVENT_STOP,&StateEyedrop_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateEyedrop_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateEyedrop_Context::event_workarea_mouse_button_down_handler)); +} + +StateEyedrop::~StateEyedrop() +{ +} + +StateEyedrop_Context::StateEyedrop_Context(CanvasView *canvas_view): + canvas_view(canvas_view), + is_working(*canvas_view) +{ + synfig::info("Entered Eyedrop State"); + canvas_view->work_area->set_cursor(Gdk::Cursor(Gdk::CROSSHAIR)); + + App::toolbox->refresh(); +} + +StateEyedrop_Context::~StateEyedrop_Context() +{ + synfig::info("Left Eyedrop State"); + canvas_view->work_area->reset_cursor(); + App::toolbox->refresh(); +} + +Smach::event_result +StateEyedrop_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //synfig::info("STATE EYEDROP: Received Stop Event"); + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +// canvas_view->get_smach().pop_state(); +// return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateEyedrop_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + synfig::info("STATE EYEDROP: Received Refresh Event"); + canvas_view->work_area->queue_render_preview(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateEyedrop_Context::event_workarea_mouse_button_down_handler(const Smach::event& x) +{ + synfig::info("STATE EYEDROP: Received mouse button down Event"); + const EventMouse& event(*reinterpret_cast(&x)); + if(event.button==BUTTON_LEFT) + { + Color color(canvas_view->get_canvas()->get_context().get_color(event.pos)); + synfigapp::Main::set_outline_color(color); + studio::App::dialog_color->set_color(color); + return Smach::RESULT_ACCEPT; + } + return Smach::RESULT_OK; +} diff --git a/synfig-studio/src/gui/states/state_eyedrop.h b/synfig-studio/src/gui/states/state_eyedrop.h new file mode 100644 index 0000000..4a90021 --- /dev/null +++ b/synfig-studio/src/gui/states/state_eyedrop.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_eyedrop.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STATE_EYEDROP_H +#define __SYNFIG_STATE_EYEDROP_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateEyedrop_Context; + +class StateEyedrop : public Smach::state +{ +public: + StateEyedrop(); + ~StateEyedrop(); +}; // END of class StateEyedrop + +extern StateEyedrop state_eyedrop; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_fill.cpp b/synfig-studio/src/gui/states/state_fill.cpp new file mode 100644 index 0000000..cf6c750 --- /dev/null +++ b/synfig-studio/src/gui/states/state_fill.cpp @@ -0,0 +1,182 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_fill.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "state_fill.h" +#include "state_normal.h" +#include "workarea.h" +#include +#include "app.h" +#include "dialogs/dialog_color.h" +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include "canvasview.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateFill_Context +{ + CanvasView *canvas_view; + CanvasView::IsWorking is_working; + +public: + StateFill_Context(CanvasView *canvas_view); + ~StateFill_Context(); + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_workarea_layer_clicked_handler(const Smach::event& x); + + + 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();} + + +}; // END of class StateFill_Context + +/* === G L O B A L S ======================================================= */ + +StateFill studio::state_fill; + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +StateFill::StateFill(): + Smach::state("fill") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateFill_Context::event_stop_handler)); + insert(event_def(EVENT_STOP,&StateFill_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateFill_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateFill_Context::event_workarea_layer_clicked_handler)); +} + +StateFill::~StateFill() +{ +} + +StateFill_Context::StateFill_Context(CanvasView *canvas_view): + canvas_view(canvas_view), + is_working(*canvas_view) +{ + synfig::info("Entered Fill State"); + canvas_view->work_area->set_cursor(Gdk::CROSSHAIR); + + App::toolbox->refresh(); +} + +StateFill_Context::~StateFill_Context() +{ + synfig::info("Left Fill State"); + canvas_view->work_area->reset_cursor(); + App::toolbox->refresh(); +} + +Smach::event_result +StateFill_Context::event_stop_handler(const Smach::event& /*x*/) +{ + synfig::info("STATE FILL: Received Stop Event"); + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +// canvas_view->get_smach().pop_state(); +// return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateFill_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + synfig::info("STATE FILL: Received Refresh Event"); + canvas_view->work_area->queue_render_preview(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateFill_Context::event_workarea_layer_clicked_handler(const Smach::event& x) +{ + synfig::info("STATE FILL: Received layer clicked Event"); + const EventLayerClick& event(*reinterpret_cast(&x)); + + if(!event.layer) + { + get_canvas_view()->get_ui_interface()->warning(_("No layer here")); + return Smach::RESULT_ACCEPT; + } + + + //synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescSet")); + synfigapp::ValueDesc value_desc(event.layer,"color"); + + if(!get_canvas_interface()->change_value(value_desc,ValueBase(synfigapp::Main::get_fill_color()))) + { + get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color")); + return Smach::RESULT_ERROR; + } + /* + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_desc",value_desc); + action->set_param("time",get_canvas_interface()->get_time()); + //action->set_param("layer",event.layer); + //if(!action->set_param("param",String("color"))) + // synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("new_value",ValueBase(synfigapp::Main::get_fill_color()))) + synfig::error("LayerParamConnect didn't like \"fill_color\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color")); + return Smach::RESULT_ERROR; + } + get_canvas_view()->get_ui_interface()->task(_("Idle")); + */ + return Smach::RESULT_ACCEPT; +} diff --git a/synfig-studio/src/gui/states/state_fill.h b/synfig-studio/src/gui/states/state_fill.h new file mode 100644 index 0000000..349a1ce --- /dev/null +++ b/synfig-studio/src/gui/states/state_fill.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_fill.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STATE_FILL_H +#define __SYNFIG_STATE_FILL_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateFill_Context; + +class StateFill : public Smach::state +{ +public: + StateFill(); + ~StateFill(); +}; // END of class StateFill + +extern StateFill state_fill; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_gradient.cpp b/synfig-studio/src/gui/states/state_gradient.cpp new file mode 100644 index 0000000..68f35c0 --- /dev/null +++ b/synfig-studio/src/gui/states/state_gradient.cpp @@ -0,0 +1,546 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_gradient.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include + +#include "state_gradient.h" +#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 "duck.h" + +#include "widgets/widget_enum.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +enum +{ + GRADIENT_INTERPOLATION_LINEAR=0, + GRADIENT_RADIAL=1, + GRADIENT_CONICAL=2, + GRADIENT_SPIRAL=3 +}; + +/* === G L O B A L S ======================================================= */ + +StateGradient studio::state_gradient; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateGradient_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + Duckmatic::Push duckmatic_push; + + synfigapp::Settings& settings; + + Point point_holder; + + etl::handle point2_duck; + + void refresh_ducks(); + + bool prev_workarea_layer_status_; + + Gtk::Table options_table; + Gtk::Entry entry_id; + Widget_Enum enum_type; +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + Widget_Enum enum_blend; +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + +public: + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + int get_type()const { return enum_type.get_value(); } + void set_type(int x) { return enum_type.set_value(x); } + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + int get_blend()const { return enum_blend.get_value(); } + void set_blend(int x) { return enum_blend.set_value(x); } +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + void refresh_tool_options(); + + StateGradient_Context(CanvasView* canvas_view); + + ~StateGradient_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 on_user_click(synfig::Point point); + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + + void make_gradient(const Point& p1, const Point& p2); + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + +}; // END of class StateGradient_Context + +/* === M E T H O D S ======================================================= */ + +StateGradient::StateGradient(): + Smach::state("gradient") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateGradient_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_STOP,&StateGradient_Context::event_stop_handler)); + insert(event_def(EVENT_TABLES_SHOW,&StateGradient_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateGradient_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateGradient_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateGradient_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateGradient_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateGradient_Context::event_mouse_click_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateGradient_Context::event_refresh_tool_options)); +} + +StateGradient::~StateGradient() +{ +} + +void +StateGradient_Context::load_settings() +{ + String value; + + if(settings.get_value("gradient.id",value)) + set_id(value); + else + set_id("Gradient"); + + if(settings.get_value("gradient.type",value)) + set_type(atoi(value.c_str())); + else + set_type(GRADIENT_INTERPOLATION_LINEAR); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + if(settings.get_value("gradient.blend",value)) + set_blend(atoi(value.c_str())); + else + set_blend(Color::BLEND_COMPOSITE); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS +} + +void +StateGradient_Context::save_settings() +{ + settings.set_value("gradient.id",get_id().c_str()); + settings.set_value("gradient.type",strprintf("%d",get_type())); +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + settings.set_value("gradient.blend",strprintf("%d",get_blend())); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS +} + +void +StateGradient_Context::reset() +{ + refresh_ducks(); +} + +void +StateGradient_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Gradient"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + String str_number; + str_number=String(id,id.size()-digits,id.size()); + id=String(id,0,id.size()-digits); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StateGradient_Context::StateGradient_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + duckmatic_push(get_work_area()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + entry_id() +{ + egress_on_selection_change=true; + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Gradient 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); + + enum_type.set_param_desc(ParamDesc("type") + .set_local_name(_("Gradient Type")) + .set_description(_("Determines the type of Gradient used")) + .set_hint("enum") + .add_enum_value(GRADIENT_INTERPOLATION_LINEAR,"linear",_("Linear")) + .add_enum_value(GRADIENT_RADIAL,"radial",_("Radial")) + .add_enum_value(GRADIENT_CONICAL,"conical",_("Conical")) + .add_enum_value(GRADIENT_SPIRAL,"spiral",_("Spiral"))); + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method") + .set_local_name(_("Blend Method")) + .set_description(_("The blend method the gradient will use"))); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + load_settings(); + + options_table.attach(enum_type, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + options_table.attach(enum_blend, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + get_work_area()->set_cursor(Gdk::CROSSHAIR); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_work_area()->refresh_cursor(); + + // Hide the tables if they are showing + get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateGradient_Context::on_user_click)); + + App::toolbox->refresh(); +} + +void +StateGradient_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Gradient Tool")); + App::dialog_tool_options->set_name("gradient"); +} + +Smach::event_result +StateGradient_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateGradient_Context::~StateGradient_Context() +{ + save_settings(); + + // Restore layer clicking +// get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + //if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_canvas_view()->queue_rebuild_ducks(); + + //get_canvas_view()->show_tables(); + + get_work_area()->refresh_cursor(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateGradient_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateGradient_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StateGradient_Context::make_gradient(const Point& _p1, const Point& _p2) +{ + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Gradient")); + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer; + + Canvas::Handle canvas(get_canvas_view()->get_canvas()); + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); + const Point p1(transform.unperform(_p1)); + const Point p2(transform.unperform(_p2)); + + switch(get_type()) + { + case GRADIENT_INTERPOLATION_LINEAR: + + layer=get_canvas_interface()->add_layer_to("linear_gradient",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer->set_param("p1",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"p1"); + layer->set_param("p2",p2); + get_canvas_interface()->signal_layer_param_changed()(layer,"p2"); + break; + case GRADIENT_RADIAL: + layer=get_canvas_interface()->add_layer_to("radial_gradient",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer->set_param("center",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"center"); + layer->set_param("radius",(p2-p1).mag()); + get_canvas_interface()->signal_layer_param_changed()(layer,"radius"); + break; + case GRADIENT_CONICAL: + layer=get_canvas_interface()->add_layer_to("conical_gradient",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer->set_param("center",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"center"); + { + Vector diff(p2-p1); + layer->set_param("angle",Angle::tan(diff[1],diff[0])); + get_canvas_interface()->signal_layer_param_changed()(layer,"angle"); + } + break; + case GRADIENT_SPIRAL: + layer=get_canvas_interface()->add_layer_to("spiral_gradient",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer->set_param("center",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"center"); + layer->set_param("radius",(p2-p1).mag()); + get_canvas_interface()->signal_layer_param_changed()(layer,"radius"); + { + Vector diff(p2-p1); + layer->set_param("angle",Angle::tan(diff[1],diff[0])); + get_canvas_interface()->signal_layer_param_changed()(layer,"angle"); + } + break; + + default: + return; + } + +#ifdef BLEND_METHOD_IN_TOOL_OPTIONS + layer->set_param("blend_method",get_blend()); + get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method"); +#endif // BLEND_METHOD_IN_TOOL_OPTIONS + + layer->set_description(get_id()); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + egress_on_selection_change=false; + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + layer_selection.push_back(layer); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + reset(); + increment_id(); +} + +Smach::event_result +StateGradient_Context::event_mouse_click_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) + { + point_holder=get_work_area()->snap_point_to_grid(event.pos); + etl::handle duck=new Duck(); + duck->set_point(point_holder); + duck->set_name("p1"); + duck->set_type(Duck::TYPE_POSITION); + get_work_area()->add_duck(duck); + + point2_duck=new Duck(); + point2_duck->set_point(point_holder); + point2_duck->set_name("p2"); + point2_duck->set_type(Duck::TYPE_POSITION); + get_work_area()->add_duck(point2_duck); + + handle bezier(new Duckmatic::Bezier()); + bezier->p1=bezier->c1=duck; + bezier->p2=bezier->c2=point2_duck; + get_work_area()->add_bezier(bezier); + + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) + { + if (!point2_duck) return Smach::RESULT_OK; + point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos)); + get_work_area()->queue_draw(); + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) + { + make_gradient(point_holder, get_work_area()->snap_point_to_grid(event.pos)); + get_work_area()->clear_ducks(); + return Smach::RESULT_ACCEPT; + } + + return Smach::RESULT_OK; +} + + +void +StateGradient_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); +} diff --git a/synfig-studio/src/gui/states/state_gradient.h b/synfig-studio/src/gui/states/state_gradient.h new file mode 100644 index 0000000..308b5ee --- /dev/null +++ b/synfig-studio/src/gui/states/state_gradient.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_gradient.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_GRADIENT_H +#define __SYNFIG_STUDIO_STATE_GRADIENT_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateGradient_Context; + +class StateGradient : public Smach::state +{ +public: + StateGradient(); + ~StateGradient(); +}; // END of class StateGradient + +extern StateGradient state_gradient; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_mirror.cpp b/synfig-studio/src/gui/states/state_mirror.cpp new file mode 100644 index 0000000..59fc759 --- /dev/null +++ b/synfig-studio/src/gui/states/state_mirror.cpp @@ -0,0 +1,336 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_mirror.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** 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 +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include + +#include "state_mirror.h" +#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 "duck.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +enum Axis { + AXIS_X, + AXIS_Y +} ; + +/* === G L O B A L S ======================================================= */ + +StateMirror studio::state_mirror; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_Mirror : public DuckDrag_Base +{ + synfig::Vector center; + + std::vector positions; + +public: + Axis axis; + + DuckDrag_Mirror(); + 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); +}; + +class studio::StateMirror_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + synfigapp::Settings& settings; + + sigc::connection keypress_connect; + sigc::connection keyrelease_connect; + + etl::handle duck_dragger_; + + Gtk::Table options_table; + + Gtk::RadioButton::Group radiobutton_group; + Gtk::RadioButton radiobutton_axis_x; + Gtk::RadioButton radiobutton_axis_y; + +public: + + Axis get_axis()const { return radiobutton_axis_x.get_active()?AXIS_X:AXIS_Y; } + void set_axis(Axis a) + { + if(a==AXIS_X) + radiobutton_axis_x.set_active(true); + else + radiobutton_axis_y.set_active(true); + + duck_dragger_->axis=get_axis(); + } + + void update_axes() + { + duck_dragger_->axis=get_axis(); + get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW); + } + + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + void refresh_tool_options(); + + StateMirror_Context(CanvasView* canvas_view); + + ~StateMirror_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(); + + bool key_event(GdkEventKey *event); +}; // END of class StateMirror_Context + +/* === M E T H O D S ======================================================= */ + +StateMirror::StateMirror(): + Smach::state("mirror") +{ + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateMirror_Context::event_refresh_tool_options)); + insert(event_def(EVENT_STOP,&StateMirror_Context::event_stop_handler)); +} + +StateMirror::~StateMirror() +{ +} + +void +StateMirror_Context::load_settings() +{ + String value; + + settings.get_value("mirror.axis",value); + set_axis((Axis)atoi(value.c_str())); +} + +void +StateMirror_Context::save_settings() +{ + settings.set_value("mirror.lock_aspect",strprintf("%d",(int)get_axis())); +} + +StateMirror_Context::StateMirror_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + settings(synfigapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_Mirror()), + radiobutton_axis_x(radiobutton_group,_("Horizontal")), + radiobutton_axis_y(radiobutton_group,_("Vertical")) +{ + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Mirror Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(radiobutton_axis_x, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(radiobutton_axis_y, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("(Shift key toggles axis)"))), 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + radiobutton_axis_x.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes)); + radiobutton_axis_y.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes)); + + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + + keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false); + keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false); + + get_work_area()->set_cursor(Gdk::SB_H_DOUBLE_ARROW); +// get_work_area()->reset_cursor(); + + App::toolbox->refresh(); + + set_axis(AXIS_X); + load_settings(); +} + +bool +StateMirror_Context::key_event(GdkEventKey *event) +{ + if (event->keyval==GDK_Shift_L || event->keyval==GDK_Shift_R ) + { + set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X); + get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW); + } + + return false; //Pass on the event to other handlers, just in case +} + +void +StateMirror_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Mirror Tool")); + App::dialog_tool_options->set_name("mirror"); +} + +Smach::event_result +StateMirror_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateMirror_Context::event_stop_handler(const Smach::event& /*x*/) +{ + throw &state_normal; + return Smach::RESULT_OK; +} + +StateMirror_Context::~StateMirror_Context() +{ + save_settings(); + + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + + keypress_connect.disconnect(); + keyrelease_connect.disconnect(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + +DuckDrag_Mirror::DuckDrag_Mirror(): + axis(AXIS_X) +{ +} + +#ifndef EPSILON +#define EPSILON 0.0000001 +#endif + +void +DuckDrag_Mirror::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& /*offset*/) +{ + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + positions.clear(); + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + Point p((*iter)->get_trans_point()); + positions.push_back(p); + } + +} + +void +DuckDrag_Mirror::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + center=vector; + int i; + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + Time time(duckmatic->get_time()); + + // do the Vertex and Position ducks first + 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) + { + Vector p(positions[i]); + + if (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0]; + else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1]; + + (*iter)->set_trans_point(p); + } + + // then do the other ducks + 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) + { + // we don't need to mirror radius ducks - they're one-dimensional + if ((*iter)->is_radius()) + continue; + + Vector p(positions[i]); + + if (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0]; + else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1]; + + (*iter)->set_trans_point(p); + } +} + +bool +DuckDrag_Mirror::end_duck_drag(Duckmatic* duckmatic) +{ + duckmatic->signal_edited_selected_ducks(); + return true; +} diff --git a/synfig-studio/src/gui/states/state_mirror.h b/synfig-studio/src/gui/states/state_mirror.h new file mode 100644 index 0000000..4ac878e --- /dev/null +++ b/synfig-studio/src/gui/states/state_mirror.h @@ -0,0 +1,55 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_mirror.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_MIRROR_H +#define __SYNFIG_STUDIO_STATE_MIRROR_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateMirror_Context; + +class StateMirror : public Smach::state +{ +public: + StateMirror(); + ~StateMirror(); +}; // END of class StateMirror + +extern StateMirror state_mirror; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_normal.cpp b/synfig-studio/src/gui/states/state_normal.cpp new file mode 100644 index 0000000..c763022 --- /dev/null +++ b/synfig-studio/src/gui/states/state_normal.cpp @@ -0,0 +1,824 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_normal.cpp +** \brief Template File +** +** $Id$ +** +** \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 +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# 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 "duck.h" +#include +#include + +#include "general.h" +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +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 DuckDrag_Combo : public DuckDrag_Base +{ + synfig::Vector last_move; + synfig::Vector drag_offset; + synfig::Vector center; + synfig::Vector snap; + + synfig::Angle original_angle; + synfig::Real original_mag; + + std::vector last_; + std::vector positions; + + + bool bad_drag; + bool move_only; + +public: + 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); + + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} +}; + + +class studio::StateNormal_Context : public sigc::trackable +{ + etl::handle canvas_view_; + + synfigapp::Settings& settings; + + sigc::connection keypress_connect; + sigc::connection keyrelease_connect; + + etl::handle duck_dragger_; + + Gtk::Table options_table; + + Gtk::CheckButton checkbutton_rotate; + Gtk::CheckButton checkbutton_scale; + Gtk::CheckButton checkbutton_constrain; + +public: + + 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(); } + + 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(); } + + StateNormal_Context(CanvasView* canvas_view); + + ~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(); + + bool key_pressed(GdkEventKey *event); + bool key_released(GdkEventKey *event); + + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_refresh_ducks_handler(const Smach::event& x); + Smach::event_result event_undo_handler(const Smach::event& x); + Smach::event_result event_redo_handler(const Smach::event& x); + Smach::event_result event_mouse_button_down_handler(const Smach::event& x); + Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + void refresh_tool_options(); + Smach::event_result event_layer_click(const Smach::event& x); + + +}; // 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() +{ +} + +void +StateNormal_Context::load_settings() +{ + 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); + +} + +void +StateNormal_Context::save_settings() +{ + 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"); +} + +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(); + //App::dialog_tool_options->set_widget(options_table); + //App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + + 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); + + //these will segfault +// get_work_area()->set_cursor(Gdk::CROSSHAIR); +// get_work_area()->reset_cursor(); + + App::toolbox->refresh(); + + load_settings(); + refresh_scale_flag(); +} + +bool +StateNormal_Context::key_pressed(GdkEventKey *event) +{ + 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 +} + +bool +StateNormal_Context::key_released(GdkEventKey *event) +{ + 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 +} + +void +StateNormal_Context::refresh_tool_options() +{ + 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"); +} + + + +StateNormal_Context::~StateNormal_Context() +{ + save_settings(); + + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + + keypress_connect.disconnect(); + keyrelease_connect.disconnect(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + +DuckDrag_Combo::DuckDrag_Combo(): + scale(false), + rotate(false), + constrain(false) // Lock aspect for scale; smooth move for translate +{ +} + +void +DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) +{ + last_move=Vector(1,1); + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + bad_drag=false; + + drag_offset=duckmatic->find_duck(offset)->get_trans_point(); + + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset_; + snap=Vector(0,0); + + // 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++) + { + 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; + + + synfig::Vector vect(offset-center); + original_angle=Angle::tan(vect[1],vect[0]); + original_mag=vect.mag(); +} + + +void +DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + if (!duckmatic) return; + + if(bad_drag) + return; + + //Override axis lock set in workarea when holding down the shift key + if (!move_only && (scale || rotate)) + duckmatic->set_axis_lock(false); + + 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; + + 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); + } + 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); + } + } + + 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()); + + 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; + + 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; + + 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); + } + } 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 + { + //vect[0]=vect[1]=vect.mag()*0.707106781; + Real amount(vect.mag()/(drag_offset-center).mag()); + vect[0]=vect[1]=amount; + } + + if(vect[0]-EPSILON) + vect[0]=1; + if(vect[1]-EPSILON) + vect[1]=1; + + 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; + + Vector p(positions[i]-center); + + 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; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p, time); + } + } + + // then patch up the tangents for the vertices we've moved + duckmatic->update_ducks(); + + last_move=vect; +} + +bool +DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic) +{ + if(bad_drag)return false; + + //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks")); + + 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; + } +} + +Smach::event_result +StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +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; +} + +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; +} + +Smach::event_result +StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Refresh Ducks"); + canvas_view_->queue_rebuild_ducks(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_undo_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Undo Event"); + canvas_view_->get_instance()->undo(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_redo_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Redo Event"); + canvas_view_->get_instance()->redo(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x) +{ + // synfig::info("STATE NORMAL: Received mouse button down Event"); + + const EventMouse& event(*reinterpret_cast(&x)); + + switch(event.button) + { + case BUTTON_RIGHT: + canvas_view_->popup_main_menu(); + return Smach::RESULT_ACCEPT; + default: + return Smach::RESULT_OK; + } +} + +Smach::event_result +StateNormal_Context::event_layer_click(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."); + } + + 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; + } +} + +/* +void +StateNormal_Context::edit_several_waypoints(std::list value_desc_list) +{ + Gtk::Dialog dialog( + "Edit Multiple Waypoints", // Title + true, // Modal + true // use_separator + ); + + Widget_WaypointModel widget_waypoint_model; + widget_waypoint_model.show(); + + dialog.get_vbox()->pack_start(widget_waypoint_model); + + + dialog.add_button(Gtk::StockID("gtk-apply"),1); + dialog.add_button(Gtk::StockID("gtk-cancel"),0); + dialog.show(); + + if(dialog.run()==0) + return; + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Set Waypoints")); + + std::list::iterator iter; + for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter) + { + synfigapp::ValueDesc value_desc(*iter); + + if(!value_desc.is_valid()) + continue; + + ValueNode_Animated::Handle value_node; + + // 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()); + + synfigapp::Action::Handle action; + + 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)); + } + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + + + 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; + } + } + else + { + if(value_desc.is_value_node()) + value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()); + } + + + if(value_node) + { + + 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; + } + + + 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()); + + 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; + } + } + else + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to animate a specific valuedesc")); + //group.cancel(); + //return; + } + + } +} +*/ + +Smach::event_result +StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received multiple duck click event"); + + //const EventMouse& event(*reinterpret_cast(&x)); + + std::list value_desc_list; + + // 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()); + + if(!value_desc.is_valid()) + continue; + + 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()) + ,ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()) + ->get_link_index_from_name("point") + ) + ); + } + 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); + + /* + synfigapp::Action::ParamList param_list; + param_list=get_canvas_interface()->generate_param_list(value_desc_list); + + canvas_view_->add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE); + + 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()); + + return Smach::RESULT_ACCEPT; +} + + diff --git a/synfig-studio/src/gui/states/state_normal.h b/synfig-studio/src/gui/states/state_normal.h new file mode 100644 index 0000000..01b040b --- /dev/null +++ b/synfig-studio/src/gui/states/state_normal.h @@ -0,0 +1,57 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_normal.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** 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 +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_NORMAL_H +#define __SYNFIG_STUDIO_STATE_NORMAL_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateNormal_Context; + +class StateNormal : public Smach::state +{ +public: + StateNormal(); + ~StateNormal(); +}; // END of class StateNormal + +extern StateNormal state_normal; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_polygon.cpp b/synfig-studio/src/gui/states/state_polygon.cpp new file mode 100644 index 0000000..7c11c05 --- /dev/null +++ b/synfig-studio/src/gui/states/state_polygon.cpp @@ -0,0 +1,945 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_polygon.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include "state_polygon.h" +#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 "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StatePolygon studio::state_polygon; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StatePolygon_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + bool prev_table_status; + bool prev_workarea_layer_status_; + + Gtk::Menu menu; + + Duckmatic::Push duckmatic_push; + + std::list polygon_point_list; + synfigapp::Settings& settings; + + + bool on_polygon_duck_change(const synfig::Point &point, std::list::iterator iter); + + + void popup_handle_menu(synfigapp::ValueDesc value_desc); + + + void refresh_ducks(); + + Gtk::Table options_table; + Gtk::Entry entry_id; + Gtk::CheckButton checkbutton_invert; + Gtk::CheckButton checkbutton_layer_polygon; + Gtk::CheckButton checkbutton_layer_region; + Gtk::CheckButton checkbutton_layer_outline; + Gtk::CheckButton checkbutton_layer_curve_gradient; + Gtk::CheckButton checkbutton_layer_plant; + Gtk::CheckButton checkbutton_layer_link_origins; + Gtk::Button button_make; + Gtk::Adjustment adj_feather; + Gtk::SpinButton spin_feather; + +public: + + // this counts the layers we create - they all have origins we can link + int layers_to_create()const + { + return + get_layer_polygon_flag() + + get_layer_region_flag() + + get_layer_outline_flag() + + get_layer_curve_gradient_flag() + + get_layer_plant_flag(); + } + + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + bool get_invert()const { return checkbutton_invert.get_active(); } + void set_invert(bool i) { checkbutton_invert.set_active(i); } + + bool get_layer_polygon_flag()const { return checkbutton_layer_polygon.get_active(); } + void set_layer_polygon_flag(bool x) { return checkbutton_layer_polygon.set_active(x); } + + bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } + void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } + + bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } + void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } + + bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } + void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } + + bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } + void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } + + bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } + void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } + + Real get_feather() const { return adj_feather.get_value(); } + void set_feather(Real x) { return adj_feather.set_value(x); } + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + void refresh_tool_options(); + + StatePolygon_Context(CanvasView* canvas_view); + + ~StatePolygon_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 on_user_click(synfig::Point point); + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + + void run(); +}; // END of class StatePolygon_Context + +/* === M E T H O D S ======================================================= */ + +StatePolygon::StatePolygon(): + Smach::state("polygon") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StatePolygon_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_STOP,&StatePolygon_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StatePolygon_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StatePolygon_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StatePolygon_Context::event_mouse_click_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StatePolygon_Context::event_refresh_tool_options)); +} + +StatePolygon::~StatePolygon() +{ +} + +void +StatePolygon_Context::load_settings() +{ + String value; + + if(settings.get_value("polygon.id",value)) + set_id(value); + else + set_id("Polygon"); + + if(settings.get_value("polygon.invert",value) && value != "0") + set_invert(true); + else + set_invert(false); + + if(settings.get_value("polygon.layer_polygon",value) && value=="0") + set_layer_polygon_flag(false); + else + set_layer_polygon_flag(true); + + if(settings.get_value("polygon.layer_region",value) && value=="1") + set_layer_region_flag(true); + else + set_layer_region_flag(false); + + if(settings.get_value("polygon.layer_outline",value) && value=="1") + set_layer_outline_flag(true); + else + set_layer_outline_flag(false); + + if(settings.get_value("polygon.layer_curve_gradient",value) && value=="1") + set_layer_curve_gradient_flag(true); + else + set_layer_curve_gradient_flag(false); + + if(settings.get_value("polygon.layer_plant",value) && value=="1") + set_layer_plant_flag(true); + else + set_layer_plant_flag(false); + + if(settings.get_value("polygon.layer_link_origins",value) && value=="0") + set_layer_link_origins_flag(false); + else + set_layer_link_origins_flag(true); + + if(settings.get_value("polygon.feather",value)) + { + Real n = atof(value.c_str()); + set_feather(n); + } +} + +void +StatePolygon_Context::save_settings() +{ + settings.set_value("polygon.id",get_id().c_str()); + settings.set_value("polygon.invert",get_invert()?"1":"0"); + settings.set_value("polygon.layer_polygon",get_layer_polygon_flag()?"1":"0"); + settings.set_value("polygon.layer_outline",get_layer_outline_flag()?"1":"0"); + settings.set_value("polygon.layer_region",get_layer_region_flag()?"1":"0"); + settings.set_value("polygon.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); + settings.set_value("polygon.layer_plant",get_layer_plant_flag()?"1":"0"); + settings.set_value("polygon.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); + settings.set_value("polygon.feather",strprintf("%f",get_feather())); +} + +void +StatePolygon_Context::reset() +{ + polygon_point_list.clear(); + refresh_ducks(); +} + +void +StatePolygon_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Polygon"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + String str_number; + str_number=String(id,id.size()-digits,id.size()); + id=String(id,0,id.size()-digits); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StatePolygon_Context::StatePolygon_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + duckmatic_push(get_work_area()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), + checkbutton_invert(_("Invert")), + checkbutton_layer_polygon(_("Create Polygon Layer")), + checkbutton_layer_region(_("Create Region BLine")), + checkbutton_layer_outline(_("Create Outline BLine")), + checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), + checkbutton_layer_plant(_("Create Plant BLine")), + checkbutton_layer_link_origins(_("Link Origins")), + button_make(_("Make")), + adj_feather(0,0,10000,0.01,0.1), + spin_feather(adj_feather,0.01,4) +{ + egress_on_selection_change=true; + load_settings(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Polygon 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_layer_polygon, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //invert flag + options_table.attach(checkbutton_invert, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //feather stuff + options_table.attach(*manage(new Gtk::Label(_("Feather"))), 0, 1, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_feather, 1, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //options_table.attach(button_make, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + button_make.signal_pressed().connect(sigc::mem_fun(*this,&StatePolygon_Context::run)); + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_work_area()->set_cursor(Gdk::CROSSHAIR); + + // Hide the tables if they are showing + prev_table_status=get_canvas_view()->tables_are_visible(); + if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_user_click)); + + App::toolbox->refresh(); +} + +void +StatePolygon_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + + App::dialog_tool_options->set_local_name(_("Polygon Tool")); + App::dialog_tool_options->set_name("polygon"); + + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-execute"), + _("Make Polygon") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &StatePolygon_Context::run + ) + ); + + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-clear"), + _("Clear current Polygon") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &StatePolygon_Context::reset + ) + ); +} + +Smach::event_result +StatePolygon_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StatePolygon_Context::~StatePolygon_Context() +{ + run(); + + save_settings(); + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + + App::dialog_tool_options->clear(); + + get_work_area()->reset_cursor(); + + // Enable the time bar + get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + App::toolbox->refresh(); +} + +Smach::event_result +StatePolygon_Context::event_stop_handler(const Smach::event& /*x*/) +{ + synfig::info("STATE RotoPolygon: Received Stop Event"); + //throw Smach::egress_exception(); + reset(); + return Smach::RESULT_ACCEPT; + +} + +Smach::event_result +StatePolygon_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + synfig::info("STATE RotoPolygon: Received Refresh Event"); + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StatePolygon_Context::run() +{ + if(polygon_point_list.empty()) + return; + + if(polygon_point_list.size()<3) + { + get_canvas_view()->get_ui_interface()->error("You need at least 3 points to create a polygon"); + return; + } + + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Polygon")); + + Layer::Handle layer; + + Canvas::Handle canvas; + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + + const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); + + std::vector new_list; + std::list::iterator iter; + int i; + for(i=0,iter=polygon_point_list.begin();iter!=polygon_point_list.end();++iter,++i) + { + *iter = transform.unperform(*iter); + new_list.push_back(*(new BLinePoint)); + new_list[i].set_width(1); + new_list[i].set_vertex(*iter); + new_list[i].set_tangent(Point(0,0)); + } + + ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); + assert(value_node_bline); + + ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector())); + assert(value_node_origin); + + // Set the looping flag + value_node_bline->set_loop(true); + + if(!canvas) + canvas=get_canvas_view()->get_canvas(); + + value_node_bline->set_member_canvas(canvas); + + // count how many layers we're going to be creating + int layers_to_create = this->layers_to_create(); + + /////////////////////////////////////////////////////////////////////////// + // P O L Y G O N + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_polygon_flag()) + { + layer=get_canvas_interface()->add_layer_to("polygon",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + if(get_feather()) + { + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + } + + layer->set_description(get_id()); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->disconnect_dynamic_param("vector_list"); + if(!layer->set_param("vector_list",polygon_point_list)) + { + group.cancel(); + get_canvas_view()->get_ui_interface()->error("Unable to set layer parameter"); + return; + } + + { + synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescConvert")); + synfigapp::ValueDesc value_desc(layer,"vector_list"); + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_desc",value_desc); + action->set_param("type","dynamic_list"); + action->set_param("time",get_canvas_interface()->get_time()); + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + group.cancel(); + get_canvas_view()->get_ui_interface()->error("Unable to execute action \"ValueDescConvert\""); + return; + } + } + + // only link the polygon's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create Polygon layer")); + group.cancel(); + throw String(_("Unable to create Polygon layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // C U R V E G R A D I E N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_curve_gradient_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Gradient")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + + // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // P L A N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_plant_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Plant")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + + // only link the plant's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // R E G I O N + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_region_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Region")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm + // using 2 separate ones. + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + + // only link the region's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // O U T L I N E + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_outline_flag()) + { + Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Outline")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + + // only link the outline's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + } + + egress_on_selection_change=false; + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + //post clean up stuff... + reset(); + increment_id(); +} + +Smach::event_result +StatePolygon_Context::event_mouse_click_handler(const Smach::event& x) +{ + synfig::info("STATE ROTOPOLYGON: Received mouse button down Event"); + const EventMouse& event(*reinterpret_cast(&x)); + switch(event.button) + { + case BUTTON_LEFT: + polygon_point_list.push_back(get_work_area()->snap_point_to_grid(event.pos)); + refresh_ducks(); + return Smach::RESULT_ACCEPT; + + default: + return Smach::RESULT_OK; + } +} + + +void +StatePolygon_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); + + if(polygon_point_list.empty()) return; + + std::list::iterator iter=polygon_point_list.begin(); + + etl::handle duck; + duck=new WorkArea::Duck(*iter); + duck->set_editable(true); + duck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter) + ); + duck->signal_user_click(0).connect(sigc::mem_fun(*this,&StatePolygon_Context::run)); + + get_work_area()->add_duck(duck); + + for(++iter;iter!=polygon_point_list.end();++iter) + { + etl::handle bezier(new WorkArea::Bezier()); + bezier->p1=bezier->c1=duck; + + duck=new WorkArea::Duck(*iter); + duck->set_editable(true); + duck->set_name(strprintf("%x",&*iter)); + duck->signal_edited().connect( + sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter) + ); + + get_work_area()->add_duck(duck); + + bezier->p2=bezier->c2=duck; + get_work_area()->add_bezier(bezier); + } + get_work_area()->queue_draw(); +} + + +bool +StatePolygon_Context::on_polygon_duck_change(const synfig::Point &point, std::list::iterator iter) +{ + *iter=point; + return true; +} diff --git a/synfig-studio/src/gui/states/state_polygon.h b/synfig-studio/src/gui/states/state_polygon.h new file mode 100644 index 0000000..c633c4e --- /dev/null +++ b/synfig-studio/src/gui/states/state_polygon.h @@ -0,0 +1,55 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_polygon.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H +#define __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StatePolygon_Context; + +class StatePolygon : public Smach::state +{ +public: + StatePolygon(); + ~StatePolygon(); +}; // END of class StatePolygon + +extern StatePolygon state_polygon; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_rectangle.cpp b/synfig-studio/src/gui/states/state_rectangle.cpp new file mode 100644 index 0000000..4f3eccb --- /dev/null +++ b/synfig-studio/src/gui/states/state_rectangle.cpp @@ -0,0 +1,875 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_rectangle.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include "state_rectangle.h" +#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 "duck.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateRectangle studio::state_rectangle; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateRectangle_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + Duckmatic::Push duckmatic_push; + + Point point_holder; + + etl::handle point2_duck; + + void refresh_ducks(); + + bool prev_workarea_layer_status_; + + //Toolbox settings + synfigapp::Settings& settings; + + //Toolbox display + Gtk::Table options_table; + + Gtk::Entry entry_id; //what to name the layer + + Gtk::Adjustment adj_expand; + Gtk::Adjustment adj_feather; + Gtk::SpinButton spin_expand; + Gtk::SpinButton spin_feather; + + Gtk::CheckButton checkbutton_invert; + Gtk::CheckButton checkbutton_layer_rectangle; + Gtk::CheckButton checkbutton_layer_region; + Gtk::CheckButton checkbutton_layer_outline; + Gtk::CheckButton checkbutton_layer_curve_gradient; + Gtk::CheckButton checkbutton_layer_plant; + Gtk::CheckButton checkbutton_layer_link_origins; + +public: + + // this only counts the layers which use blines - they're the only + // ones we link the origins for + int layers_to_create()const + { + return + get_layer_region_flag() + + get_layer_outline_flag() + + get_layer_curve_gradient_flag() + + get_layer_plant_flag(); + } + + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + Real get_expand()const { return adj_expand.get_value(); } + void set_expand(Real f) { adj_expand.set_value(f); } + + Real get_feather()const { return adj_feather.get_value(); } + void set_feather(Real f) { adj_feather.set_value(f); } + + bool get_invert()const { return checkbutton_invert.get_active(); } + void set_invert(bool i) { checkbutton_invert.set_active(i); } + + bool get_layer_rectangle_flag()const { return checkbutton_layer_rectangle.get_active(); } + void set_layer_rectangle_flag(bool x) { return checkbutton_layer_rectangle.set_active(x); } + + bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } + void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } + + bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } + void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } + + bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } + void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } + + bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } + void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } + + bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } + void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } + + void refresh_tool_options(); //to refresh the toolbox + + //events + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + //constructor destructor + StateRectangle_Context(CanvasView* canvas_view); + ~StateRectangle_Context(); + + //Canvas interaction + 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();} + + //Modifying settings etc. + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + + void make_rectangle(const Point& p1, const Point& p2); + +}; // END of class StateGradient_Context + +/* === M E T H O D S ======================================================= */ + +StateRectangle::StateRectangle(): + Smach::state("rectangle") +{ + insert(event_def(EVENT_STOP,&StateRectangle_Context::event_stop_handler)); + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateRectangle_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_REFRESH,&StateRectangle_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateRectangle_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateRectangle_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateRectangle_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateRectangle_Context::event_mouse_click_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRectangle_Context::event_refresh_tool_options)); +} + +StateRectangle::~StateRectangle() +{ +} + +void +StateRectangle_Context::load_settings() +{ + String value; + + //parse the arguments yargh! + if(settings.get_value("rectangle.id",value)) + set_id(value); + else + set_id("Rectangle"); + + if(settings.get_value("rectangle.expand",value)) + set_expand(atof(value.c_str())); + else + set_expand(0); + + if(settings.get_value("rectangle.feather",value)) + set_feather(atof(value.c_str())); + else + set_feather(0); + + if(settings.get_value("rectangle.invert",value) && value != "0") + set_invert(true); + else + set_invert(false); + + if(settings.get_value("rectangle.layer_rectangle",value) && value=="0") + set_layer_rectangle_flag(false); + else + set_layer_rectangle_flag(true); + + if(settings.get_value("rectangle.layer_region",value) && value=="1") + set_layer_region_flag(true); + else + set_layer_region_flag(false); + + if(settings.get_value("rectangle.layer_outline",value) && value=="1") + set_layer_outline_flag(true); + else + set_layer_outline_flag(false); + + if(settings.get_value("rectangle.layer_curve_gradient",value) && value=="1") + set_layer_curve_gradient_flag(true); + else + set_layer_curve_gradient_flag(false); + + if(settings.get_value("rectangle.layer_plant",value) && value=="1") + set_layer_plant_flag(true); + else + set_layer_plant_flag(false); + + if(settings.get_value("rectangle.layer_link_origins",value) && value=="0") + set_layer_link_origins_flag(false); + else + set_layer_link_origins_flag(true); +} + +void +StateRectangle_Context::save_settings() +{ + settings.set_value("rectangle.id",get_id().c_str()); + settings.set_value("rectangle.expand",strprintf("%f",get_expand())); + settings.set_value("rectangle.feather",strprintf("%f",(float)get_feather())); + settings.set_value("rectangle.invert",get_invert()?"1":"0"); + settings.set_value("rectangle.layer_rectangle",get_layer_rectangle_flag()?"1":"0"); + settings.set_value("rectangle.layer_outline",get_layer_outline_flag()?"1":"0"); + settings.set_value("rectangle.layer_region",get_layer_region_flag()?"1":"0"); + settings.set_value("rectangle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); + settings.set_value("rectangle.layer_plant",get_layer_plant_flag()?"1":"0"); + settings.set_value("rectangle.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); +} + +void +StateRectangle_Context::reset() +{ + refresh_ducks(); +} + +void +StateRectangle_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Rectangle"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + String str_number; + str_number=String(id,id.size()-digits,id.size()); + id=String(id,0,id.size()-digits); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StateRectangle_Context::StateRectangle_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + duckmatic_push(get_work_area()), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), + adj_expand(0,0,1,0.01,0.1), + adj_feather(0,0,1,0.01,0.1), + spin_expand(adj_expand,0.1,3), + spin_feather(adj_feather,0.1,3), + checkbutton_invert(_("Invert")), + checkbutton_layer_rectangle(_("Create Rectangle Layer")), + checkbutton_layer_region(_("Create Region BLine")), + checkbutton_layer_outline(_("Create Outline BLine")), + checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), + checkbutton_layer_plant(_("Create Plant BLine")), + checkbutton_layer_link_origins(_("Link BLine Origins")) +{ + egress_on_selection_change=true; + load_settings(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Rectangle 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_layer_rectangle, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //invert flag + options_table.attach(checkbutton_invert, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //expand stuff + options_table.attach(*manage(new Gtk::Label(_("Expansion:"))), 0, 1, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_expand, 1, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //feather stuff + options_table.attach(*manage(new Gtk::Label(_("Feather:"))), 0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_feather, 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.show_all(); + + //App::dialog_tool_options->set_widget(options_table); + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_work_area()->set_cursor(Gdk::DOTBOX); + + // Hide the tables if they are showing + //prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateRectangle_Context::on_user_click)); + + App::toolbox->refresh(); +} + +void +StateRectangle_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Rectangle Tool")); + App::dialog_tool_options->set_name("rectangle"); +} + +Smach::event_result +StateRectangle_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateRectangle_Context::~StateRectangle_Context() +{ + save_settings(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + //if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_canvas_view()->queue_rebuild_ducks(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateRectangle_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateRectangle_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StateRectangle_Context::make_rectangle(const Point& _p1, const Point& _p2) +{ + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Rectangle")); + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer; + + Canvas::Handle canvas; + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + + const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); + const Point p1(transform.unperform(_p1)); + const Point p2(transform.unperform(_p2)); + Real x_min, x_max, y_min, y_max; + if (p1[0] < p2[0]) { x_min = p1[0]; x_max = p2[0]; } else { x_min = p2[0]; x_max = p1[0]; } + if (p1[1] < p2[1]) { y_min = p1[1]; y_max = p2[1]; } else { y_min = p2[1]; y_max = p1[1]; } + x_min -= get_expand(); x_max += get_expand(); y_min -= get_expand(); y_max += get_expand(); + + std::vector new_list; + for (int i = 0; i < 4; i++) + { + new_list.push_back(*(new BLinePoint)); + new_list[i].set_width(1); + new_list[i].set_vertex(Point((i==0||i==3)?x_min:x_max, + (i==0||i==1)?y_min:y_max)); + new_list[i].set_tangent(Point(0,0)); + } + + ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); + assert(value_node_bline); + + ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector())); + assert(value_node_origin); + + // Set the looping flag + value_node_bline->set_loop(true); + + if(!canvas) + canvas=get_canvas_view()->get_canvas(); + + value_node_bline->set_member_canvas(canvas); + + // count how many layers we're going to be creating + int layers_to_create = this->layers_to_create(); + + /////////////////////////////////////////////////////////////////////////// + // R E C T A N G L E + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_rectangle_flag()) + { + layer=get_canvas_interface()->add_layer_to("rectangle",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + + layer->set_param("point1",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"point1"); + + layer->set_param("point2",p2); + get_canvas_interface()->signal_layer_param_changed()(layer,"point2"); + + layer->set_param("expand",get_expand()); + get_canvas_interface()->signal_layer_param_changed()(layer,"expand"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + layer->set_description(get_id()); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + } + + /////////////////////////////////////////////////////////////////////////// + // C U R V E G R A D I E N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_curve_gradient_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Gradient")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + + // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // P L A N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_plant_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Plant")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + + // only link the plant's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // R E G I O N + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_region_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Region")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm + // using 2 separate ones. + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + + // only link the region's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // O U T L I N E + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_outline_flag()) + { + Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Outline")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + + // only link the outline's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + } + + egress_on_selection_change=false; + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + //post clean up stuff... + reset(); + increment_id(); +} + +Smach::event_result +StateRectangle_Context::event_mouse_click_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) + { + point_holder=get_work_area()->snap_point_to_grid(event.pos); + etl::handle duck=new Duck(); + duck->set_point(point_holder); + duck->set_name("p1"); + duck->set_type(Duck::TYPE_POSITION); + get_work_area()->add_duck(duck); + + point2_duck=new Duck(); + point2_duck->set_point(point_holder); + point2_duck->set_name("p2"); + point2_duck->set_type(Duck::TYPE_POSITION); + point2_duck->set_box_duck(duck); + get_work_area()->add_duck(point2_duck); + + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) + { + if (!point2_duck) return Smach::RESULT_OK; + point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos)); + get_work_area()->queue_draw(); + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) + { + make_rectangle(point_holder, get_work_area()->snap_point_to_grid(event.pos)); + get_work_area()->clear_ducks(); + return Smach::RESULT_ACCEPT; + } + + return Smach::RESULT_OK; +} + + +void +StateRectangle_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); +} diff --git a/synfig-studio/src/gui/states/state_rectangle.h b/synfig-studio/src/gui/states/state_rectangle.h new file mode 100644 index 0000000..131dd40 --- /dev/null +++ b/synfig-studio/src/gui/states/state_rectangle.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_rectangle.h +** \brief Rectangle creation state +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_RECTANGLE_H +#define __SYNFIG_STUDIO_STATE_RECTANGLE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateRectangle_Context; + +class StateRectangle : public Smach::state +{ +public: + StateRectangle(); + ~StateRectangle(); +}; // END of class StateRectangle + +extern StateRectangle state_rectangle; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_rotate.cpp b/synfig-studio/src/gui/states/state_rotate.cpp new file mode 100644 index 0000000..5463a41 --- /dev/null +++ b/synfig-studio/src/gui/states/state_rotate.cpp @@ -0,0 +1,398 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_rotate.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include + +#include "state_rotate.h" +#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 "duck.h" +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +#ifndef EPSILON +#define EPSILON 0.0000001 +#endif + +/* === G L O B A L S ======================================================= */ + +StateRotate studio::state_rotate; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_Rotate : public DuckDrag_Base +{ + + synfig::Vector last_rotate; + synfig::Vector drag_offset; + synfig::Vector center; + synfig::Vector snap; + + Angle original_angle; + Real original_mag; + + std::vector positions; + + + bool bad_drag; + bool move_only; + +public: + etl::handle canvas_view_; + bool use_magnitude; + DuckDrag_Rotate(); + 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); + + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} +}; + + +class studio::StateRotate_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + synfigapp::Settings& settings; + + etl::handle duck_dragger_; + + Gtk::Table options_table; + + Gtk::CheckButton checkbutton_scale; + +public: + + bool get_scale_flag()const { return checkbutton_scale.get_active(); } + void set_scale_flag(bool x) { return checkbutton_scale.set_active(x); refresh_scale_flag(); } + + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + void refresh_tool_options(); + + void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->use_magnitude=get_scale_flag(); } + + StateRotate_Context(CanvasView* canvas_view); + + ~StateRotate_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(); +}; // END of class StateRotate_Context + +/* === M E T H O D S ======================================================= */ + +StateRotate::StateRotate(): + Smach::state("rotate") +{ + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRotate_Context::event_refresh_tool_options)); + insert(event_def(EVENT_STOP,&StateRotate_Context::event_stop_handler)); +} + +StateRotate::~StateRotate() +{ +} + +void +StateRotate_Context::load_settings() +{ + String value; + + if(settings.get_value("rotate.scale",value) && value=="0") + set_scale_flag(false); + else + set_scale_flag(true); +} + +void +StateRotate_Context::save_settings() +{ + settings.set_value("rotate.scale",get_scale_flag()?"1":"0"); +} + +StateRotate_Context::StateRotate_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + settings(synfigapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_Rotate()), + checkbutton_scale(_("Allow Scale")) +{ + duck_dragger_->canvas_view_=get_canvas_view(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Rotate Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_scale, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateRotate_Context::refresh_scale_flag)); + + options_table.show_all(); + refresh_tool_options(); + //App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + + get_work_area()->set_cursor(Gdk::EXCHANGE); +// get_work_area()->reset_cursor(); + + App::toolbox->refresh(); + + load_settings(); + refresh_scale_flag(); +} + +void +StateRotate_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Rotate Tool")); + App::dialog_tool_options->set_name("rotate"); +} + +Smach::event_result +StateRotate_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateRotate_Context::event_stop_handler(const Smach::event& /*x*/) +{ + throw &state_normal; + return Smach::RESULT_OK; +} + +StateRotate_Context::~StateRotate_Context() +{ + save_settings(); + + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + + + + +DuckDrag_Rotate::DuckDrag_Rotate() +{ + use_magnitude=true; +} + +void +DuckDrag_Rotate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) +{ + last_rotate=Vector(1,1); + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + +/* + if(duckmatic->get_selected_ducks().size()<2) + { + bad_drag=true; + return; + } +*/ + bad_drag=false; + + drag_offset=duckmatic->find_duck(offset)->get_trans_point(); + + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset; + snap=Vector(0,0); + + // 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++) + { + 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; + + + synfig::Vector vect(offset-center); + original_angle=Angle::tan(vect[1],vect[0]); + original_mag=vect.mag(); +} + + +void +DuckDrag_Rotate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + if(bad_drag) + return; + + //std::set >::iterator iter; + synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center+snap); + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + if(move_only) + { + int i; + 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; + + Vector p(positions[i]); + + p[0]+=vect[0]; + p[1]+=vect[1]; + (*iter)->set_trans_point(p); + } + 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; + + Vector p(positions[i]); + + p[0]+=vect[0]; + p[1]+=vect[1]; + (*iter)->set_trans_point(p); + } + return; + } + + Angle::tan angle(vect[1],vect[0]); + angle=original_angle-angle; + Real mag(vect.mag()/original_mag); + Real sine(Angle::sin(angle).get()); + Real cosine(Angle::cos(angle).get()); + + int i; + 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; + + Vector x(positions[i]-center),p; + + p[0]=cosine*x[0]+sine*x[1]; + p[1]=-sine*x[0]+cosine*x[1]; + if(use_magnitude)p*=mag; + p+=center; + (*iter)->set_trans_point(p); + } + 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; + + Vector x(positions[i]-center),p; + + p[0]=cosine*x[0]+sine*x[1]; + p[1]=-sine*x[0]+cosine*x[1]; + if(use_magnitude)p*=mag; + p+=center; + (*iter)->set_trans_point(p); + } + + last_rotate=vect; + //snap=Vector(0,0); +} + +bool +DuckDrag_Rotate::end_duck_drag(Duckmatic* duckmatic) +{ + if(bad_drag)return false; + if(move_only) + { + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Move Duck")); + duckmatic->signal_edited_selected_ducks(); + return true; + } + + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks")); + + if((last_rotate-Vector(1,1)).mag()>0.0001) + { + duckmatic->signal_edited_selected_ducks(); + return true; + } + else + { + duckmatic->signal_user_click_selected_ducks(0); + return false; + } +} diff --git a/synfig-studio/src/gui/states/state_rotate.h b/synfig-studio/src/gui/states/state_rotate.h new file mode 100644 index 0000000..e2caafe --- /dev/null +++ b/synfig-studio/src/gui/states/state_rotate.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_rotate.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_ROTATE_H +#define __SYNFIG_STUDIO_STATE_ROTATE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateRotate_Context; + +class StateRotate : public Smach::state +{ +public: + StateRotate(); + ~StateRotate(); +}; // END of class StateRotate + +extern StateRotate state_rotate; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_scale.cpp b/synfig-studio/src/gui/states/state_scale.cpp new file mode 100644 index 0000000..edfb89b --- /dev/null +++ b/synfig-studio/src/gui/states/state_scale.cpp @@ -0,0 +1,389 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_scale.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include + +#include "state_scale.h" +#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 "duck.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateScale studio::state_scale; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_Scale : public DuckDrag_Base +{ + + synfig::Vector last_scale; + synfig::Vector drag_offset; + synfig::Vector center; + synfig::Vector snap; + + std::vector positions; + + bool move_only; + + bool bad_drag; +public: + bool lock_aspect; + DuckDrag_Scale(); + 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); +}; + + +class studio::StateScale_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + synfigapp::Settings& settings; + + etl::handle duck_dragger_; + + Gtk::Table options_table; + + + Gtk::CheckButton checkbutton_aspect_lock; + +public: + + bool get_aspect_lock_flag()const { return checkbutton_aspect_lock.get_active(); } + void set_aspect_lock_flag(bool x) { return checkbutton_aspect_lock.set_active(x); refresh_aspect_lock_flag(); } + + void refresh_aspect_lock_flag() { if(duck_dragger_)duck_dragger_->lock_aspect=get_aspect_lock_flag(); } + + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + void refresh_tool_options(); + + StateScale_Context(CanvasView* canvas_view); + + ~StateScale_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(); +}; // END of class StateScale_Context + +/* === M E T H O D S ======================================================= */ + +StateScale::StateScale(): + Smach::state("scale") +{ + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateScale_Context::event_refresh_tool_options)); + insert(event_def(EVENT_STOP,&StateScale_Context::event_stop_handler)); +} + +StateScale::~StateScale() +{ +} + +void +StateScale_Context::load_settings() +{ + String value; + + if(settings.get_value("scale.lock_aspect",value) && value=="0") + set_aspect_lock_flag(false); + else + set_aspect_lock_flag(true); +} + +void +StateScale_Context::save_settings() +{ + settings.set_value("scale.lock_aspect",get_aspect_lock_flag()?"1":"0"); +} + +StateScale_Context::StateScale_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + settings(synfigapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_Scale()), + checkbutton_aspect_lock(_("Lock Aspect Ratio")) +{ + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Scale Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_aspect_lock, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + checkbutton_aspect_lock.signal_toggled().connect(sigc::mem_fun(*this,&StateScale_Context::refresh_aspect_lock_flag)); + + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + + get_work_area()->set_cursor(Gdk::SIZING); +// get_work_area()->reset_cursor(); + + App::toolbox->refresh(); + + set_aspect_lock_flag(true); + load_settings(); +} + +void +StateScale_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Scale Tool")); + App::dialog_tool_options->set_name("scale"); +} + +Smach::event_result +StateScale_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateScale_Context::event_stop_handler(const Smach::event& /*x*/) +{ + throw &state_normal; + return Smach::RESULT_OK; +} + +StateScale_Context::~StateScale_Context() +{ + save_settings(); + + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + + + + +DuckDrag_Scale::DuckDrag_Scale(): + lock_aspect(true) +{ +} + +#ifndef EPSILON +#define EPSILON 0.0000001 +#endif + +void +DuckDrag_Scale::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) +{ + last_scale=Vector(1,1); + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + //if(duckmatic->get_selected_ducks().size()<2) + //{ + // bad_drag=true; +// return; +// } + bad_drag=false; + + drag_offset=duckmatic->find_duck(offset)->get_trans_point(); + + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset; + snap=Vector(0,0); + + // 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++) + { + 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); + } + if((vmin-vmax).mag()<=EPSILON) + move_only=true; + else + move_only=false; + + center=(vmin+vmax)*0.5; +} + + +void +DuckDrag_Scale::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + if(bad_drag) + return; + + //std::set >::iterator iter; + synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center); + last_scale=vect; + + if(move_only) + { + int i; + 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; + + Vector p(positions[i]); + + p[0]+=vect[0]; + p[1]+=vect[1]; + (*iter)->set_trans_point(p); + } + 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; + + Vector p(positions[i]); + + p[0]+=vect[0]; + p[1]+=vect[1]; + (*iter)->set_trans_point(p); + } + return; + } + + if(!lock_aspect) + { + 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 + { + //vect[0]=vect[1]=vect.mag()*0.707106781; + Real amount(vect.mag()/(drag_offset-center).mag()); + vect[0]=vect[1]=amount; + } + + if(vect[0]-EPSILON) + vect[0]=1; + if(vect[1]-EPSILON) + vect[1]=1; + + int i; + 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; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p); + } + 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; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p); + } + + last_scale=vect; + //snap=Vector(0,0); +} + +bool +DuckDrag_Scale::end_duck_drag(Duckmatic* duckmatic) +{ + if(bad_drag)return false; + + if((last_scale-Vector(1,1)).mag()>0.0001) + { + duckmatic->signal_edited_selected_ducks(); + return true; + } + else + { + duckmatic->signal_user_click_selected_ducks(0); + return false; + } +} diff --git a/synfig-studio/src/gui/states/state_scale.h b/synfig-studio/src/gui/states/state_scale.h new file mode 100644 index 0000000..f351c12 --- /dev/null +++ b/synfig-studio/src/gui/states/state_scale.h @@ -0,0 +1,55 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_scale.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_SCALE_H +#define __SYNFIG_STUDIO_STATE_SCALE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateScale_Context; + +class StateScale : public Smach::state +{ +public: + StateScale(); + ~StateScale(); +}; // END of class StateScale + +extern StateScale state_scale; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_sketch.cpp b/synfig-studio/src/gui/states/state_sketch.cpp new file mode 100644 index 0000000..f8b77a3 --- /dev/null +++ b/synfig-studio/src/gui/states/state_sketch.cpp @@ -0,0 +1,508 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_sketch.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include "state_sketch.h" +#include "state_normal.h" +#include "state_stroke.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" +#include +#include +#include +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" + +#include +#include + +#include + +#include "dialog_tooloptions.h" + +#include +#include +#include +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateSketch studio::state_sketch; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateSketch_Context : public sigc::trackable +{ + Glib::RefPtr action_group; + + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + bool prev_table_status; + bool prev_workarea_layer_status_; + + Gtk::Table options_table; + Gtk::Button button_clear_sketch; + Gtk::Button button_undo_stroke; + Gtk::Button button_save_sketch; + Gtk::Button button_load_sketch; + Gtk::CheckButton checkbutton_show_sketch; + + void clear_sketch(); + void save_sketch(); + void load_sketch(); + void undo_stroke(); + void toggle_show_sketch(); + +public: + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_mouse_down_handler(const Smach::event& x); + + Smach::event_result event_stroke(const Smach::event& x); + + Smach::event_result event_refresh_tool_options(const Smach::event& x); + Smach::event_result event_yield_tool_options(const Smach::event& x); + + void refresh_tool_options(); + void yield_tool_options(); + + StateSketch_Context(CanvasView* canvas_view); + + ~StateSketch_Context(); + + const etl::handle& get_canvas_view()const{return canvas_view_;} + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} + synfig::Time get_time()const { return get_canvas_interface()->get_time(); } + synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} + WorkArea * get_work_area()const{return canvas_view_->get_work_area();} + +}; // END of class StateSketch_Context + + +/* === M E T H O D S ======================================================= */ + +StateSketch::StateSketch(): + Smach::state("sketch") +{ + insert(event_def(EVENT_STOP,&StateSketch_Context::event_stop_handler)); + //insert(event_def(EVENT_REFRESH,&StateSketch_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateSketch_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateSketch_Context::event_mouse_down_handler)); + insert(event_def(EVENT_WORKAREA_STROKE,&StateSketch_Context::event_stroke)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSketch_Context::event_refresh_tool_options)); + insert(event_def(EVENT_YIELD_TOOL_OPTIONS,&StateSketch_Context::event_yield_tool_options)); +} + +StateSketch::~StateSketch() +{ +} + +void +StateSketch_Context::save_sketch() +{ + synfig::String filename(basename(get_canvas()->get_file_name())+".sketch"); + + while(App::dialog_save_file(_("Save Sketch"), filename, SKETCH_DIR_PREFERENCE)) + { + // If the filename still has wildcards, then we should + // continue looking for the file we want + if(find(filename.begin(),filename.end(),'*')!=filename.end()) + continue; + + if(get_work_area()->save_sketch(filename)) + break; + + get_canvas_view()->get_ui_interface()->error(_("Unable to save sketch")); + } +} + +void +StateSketch_Context::load_sketch() +{ + synfig::String filename(basename(get_canvas()->get_file_name())+".sketch"); + + while(App::dialog_open_file(_("Load Sketch"), filename, SKETCH_DIR_PREFERENCE)) + { + // If the filename still has wildcards, then we should + // continue looking for the file we want + if(find(filename.begin(),filename.end(),'*')!=filename.end()) + continue; + + if(get_work_area()->load_sketch(filename)) + break; + + get_canvas_view()->get_ui_interface()->error(_("Unable to load sketch")); + } + get_work_area()->queue_draw(); +} + +void +StateSketch_Context::clear_sketch() +{ + get_work_area()->clear_persistent_strokes(); + + // if the sketch is currently shown, make sure it is updated + //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_? + if (checkbutton_show_sketch.get_active()) + { + get_work_area()->set_show_persistent_strokes(false); + get_work_area()->set_show_persistent_strokes(true); + get_canvas_view()->get_smach().process_event(EVENT_REFRESH); + } +} + +void +StateSketch_Context::undo_stroke() +{ + if(!get_work_area()->persistent_stroke_list().empty()) + { + get_work_area()->persistent_stroke_list().pop_back(); + + // if the sketch is currently shown, make sure it is updated + //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_? + if (checkbutton_show_sketch.get_active()) + { + get_work_area()->set_show_persistent_strokes(false); + get_work_area()->set_show_persistent_strokes(true); + get_canvas_view()->get_smach().process_event(EVENT_REFRESH); + } + } +} + +void +StateSketch_Context::toggle_show_sketch() +{ + get_work_area()->set_show_persistent_strokes(checkbutton_show_sketch.get_active()); + get_work_area()->queue_draw(); +} + +StateSketch_Context::StateSketch_Context(CanvasView* canvas_view): + action_group(Gtk::ActionGroup::create("action_group_state_sketch")), + canvas_view_(canvas_view), + is_working(*canvas_view), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + button_clear_sketch(_("Clear Sketch")), + button_undo_stroke(_("Undo Stroke")), + button_save_sketch(_("Save Sketch")), + button_load_sketch(_("Load Sketch")), + checkbutton_show_sketch(_("Show Sketch")) +{ + Glib::ustring ui_info = + "" + " " + " " + " " + " " + " " + " " + ""; + + action_group->add(Gtk::Action::create( + "sketch-undo", + Gtk::StockID("gtk-undo"), + _("Undo Last Stroke"), + _("Undo Last Stroke") + ), + sigc::mem_fun( + *this, + &studio::StateSketch_Context::undo_stroke + ) + ); + + action_group->add(Gtk::Action::create( + "sketch-clear", + Gtk::StockID("gtk-clear"), + _("Clear Sketch"), + _("Clear Sketch") + ), + sigc::mem_fun( + *this, + &studio::StateSketch_Context::clear_sketch + ) + ); + + action_group->add(Gtk::Action::create( + "sketch-save-as", + Gtk::StockID("gtk-save-as"), + _("Save Sketch As..."), + _("Save Sketch As...") + ), + sigc::mem_fun( + *this, + &studio::StateSketch_Context::save_sketch + ) + ); + + action_group->add(Gtk::Action::create( + "sketch-save-as", + Gtk::StockID("gtk-save-as"), + _("Save Sketch As..."), + _("Save Sketch As...") + ), + sigc::mem_fun( + *this, + &studio::StateSketch_Context::save_sketch + ) + ); + + action_group->add(Gtk::Action::create( + "sketch-open", + Gtk::StockID("gtk-open"), + _("Open a Sketch"), + _("Open a Sketch") + ), + sigc::mem_fun( + *this, + &studio::StateSketch_Context::load_sketch + ) + ); + + action_group->add( Gtk::Action::create("toolbar-sketch", "Sketch Toolbar") ); + + App::ui_manager()->add_ui_from_string(ui_info); + + checkbutton_show_sketch.set_active(get_work_area()->get_show_persistent_strokes()); + + button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch)); + button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke)); + button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch)); + button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch)); + checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch)); + + options_table.attach(*manage(new Gtk::Label(_("Sketch Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_show_sketch, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + //options_table.attach(button_undo_stroke, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + //options_table.attach(button_clear_sketch, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + //options_table.attach(button_save_sketch, 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + //options_table.attach(button_load_sketch, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + get_work_area()->set_cursor(Gdk::PENCIL); + + // Turn off duck clicking + get_work_area()->set_allow_duck_clicks(false); + + // clear out the ducks + //get_work_area()->clear_ducks(); + + // Refresh the work area + //get_work_area()->queue_draw(); + + // Hide the tables if they are showing + prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::on_user_click)); + + App::toolbox->refresh(); +} + +StateSketch_Context::~StateSketch_Context() +{ + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + + // Restore duck clicking + get_work_area()->set_allow_duck_clicks(true); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + //get_work_area()->queue_draw(); + + App::toolbox->refresh(); +} + +void +StateSketch_Context::yield_tool_options() +{ + App::dialog_tool_options->clear(); + App::ui_manager()->remove_action_group(action_group); +} + +void +StateSketch_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Sketch Tool")); + App::dialog_tool_options->set_name("sketch"); + + App::ui_manager()->insert_action_group(action_group); + App::dialog_tool_options->set_toolbar(*dynamic_cast(App::ui_manager()->get_widget("/toolbar-sketch"))); + + /* + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-undo"), + _("Undo Last Stroke") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &studio::StateSketch_Context::undo_stroke + ) + ); + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-clear"), + _("Clear Sketch") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &studio::StateSketch_Context::clear_sketch + ) + ); + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-save"), + _("Save Sketch to a File") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &studio::StateSketch_Context::save_sketch + ) + ); + + App::dialog_tool_options->add_button( + Gtk::StockID("gtk-open"), + _("Open a Sketch") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &studio::StateSketch_Context::load_sketch + ) + ); + */ + //button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch)); + //button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke)); + //button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch)); + //button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch)); + //checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch)); +} + +Smach::event_result +StateSketch_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateSketch_Context::event_yield_tool_options(const Smach::event& /*x*/) +{ + yield_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateSketch_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateSketch_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateSketch_Context::event_mouse_down_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + switch(event.button) + { + case BUTTON_LEFT: + { + // Enter the stroke state to get the stroke + get_canvas_view()->get_smach().push_state(&state_stroke); + return Smach::RESULT_ACCEPT; + } + + default: + return Smach::RESULT_OK; + } +} + +Smach::event_result +StateSketch_Context::event_stroke(const Smach::event& x) +{ + const EventStroke& event(*reinterpret_cast(&x)); + + assert(event.stroke_data); + + get_work_area()->add_persistent_stroke(event.stroke_data,synfigapp::Main::get_outline_color()); + + return Smach::RESULT_ACCEPT; +} diff --git a/synfig-studio/src/gui/states/state_sketch.h b/synfig-studio/src/gui/states/state_sketch.h new file mode 100644 index 0000000..301c81d --- /dev/null +++ b/synfig-studio/src/gui/states/state_sketch.h @@ -0,0 +1,55 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_sketch.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_SKETCH_H +#define __SYNFIG_STUDIO_STATE_SKETCH_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateSketch_Context; + +class StateSketch : public Smach::state +{ +public: + StateSketch(); + ~StateSketch(); +}; // END of class StateSketch + +extern StateSketch state_sketch; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_smoothmove.cpp b/synfig-studio/src/gui/states/state_smoothmove.cpp new file mode 100644 index 0000000..f42df35 --- /dev/null +++ b/synfig-studio/src/gui/states/state_smoothmove.cpp @@ -0,0 +1,388 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_smoothmove.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 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 +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include +#include + +#include "state_smoothmove.h" +#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 "duck.h" +#include "onemoment.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateSmoothMove studio::state_smooth_move; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_SmoothMove : public DuckDrag_Base +{ + float radius; + + synfig::Vector last_translate_; + synfig::Vector drag_offset_; + synfig::Vector snap; + + std::vector last_; + std::vector positions; + +public: + DuckDrag_SmoothMove(); + 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); + + void set_radius(float x) { radius=x; } + float get_radius()const { return radius; } +}; + + +class studio::StateSmoothMove_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + //Duckmatic::Push duckmatic_push; + + synfigapp::Settings& settings; + + etl::handle duck_dragger_; + + Gtk::Table options_table; + + Gtk::Adjustment adj_radius; + Gtk::SpinButton spin_radius; + + float pressure; + +public: + float get_radius()const { return adj_radius.get_value(); } + void set_radius(float x) { return adj_radius.set_value(x); } + + void refresh_radius() { duck_dragger_->set_radius(get_radius()*pressure); } + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + void refresh_tool_options(); + + StateSmoothMove_Context(CanvasView* canvas_view); + + ~StateSmoothMove_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(); +}; // END of class StateSmoothMove_Context + +/* === M E T H O D S ======================================================= */ + +StateSmoothMove::StateSmoothMove(): + Smach::state("smooth_move") +{ + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSmoothMove_Context::event_refresh_tool_options)); + insert(event_def(EVENT_STOP,&StateSmoothMove_Context::event_stop_handler)); +} + +StateSmoothMove::~StateSmoothMove() +{ +} + +void +StateSmoothMove_Context::load_settings() +{ + String value; + + if(settings.get_value("smooth_move.radius",value)) + set_radius(atof(value.c_str())); + else + set_radius(1.0f); +} + +void +StateSmoothMove_Context::save_settings() +{ + settings.set_value("smooth_move.radius",strprintf("%f",get_radius())); +} + +StateSmoothMove_Context::StateSmoothMove_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), +// duckmatic_push(get_work_area()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_SmoothMove()), + adj_radius(1,0,100000,0.01,0.1), + spin_radius(adj_radius,0.1,3) +{ + pressure=1.0f; + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("SmoothMove Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Radius"))), 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_radius, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + spin_radius.signal_value_changed().connect(sigc::mem_fun(*this,&StateSmoothMove_Context::refresh_radius)); + + options_table.show_all(); + refresh_tool_options(); + //App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + + App::toolbox->refresh(); + + get_work_area()->set_cursor(Gdk::FLEUR); + //get_work_area()->reset_cursor(); + + load_settings(); +} + +void +StateSmoothMove_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Smooth Move")); + App::dialog_tool_options->set_name("smooth_move"); +} + +Smach::event_result +StateSmoothMove_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateSmoothMove_Context::event_stop_handler(const Smach::event& /*x*/) +{ + throw &state_normal; + return Smach::RESULT_OK; +} + +StateSmoothMove_Context::~StateSmoothMove_Context() +{ + save_settings(); + + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + + + + +DuckDrag_SmoothMove::DuckDrag_SmoothMove():radius(1.0f) +{ +} + +void +DuckDrag_SmoothMove::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) +{ + last_translate_=Vector(0,0); + drag_offset_=duckmatic->find_duck(offset)->get_trans_point(); + + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset_; + snap=Vector(0,0); + + last_.clear(); + positions.clear(); + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + last_.push_back(Vector(0,0)); + positions.push_back((*iter)->get_trans_point()); + } +} + +void +DuckDrag_SmoothMove::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_+snap); + + int i; + + Time time(duckmatic->get_time()); + + // process vertex and position ducks first + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + // skip this duck if it is NOT a vertex or a position + if (((*iter)->get_type() != Duck::TYPE_VERTEX && + (*iter)->get_type() != Duck::TYPE_POSITION)) + continue; + Point p(positions[i]); + + float dist(1.0f-(p-drag_offset_).mag()/get_radius()); + if(dist<0) + dist=0; + + last_[i]=vect*dist; + (*iter)->set_trans_point(p+last_[i], time); + } + + // then process non vertex and non position ducks + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + // skip this duck if it IS a vertex or a position + if (!((*iter)->get_type() != Duck::TYPE_VERTEX && + (*iter)->get_type() != Duck::TYPE_POSITION)) + continue; + Point p(positions[i]); + + float dist(1.0f-(p-drag_offset_).mag()/get_radius()); + if(dist<0) + dist=0; + + last_[i]=vect*dist; + (*iter)->set_trans_point(p+last_[i], time); + } + + // then patch up the tangents for the vertices we've moved + duckmatic->update_ducks(); + + last_translate_=vect; + //snap=Vector(0,0); +} + +bool +DuckDrag_SmoothMove::end_duck_drag(Duckmatic* duckmatic) +{ + //synfig::info("end_duck_drag(): Diff= %f",last_translate_.mag()); + if(last_translate_.mag()>0.0001) + { + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + int i; + + smart_ptr wait;if(selected_ducks.size()>20)wait.spawn(); + + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(last_[i].mag()>0.0001) + { + if ((*iter)->get_type() == Duck::TYPE_ANGLE) + { + if(!(*iter)->signal_edited_angle()((*iter)->get_rotations())) + { + throw String("Bad edit"); + } + } + else if (App::restrict_radius_ducks && + (*iter)->is_radius()) + { + Point point((*iter)->get_point()); + bool changed = false; + + if (point[0] < 0) + { + point[0] = 0; + changed = true; + } + if (point[1] < 0) + { + point[1] = 0; + changed = true; + } + + if (changed) (*iter)->set_point(point); + + if(!(*iter)->signal_edited()(point)) + { + throw String("Bad edit"); + } + } + else + { + if(!(*iter)->signal_edited()((*iter)->get_point())) + { + throw String("Bad edit"); + } + } + } + } + //duckmatic->get_selected_ducks()=new_set; + //duckmatic->refresh_selected_ducks(); + return true; + } + else + { + duckmatic->signal_user_click_selected_ducks(0); + return false; + } +} diff --git a/synfig-studio/src/gui/states/state_smoothmove.h b/synfig-studio/src/gui/states/state_smoothmove.h new file mode 100644 index 0000000..07442af --- /dev/null +++ b/synfig-studio/src/gui/states/state_smoothmove.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_smoothmove.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H +#define __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateSmoothMove_Context; + +class StateSmoothMove : public Smach::state +{ +public: + StateSmoothMove(); + ~StateSmoothMove(); +}; // END of class StateSmoothMove + +extern StateSmoothMove state_smooth_move; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_star.cpp b/synfig-studio/src/gui/states/state_star.cpp new file mode 100644 index 0000000..3be4b53 --- /dev/null +++ b/synfig-studio/src/gui/states/state_star.cpp @@ -0,0 +1,1091 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_star.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include "state_star.h" +#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 "duck.h" +#include "widgets/widget_enum.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateStar studio::state_star; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateStar_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + Duckmatic::Push duckmatic_push; + + Point point_holder; + + etl::handle point2_duck; + + void refresh_ducks(); + + bool prev_workarea_layer_status_; + + //Toolbox settings + synfigapp::Settings& settings; + + //Toolbox display + Gtk::Table options_table; + + Gtk::Entry entry_id; //what to name the layer + + Gtk::Adjustment adj_feather; + Gtk::Adjustment adj_number_of_points; + Gtk::Adjustment adj_inner_tangent; + Gtk::Adjustment adj_outer_tangent; + Gtk::Adjustment adj_inner_width; + Gtk::Adjustment adj_outer_width; + Gtk::Adjustment adj_radius_ratio; + Gtk::Adjustment adj_angle_offset; + Gtk::SpinButton spin_feather; + Gtk::SpinButton spin_number_of_points; + Gtk::SpinButton spin_inner_tangent; + Gtk::SpinButton spin_outer_tangent; + Gtk::SpinButton spin_inner_width; + Gtk::SpinButton spin_outer_width; + Gtk::SpinButton spin_radius_ratio; + Gtk::SpinButton spin_angle_offset; + + Gtk::CheckButton checkbutton_invert; + Gtk::CheckButton checkbutton_regular_polygon; + Gtk::CheckButton checkbutton_layer_star; + Gtk::CheckButton checkbutton_layer_region; + Gtk::CheckButton checkbutton_layer_outline; + Gtk::CheckButton checkbutton_layer_curve_gradient; + Gtk::CheckButton checkbutton_layer_plant; + Gtk::CheckButton checkbutton_layer_link_origins; + Gtk::CheckButton checkbutton_layer_origins_at_center; + +public: + + // this only counts the layers which will have their origins linked + int layers_to_create()const + { + return + (get_layer_star_flag() && get_layer_origins_at_center_flag()) + + get_layer_region_flag() + + get_layer_outline_flag() + + get_layer_curve_gradient_flag() + + get_layer_plant_flag(); + } + + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + Real get_feather()const { return adj_feather.get_value(); } + void set_feather(Real f) { adj_feather.set_value(f); } + + Real get_number_of_points()const { return adj_number_of_points.get_value(); } + void set_number_of_points(Real f) { adj_number_of_points.set_value(f); } + + Real get_inner_tangent()const { return adj_inner_tangent.get_value(); } + void set_inner_tangent(Real f) { adj_inner_tangent.set_value(f); } + + Real get_outer_tangent()const { return adj_outer_tangent.get_value(); } + void set_outer_tangent(Real f) { adj_outer_tangent.set_value(f); } + + Real get_inner_width()const { return adj_inner_width.get_value(); } + void set_inner_width(Real f) { adj_inner_width.set_value(f); } + + Real get_outer_width()const { return adj_outer_width.get_value(); } + void set_outer_width(Real f) { adj_outer_width.set_value(f); } + + Real get_radius_ratio()const { return adj_radius_ratio.get_value(); } + void set_radius_ratio(Real f) { adj_radius_ratio.set_value(f); } + + Real get_angle_offset()const { return adj_angle_offset.get_value(); } + void set_angle_offset(Real f) { adj_angle_offset.set_value(f); } + + bool get_invert()const { return checkbutton_invert.get_active(); } + void set_invert(bool i) { checkbutton_invert.set_active(i); } + + bool get_regular_polygon()const { return checkbutton_regular_polygon.get_active(); } + void set_regular_polygon(bool i) { checkbutton_regular_polygon.set_active(i); } + + bool get_layer_star_flag()const { return checkbutton_layer_star.get_active(); } + void set_layer_star_flag(bool x) { return checkbutton_layer_star.set_active(x); } + + bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); } + void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); } + + bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); } + void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); } + + bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); } + void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); } + + bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); } + void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); } + + bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); } + void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); } + + bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); } + void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); } + + void refresh_tool_options(); //to refresh the toolbox + + //events + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + //constructor destructor + StateStar_Context(CanvasView* canvas_view); + ~StateStar_Context(); + + //Canvas interaction + 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();} + + //Modifying settings etc. + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + + void make_star(const Point& p1, const Point& p2); + +}; // END of class StateStar_Context + +/* === M E T H O D S ======================================================= */ + +StateStar::StateStar(): + Smach::state("star") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateStar_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_STOP,&StateStar_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateStar_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateStar_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStar_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStar_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStar_Context::event_mouse_click_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStar_Context::event_refresh_tool_options)); +} + +StateStar::~StateStar() +{ +} + +void +StateStar_Context::load_settings() +{ + String value; + + //parse the arguments yargh! + if(settings.get_value("star.id",value)) + set_id(value); + else + set_id("Star"); + + if(settings.get_value("star.feather",value)) + set_feather(atof(value.c_str())); + else + set_feather(0); + + if(settings.get_value("star.number_of_points",value)) + set_number_of_points(atof(value.c_str())); + else + set_number_of_points(5); + + if(settings.get_value("star.inner_tangent",value)) + set_inner_tangent(atof(value.c_str())); + else + set_inner_tangent(0); + + if(settings.get_value("star.outer_tangent",value)) + set_outer_tangent(atof(value.c_str())); + else + set_outer_tangent(0); + + if(settings.get_value("star.inner_width",value)) + set_inner_width(atof(value.c_str())); + else + set_inner_width(1); + + if(settings.get_value("star.outer_width",value)) + set_outer_width(atof(value.c_str())); + else + set_outer_width(1); + + if(settings.get_value("star.radius_ratio",value)) + set_radius_ratio(atof(value.c_str())); + else + set_radius_ratio(0.5); + + if(settings.get_value("star.angle_offset",value)) + set_angle_offset(atof(value.c_str())); + else + set_angle_offset(0); + + if(settings.get_value("star.invert",value) && value != "0") + set_invert(true); + else + set_invert(false); + + if(settings.get_value("star.regular_polygon",value) && value != "0") + set_regular_polygon(true); + else + set_regular_polygon(false); + + if(settings.get_value("star.layer_star",value) && value=="0") + set_layer_star_flag(false); + else + set_layer_star_flag(true); + + if(settings.get_value("star.layer_region",value) && value=="1") + set_layer_region_flag(true); + else + set_layer_region_flag(false); + + if(settings.get_value("star.layer_outline",value) && value=="1") + set_layer_outline_flag(true); + else + set_layer_outline_flag(false); + + if(settings.get_value("star.layer_curve_gradient",value) && value=="1") + set_layer_curve_gradient_flag(true); + else + set_layer_curve_gradient_flag(false); + + if(settings.get_value("star.layer_plant",value) && value=="1") + set_layer_plant_flag(true); + else + set_layer_plant_flag(false); + + if(settings.get_value("star.layer_link_origins",value) && value=="0") + set_layer_link_origins_flag(false); + else + set_layer_link_origins_flag(true); + + if(settings.get_value("star.layer_origins_at_center",value) && value=="0") + set_layer_origins_at_center_flag(false); + else + set_layer_origins_at_center_flag(true); +} + +void +StateStar_Context::save_settings() +{ + settings.set_value("star.id",get_id()); + settings.set_value("star.feather",strprintf("%f",(float)get_feather())); + settings.set_value("star.number_of_points",strprintf("%d",(int)(get_number_of_points() + 0.5))); + settings.set_value("star.inner_tangent",strprintf("%f",(float)get_inner_tangent())); + settings.set_value("star.outer_tangent",strprintf("%f",(float)get_outer_tangent())); + settings.set_value("star.inner_width",strprintf("%f",(float)get_inner_width())); + settings.set_value("star.outer_width",strprintf("%f",(float)get_outer_width())); + settings.set_value("star.radius_ratio",strprintf("%f",(float)get_radius_ratio())); + settings.set_value("star.angle_offset",strprintf("%f",(float)get_angle_offset())); + settings.set_value("star.invert",get_invert()?"1":"0"); + settings.set_value("star.regular_polygon",get_regular_polygon()?"1":"0"); + settings.set_value("star.layer_star",get_layer_star_flag()?"1":"0"); + settings.set_value("star.layer_outline",get_layer_outline_flag()?"1":"0"); + settings.set_value("star.layer_region",get_layer_region_flag()?"1":"0"); + settings.set_value("star.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0"); + settings.set_value("star.layer_plant",get_layer_plant_flag()?"1":"0"); + settings.set_value("star.layer_link_origins",get_layer_link_origins_flag()?"1":"0"); + settings.set_value("star.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0"); +} + +void +StateStar_Context::reset() +{ + refresh_ducks(); +} + +void +StateStar_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Star"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + String str_number; + str_number=String(id,id.size()-digits,id.size()); + id=String(id,0,id.size()-digits); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StateStar_Context::StateStar_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + duckmatic_push(get_work_area()), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), // value lower upper step page + adj_feather( 0, 0, 1, 0.01, 0.1), + adj_number_of_points( 0, 2, 120, 1 , 1 ), + adj_inner_tangent( 0, -10, 10, 0.01, 0.1), + adj_outer_tangent( 0, -10, 10, 0.01, 0.1), + adj_inner_width( 0, -10, 10, 0.01, 0.1), + adj_outer_width( 0, -10, 10, 0.01, 0.1), + adj_radius_ratio( 0, -10, 10, 0.01, 0.1), + adj_angle_offset( 0, -360, 360, 0.1 , 1 ), + spin_feather(adj_feather,0.1,3), + spin_number_of_points(adj_number_of_points,1,0), + spin_inner_tangent(adj_inner_tangent,1,2), + spin_outer_tangent(adj_outer_tangent,1,2), + spin_inner_width(adj_inner_width,1,2), + spin_outer_width(adj_outer_width,1,2), + spin_radius_ratio(adj_radius_ratio,1,2), + spin_angle_offset(adj_angle_offset,1,1), + checkbutton_invert(_("Invert")), + checkbutton_regular_polygon(_("Regular Polygon")), + checkbutton_layer_star(_("Create Star Layer")), + checkbutton_layer_region(_("Create Region BLine")), + checkbutton_layer_outline(_("Create Outline BLine")), + checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")), + checkbutton_layer_plant(_("Create Plant BLine")), + checkbutton_layer_link_origins(_("Link Origins")), + checkbutton_layer_origins_at_center(_("BLine Origins at Center")) +{ + egress_on_selection_change=true; + + load_settings(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Star 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_layer_star, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_outline, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_region, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_plant, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_curve_gradient, 0, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_link_origins, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_layer_origins_at_center, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_invert, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_regular_polygon, 0, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Feather:"))), 0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_feather, 1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Number of Points:"))), 0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_number_of_points, 1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Inner Tangent:"))), 0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_inner_tangent, 1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Outer Tangent:"))), 0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_outer_tangent, 1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Inner Width:"))), 0, 1, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_inner_width, 1, 2, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Outer Width:"))), 0, 1, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_outer_width, 1, 2, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Radius Ratio:"))), 0, 1, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_radius_ratio, 1, 2, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Angle Offset:"))), 0, 1, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_angle_offset, 1, 2, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.show_all(); + + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + // Hide the tables if they are showing + //prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateStar_Context::on_user_click)); + get_work_area()->set_cursor(Gdk::STAR); + + App::toolbox->refresh(); +} + +void +StateStar_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Star Tool")); + App::dialog_tool_options->set_name("star"); +} + +Smach::event_result +StateStar_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateStar_Context::~StateStar_Context() +{ + save_settings(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + //if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + get_canvas_view()->queue_rebuild_ducks(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateStar_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateStar_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StateStar_Context::make_star(const Point& _p1, const Point& _p2) +{ + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Star")); + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer; + + Canvas::Handle canvas; + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + + const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); + const Point p1(transform.unperform(_p1)); + const Point p2(transform.unperform(_p2)); + + Real radius_ratio(get_radius_ratio()); + Real radius1((p2-p1).mag()); + Real radius2(radius1 * radius_ratio); + int points = get_number_of_points(); + Real inner_tangent = get_inner_tangent() * radius1; + Real outer_tangent = get_outer_tangent() * radius2; + Real inner_width = get_inner_width(); + Real outer_width = get_outer_width(); + Angle::deg offset(get_angle_offset()); + bool regular(get_regular_polygon()); + Angle::deg angle(360.0/points); + Vector origin; + Real x, y; + + if (get_layer_origins_at_center_flag()) + { + x = y = 0; + origin = p1; + } + else + { + x = p1[0]; + y = p1[1]; + } + + std::vector new_list; + int point(0); + for (int i = 0; i < points; i++) + { + new_list.push_back(*(new BLinePoint)); + new_list[point].set_width(outer_width); + new_list[point].set_vertex(Point(radius1*Angle::cos(angle*i + offset).get() + x, + radius1*Angle::sin(angle*i + offset).get() + y)); + new_list[point++].set_tangent(Point(-Angle::sin(angle*i + offset).get(), + Angle::cos(angle*i + offset).get()) * outer_tangent); + + if (!regular) + { + new_list.push_back(*(new BLinePoint)); + new_list[point].set_width(inner_width); + new_list[point].set_vertex(Point(radius2*Angle::cos(angle*i + angle/2 + offset).get() + x, + radius2*Angle::sin(angle*i + angle/2 + offset).get() + y)); + new_list[point++].set_tangent(Point(-Angle::sin(angle*i + angle/2 + offset).get(), + Angle::cos(angle*i + angle/2 + offset).get()) * inner_tangent); + } + } + + ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list)); + assert(value_node_bline); + + ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin)); + assert(value_node_origin); + + // Set the looping flag + value_node_bline->set_loop(true); + + if(!canvas) + canvas=get_canvas_view()->get_canvas(); + + value_node_bline->set_member_canvas(canvas); + + // count how many layers we're going to be creating + int layers_to_create = this->layers_to_create(); + + /////////////////////////////////////////////////////////////////////////// + // S T A R + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_star_flag()) + { + layer=get_canvas_interface()->add_layer_to("star",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + + layer->set_param("radius1",radius1); + get_canvas_interface()->signal_layer_param_changed()(layer,"radius1"); + + layer->set_param("radius2",radius2); + get_canvas_interface()->signal_layer_param_changed()(layer,"radius2"); + + layer->set_param("angle",offset); + get_canvas_interface()->signal_layer_param_changed()(layer,"angle"); + + layer->set_param("points",points); + get_canvas_interface()->signal_layer_param_changed()(layer,"points"); + + layer->set_param("regular_polygon",regular); + get_canvas_interface()->signal_layer_param_changed()(layer,"regular_polygon"); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + layer->set_description(get_id()); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + // only link the star's origin parameter if the option is selected, we're putting bline + // origins at their centers, and we're creating more than one layer + if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Star layer")); + group.cancel(); + throw String(_("Unable to create Star layer")); + return; + } + } + else + { + layer->set_param("origin",p1); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // C U R V E G R A D I E N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_curve_gradient_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Gradient")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + + // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Gradient layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // P L A N T + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_plant_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Plant")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + + // only link the plant's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Plant layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // R E G I O N + /////////////////////////////////////////////////////////////////////////// + + if(get_layer_region_flag()) + { + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Region")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm + // using 2 separate ones. + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + + // only link the region's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer")); + group.cancel(); + throw String(_("Unable to create Region layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + /////////////////////////////////////////////////////////////////////////// + // O U T L I N E + /////////////////////////////////////////////////////////////////////////// + + if (get_layer_outline_flag()) + { + Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth)); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + layer->set_description(get_id()+_(" Outline")); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + layer->set_param("feather",get_feather()); + get_canvas_interface()->signal_layer_param_changed()(layer,"feather"); + + layer->set_param("invert",get_invert()); + get_canvas_interface()->signal_layer_param_changed()(layer,"invert"); + + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("bline"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_bline))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + + // only link the outline's origin parameter if the option is selected and we're creating more than one layer + if (get_layer_link_origins_flag() && layers_to_create > 1) + { + synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("layer",layer); + if(!action->set_param("param",String("origin"))) + synfig::error("LayerParamConnect didn't like \"param\""); + if(!action->set_param("value_node",ValueNode::Handle(value_node_origin))) + synfig::error("LayerParamConnect didn't like \"value_node\""); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer")); + group.cancel(); + throw String(_("Unable to create Outline layer")); + return; + } + } + else + { + layer->set_param("origin",origin); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + } + } + + egress_on_selection_change=false; + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + reset(); + increment_id(); +} + +Smach::event_result +StateStar_Context::event_mouse_click_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT) + { + point_holder=get_work_area()->snap_point_to_grid(event.pos); + etl::handle duck=new Duck(); + duck->set_point(point_holder); + duck->set_name("p1"); + duck->set_type(Duck::TYPE_POSITION); + duck->set_editable(false); + get_work_area()->add_duck(duck); + + point2_duck=new Duck(); + point2_duck->set_point(Vector(0,0)); + point2_duck->set_name("radius"); + point2_duck->set_origin(duck); + point2_duck->set_radius(true); + point2_duck->set_scalar(-1); + point2_duck->set_type(Duck::TYPE_RADIUS); + point2_duck->set_hover(true); + get_work_area()->add_duck(point2_duck); + + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT) + { + if (!point2_duck) return Smach::RESULT_OK; + point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos)); + get_work_area()->queue_draw(); + return Smach::RESULT_ACCEPT; + } + + if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT) + { + Point point(get_work_area()->snap_point_to_grid(event.pos)); + + if (App::restrict_radius_ducks) + { + if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0]; + if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1]; + } + + make_star(point_holder, point); + get_work_area()->clear_ducks(); + return Smach::RESULT_ACCEPT; + } + + return Smach::RESULT_OK; +} + + +void +StateStar_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); +} diff --git a/synfig-studio/src/gui/states/state_star.h b/synfig-studio/src/gui/states/state_star.h new file mode 100644 index 0000000..606f77d --- /dev/null +++ b/synfig-studio/src/gui/states/state_star.h @@ -0,0 +1,57 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_star.h +** \brief Star creation state +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_STAR_H +#define __SYNFIG_STUDIO_STATE_STAR_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateStar_Context; + +class StateStar : public Smach::state +{ +public: + StateStar(); + ~StateStar(); +}; // END of class StateStar + +extern StateStar state_star; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_stroke.cpp b/synfig-studio/src/gui/states/state_stroke.cpp new file mode 100644 index 0000000..a0f7eca --- /dev/null +++ b/synfig-studio/src/gui/states/state_stroke.cpp @@ -0,0 +1,198 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_stroke.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include "state_stroke.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" +#include +#include +#include +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateStroke studio::state_stroke; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateStroke_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + Duckmatic::Push duckmatic_push; + + etl::smart_ptr > stroke_data; + + etl::smart_ptr > width_data; + + Gdk::ModifierType modifier; + +public: + + Smach::event_result event_stop_handler(const Smach::event& x); + + Smach::event_result event_refresh_handler(const Smach::event& x); + + Smach::event_result event_mouse_up_handler(const Smach::event& x); + + Smach::event_result event_mouse_draw_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + StateStroke_Context(CanvasView* canvas_view); + + ~StateStroke_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();} + +}; // END of class StateStroke_Context + + +/* === M E T H O D S ======================================================= */ + +StateStroke::StateStroke(): + Smach::state("stroke") +{ + insert(event_def(EVENT_STOP,&StateStroke_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateStroke_Context::event_refresh_handler)); +// insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStroke_Context::event_mouse_down_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStroke_Context::event_mouse_up_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStroke_Context::event_mouse_draw_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStroke_Context::event_refresh_tool_options)); +} + +StateStroke::~StateStroke() +{ +} + + +StateStroke_Context::StateStroke_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + duckmatic_push(get_work_area()) +{ + width_data.spawn(); + stroke_data.spawn(); + + get_work_area()->add_stroke(stroke_data, synfigapp::Main::get_outline_color()); +} + +StateStroke_Context::~StateStroke_Context() +{ + duckmatic_push.restore(); + + App::toolbox->refresh(); + + // Send the stroke data to whatever previously called this state. + if(stroke_data->size()>=2) + get_canvas_view()->get_smach().process_event(EventStroke(stroke_data,width_data,modifier)); +} + +Smach::event_result +StateStroke_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateStroke_Context::event_stop_handler(const Smach::event& /*x*/) +{ + throw Smach::pop_exception(); +} + +Smach::event_result +StateStroke_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateStroke_Context::event_mouse_up_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + switch(event.button) + { + case BUTTON_LEFT: + { + modifier=event.modifier; + throw Smach::pop_exception(); + } + + default: + return Smach::RESULT_OK; + } +} + +Smach::event_result +StateStroke_Context::event_mouse_draw_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + switch(event.button) + { + case BUTTON_LEFT: + { + stroke_data->push_back(event.pos); + width_data->push_back(event.pressure); + get_work_area()->queue_draw(); + return Smach::RESULT_ACCEPT; + } + + default: + return Smach::RESULT_OK; + } +} diff --git a/synfig-studio/src/gui/states/state_stroke.h b/synfig-studio/src/gui/states/state_stroke.h new file mode 100644 index 0000000..0beade5 --- /dev/null +++ b/synfig-studio/src/gui/states/state_stroke.h @@ -0,0 +1,80 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_stroke.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_STROKE_H +#define __SYNFIG_STUDIO_STATE_STROKE_H + +/* === H E A D E R S ======================================================= */ + +#include "canvasview.h" +#include "workarea.h" +#include +#include "duckmatic.h" +#include +#include +#include +#include "eventkey.h" +#include + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateStroke_Context; + +class StateStroke : public Smach::state +{ +public: + StateStroke(); + ~StateStroke(); +}; // END of class StateStroke + +extern StateStroke state_stroke; + +struct EventStroke : public Smach::event +{ + etl::smart_ptr > stroke_data; + etl::smart_ptr > width_data; + Gdk::ModifierType modifier; + + EventStroke(etl::smart_ptr > stroke_data, + etl::smart_ptr > width_data, + Gdk::ModifierType modifier=Gdk::ModifierType(0) + ): + Smach::event(EVENT_WORKAREA_STROKE), + stroke_data(stroke_data), + width_data(width_data), + modifier(modifier) + { } +}; // END of EventStroke + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_text.cpp b/synfig-studio/src/gui/states/state_text.cpp new file mode 100644 index 0000000..733f907 --- /dev/null +++ b/synfig-studio/src/gui/states/state_text.cpp @@ -0,0 +1,460 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_text.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "state_text.h" +#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 "duck.h" +#include "widgets/widget_enum.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateText studio::state_text; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateText_Context +{ + etl::handle canvas_view; + CanvasView::IsWorking is_working; + + Duckmatic::Push duckmatic_push; + + void refresh_ducks(); + + bool prev_workarea_layer_status_; + + //Toolbox settings + synfigapp::Settings& settings; + + //Toolbox display + Gtk::Table options_table; + + Gtk::Entry entry_id; //what to name the layer + Gtk::Entry entry_family; + Widget_Vector widget_size; + Widget_Vector widget_orientation; + Gtk::CheckButton checkbutton_paragraph; + +public: + synfig::String get_id()const { return entry_id.get_text(); } + void set_id(const synfig::String& x) { return entry_id.set_text(x); } + + bool get_paragraph_flag()const { return checkbutton_paragraph.get_active(); } + void set_paragraph_flag(bool x) { return checkbutton_paragraph.set_active(x); } + + Vector get_size() { return widget_size.get_value(); } + void set_size(Vector s) { return widget_size.set_value(s); } + + Vector get_orientation() { return widget_orientation.get_value(); } + void set_orientation(Vector s) { return widget_orientation.set_value(s); } + + String get_family()const { return entry_family.get_text(); } + void set_family(String s) { return entry_family.set_text(s); } + + void refresh_tool_options(); //to refresh the toolbox + + //events + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_mouse_click_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x); + + //constructor destructor + StateText_Context(CanvasView *canvas_view); + ~StateText_Context(); + + const etl::handle& get_canvas_view()const{return canvas_view;} + etl::handle get_canvas_interface()const{return canvas_view->canvas_interface();} + WorkArea * get_work_area()const{return canvas_view->get_work_area();} + + //Modifying settings etc. + void load_settings(); + void save_settings(); + void reset(); + void increment_id(); + bool egress_on_selection_change; + Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/) + { + if(egress_on_selection_change) + throw &state_normal; //throw Smach::egress_exception(); + return Smach::RESULT_OK; + } + + void make_text(const Point& point); + +}; // END of class StateText_Context + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +StateText::StateText(): + Smach::state("text") +{ + insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateText_Context::event_layer_selection_changed_handler)); + insert(event_def(EVENT_STOP,&StateText_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateText_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateText_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateText_Context::event_workarea_mouse_button_down_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateText_Context::event_refresh_tool_options)); +} + +StateText::~StateText() +{ +} + +void +StateText_Context::load_settings() +{ + String value; + Vector v; + + //parse the arguments yargh! + if(settings.get_value("text.id",value)) + set_id(value); + else + set_id("Text"); + + if(settings.get_value("text.paragraph",value) && value=="1") + set_paragraph_flag(true); + else + set_paragraph_flag(false); + + if(settings.get_value("text.size_x",value)) + v[0] = atof(value.c_str()); + else + v[0] = 0.25; + if(settings.get_value("text.size_y",value)) + v[1] = atof(value.c_str()); + else + v[1] = 0.25; + set_size(v); + + if(settings.get_value("text.orient_x",value)) + v[0] = atof(value.c_str()); + else + v[0] = 0.5; + if(settings.get_value("text.orient_y",value)) + v[1] = atof(value.c_str()); + else + v[1] = 0.5; + set_orientation(v); + + if(settings.get_value("text.family",value)) + set_family(value); + else + set_family("Sans Serif"); +} + +void +StateText_Context::save_settings() +{ + settings.set_value("text.id",get_id()); + settings.set_value("text.paragraph",get_paragraph_flag()?"1":"0"); + settings.set_value("text.size_x",strprintf("%f",(float)get_size()[0])); + settings.set_value("text.size_y",strprintf("%f",(float)get_size()[1])); + settings.set_value("text.orient_x",strprintf("%f",(float)get_orientation()[0])); + settings.set_value("text.orient_y",strprintf("%f",(float)get_orientation()[1])); + settings.set_value("text.family",get_family()); +} + +void +StateText_Context::reset() +{ + refresh_ducks(); +} + +void +StateText_Context::increment_id() +{ + String id(get_id()); + int number=1; + int digits=0; + + if(id.empty()) + id="Text"; + + // If there is a number + // already at the end of the + // id, then remove it. + 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++) + ; + + String str_number; + str_number=String(id,id.size()-digits,id.size()); + id=String(id,0,id.size()-digits); + + number=atoi(str_number.c_str()); + } + else + { + number=1; + digits=3; + } + + number++; + + // Add the number back onto the id + { + const String format(strprintf("%%0%dd",digits)); + id+=strprintf(format.c_str(),number); + } + + // Set the ID + set_id(id); +} + +StateText_Context::StateText_Context(CanvasView *canvas_view): + canvas_view(canvas_view), + is_working(*canvas_view), + duckmatic_push(get_work_area()), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()), + settings(synfigapp::Main::get_selected_input_device()->settings()), + entry_id(), + checkbutton_paragraph(_("Multiline Editor")) +{ + egress_on_selection_change=true; + + widget_size.set_digits(2); + widget_size.set_canvas(canvas_view->get_canvas()); + + widget_orientation.set_digits(2); + + options_table.attach(*manage(new Gtk::Label(_("Text 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_paragraph, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Size:"))), 0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(widget_size, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Orientation:"))), 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(widget_orientation, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("Family:"))), 0, 1, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(entry_family, 1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + load_settings(); + + options_table.show_all(); + + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + // Hide the tables if they are showing + //prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateText_Context::on_user_click)); + get_work_area()->set_cursor(Gdk::XTERM); + + App::toolbox->refresh(); +} + +void +StateText_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Text Tool")); + App::dialog_tool_options->set_name("text"); +} + +Smach::event_result +StateText_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateText_Context::~StateText_Context() +{ + save_settings(); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + get_work_area()->reset_cursor(); + + App::dialog_tool_options->clear(); + + get_work_area()->queue_draw(); + + get_canvas_view()->queue_rebuild_ducks(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateText_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateText_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StateText_Context::make_text(const Point& _point) +{ + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Text")); + synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL); + + Layer::Handle layer; + + Canvas::Handle canvas(get_canvas_view()->get_canvas()); + int depth(0); + + // we are temporarily using the layer to hold something + layer=get_canvas_view()->get_selection_manager()->get_selected_layer(); + if(layer) + { + depth=layer->get_depth(); + canvas=layer->get_canvas(); + } + + synfigapp::SelectionManager::LayerList layer_selection; + if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION")) + layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers(); + + const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack()); + const Point point(transform.unperform(_point)); + + String text; + if (get_paragraph_flag()) + App::dialog_paragraph(_("Text Paragraph"), _("Enter text here:"), text); + else + App::dialog_entry(_("Text Entry"), _("Enter text here:"), text); + + layer=get_canvas_interface()->add_layer_to("text",canvas,depth); + if (!layer) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to create layer")); + group.cancel(); + return; + } + layer_selection.push_back(layer); + + layer->set_param("origin",point); + get_canvas_interface()->signal_layer_param_changed()(layer,"origin"); + + layer->set_param("text",text); + get_canvas_interface()->signal_layer_param_changed()(layer,"text"); + + layer->set_param("size",get_size()); + get_canvas_interface()->signal_layer_param_changed()(layer,"size"); + + layer->set_param("orient",get_orientation()); + get_canvas_interface()->signal_layer_param_changed()(layer,"orient"); + + layer->set_param("family",get_family()); + get_canvas_interface()->signal_layer_param_changed()(layer,"family"); + + layer->set_description(get_id()); + get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description()); + + egress_on_selection_change=false; + get_canvas_interface()->get_selection_manager()->clear_selected_layers(); + get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection); + egress_on_selection_change=true; + + reset(); + increment_id(); +} + +Smach::event_result +StateText_Context::event_workarea_mouse_button_down_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + if(event.button==BUTTON_LEFT) + { + make_text(get_work_area()->snap_point_to_grid(event.pos)); + + get_work_area()->clear_ducks(); + return Smach::RESULT_ACCEPT; + } + return Smach::RESULT_OK; +} + +void +StateText_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); +} diff --git a/synfig-studio/src/gui/states/state_text.h b/synfig-studio/src/gui/states/state_text.h new file mode 100644 index 0000000..4b05db5 --- /dev/null +++ b/synfig-studio/src/gui/states/state_text.h @@ -0,0 +1,57 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_text.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STATE_TEXT_H +#define __SYNFIG_STATE_TEXT_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateText_Context; + +class StateText : public Smach::state +{ +public: + StateText(); + ~StateText(); +}; // END of class StateText + +extern StateText state_text; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_width.cpp b/synfig-studio/src/gui/states/state_width.cpp new file mode 100644 index 0000000..8c74daa --- /dev/null +++ b/synfig-studio/src/gui/states/state_width.cpp @@ -0,0 +1,606 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_width.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include +#include + +#include "state_width.h" +#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 "duck.h" + +//#include +#include + +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace synfigapp; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateWidth studio::state_width; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateWidth_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + //Point mouse_pos; + + handle center; + handle radius; + handle closestpoint; + + map,Real> changetable; + + etl::clock clocktime; + Real lastt; + + bool added; + + void refresh_ducks(); + + bool prev_workarea_layer_clicking; + bool prev_workarea_duck_clicking; + Duckmatic::Type old_duckmask; + + //Toolbox settings + synfigapp::Settings& settings; + + //Toolbox display + Gtk::Table options_table; + + Gtk::Adjustment adj_delta; + Gtk::SpinButton spin_delta; + + Gtk::Adjustment adj_radius; + Gtk::SpinButton spin_radius; + + Gtk::CheckButton check_relative; + + void AdjustWidth(handle c, float t, Real mult, bool invert); + +public: + + Real get_delta()const { return adj_delta.get_value(); } + void set_delta(Real f) { adj_delta.set_value(f); } + + Real get_radius()const { return adj_radius.get_value(); } + void set_radius(Real f) { adj_radius.set_value(f); } + + bool get_relative() const { return check_relative.get_active(); } + void set_relative(bool r) { check_relative.set_active(r); } + + void refresh_tool_options(); //to refresh the toolbox + + //events + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_mouse_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + //constructor destructor + StateWidth_Context(CanvasView* canvas_view); + ~StateWidth_Context(); + + //Canvas interaction + 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();} + + //Modifying settings etc. + void load_settings(); + void save_settings(); + void reset(); + +}; // END of class StateWidth_Context + +/* === M E T H O D S ======================================================= */ + +StateWidth::StateWidth(): + Smach::state("width") +{ + insert(event_def(EVENT_STOP,&StateWidth_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateWidth_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateWidth_Context::event_mouse_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateWidth_Context::event_mouse_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateWidth_Context::event_mouse_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateWidth_Context::event_refresh_tool_options)); +} + +StateWidth::~StateWidth() +{ +} + +void +StateWidth_Context::load_settings() +{ + String value; + + //parse the arguments yargh! + if(settings.get_value("width.delta",value)) + set_delta(atof(value.c_str())); + else + set_delta(6); + + if(settings.get_value("width.radius",value)) + set_radius(atof(value.c_str())); + else + set_radius(15); + + //defaults to false + if(settings.get_value("width.relative",value) && value == "1") + set_relative(true); + else + set_relative(false); +} + +void +StateWidth_Context::save_settings() +{ + settings.set_value("width.delta",strprintf("%f",get_delta())); + settings.set_value("width.radius",strprintf("%f",get_radius())); + settings.set_value("width.relative",get_relative()?"1":"0"); +} + +void +StateWidth_Context::reset() +{ + refresh_ducks(); +} + +StateWidth_Context::StateWidth_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + prev_workarea_layer_clicking(get_work_area()->get_allow_layer_clicks()), + prev_workarea_duck_clicking(get_work_area()->get_allow_duck_clicks()), + old_duckmask(get_work_area()->get_type_mask()), + + settings(synfigapp::Main::get_selected_input_device()->settings()), + + adj_delta(6,0,20,0.01,0.1), + spin_delta(adj_delta,0.01,3), + + adj_radius(200,0,1e50,1,10), + spin_radius(adj_radius,1,1), + + check_relative(_("Relative Growth")) +{ + load_settings(); + + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Width Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + //expand stuff + options_table.attach(*manage(new Gtk::Label(_("Growth:"))), 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_delta, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(*manage(new Gtk::Label(_("Radius:"))), 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(spin_radius, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.attach(check_relative, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.show_all(); + + refresh_tool_options(); + App::dialog_tool_options->present(); + + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + //get_work_area()->clear_ducks(); + + // Refresh the work area + get_work_area()->queue_draw(); + + //Create the new ducks + added = false; + + if(!center) + { + center = new Duck(); + center->set_name("p1"); + center->set_type(Duck::TYPE_POSITION); + } + + if(!radius) + { + radius = new Duck(); + radius->set_origin(center); + radius->set_radius(true); + radius->set_type(Duck::TYPE_RADIUS); + radius->set_name("radius"); + } + + if(!closestpoint) + { + closestpoint = new Duck(); + closestpoint->set_name("closest"); + closestpoint->set_type(Duck::TYPE_POSITION); + } + + //Disable duck clicking for the maximum coolness :) + get_work_area()->set_allow_duck_clicks(false); + get_work_area()->set_type_mask((Duck::Type)((int)Duck::TYPE_WIDTH + (int)Duck::TYPE_RADIUS)); + + // Turn the mouse pointer to crosshairs + get_work_area()->set_cursor(Gdk::CROSSHAIR); + + // Hide the tables if they are showing + //prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateWidth_Context::on_user_click)); + + App::toolbox->refresh(); +} + +void +StateWidth_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Width Tool")); + App::dialog_tool_options->set_name("width"); +} + +Smach::event_result +StateWidth_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateWidth_Context::~StateWidth_Context() +{ + save_settings(); + + //remove ducks if need be + if(added) + { + get_work_area()->erase_duck(center); + get_work_area()->erase_duck(radius); + get_work_area()->erase_duck(closestpoint); + added = false; + } + + // Restore Duck clicking + get_work_area()->set_allow_duck_clicks(prev_workarea_duck_clicking); + + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_clicking); + + // Restore the mouse pointer + get_work_area()->reset_cursor(); + + // Restore duck masking + get_work_area()->set_type_mask(old_duckmask); + + // Tool options be rid of ye!! + App::dialog_tool_options->clear(); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + //if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + App::toolbox->refresh(); +} + +Smach::event_result +StateWidth_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateWidth_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + refresh_ducks(); + return Smach::RESULT_ACCEPT; +} + +void +StateWidth_Context::AdjustWidth(handle c, float t, Real mult, bool invert) +{ + //Leave the function if there is no curve + if(!c)return; + + Real amount1=0,amount2=0; + + //decide how much to change each width + /* + t \in [0,1] + + both pressure and multiply amount are in mult + (may want to change this to allow different types of falloff) + + rsq is the squared distance from the point on the curve (also part of the falloff) + + + */ + //may want to provide a different falloff function... + if(t <= 0.2) + amount1 = mult; + else if(t >= 0.8) + amount2 = mult; + else + { + t = (t-0.2)/0.6; + amount1 = (1-t)*mult; + amount2 = t*mult; + } + + if(invert) + { + amount1 *= -1; + amount2 *= -1; + } + + handle p1 = c->p1; + handle p2 = c->p2; + + handle w1,w2; + + //find w1,w2 + { + const DuckList dl = get_work_area()->get_duck_list(); + + DuckList::const_iterator i = dl.begin(); + + for(;i != dl.end(); ++i) + { + if((*i)->get_type() == Duck::TYPE_WIDTH) + { + if((*i)->get_origin_duck() == p1) + { + w1 = *i; + } + + if((*i)->get_origin_duck() == p2) + { + w2 = *i; + } + } + } + } + + if(amount1 != 0 && w1) + { + Real width = w1->get_point().mag(); + + width += amount1; + w1->set_point(Vector(width,0)); + + //log in the list of changes... + //to truly be changed after everything is said and done + changetable[w1] = width; + } + + if(amount2 != 0 && w2) + { + Real width = w2->get_point().mag(); + + width += amount2; + w2->set_point(Vector(width,0)); + + //log in the list of changes... + //to truly be changed after everything is said and done + changetable[w2] = width; + } +} + +Smach::event_result +StateWidth_Context::event_mouse_handler(const Smach::event& x) +{ + const EventMouse& event(*reinterpret_cast(&x)); + + //handle the click + if( (event.key == EVENT_WORKAREA_MOUSE_BUTTON_DOWN || event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG) + && event.button == BUTTON_LEFT ) + { + const Real pw = get_work_area()->get_pw(); + const Real ph = get_work_area()->get_ph(); + const Real scale = sqrt(pw*pw+ph*ph); + const Real rad = get_relative() ? scale * get_radius() : get_radius(); + + bool invert = (event.modifier&Gdk::CONTROL_MASK); + + const Real threshold = 0.08; + + float t = 0; + Real rsq = 0; + + Real dtime = 1/60.0; + + //if we're dragging get the difference in time between now and then + if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG) + { + dtime = min(1/15.0,clocktime()); + } + clocktime.reset(); + + //make way for new ducks + //get_work_area()->clear_ducks(); + + //update positions + //mouse_pos = event.pos; + + center->set_point(event.pos); + if(!added)get_work_area()->add_duck(center); + + radius->set_scalar(rad); + if(!added)get_work_area()->add_duck(radius); + + //the other duck is at the current duck + closestpoint->set_point(event.pos); + if(!added)get_work_area()->add_duck(closestpoint); + + //get the closest curve... + handle c; + if(event.pressure >= threshold) + c = get_work_area()->find_bezier(event.pos,scale*8,rad,&t); + + //run algorithm on event.pos to get 2nd placement + if(!c.empty()) + { + bezier curve; + Point p; + + curve[0] = c->p1->get_trans_point(); + curve[1] = c->c1->get_trans_point(); + curve[2] = c->c2->get_trans_point(); + curve[3] = c->p2->get_trans_point(); + + p = curve(t); + rsq = (p-event.pos).mag_squared(); + + const Real r = rad*rad; + + if(rsq < r) + { + closestpoint->set_point(curve(t)); + + //adjust the width... + //squared falloff for radius... [0,1] + + Real ri = (r - rsq)/r; + AdjustWidth(c,t,ri*event.pressure*get_delta()*dtime,invert); + } + } + + //the points have been added + added = true; + + //draw where it is yo! + get_work_area()->queue_draw(); + + return Smach::RESULT_ACCEPT; + } + + if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button == BUTTON_LEFT) + { + if(added) + { + get_work_area()->erase_duck(center); + get_work_area()->erase_duck(radius); + get_work_area()->erase_duck(closestpoint); + added = false; + } + + //Affect the width changes here... + map,Real>::iterator i = changetable.begin(); + + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch Width")); + for(; i != changetable.end(); ++i) + { + //for each duck modify IT!!! + ValueDesc desc = i->first->get_value_desc(); + + if( desc.get_value_type() == ValueBase::TYPE_REAL ) + { + Action::Handle action(Action::create("ValueDescSet")); + assert(action); + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + + action->set_param("value_desc",desc); + action->set_param("new_value",ValueBase(i->second)); + action->set_param("time",get_canvas_view()->get_time()); + + if(!action->is_ready() || !get_canvas_view()->get_instance()->perform_action(action)) + { + group.cancel(); + synfig::warning("Changing the width action has failed"); + return Smach::RESULT_ERROR; + } + } + } + + changetable.clear(); + + get_work_area()->queue_draw(); + + return Smach::RESULT_ACCEPT; + } + + return Smach::RESULT_OK; +} + + +void +StateWidth_Context::refresh_ducks() +{ + get_work_area()->clear_ducks(); + get_work_area()->queue_draw(); +} diff --git a/synfig-studio/src/gui/states/state_width.h b/synfig-studio/src/gui/states/state_width.h new file mode 100644 index 0000000..f649140 --- /dev/null +++ b/synfig-studio/src/gui/states/state_width.h @@ -0,0 +1,56 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_width.h +** \brief Width creation state +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_STATE_WIDTH_H +#define __SYNFIG_STUDIO_STATE_WIDTH_H + +/* === H E A D E R S ======================================================= */ + +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateWidth_Context; + +class StateWidth : public Smach::state +{ +public: + StateWidth(); + ~StateWidth(); +}; // END of class StateWidth + +extern StateWidth state_width; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --git a/synfig-studio/src/gui/states/state_zoom.cpp b/synfig-studio/src/gui/states/state_zoom.cpp new file mode 100644 index 0000000..56363e6 --- /dev/null +++ b/synfig-studio/src/gui/states/state_zoom.cpp @@ -0,0 +1,263 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_zoom.cpp +** \brief Zoom Tool Implementation File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include + + +#include "state_zoom.h" +#include "state_normal.h" +#include "event_mouse.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" +#include "toolbox.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ +StateZoom studio::state_zoom; + +const float ZOOMFACTOR = 1.25f; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class studio::StateZoom_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + + Point p1,p2; + + bool prev_workarea_layer_status_; + +public: + + //events + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_mouse_click_handler(const Smach::event& x); + + //constructor destructor + StateZoom_Context(CanvasView* canvas_view); + ~StateZoom_Context(); + + //Canvas interaction + 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 zoom(const Point& p1, const Point& p2); + +}; // END of class StateZoom_Context + +/* === M E T H O D S ======================================================= */ + +StateZoom::StateZoom(): + Smach::state("zoom") +{ + insert(event_def(EVENT_STOP,&StateZoom_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateZoom_Context::event_refresh_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateZoom_Context::event_mouse_click_handler)); + //insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateZoom_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_BOX,&StateZoom_Context::event_mouse_click_handler)); + //insert(event_def(EVENT_WORKAREA_BUTTON_CLICK,&StateZoom_Context::event_mouse_click_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateZoom_Context::event_mouse_click_handler)); +} + +StateZoom::~StateZoom() +{ +} + +StateZoom_Context::StateZoom_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), + prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()) +{ + // Turn off layer clicking + get_work_area()->set_allow_layer_clicks(false); + + // clear out the ducks + get_work_area()->clear_ducks(); //??? + + // Refresh the work area + get_work_area()->queue_draw(); + + // Hide the tables if they are showing + //prev_table_status=get_canvas_view()->tables_are_visible(); + //if(prev_table_status)get_canvas_view()->hide_tables(); + + // Disable the time bar + //get_canvas_view()->set_sensitive_timebar(false); + + // Connect a signal + //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateZoom_Context::on_user_click)); + get_work_area()->set_cursor(Gdk::CROSSHAIR); + + App::toolbox->refresh(); +} + +StateZoom_Context::~StateZoom_Context() +{ + // Restore layer clicking + get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_); + get_work_area()->reset_cursor(); + + // Enable the time bar + //get_canvas_view()->set_sensitive_timebar(true); + + // Bring back the tables if they were out before + //if(prev_table_status)get_canvas_view()->show_tables(); + + // Refresh the work area + get_work_area()->queue_draw(); + + App::toolbox->refresh(); + + get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS); +} + +Smach::event_result +StateZoom_Context::event_stop_handler(const Smach::event& /*x*/) +{ + //throw Smach::egress_exception(); + throw &state_normal; + return Smach::RESULT_OK; +} + +Smach::event_result +StateZoom_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateZoom_Context::event_mouse_click_handler(const Smach::event& x) +{ + if(x.key==EVENT_WORKAREA_BOX) + { + const EventBox& event(*reinterpret_cast(&x)); + + if(event.button==BUTTON_LEFT) + { + Point tl = get_work_area()->get_window_tl(); + Point br = get_work_area()->get_window_br(); + Vector window_span = br - tl, window_middle = (br+tl)/2; + Vector box_span = event.p2 - event.p1, box_middle = (event.p1+event.p2)/2; + Point newpos; + float zoom; + + if(event.modifier & Gdk::CONTROL_MASK) //zoom out... + { + if (window_span[0] == 0 || window_span[1] == 0) zoom = 1; + else zoom = max(abs(box_span[0]/window_span[0]), abs(box_span[1]/window_span[1])); + + // focus_point is -1 times the real position for some reason... + // center the window so the old contents fill the drawn box + newpos = -((window_middle - box_middle)/zoom + window_middle); + } + else // zoom in + { + if (box_span[0] == 0 || box_span[1] == 0) zoom = 1; + else zoom = min(abs(window_span[0]/box_span[0]), abs(window_span[1]/box_span[1])); + + // center the window at the center of the box + newpos = -(-get_work_area()->get_focus_point() + (box_middle - window_middle)); + } + + get_work_area()->set_focus_point(newpos); + get_work_area()->set_zoom(get_work_area()->get_zoom()*zoom); + + return Smach::RESULT_ACCEPT; + } + } + + if(x.key==EVENT_WORKAREA_MOUSE_BUTTON_UP) + { + const EventMouse& event(*reinterpret_cast(&x)); + + if(event.button==BUTTON_LEFT) + { + Point evpos; + + //make the event pos be in the same space... + // The weird ass inverted center normalized space... + { + const Point realcenter = (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2; + evpos = -(event.pos - realcenter) + get_work_area()->get_focus_point(); + } + + /* Zooming: + focus point must zoom about the point evpos... + + trans about an origin not 0: + p' = A(p - o) + o + */ + + Vector v = get_work_area()->get_focus_point() - evpos; + + if(event.modifier & Gdk::CONTROL_MASK) //zoom out... + { + v*=ZOOMFACTOR; + //get_work_area()->zoom_out(); + get_work_area()->set_focus_point(evpos + v); + get_work_area()->set_zoom(get_work_area()->get_zoom()/ZOOMFACTOR); + }else //zoom in + { + v/=ZOOMFACTOR; + //get_work_area()->zoom_in(); + get_work_area()->set_focus_point(evpos + v); + get_work_area()->set_zoom(get_work_area()->get_zoom()*ZOOMFACTOR); + } + + return Smach::RESULT_ACCEPT; + } + } + + return Smach::RESULT_OK; +} diff --git a/synfig-studio/src/gui/states/state_zoom.h b/synfig-studio/src/gui/states/state_zoom.h new file mode 100644 index 0000000..e5e7260 --- /dev/null +++ b/synfig-studio/src/gui/states/state_zoom.h @@ -0,0 +1,55 @@ +/* === S Y N F I G ========================================================= */ +/*! \file state_zoom.h +** \brief Zoom tool Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STATE_ZOOM_H +#define __SYNFIG_STATE_ZOOM_H + +/* === H E A D E R S ======================================================= */ +#include "smach.h" + + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class StateZoom_Context; + +class StateZoom : public Smach::state +{ +public: + StateZoom(); + ~StateZoom(); +}; // END of class StateZoom + +extern StateZoom state_zoom; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif -- 2.7.4