]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/entity/rotation.h
Merge branch 'transfilterfix' into 'master'
[xonotic/netradiant.git] / plugins / entity / rotation.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_ROTATION_H )
23 #define INCLUDED_ROTATION_H
24
25 #include "ientity.h"
26
27 #include "stream/stringstream.h"
28 #include "math/quaternion.h"
29 #include "generic/callback.h"
30 #include "stringio.h"
31
32 #include "angle.h"
33
34 typedef float Float9[9];
35
36 inline void default_rotation(Float9 rotation)
37 {
38     rotation[0] = 1;
39     rotation[1] = 0;
40     rotation[2] = 0;
41     rotation[3] = 0;
42     rotation[4] = 1;
43     rotation[5] = 0;
44     rotation[6] = 0;
45     rotation[7] = 0;
46     rotation[8] = 1;
47 }
48
49 inline void write_rotation(const Float9 rotation, Entity *entity, const char *key = "rotation")
50 {
51     if (rotation[0] == 1
52         && rotation[1] == 0
53         && rotation[2] == 0
54         && rotation[3] == 0
55         && rotation[4] == 1
56         && rotation[5] == 0
57         && rotation[6] == 0
58         && rotation[7] == 0
59         && rotation[8] == 1) {
60         entity->setKeyValue(key, "");
61     } else {
62         StringOutputStream value(256);
63         value << rotation[0] << ' '
64               << rotation[1] << ' '
65               << rotation[2] << ' '
66               << rotation[3] << ' '
67               << rotation[4] << ' '
68               << rotation[5] << ' '
69               << rotation[6] << ' '
70               << rotation[7] << ' '
71               << rotation[8];
72         entity->setKeyValue(key, value.c_str());
73     }
74 }
75
76 inline void read_rotation(Float9 rotation, const char *value)
77 {
78     if (!string_parse_vector(value, rotation, rotation + 9)) {
79         default_rotation(rotation);
80     }
81 }
82
83 inline Matrix4 rotation_toMatrix(const Float9 rotation)
84 {
85     return Matrix4(
86             rotation[0],
87             rotation[1],
88             rotation[2],
89             0,
90             rotation[3],
91             rotation[4],
92             rotation[5],
93             0,
94             rotation[6],
95             rotation[7],
96             rotation[8],
97             0,
98             0,
99             0,
100             0,
101             1
102     );
103 }
104
105 inline void rotation_fromMatrix(Float9 rotation, const Matrix4 &matrix)
106 {
107     rotation[0] = matrix.xx();
108     rotation[1] = matrix.xy();
109     rotation[2] = matrix.xz();
110     rotation[3] = matrix.yx();
111     rotation[4] = matrix.yy();
112     rotation[5] = matrix.yz();
113     rotation[6] = matrix.zx();
114     rotation[7] = matrix.zy();
115     rotation[8] = matrix.zz();
116 }
117
118 inline void rotation_assign(Float9 rotation, const Float9 other)
119 {
120     rotation[0] = other[0];
121     rotation[1] = other[1];
122     rotation[2] = other[2];
123     rotation[3] = other[3];
124     rotation[4] = other[4];
125     rotation[5] = other[5];
126     rotation[6] = other[6];
127     rotation[7] = other[7];
128     rotation[8] = other[8];
129 }
130
131 inline void rotation_rotate(Float9 rotation, const Quaternion &rotate)
132 {
133     rotation_fromMatrix(rotation,
134                         matrix4_multiplied_by_matrix4(
135                                 rotation_toMatrix(rotation),
136                                 matrix4_rotation_for_quaternion_quantised(rotate)
137                         )
138     );
139 }
140
141 inline void read_angle(Float9 rotation, const char *value)
142 {
143     float angle;
144     if (!string_parse_float(value, angle)) {
145         default_rotation(rotation);
146     } else {
147         rotation_fromMatrix(rotation, matrix4_rotation_for_z_degrees(angle));
148     }
149 }
150
151 class RotationKey {
152     Callback<void()> m_rotationChanged;
153 public:
154     Float9 m_rotation;
155
156
157     RotationKey(const Callback<void()> &rotationChanged)
158             : m_rotationChanged(rotationChanged)
159     {
160         default_rotation(m_rotation);
161     }
162
163     void angleChanged(const char *value)
164     {
165         read_angle(m_rotation, value);
166         m_rotationChanged();
167     }
168
169     typedef MemberCaller<RotationKey, void(const char *), &RotationKey::angleChanged> AngleChangedCaller;
170
171     void rotationChanged(const char *value)
172     {
173         read_rotation(m_rotation, value);
174         m_rotationChanged();
175     }
176
177     typedef MemberCaller<RotationKey, void(const char *), &RotationKey::rotationChanged> RotationChangedCaller;
178
179     void write(Entity *entity) const
180     {
181         Vector3 euler = matrix4_get_rotation_euler_xyz_degrees(rotation_toMatrix(m_rotation));
182         if (euler[0] == 0 && euler[1] == 0) {
183             entity->setKeyValue("rotation", "");
184             write_angle(euler[2], entity);
185         } else {
186             entity->setKeyValue("angle", "");
187             write_rotation(m_rotation, entity);
188         }
189     }
190 };
191
192 #endif