source: synfigstudio/trunk/fuentes/src/gui/states/state_smoothmove.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 10.3 KB
Line 
1/* === S Y N F I G ========================================================= */
2/*!     \file state_smoothmove.cpp
3**      \brief Template File
4**
5**      $Id$
6**
7**      \legal
8**      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9**  Copyright (c) 2008 Chris Moore
10**      Copyright (c) 2009 Nikita Kitaev
11**  Copyright (c) 2010 Carlos López
12**
13**      This package is free software; you can redistribute it and/or
14**      modify it under the terms of the GNU General Public License as
15**      published by the Free Software Foundation; either version 2 of
16**      the License, or (at your option) any later version.
17**
18**      This package is distributed in the hope that it will be useful,
19**      but WITHOUT ANY WARRANTY; without even the implied warranty of
20**      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21**      General Public License for more details.
22**      \endlegal
23*/
24/* ========================================================================= */
25
26/* === H E A D E R S ======================================================= */
27
28#ifdef USING_PCH
29#       include "pch.h"
30#else
31#ifdef HAVE_CONFIG_H
32#       include <config.h>
33#endif
34
35#include <gtkmm/dialog.h>
36#include <gtkmm/entry.h>
37
38#include <synfig/valuenodes/valuenode_blinecalcvertex.h>
39#include <synfig/valuenodes/valuenode_composite.h>
40#include <synfig/valuenodes/valuenode_dynamiclist.h>
41#include <synfigapp/action_system.h>
42
43#include "state_smoothmove.h"
44#include "state_normal.h"
45#include "canvasview.h"
46#include "workarea.h"
47#include "app.h"
48
49#include <synfigapp/action.h>
50#include "event_mouse.h"
51#include "event_layerclick.h"
52#include "docks/dock_toolbox.h"
53#include "docks/dialog_tooloptions.h"
54#include "duck.h"
55#include "onemoment.h"
56#include <synfigapp/main.h>
57
58#include "general.h"
59
60#endif
61
62/* === U S I N G =========================================================== */
63
64using namespace std;
65using namespace etl;
66using namespace synfig;
67using namespace studio;
68
69/* === M A C R O S ========================================================= */
70
71/* === G L O B A L S ======================================================= */
72
73StateSmoothMove studio::state_smooth_move;
74
75/* === C L A S S E S & S T R U C T S ======================================= */
76
77class DuckDrag_SmoothMove : public DuckDrag_Base
78{
79        float radius;
80
81        synfig::Vector last_translate_;
82        synfig::Vector drag_offset_;
83        synfig::Vector snap;
84
85        std::vector<synfig::Vector> last_;
86        std::vector<synfig::Vector> positions;
87
88public:
89        DuckDrag_SmoothMove();
90        void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
91        bool end_duck_drag(Duckmatic* duckmatic);
92        void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
93
94        void set_radius(float x) { radius=x; }
95        float get_radius()const { return radius; }
96};
97
98
99class studio::StateSmoothMove_Context : public sigc::trackable
100{
101        etl::handle<CanvasView> canvas_view_;
102        CanvasView::IsWorking is_working;
103
104        //Duckmatic::Push duckmatic_push;
105
106        synfigapp::Settings& settings;
107
108        etl::handle<DuckDrag_SmoothMove> duck_dragger_;
109
110        Gtk::Table options_table;
111
112        Glib::RefPtr<Gtk::Adjustment> adj_radius;
113        Gtk::SpinButton  spin_radius;
114
115        float pressure;
116
117public:
118        float get_radius()const { return adj_radius->get_value(); }
119        void set_radius(float x) { return adj_radius->set_value(x); }
120
121        void refresh_radius() { duck_dragger_->set_radius(get_radius()*pressure); }
122
123        Smach::event_result event_stop_handler(const Smach::event& x);
124
125        Smach::event_result event_refresh_tool_options(const Smach::event& x);
126
127        void refresh_tool_options();
128
129        StateSmoothMove_Context(CanvasView* canvas_view);
130
131        ~StateSmoothMove_Context();
132
133        const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
134        etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
135        synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
136        WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
137
138        void load_settings();
139        void save_settings();
140};      // END of class StateSmoothMove_Context
141
142/* === M E T H O D S ======================================================= */
143
144StateSmoothMove::StateSmoothMove():
145        Smach::state<StateSmoothMove_Context>("smooth_move")
146{
147        insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSmoothMove_Context::event_refresh_tool_options));
148        insert(event_def(EVENT_STOP,&StateSmoothMove_Context::event_stop_handler));
149}
150
151StateSmoothMove::~StateSmoothMove()
152{
153}
154
155void
156StateSmoothMove_Context::load_settings()
157{
158        try
159        {
160                synfig::ChangeLocale change_locale(LC_NUMERIC, "C");
161                String value;
162
163                if(settings.get_value("smooth_move.radius",value))
164                        set_radius(atof(value.c_str()));
165                else
166                        set_radius(1.0f);
167        }
168        catch(...)
169        {
170                synfig::warning("State SmothMove: Caught exception when attempting to load settings.");
171        }
172}
173
174void
175StateSmoothMove_Context::save_settings()
176{
177        try
178        {
179        synfig::ChangeLocale change_locale(LC_NUMERIC, "C");
180                settings.set_value("smooth_move.radius",strprintf("%f",get_radius()));
181        }
182        catch(...)
183        {
184                synfig::warning("State SmoothMove: Caught exception when attempting to save settings.");
185        }
186}
187
188StateSmoothMove_Context::StateSmoothMove_Context(CanvasView* canvas_view):
189        canvas_view_(canvas_view),
190        is_working(*canvas_view),
191//      duckmatic_push(get_work_area()),
192        settings(synfigapp::Main::get_selected_input_device()->settings()),
193        duck_dragger_(new DuckDrag_SmoothMove()),
194        adj_radius(Gtk::Adjustment::create(1,0,100000,0.01,0.1)),
195        spin_radius(adj_radius,0.1,3)
196{
197        pressure=1.0f;
198
199        // Set up the tool options dialog
200        options_table.attach(*manage(new Gtk::Label(_("SmoothMove Tool"))),     0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
201        options_table.attach(*manage(new Gtk::Label(_("Radius"))),                      0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
202        options_table.attach(spin_radius,                                                                       0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
203
204        spin_radius.signal_value_changed().connect(sigc::mem_fun(*this,&StateSmoothMove_Context::refresh_radius));
205
206        options_table.show_all();
207        refresh_tool_options();
208        //App::dialog_tool_options->set_widget(options_table);
209        App::dialog_tool_options->present();
210
211        get_work_area()->set_allow_layer_clicks(true);
212        get_work_area()->set_duck_dragger(duck_dragger_);
213
214        App::dock_toolbox->refresh();
215
216        get_work_area()->set_cursor(Gdk::FLEUR);
217        //get_work_area()->reset_cursor();
218
219        load_settings();
220}
221
222void
223StateSmoothMove_Context::refresh_tool_options()
224{
225        App::dialog_tool_options->clear();
226        App::dialog_tool_options->set_widget(options_table);
227        App::dialog_tool_options->set_local_name(_("Smooth Move"));
228        App::dialog_tool_options->set_name("smooth_move");
229}
230
231Smach::event_result
232StateSmoothMove_Context::event_refresh_tool_options(const Smach::event& /*x*/)
233{
234        refresh_tool_options();
235        return Smach::RESULT_ACCEPT;
236}
237
238Smach::event_result
239StateSmoothMove_Context::event_stop_handler(const Smach::event& /*x*/)
240{
241        throw &state_normal;
242        return Smach::RESULT_OK;
243}
244
245StateSmoothMove_Context::~StateSmoothMove_Context()
246{
247        save_settings();
248
249        get_work_area()->clear_duck_dragger();
250        get_work_area()->reset_cursor();
251
252        App::dialog_tool_options->clear();
253
254        App::dock_toolbox->refresh();
255}
256
257
258
259
260DuckDrag_SmoothMove::DuckDrag_SmoothMove():radius(1.0f)
261{
262}
263
264void
265DuckDrag_SmoothMove::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
266{
267        last_translate_=Vector(0,0);
268                drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
269
270                //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
271                //snap=offset-drag_offset_;
272                snap=Vector(0,0);
273
274        last_.clear();
275        positions.clear();
276        const DuckList selected_ducks(duckmatic->get_selected_ducks());
277        DuckList::const_iterator iter;
278        int i;
279        for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
280        {
281                last_.push_back(Vector(0,0));
282                positions.push_back((*iter)->get_trans_point());
283        }
284}
285
286void
287DuckDrag_SmoothMove::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
288{
289        const DuckList selected_ducks(duckmatic->get_selected_ducks());
290        DuckList::const_iterator iter;
291        synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_+snap);
292
293        int i;
294
295        Time time(duckmatic->get_time());
296
297        // process vertex and position ducks first
298        for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
299        {
300                // skip this duck if it is NOT a vertex or a position
301                if (((*iter)->get_type() != Duck::TYPE_VERTEX &&
302                         (*iter)->get_type() != Duck::TYPE_POSITION))
303                        continue;
304                Point p(positions[i]);
305
306                float dist(1.0f-(p-drag_offset_).mag()/get_radius());
307                if(dist<0)
308                        dist=0;
309
310                last_[i]=vect*dist;
311                (*iter)->set_trans_point(p+last_[i], time);
312        }
313
314        // then process non vertex and non position ducks
315        for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
316        {
317                // skip this duck if it IS a vertex or a position
318                if (!((*iter)->get_type() != Duck::TYPE_VERTEX &&
319                         (*iter)->get_type() != Duck::TYPE_POSITION))
320                        continue;
321                Point p(positions[i]);
322
323                float dist(1.0f-(p-drag_offset_).mag()/get_radius());
324                if(dist<0)
325                        dist=0;
326
327                last_[i]=vect*dist;
328                (*iter)->set_trans_point(p+last_[i], time);
329        }
330
331        // then patch up the tangents for the vertices we've moved
332        duckmatic->update_ducks();
333
334        last_translate_=vect;
335        //snap=Vector(0,0);
336}
337
338bool
339DuckDrag_SmoothMove::end_duck_drag(Duckmatic* duckmatic)
340{
341        //synfig::info("end_duck_drag(): Diff= %f",last_translate_.mag());
342        if(last_translate_.mag()>0.0001)
343        {
344                const DuckList selected_ducks(duckmatic->get_selected_ducks());
345                DuckList::const_iterator iter;
346
347                int i;
348
349                smart_ptr<OneMoment> wait;if(selected_ducks.size()>20)wait.spawn();
350
351                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
352                {
353                        if(last_[i].mag()>0.0001)
354                                {
355                                if ((*iter)->get_type() == Duck::TYPE_ANGLE)
356                                        {
357                                                if(!(*iter)->signal_edited()(**iter))
358                                                {
359                                                        throw String("Bad edit");
360                                                }
361                                        }
362                                        else if (App::restrict_radius_ducks &&
363                                                         (*iter)->is_radius())
364                                        {
365                                                Point point((*iter)->get_point());
366                                                bool changed = false;
367
368                                                if (point[0] < 0)
369                                                {
370                                                        point[0] = 0;
371                                                        changed = true;
372                                                }
373                                                if (point[1] < 0)
374                                                {
375                                                        point[1] = 0;
376                                                        changed = true;
377                                                }
378
379                                                if (changed) (*iter)->set_point(point);
380
381                                                if(!(*iter)->signal_edited()(**iter))
382                                                {
383                                                        throw String("Bad edit");
384                                                }
385                                        }
386                                        else
387                                        {
388                                                if(!(*iter)->signal_edited()(**iter))
389                                                {
390                                                        throw String("Bad edit");
391                                                }
392                                        }
393                                }
394                }
395                //duckmatic->get_selected_ducks()=new_set;
396                //duckmatic->refresh_selected_ducks();
397                return true;
398        }
399        else
400        {
401                duckmatic->signal_user_click_selected_ducks(0);
402                return false;
403        }
404}
Note: See TracBrowser for help on using the repository browser.