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 = \
#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"
#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"
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_bline.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/spinbutton.h>
-#include <synfig/transform.h>
-#include <synfigapp/main.h>
-
-#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<CanvasView> 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<Duck> curr_duck;
-
- etl::handle<Duck> next_duck;
-
- std::list<synfig::ValueNode_Const::Handle> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateBLine_Context>("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<BLinePoint> new_list;
- std::list<synfig::ValueNode_Const::Handle>::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<const EventMouse*>(&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<const EventMouse*>(&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<synfig::ValueNode_Const::Handle>::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<ValueNode_Const::Handle>::iterator iter;
-
- handle<WorkArea::Bezier> bezier;
- handle<WorkArea::Duck> 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<ValueNode_Const::Handle>::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<ValueNode_Const::Handle>::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<ValueNode_Const::Handle>::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<Vector> 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<Vector> > 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<ValueNode_Const::Handle>::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);
-}
+++ /dev/null
-/* === 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<StateBLine_Context>
-{
-public:
- StateBLine();
- ~StateBLine();
-}; // END of class StateBLine
-
-extern StateBLine state_bline;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_circle.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- Duckmatic::Push duckmatic_push;
-
- Point point_holder;
-
- etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateCircle_Context>("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<BLinePoint> 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<const EventMouse*>(&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> 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();
-}
+++ /dev/null
-/* === 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<StateCircle_Context>
-{
-public:
- StateCircle();
- ~StateCircle();
-}; // END of class StateCircle
-
-extern StateCircle state_circle;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_draw.h"
-#include "state_stroke.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <synfig/valuenode_composite.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-
-#include <synfigapp/blineconvert.h>
-#include <synfigapp/main.h>
-
-#include <ETL/gaussian>
-#include "dialog_tooloptions.h"
-
-#include <gtkmm/table.h>
-#include <gtkmm/label.h>
-#include <gtkmm/button.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/scale.h>
-#include <sigc++/connection.h>
-
-#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<std::list<synfig::Point> > StrokeData;
- typedef etl::smart_ptr<std::list<synfig::Real> > WidthData;
-
- typedef list< pair<StrokeData,WidthData> > StrokeQueue;
-
- StrokeQueue stroke_queue;
-
-
- etl::handle<CanvasView> 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<std::list<synfig::Point> > > 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<synfig::BLinePoint> bline,bool loop_bline_flag,float radius);
-
- Smach::event_result new_region(std::list<synfig::BLinePoint> bline,synfig::Real radius);
-
- Smach::event_result extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
- Smach::event_result extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
- void reverse_bline(std::list<synfig::BLinePoint> &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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateDraw_Context>("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<const EventMouse*>(&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<const EventStroke*>(&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<StrokeData,WidthData>(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<StrokeData,WidthData> 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<synfig::Real>::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<synfig::BLinePoint> 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<synfig::BLinePoint> 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<Duck> start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX));
- etl::handle<Duck> finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX));
-
- // 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<synfig::BLinePoint> trans_bline;
-
- {
- std::list<synfig::BLinePoint>::iterator iter;
- const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-
- for(iter=bline.begin();iter!=bline.end();++iter)
- {
- BLinePoint bline_point(*iter);
- Point new_vertex(transform.unperform(bline_point.get_vertex()));
-
- bline_point.set_tangent1(
- transform.unperform(
- bline_point.get_tangent1()+bline_point.get_vertex()
- ) -new_vertex
- );
-
- bline_point.set_tangent2(
- transform.unperform(
- bline_point.get_tangent2()+bline_point.get_vertex()
- ) -new_vertex
- );
-
- 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<synfigapp::ValueDesc>& vertex_list,
- std::string title, int current)
-{
- std::list<synfigapp::ValueDesc>::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<synfig::BLinePoint> bline, synfig::Real radius)
-{
- // Create the action group
- synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Define Region"));
-
- std::list<synfigapp::ValueDesc> 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<synfig::BLinePoint>::iterator iter;
- for(iter=bline.begin();iter!=bline.end();++iter)
- {
- etl::handle<Duck> 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<synfigapp::ValueDesc>::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<synfigapp::ValueDesc>::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<synfigapp::ValueDesc>::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()-1)
- // {
- // debug_show_vertex_list(i, vertex_list,
- // strprintf("same parent, different points this %d < next-1 %d",
- // value_desc.get_index(), ((value_next.get_index()-1))),
- // current);
- // for (int index = value_desc.get_index()+1; index < value_next.get_index(); index++)
- // {
- // printf("inserting up %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;
- // }
- // if(value_next.get_index()<value_desc.get_index()-1)
- // {
- // debug_show_vertex_list(i, vertex_list,
- // strprintf("same parent, different points next %d < this-1 %d",
- // value_next.get_index(), ((value_desc.get_index()-1))),
- // current);
- // for (int index = value_desc.get_index()-1; 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()<radius*radius)
- {
- printf("in one - it's close\n");
- ValueNode_Composite::Handle value_node;
- ValueNode_Composite::Handle value_node_next;
- value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node().clone());
- value_node_next=ValueNode_Composite::Handle::cast_dynamic(value_next.get_value_node().clone());
- if(!value_node || !value_node_next)
- {
- synfig::info(__FILE__":%d: Unable to properly connect blines.",__LINE__);
- continue;
- }
- // \todo if next isn't split, don't we want to copy its 'Tangent 1' instead?
- value_node->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()<LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->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<synfigapp::ValueDesc>::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<std::list<synfig::Point> > >::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<synfig::BLinePoint> 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<synfig::BLinePoint>::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<synfig::BLinePoint> 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<synfig::BLinePoint>::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<synfig::BLinePoint> &bline)
-{
- int i;
-
- std::list<synfig::BLinePoint>::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);
-}
+++ /dev/null
-/* === 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<StateDraw_Context>
-{
-public:
- StateDraw();
- ~StateDraw();
-}; // END of class StateDraw
-
-extern StateDraw state_draw;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include "state_eyedrop.h"
-#include "state_normal.h"
-#include "workarea.h"
-#include <synfig/context.h>
-#include "app.h"
-#include "dialogs/dialog_color.h"
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "canvasview.h"
-#include <synfigapp/main.h>
-
-#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<StateEyedrop_Context>("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<const EventMouse*>(&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;
-}
+++ /dev/null
-/* === 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<StateEyedrop_Context>
-{
-public:
- StateEyedrop();
- ~StateEyedrop();
-}; // END of class StateEyedrop
-
-extern StateEyedrop state_eyedrop;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include "state_fill.h"
-#include "state_normal.h"
-#include "workarea.h"
-#include <synfig/context.h>
-#include "app.h"
-#include "dialogs/dialog_color.h"
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "canvasview.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> get_canvas_view()const{return canvas_view;}
- etl::handle<synfigapp::CanvasInterface> 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<StateFill_Context>("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<const EventLayerClick*>(&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;
-}
+++ /dev/null
-/* === 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<StateFill_Context>
-{
-public:
- StateFill();
- ~StateFill();
-}; // END of class StateFill
-
-extern StateFill state_fill;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_gradient.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- Duckmatic::Push duckmatic_push;
-
- synfigapp::Settings& settings;
-
- Point point_holder;
-
- etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateGradient_Context>("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<const EventMouse*>(&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> 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<Duckmatic::Bezier> 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();
-}
+++ /dev/null
-/* === 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<StateGradient_Context>
-{
-public:
- StateGradient();
- ~StateGradient();
-}; // END of class StateGradient
-
-extern StateGradient state_gradient;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_mirror.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfigapp/main.h>
-
-#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<synfig::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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- synfigapp::Settings& settings;
-
- sigc::connection keypress_connect;
- sigc::connection keyrelease_connect;
-
- etl::handle<DuckDrag_Mirror> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateMirror_Context>("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;
-}
+++ /dev/null
-/* === 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<StateMirror_Context>
-{
-public:
- StateMirror();
- ~StateMirror();
-}; // END of class StateMirror
-
-extern StateMirror state_mirror;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_animated.h>
-#include <synfig/valuenode_blinecalcvertex.h>
-#include <synfig/valuenode_composite.h>
-#include <synfig/valuenode_const.h>
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfig/angle.h>
-#include <synfigapp/main.h>
-
-#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<synfig::Vector> last_;
- std::vector<synfig::Vector> positions;
-
-
- bool bad_drag;
- bool move_only;
-
-public:
- etl::handle<CanvasView> 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<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-};
-
-
-class studio::StateNormal_Context : public sigc::trackable
-{
- etl::handle<CanvasView> canvas_view_;
-
- synfigapp::Settings& settings;
-
- sigc::connection keypress_connect;
- sigc::connection keyrelease_connect;
-
- etl::handle<DuckDrag_Combo> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateNormal_Context>("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<etl::handle<Duck> >::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]>-EPSILON)
- vect[0]=1;
- if(vect[1]<EPSILON && 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<const EventMouse*>(&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<const EventLayerClick*>(&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::Handle> layer_list(canvas_view_->get_selection_manager()->get_selected_layers());
- std::set<Layer::Handle> layers(layer_list.begin(),layer_list.end());
- if(layers.count(event.layer))
- {
- layers.erase(event.layer);
- layer_list=std::list<Layer::Handle>(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<synfigapp::ValueDesc> 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<synfigapp::ValueDesc>::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<const EventMouse*>(&x));
-
- std::list<synfigapp::ValueDesc> 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;
-}
-
-
+++ /dev/null
-/* === 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<StateNormal_Context>
-{
-public:
- StateNormal();
- ~StateNormal();
-}; // END of class StateNormal
-
-extern StateNormal state_normal;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_polygon.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- bool prev_table_status;
- bool prev_workarea_layer_status_;
-
- Gtk::Menu menu;
-
- Duckmatic::Push duckmatic_push;
-
- std::list<synfig::Point> polygon_point_list;
- synfigapp::Settings& settings;
-
-
- bool on_polygon_duck_change(const synfig::Point &point, std::list<synfig::Point>::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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StatePolygon_Context>("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<BLinePoint> new_list;
- std::list<synfig::Point>::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<const EventMouse*>(&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<synfig::Point>::iterator iter=polygon_point_list.begin();
-
- etl::handle<WorkArea::Duck> 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<WorkArea::Bezier> 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<synfig::Point>::iterator iter)
-{
- *iter=point;
- return true;
-}
+++ /dev/null
-/* === 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<StatePolygon_Context>
-{
-public:
- StatePolygon();
- ~StatePolygon();
-}; // END of class StatePolygon
-
-extern StatePolygon state_polygon;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_rectangle.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- Duckmatic::Push duckmatic_push;
-
- Point point_holder;
-
- etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateRectangle_Context>("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<BLinePoint> 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<const EventMouse*>(&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> 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();
-}
+++ /dev/null
-/* === 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<StateRectangle_Context>
-{
-public:
- StateRectangle();
- ~StateRectangle();
-}; // END of class StateRectangle
-
-extern StateRectangle state_rectangle;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_rotate.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfig/angle.h>
-#include <synfigapp/main.h>
-
-#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<synfig::Vector> positions;
-
-
- bool bad_drag;
- bool move_only;
-
-public:
- etl::handle<CanvasView> 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<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-};
-
-
-class studio::StateRotate_Context : public sigc::trackable
-{
- etl::handle<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- synfigapp::Settings& settings;
-
- etl::handle<DuckDrag_Rotate> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateRotate_Context>("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<etl::handle<Duck> >::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<etl::handle<Duck> >::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;
- }
-}
+++ /dev/null
-/* === 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<StateRotate_Context>
-{
-public:
- StateRotate();
- ~StateRotate();
-}; // END of class StateRotate
-
-extern StateRotate state_rotate;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_scale.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfigapp/main.h>
-
-#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<synfig::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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- synfigapp::Settings& settings;
-
- etl::handle<DuckDrag_Scale> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateScale_Context>("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<etl::handle<Duck> >::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<etl::handle<Duck> >::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]>-EPSILON)
- vect[0]=1;
- if(vect[1]<EPSILON && 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;
- }
-}
+++ /dev/null
-/* === 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<StateScale_Context>
-{
-public:
- StateScale();
- ~StateScale();
-}; // END of class StateScale
-
-extern StateScale state_scale;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_sketch.h"
-#include "state_normal.h"
-#include "state_stroke.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-
-#include <synfigapp/blineconvert.h>
-#include <synfigapp/main.h>
-
-#include <ETL/gaussian>
-
-#include "dialog_tooloptions.h"
-
-#include <gtkmm/table.h>
-#include <gtkmm/label.h>
-#include <gtkmm/button.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/actiongroup.h>
-
-#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<Gtk::ActionGroup> action_group;
-
- etl::handle<CanvasView> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateSketch_Context>("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 =
- "<ui>"
- " <toolbar action='toolbar-sketch'>"
- " <toolitem action='sketch-undo' />"
- " <toolitem action='sketch-clear' />"
- " <toolitem action='sketch-save-as' />"
- " <toolitem action='sketch-open' />"
- " </toolbar>"
- "</ui>";
-
- 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<Gtk::Toolbar*>(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<const EventMouse*>(&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<const EventStroke*>(&x));
-
- assert(event.stroke_data);
-
- get_work_area()->add_persistent_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
-
- return Smach::RESULT_ACCEPT;
-}
+++ /dev/null
-/* === 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<StateSketch_Context>
-{
-public:
- StateSketch();
- ~StateSketch();
-}; // END of class StateSketch
-
-extern StateSketch state_sketch;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_blinecalcvertex.h>
-#include <synfig/valuenode_composite.h>
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_smoothmove.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "onemoment.h"
-#include <synfigapp/main.h>
-
-#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<synfig::Vector> last_;
- std::vector<synfig::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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- //Duckmatic::Push duckmatic_push;
-
- synfigapp::Settings& settings;
-
- etl::handle<DuckDrag_SmoothMove> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateSmoothMove_Context>("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<OneMoment> 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;
- }
-}
+++ /dev/null
-/* === 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<StateSmoothMove_Context>
-{
-public:
- StateSmoothMove();
- ~StateSmoothMove();
-}; // END of class StateSmoothMove
-
-extern StateSmoothMove state_smooth_move;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_star.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- Duckmatic::Push duckmatic_push;
-
- Point point_holder;
-
- etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateStar_Context>("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<BLinePoint> 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<const EventMouse*>(&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> 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();
-}
+++ /dev/null
-/* === 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<StateStar_Context>
-{
-public:
- StateStar();
- ~StateStar();
-}; // END of class StateStar
-
-extern StateStar state_star;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_stroke.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- Duckmatic::Push duckmatic_push;
-
- etl::smart_ptr<std::list<synfig::Point> > stroke_data;
-
- etl::smart_ptr<std::list<synfig::Real> > 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateStroke_Context>("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<const EventMouse*>(&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<const EventMouse*>(&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;
- }
-}
+++ /dev/null
-/* === 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 <sigc++/object.h>
-#include "duckmatic.h"
-#include <synfig/blinepoint.h>
-#include <list>
-#include <ETL/smart_ptr>
-#include "eventkey.h"
-#include <gdkmm/types.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 StateStroke_Context;
-
-class StateStroke : public Smach::state<StateStroke_Context>
-{
-public:
- StateStroke();
- ~StateStroke();
-}; // END of class StateStroke
-
-extern StateStroke state_stroke;
-
-struct EventStroke : public Smach::event
-{
- etl::smart_ptr<std::list<synfig::Point> > stroke_data;
- etl::smart_ptr<std::list<synfig::Real> > width_data;
- Gdk::ModifierType modifier;
-
- EventStroke(etl::smart_ptr<std::list<synfig::Point> > stroke_data,
- etl::smart_ptr<std::list<synfig::Real> > 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
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include "state_text.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#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<CanvasView> 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<CanvasView>& get_canvas_view()const{return canvas_view;}
- etl::handle<synfigapp::CanvasInterface> 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<StateText_Context>("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<const EventMouse*>(&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();
-}
+++ /dev/null
-/* === 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<StateText_Context>
-{
-public:
- StateText();
- ~StateText();
-}; // END of class StateText
-
-extern StateText state_text;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <ETL/bezier>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_width.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-
-//#include <synfigapp/value_desc.h>
-#include <synfigapp/main.h>
-
-#include <ETL/clock>
-
-#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<CanvasView> canvas_view_;
- CanvasView::IsWorking is_working;
-
- //Point mouse_pos;
-
- handle<Duck> center;
- handle<Duck> radius;
- handle<Duck> closestpoint;
-
- map<handle<Duck>,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<Duckmatic::Bezier> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateWidth_Context>("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<Duckmatic::Bezier> 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<Duck> p1 = c->p1;
- handle<Duck> p2 = c->p2;
-
- handle<Duck> 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<const EventMouse*>(&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<Duckmatic::Bezier> 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<Point> 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<handle<Duck>,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();
-}
+++ /dev/null
-/* === 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<StateWidth_Context>
-{
-public:
- StateWidth();
- ~StateWidth();
-}; // END of class StateWidth
-
-extern StateWidth state_width;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
+++ /dev/null
-/* === 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 <config.h>
-#endif
-
-#include <sigc++/signal.h>
-#include <sigc++/object.h>
-
-#include <ETL/handle>
-#include <synfig/vector.h>
-
-
-#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 <synfigapp/main.h>
-
-#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<CanvasView> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
- etl::handle<synfigapp::CanvasInterface> 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<StateZoom_Context>("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<const EventBox*>(&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<const EventMouse*>(&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;
-}
+++ /dev/null
-/* === 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<StateZoom_Context>
-{
-public:
- StateZoom();
- ~StateZoom();
-}; // END of class StateZoom
-
-extern StateZoom state_zoom;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_bline.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/spinbutton.h>
+#include <synfig/transform.h>
+#include <synfigapp/main.h>
+
+#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<CanvasView> 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<Duck> curr_duck;
+
+ etl::handle<Duck> next_duck;
+
+ std::list<synfig::ValueNode_Const::Handle> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateBLine_Context>("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<BLinePoint> new_list;
+ std::list<synfig::ValueNode_Const::Handle>::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<const EventMouse*>(&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<const EventMouse*>(&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<synfig::ValueNode_Const::Handle>::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<ValueNode_Const::Handle>::iterator iter;
+
+ handle<WorkArea::Bezier> bezier;
+ handle<WorkArea::Duck> 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<ValueNode_Const::Handle>::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<ValueNode_Const::Handle>::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<ValueNode_Const::Handle>::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<Vector> 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<Vector> > 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<ValueNode_Const::Handle>::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);
+}
--- /dev/null
+/* === 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<StateBLine_Context>
+{
+public:
+ StateBLine();
+ ~StateBLine();
+}; // END of class StateBLine
+
+extern StateBLine state_bline;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_circle.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ Duckmatic::Push duckmatic_push;
+
+ Point point_holder;
+
+ etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateCircle_Context>("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<BLinePoint> 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<const EventMouse*>(&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> 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();
+}
--- /dev/null
+/* === 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<StateCircle_Context>
+{
+public:
+ StateCircle();
+ ~StateCircle();
+}; // END of class StateCircle
+
+extern StateCircle state_circle;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_draw.h"
+#include "state_stroke.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <synfig/valuenode_composite.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+
+#include <synfigapp/blineconvert.h>
+#include <synfigapp/main.h>
+
+#include <ETL/gaussian>
+#include "dialog_tooloptions.h"
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/button.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/scale.h>
+#include <sigc++/connection.h>
+
+#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<std::list<synfig::Point> > StrokeData;
+ typedef etl::smart_ptr<std::list<synfig::Real> > WidthData;
+
+ typedef list< pair<StrokeData,WidthData> > StrokeQueue;
+
+ StrokeQueue stroke_queue;
+
+
+ etl::handle<CanvasView> 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<std::list<synfig::Point> > > 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<synfig::BLinePoint> bline,bool loop_bline_flag,float radius);
+
+ Smach::event_result new_region(std::list<synfig::BLinePoint> bline,synfig::Real radius);
+
+ Smach::event_result extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
+ Smach::event_result extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
+ void reverse_bline(std::list<synfig::BLinePoint> &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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateDraw_Context>("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<const EventMouse*>(&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<const EventStroke*>(&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<StrokeData,WidthData>(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<StrokeData,WidthData> 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<synfig::Real>::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<synfig::BLinePoint> 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<synfig::BLinePoint> 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<Duck> start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX));
+ etl::handle<Duck> finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX));
+
+ // 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<synfig::BLinePoint> trans_bline;
+
+ {
+ std::list<synfig::BLinePoint>::iterator iter;
+ const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+
+ for(iter=bline.begin();iter!=bline.end();++iter)
+ {
+ BLinePoint bline_point(*iter);
+ Point new_vertex(transform.unperform(bline_point.get_vertex()));
+
+ bline_point.set_tangent1(
+ transform.unperform(
+ bline_point.get_tangent1()+bline_point.get_vertex()
+ ) -new_vertex
+ );
+
+ bline_point.set_tangent2(
+ transform.unperform(
+ bline_point.get_tangent2()+bline_point.get_vertex()
+ ) -new_vertex
+ );
+
+ 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<synfigapp::ValueDesc>& vertex_list,
+ std::string title, int current)
+{
+ std::list<synfigapp::ValueDesc>::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<synfig::BLinePoint> bline, synfig::Real radius)
+{
+ // Create the action group
+ synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Define Region"));
+
+ std::list<synfigapp::ValueDesc> 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<synfig::BLinePoint>::iterator iter;
+ for(iter=bline.begin();iter!=bline.end();++iter)
+ {
+ etl::handle<Duck> 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<synfigapp::ValueDesc>::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<synfigapp::ValueDesc>::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<synfigapp::ValueDesc>::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()-1)
+ // {
+ // debug_show_vertex_list(i, vertex_list,
+ // strprintf("same parent, different points this %d < next-1 %d",
+ // value_desc.get_index(), ((value_next.get_index()-1))),
+ // current);
+ // for (int index = value_desc.get_index()+1; index < value_next.get_index(); index++)
+ // {
+ // printf("inserting up %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;
+ // }
+ // if(value_next.get_index()<value_desc.get_index()-1)
+ // {
+ // debug_show_vertex_list(i, vertex_list,
+ // strprintf("same parent, different points next %d < this-1 %d",
+ // value_next.get_index(), ((value_desc.get_index()-1))),
+ // current);
+ // for (int index = value_desc.get_index()-1; 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()<radius*radius)
+ {
+ printf("in one - it's close\n");
+ ValueNode_Composite::Handle value_node;
+ ValueNode_Composite::Handle value_node_next;
+ value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node().clone());
+ value_node_next=ValueNode_Composite::Handle::cast_dynamic(value_next.get_value_node().clone());
+ if(!value_node || !value_node_next)
+ {
+ synfig::info(__FILE__":%d: Unable to properly connect blines.",__LINE__);
+ continue;
+ }
+ // \todo if next isn't split, don't we want to copy its 'Tangent 1' instead?
+ value_node->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()<LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->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<synfigapp::ValueDesc>::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<std::list<synfig::Point> > >::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<synfig::BLinePoint> 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<synfig::BLinePoint>::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<synfig::BLinePoint> 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<synfig::BLinePoint>::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<synfig::BLinePoint> &bline)
+{
+ int i;
+
+ std::list<synfig::BLinePoint>::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);
+}
--- /dev/null
+/* === 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<StateDraw_Context>
+{
+public:
+ StateDraw();
+ ~StateDraw();
+}; // END of class StateDraw
+
+extern StateDraw state_draw;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include "state_eyedrop.h"
+#include "state_normal.h"
+#include "workarea.h"
+#include <synfig/context.h>
+#include "app.h"
+#include "dialogs/dialog_color.h"
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "canvasview.h"
+#include <synfigapp/main.h>
+
+#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<StateEyedrop_Context>("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<const EventMouse*>(&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;
+}
--- /dev/null
+/* === 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<StateEyedrop_Context>
+{
+public:
+ StateEyedrop();
+ ~StateEyedrop();
+}; // END of class StateEyedrop
+
+extern StateEyedrop state_eyedrop;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include "state_fill.h"
+#include "state_normal.h"
+#include "workarea.h"
+#include <synfig/context.h>
+#include "app.h"
+#include "dialogs/dialog_color.h"
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "canvasview.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> get_canvas_view()const{return canvas_view;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateFill_Context>("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<const EventLayerClick*>(&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;
+}
--- /dev/null
+/* === 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<StateFill_Context>
+{
+public:
+ StateFill();
+ ~StateFill();
+}; // END of class StateFill
+
+extern StateFill state_fill;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_gradient.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ Duckmatic::Push duckmatic_push;
+
+ synfigapp::Settings& settings;
+
+ Point point_holder;
+
+ etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateGradient_Context>("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<const EventMouse*>(&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> 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<Duckmatic::Bezier> 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();
+}
--- /dev/null
+/* === 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<StateGradient_Context>
+{
+public:
+ StateGradient();
+ ~StateGradient();
+}; // END of class StateGradient
+
+extern StateGradient state_gradient;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_mirror.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfigapp/main.h>
+
+#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<synfig::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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ synfigapp::Settings& settings;
+
+ sigc::connection keypress_connect;
+ sigc::connection keyrelease_connect;
+
+ etl::handle<DuckDrag_Mirror> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateMirror_Context>("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;
+}
--- /dev/null
+/* === 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<StateMirror_Context>
+{
+public:
+ StateMirror();
+ ~StateMirror();
+}; // END of class StateMirror
+
+extern StateMirror state_mirror;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_animated.h>
+#include <synfig/valuenode_blinecalcvertex.h>
+#include <synfig/valuenode_composite.h>
+#include <synfig/valuenode_const.h>
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfig/angle.h>
+#include <synfigapp/main.h>
+
+#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<synfig::Vector> last_;
+ std::vector<synfig::Vector> positions;
+
+
+ bool bad_drag;
+ bool move_only;
+
+public:
+ etl::handle<CanvasView> 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<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+};
+
+
+class studio::StateNormal_Context : public sigc::trackable
+{
+ etl::handle<CanvasView> canvas_view_;
+
+ synfigapp::Settings& settings;
+
+ sigc::connection keypress_connect;
+ sigc::connection keyrelease_connect;
+
+ etl::handle<DuckDrag_Combo> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateNormal_Context>("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<etl::handle<Duck> >::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]>-EPSILON)
+ vect[0]=1;
+ if(vect[1]<EPSILON && 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<const EventMouse*>(&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<const EventLayerClick*>(&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::Handle> layer_list(canvas_view_->get_selection_manager()->get_selected_layers());
+ std::set<Layer::Handle> layers(layer_list.begin(),layer_list.end());
+ if(layers.count(event.layer))
+ {
+ layers.erase(event.layer);
+ layer_list=std::list<Layer::Handle>(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<synfigapp::ValueDesc> 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<synfigapp::ValueDesc>::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<const EventMouse*>(&x));
+
+ std::list<synfigapp::ValueDesc> 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;
+}
+
+
--- /dev/null
+/* === 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<StateNormal_Context>
+{
+public:
+ StateNormal();
+ ~StateNormal();
+}; // END of class StateNormal
+
+extern StateNormal state_normal;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_polygon.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ bool prev_table_status;
+ bool prev_workarea_layer_status_;
+
+ Gtk::Menu menu;
+
+ Duckmatic::Push duckmatic_push;
+
+ std::list<synfig::Point> polygon_point_list;
+ synfigapp::Settings& settings;
+
+
+ bool on_polygon_duck_change(const synfig::Point &point, std::list<synfig::Point>::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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StatePolygon_Context>("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<BLinePoint> new_list;
+ std::list<synfig::Point>::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<const EventMouse*>(&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<synfig::Point>::iterator iter=polygon_point_list.begin();
+
+ etl::handle<WorkArea::Duck> 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<WorkArea::Bezier> 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<synfig::Point>::iterator iter)
+{
+ *iter=point;
+ return true;
+}
--- /dev/null
+/* === 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<StatePolygon_Context>
+{
+public:
+ StatePolygon();
+ ~StatePolygon();
+}; // END of class StatePolygon
+
+extern StatePolygon state_polygon;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_rectangle.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ Duckmatic::Push duckmatic_push;
+
+ Point point_holder;
+
+ etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateRectangle_Context>("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<BLinePoint> 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<const EventMouse*>(&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> 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();
+}
--- /dev/null
+/* === 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<StateRectangle_Context>
+{
+public:
+ StateRectangle();
+ ~StateRectangle();
+}; // END of class StateRectangle
+
+extern StateRectangle state_rectangle;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_rotate.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfig/angle.h>
+#include <synfigapp/main.h>
+
+#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<synfig::Vector> positions;
+
+
+ bool bad_drag;
+ bool move_only;
+
+public:
+ etl::handle<CanvasView> 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<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+};
+
+
+class studio::StateRotate_Context : public sigc::trackable
+{
+ etl::handle<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ synfigapp::Settings& settings;
+
+ etl::handle<DuckDrag_Rotate> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateRotate_Context>("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<etl::handle<Duck> >::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<etl::handle<Duck> >::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;
+ }
+}
--- /dev/null
+/* === 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<StateRotate_Context>
+{
+public:
+ StateRotate();
+ ~StateRotate();
+}; // END of class StateRotate
+
+extern StateRotate state_rotate;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_scale.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfigapp/main.h>
+
+#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<synfig::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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ synfigapp::Settings& settings;
+
+ etl::handle<DuckDrag_Scale> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateScale_Context>("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<etl::handle<Duck> >::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<etl::handle<Duck> >::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]>-EPSILON)
+ vect[0]=1;
+ if(vect[1]<EPSILON && 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;
+ }
+}
--- /dev/null
+/* === 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<StateScale_Context>
+{
+public:
+ StateScale();
+ ~StateScale();
+}; // END of class StateScale
+
+extern StateScale state_scale;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_sketch.h"
+#include "state_normal.h"
+#include "state_stroke.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+
+#include <synfigapp/blineconvert.h>
+#include <synfigapp/main.h>
+
+#include <ETL/gaussian>
+
+#include "dialog_tooloptions.h"
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/button.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/actiongroup.h>
+
+#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<Gtk::ActionGroup> action_group;
+
+ etl::handle<CanvasView> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateSketch_Context>("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 =
+ "<ui>"
+ " <toolbar action='toolbar-sketch'>"
+ " <toolitem action='sketch-undo' />"
+ " <toolitem action='sketch-clear' />"
+ " <toolitem action='sketch-save-as' />"
+ " <toolitem action='sketch-open' />"
+ " </toolbar>"
+ "</ui>";
+
+ 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<Gtk::Toolbar*>(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<const EventMouse*>(&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<const EventStroke*>(&x));
+
+ assert(event.stroke_data);
+
+ get_work_area()->add_persistent_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
+
+ return Smach::RESULT_ACCEPT;
+}
--- /dev/null
+/* === 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<StateSketch_Context>
+{
+public:
+ StateSketch();
+ ~StateSketch();
+}; // END of class StateSketch
+
+extern StateSketch state_sketch;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_blinecalcvertex.h>
+#include <synfig/valuenode_composite.h>
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_smoothmove.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "onemoment.h"
+#include <synfigapp/main.h>
+
+#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<synfig::Vector> last_;
+ std::vector<synfig::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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ //Duckmatic::Push duckmatic_push;
+
+ synfigapp::Settings& settings;
+
+ etl::handle<DuckDrag_SmoothMove> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateSmoothMove_Context>("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<OneMoment> 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;
+ }
+}
--- /dev/null
+/* === 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<StateSmoothMove_Context>
+{
+public:
+ StateSmoothMove();
+ ~StateSmoothMove();
+}; // END of class StateSmoothMove
+
+extern StateSmoothMove state_smooth_move;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_star.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ Duckmatic::Push duckmatic_push;
+
+ Point point_holder;
+
+ etl::handle<Duck> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateStar_Context>("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<BLinePoint> 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<const EventMouse*>(&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> 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();
+}
--- /dev/null
+/* === 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<StateStar_Context>
+{
+public:
+ StateStar();
+ ~StateStar();
+}; // END of class StateStar
+
+extern StateStar state_star;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_stroke.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ Duckmatic::Push duckmatic_push;
+
+ etl::smart_ptr<std::list<synfig::Point> > stroke_data;
+
+ etl::smart_ptr<std::list<synfig::Real> > 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateStroke_Context>("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<const EventMouse*>(&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<const EventMouse*>(&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;
+ }
+}
--- /dev/null
+/* === 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 <sigc++/object.h>
+#include "duckmatic.h"
+#include <synfig/blinepoint.h>
+#include <list>
+#include <ETL/smart_ptr>
+#include "eventkey.h"
+#include <gdkmm/types.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 StateStroke_Context;
+
+class StateStroke : public Smach::state<StateStroke_Context>
+{
+public:
+ StateStroke();
+ ~StateStroke();
+}; // END of class StateStroke
+
+extern StateStroke state_stroke;
+
+struct EventStroke : public Smach::event
+{
+ etl::smart_ptr<std::list<synfig::Point> > stroke_data;
+ etl::smart_ptr<std::list<synfig::Real> > width_data;
+ Gdk::ModifierType modifier;
+
+ EventStroke(etl::smart_ptr<std::list<synfig::Point> > stroke_data,
+ etl::smart_ptr<std::list<synfig::Real> > 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
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include "state_text.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#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<CanvasView> 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<CanvasView>& get_canvas_view()const{return canvas_view;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateText_Context>("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<const EventMouse*>(&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();
+}
--- /dev/null
+/* === 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<StateText_Context>
+{
+public:
+ StateText();
+ ~StateText();
+}; // END of class StateText
+
+extern StateText state_text;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <ETL/bezier>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_width.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+
+//#include <synfigapp/value_desc.h>
+#include <synfigapp/main.h>
+
+#include <ETL/clock>
+
+#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<CanvasView> canvas_view_;
+ CanvasView::IsWorking is_working;
+
+ //Point mouse_pos;
+
+ handle<Duck> center;
+ handle<Duck> radius;
+ handle<Duck> closestpoint;
+
+ map<handle<Duck>,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<Duckmatic::Bezier> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateWidth_Context>("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<Duckmatic::Bezier> 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<Duck> p1 = c->p1;
+ handle<Duck> p2 = c->p2;
+
+ handle<Duck> 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<const EventMouse*>(&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<Duckmatic::Bezier> 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<Point> 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<handle<Duck>,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();
+}
--- /dev/null
+/* === 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<StateWidth_Context>
+{
+public:
+ StateWidth();
+ ~StateWidth();
+}; // END of class StateWidth
+
+extern StateWidth state_width;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
--- /dev/null
+/* === 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 <config.h>
+#endif
+
+#include <sigc++/signal.h>
+#include <sigc++/object.h>
+
+#include <ETL/handle>
+#include <synfig/vector.h>
+
+
+#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 <synfigapp/main.h>
+
+#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<CanvasView> 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<CanvasView>& get_canvas_view()const{return canvas_view_;}
+ etl::handle<synfigapp::CanvasInterface> 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<StateZoom_Context>("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<const EventBox*>(&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<const EventMouse*>(&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;
+}
--- /dev/null
+/* === 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<StateZoom_Context>
+{
+public:
+ StateZoom();
+ ~StateZoom();
+}; // END of class StateZoom
+
+extern StateZoom state_zoom;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif