Initial support for duck drags of more than 180 degrees.
[synfig.git] / synfig-studio / trunk / src / gtkmm / duck.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file duck.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "duck.h"
33 #include <ETL/misc>
34
35 #endif
36
37 /* === U S I N G =========================================================== */
38
39 using namespace std;
40 using namespace etl;
41 using namespace synfig;
42 using namespace studio;
43
44 /* === M A C R O S ========================================================= */
45
46 /* === G L O B A L S ======================================================= */
47
48 int studio::Duck::duck_count(0);
49
50 struct _DuckCounter
51 {
52         static int counter;
53         ~_DuckCounter()
54         {
55                 if(counter)
56                         synfig::error("%d ducks not yet deleted!",counter);
57         }
58 } _duck_counter;
59
60 int _DuckCounter::counter(0);
61
62
63 /* === P R O C E D U R E S ================================================= */
64
65 /* === M E T H O D S ======================================================= */
66
67 Duck::Duck():
68         rotations(synfig::Angle::deg(0)),
69         origin(0,0),
70         scalar(1),
71         editable(false),
72         radius_(false),
73         tangent_(false)
74 { duck_count++; _DuckCounter::counter++; }
75
76 Duck::Duck(const synfig::Point &point):
77         type_(TYPE_NONE),
78         point(point),
79         rotations(synfig::Angle::deg(0)),
80         origin(0,0),
81         scalar(1),
82         guid_(0),
83         editable(false),
84         radius_(false),
85         tangent_(false)
86 { duck_count++; _DuckCounter::counter++;}
87
88 Duck::Duck(const synfig::Point &point,const synfig::Point &origin):
89         point(point),
90         rotations(synfig::Angle::deg(0)),
91         origin(origin),
92         scalar(1),
93         guid_(0),
94         editable(false),
95         radius_(true),
96         tangent_(false)
97 { duck_count++; _DuckCounter::counter++;}
98
99 Duck::~Duck() { duck_count--; _DuckCounter::counter--;}
100
101 synfig::GUID
102 Duck::get_data_guid()const
103 {
104         if(value_desc_.is_value_node())
105                 return value_desc_.get_value_node()->get_guid();
106         return GUID::hasher(get_name());
107 }
108
109 void
110 Duck::set_name(const synfig::String &x)
111 {
112         name=x;
113         if(guid_==GUID::zero())
114         {
115                 guid_=GUID::hasher(name);
116         }
117 }
118
119
120 bool
121 Duck::operator==(const Duck &rhs)const
122 {
123         if(this==&rhs)
124                 return true;
125         return
126                 name==rhs.name &&
127                 scalar==rhs.scalar &&
128                 type_==rhs.type_ &&
129                 transform_stack_.size()==rhs.transform_stack_.size();
130                 //true;
131                 //(origin_duck?*origin_duck==*rhs.origin_duck:origin==rhs.origin) &&
132                 //(shared_point?*shared_point==*rhs.shared_point:point==rhs.point) ;
133 }
134
135 synfig::Point
136 Duck::get_trans_point()const
137 {
138         return transform_stack_.perform(get_sub_trans_point());
139 }
140
141 void
142 Duck::set_trans_point(const synfig::Point &x)
143 {
144         set_sub_trans_point(transform_stack_.unperform(x));
145 }
146
147 //! Sets the origin point.
148 void
149 Duck::set_origin(const synfig::Point &x)
150 {
151         origin=x; origin_duck=0;
152 }
153
154 //! Sets the origin point as another duck
155 void
156 Duck::set_origin(const etl::handle<Duck> &x)
157 {
158         origin_duck=x;
159 }
160
161 //! Retrieves the origin location
162 synfig::Point
163 Duck::get_origin()const
164 {
165         return origin_duck?origin_duck->get_point():origin;
166 }
167
168 //! Retrieves the origin duck
169 const etl::handle<Duck> &
170 Duck::get_origin_duck() const
171 {
172         return origin_duck;
173 }
174
175 //! Retrieves the origin location
176 synfig::Point
177 Duck::get_trans_origin()const
178 {
179         return transform_stack_.perform(get_sub_trans_origin());
180 }
181
182 synfig::Point
183 Duck::get_sub_trans_point()const
184 {
185         return get_point()*get_scalar()+get_sub_trans_origin();
186 }
187
188 void
189 Duck::set_sub_trans_point(const synfig::Point &x)
190 {
191         if (get_type() == Duck::TYPE_TANGENT ||
192                 get_type() == Duck::TYPE_ANGLE)
193         {
194                 Angle old_angle = get_point().angle();
195                 set_point((x-get_sub_trans_origin())/get_scalar());
196                 Angle new_angle = get_point().angle();
197                 int old_quarters = round_to_int(Angle::deg(rotations).get()/90);
198                 rotations += new_angle.dist(old_angle);
199                 int new_quarters = round_to_int(Angle::deg(rotations).get()/90);
200                 if (old_quarters != new_quarters)
201                         synfig::info("rotation: %.2f turns", new_quarters/4.0);
202         }
203         else
204                 set_point((x-get_sub_trans_origin())/get_scalar());
205 }
206
207 synfig::Point
208 Duck::get_sub_trans_origin()const
209 {
210         return origin_duck?origin_duck->get_sub_trans_point():origin;
211 }