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