4c566d96f420dd5264a6f509b3920160543c791f
[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         rotation[0] = 1;
38         rotation[1] = 0;
39         rotation[2] = 0;
40         rotation[3] = 0;
41         rotation[4] = 1;
42         rotation[5] = 0;
43         rotation[6] = 0;
44         rotation[7] = 0;
45         rotation[8] = 1;
46 }
47 inline void write_rotation( const Float9 rotation, Entity* entity, const char* key = "rotation" ){
48         if ( rotation[0] == 1
49                  && rotation[1] == 0
50                  && rotation[2] == 0
51                  && rotation[3] == 0
52                  && rotation[4] == 1
53                  && rotation[5] == 0
54                  && rotation[6] == 0
55                  && rotation[7] == 0
56                  && rotation[8] == 1 ) {
57                 entity->setKeyValue( key, "" );
58         }
59         else
60         {
61                 StringOutputStream value( 256 );
62                 value << rotation[0] << ' '
63                           << rotation[1] << ' '
64                           << rotation[2] << ' '
65                           << rotation[3] << ' '
66                           << rotation[4] << ' '
67                           << rotation[5] << ' '
68                           << rotation[6] << ' '
69                           << rotation[7] << ' '
70                           << rotation[8];
71                 entity->setKeyValue( key, value.c_str() );
72         }
73 }
74 inline void read_rotation( Float9 rotation, const char* value ){
75         if ( !string_parse_vector( value, rotation, rotation + 9 ) ) {
76                 default_rotation( rotation );
77         }
78 }
79
80 inline Matrix4 rotation_toMatrix( const Float9 rotation ){
81         return Matrix4(
82                            rotation[0],
83                            rotation[1],
84                            rotation[2],
85                            0,
86                            rotation[3],
87                            rotation[4],
88                            rotation[5],
89                            0,
90                            rotation[6],
91                            rotation[7],
92                            rotation[8],
93                            0,
94                            0,
95                            0,
96                            0,
97                            1
98                            );
99 }
100
101 inline void rotation_fromMatrix( Float9 rotation, const Matrix4& matrix ){
102         rotation[0] = matrix.xx();
103         rotation[1] = matrix.xy();
104         rotation[2] = matrix.xz();
105         rotation[3] = matrix.yx();
106         rotation[4] = matrix.yy();
107         rotation[5] = matrix.yz();
108         rotation[6] = matrix.zx();
109         rotation[7] = matrix.zy();
110         rotation[8] = matrix.zz();
111 }
112
113 inline void rotation_assign( Float9 rotation, const Float9 other ){
114         rotation[0] = other[0];
115         rotation[1] = other[1];
116         rotation[2] = other[2];
117         rotation[3] = other[3];
118         rotation[4] = other[4];
119         rotation[5] = other[5];
120         rotation[6] = other[6];
121         rotation[7] = other[7];
122         rotation[8] = other[8];
123 }
124
125 inline void rotation_rotate( Float9 rotation, const Quaternion& rotate ){
126         rotation_fromMatrix( rotation,
127                                                  matrix4_multiplied_by_matrix4(
128                                                          rotation_toMatrix( rotation ),
129                                                          matrix4_rotation_for_quaternion_quantised( rotate )
130                                                          )
131                                                  );
132 }
133
134 inline void read_angle( Float9 rotation, const char* value ){
135         float angle;
136         if ( !string_parse_float( value, angle ) ) {
137                 default_rotation( rotation );
138         }
139         else
140         {
141                 rotation_fromMatrix( rotation,  matrix4_rotation_for_z_degrees( angle ) );
142         }
143 }
144
145 class RotationKey
146 {
147 Callback<void()> m_rotationChanged;
148 public:
149 Float9 m_rotation;
150
151
152 RotationKey( const Callback<void()>& rotationChanged )
153         : m_rotationChanged( rotationChanged ){
154         default_rotation( m_rotation );
155 }
156
157 void angleChanged( const char* value ){
158         read_angle( m_rotation, value );
159         m_rotationChanged();
160 }
161 typedef MemberCaller<RotationKey, void(const char*), &RotationKey::angleChanged> AngleChangedCaller;
162
163 void rotationChanged( const char* value ){
164         read_rotation( m_rotation, value );
165         m_rotationChanged();
166 }
167 typedef MemberCaller<RotationKey, void(const char*), &RotationKey::rotationChanged> RotationChangedCaller;
168
169 void write( Entity* entity ) const {
170         Vector3 euler = matrix4_get_rotation_euler_xyz_degrees( rotation_toMatrix( m_rotation ) );
171         if ( euler[0] == 0 && euler[1] == 0 ) {
172                 entity->setKeyValue( "rotation", "" );
173                 write_angle( euler[2], entity );
174         }
175         else
176         {
177                 entity->setKeyValue( "angle", "" );
178                 write_rotation( m_rotation, entity );
179         }
180 }
181 };
182
183 #endif