]> git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/selection.cpp
Radiant:
[xonotic/netradiant.git] / radiant / selection.cpp
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 #include "selection.h"
23
24 #include "debugging/debugging.h"
25
26 #include <map>
27 #include <list>
28 #include <set>
29
30 #include "windowobserver.h"
31 #include "iundo.h"
32 #include "ientity.h"
33 #include "cullable.h"
34 #include "renderable.h"
35 #include "selectable.h"
36 #include "editable.h"
37
38 #include "math/frustum.h"
39 #include "signal/signal.h"
40 #include "generic/object.h"
41 #include "selectionlib.h"
42 #include "render.h"
43 #include "view.h"
44 #include "renderer.h"
45 #include "stream/stringstream.h"
46 #include "eclasslib.h"
47 #include "generic/bitfield.h"
48 #include "generic/static.h"
49 #include "pivot.h"
50 #include "stringio.h"
51 #include "container/container.h"
52
53 #include "grid.h"
54
55 TextOutputStream& ostream_write( TextOutputStream& t, const Vector4& v ){
56         return t << "[ " << v.x() << " " << v.y() << " " << v.z() << " " << v.w() << " ]";
57 }
58
59 TextOutputStream& ostream_write( TextOutputStream& t, const Matrix4& m ){
60         return t << "[ " << m.x() << " " << m.y() << " " << m.z() << " " << m.t() << " ]";
61 }
62
63 struct Pivot2World
64 {
65         Matrix4 m_worldSpace;
66         Matrix4 m_viewpointSpace;
67         Matrix4 m_viewplaneSpace;
68         Vector3 m_axis_screen;
69
70         void update( const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport ){
71                 Pivot2World_worldSpace( m_worldSpace, pivot2world, modelview, projection, viewport );
72                 Pivot2World_viewpointSpace( m_viewpointSpace, m_axis_screen, pivot2world, modelview, projection, viewport );
73                 Pivot2World_viewplaneSpace( m_viewplaneSpace, pivot2world, modelview, projection, viewport );
74         }
75 };
76
77
78 void point_for_device_point( Vector3& point, const Matrix4& device2object, const float x, const float y, const float z ){
79         // transform from normalised device coords to object coords
80         point = vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, z, 1 ) ) );
81 }
82
83 void ray_for_device_point( Ray& ray, const Matrix4& device2object, const float x, const float y ){
84         // point at x, y, zNear
85         point_for_device_point( ray.origin, device2object, x, y, -1 );
86
87         // point at x, y, zFar
88         point_for_device_point( ray.direction, device2object, x, y, 1 );
89
90         // construct ray
91         vector3_subtract( ray.direction, ray.origin );
92         vector3_normalise( ray.direction );
93 }
94
95 bool sphere_intersect_ray( const Vector3& origin, float radius, const Ray& ray, Vector3& intersection ){
96         intersection = vector3_subtracted( origin, ray.origin );
97         const double a = vector3_dot( intersection, ray.direction );
98         const double d = radius * radius - ( vector3_dot( intersection, intersection ) - a * a );
99
100         if ( d > 0 ) {
101                 intersection = vector3_added( ray.origin, vector3_scaled( ray.direction, a - sqrt( d ) ) );
102                 return true;
103         }
104         else
105         {
106                 intersection = vector3_added( ray.origin, vector3_scaled( ray.direction, a ) );
107                 return false;
108         }
109 }
110
111 void ray_intersect_ray( const Ray& ray, const Ray& other, Vector3& intersection ){
112         intersection = vector3_subtracted( ray.origin, other.origin );
113         //float a = 1;//vector3_dot(ray.direction, ray.direction);        // always >= 0
114         double dot = vector3_dot( ray.direction, other.direction );
115         //float c = 1;//vector3_dot(other.direction, other.direction);        // always >= 0
116         double d = vector3_dot( ray.direction, intersection );
117         double e = vector3_dot( other.direction, intersection );
118         double D = 1 - dot * dot; //a*c - dot*dot;       // always >= 0
119
120         if ( D < 0.000001 ) {
121                 // the lines are almost parallel
122                 intersection = vector3_added( other.origin, vector3_scaled( other.direction, e ) );
123         }
124         else
125         {
126                 intersection = vector3_added( other.origin, vector3_scaled( other.direction, ( e - dot * d ) / D ) );
127         }
128 }
129
130 const Vector3 g_origin( 0, 0, 0 );
131 const float g_radius = 64;
132
133 void point_on_sphere( Vector3& point, const Matrix4& device2object, const float x, const float y ){
134         Ray ray;
135         ray_for_device_point( ray, device2object, x, y );
136         sphere_intersect_ray( g_origin, g_radius, ray, point );
137 }
138
139 void point_on_axis( Vector3& point, const Vector3& axis, const Matrix4& device2object, const float x, const float y ){
140         Ray ray;
141         ray_for_device_point( ray, device2object, x, y );
142         ray_intersect_ray( ray, Ray( Vector3( 0, 0, 0 ), axis ), point );
143 }
144
145 void point_on_plane( Vector3& point, const Matrix4& device2object, const float x, const float y ){
146         Matrix4 object2device( matrix4_full_inverse( device2object ) );
147         point = vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, object2device[14] / object2device[15], 1 ) ) );
148 }
149
150 //! a and b are unit vectors .. returns angle in radians
151 inline float angle_between( const Vector3& a, const Vector3& b ){
152         return static_cast<float>( 2.0 * atan2(
153                                                                    vector3_length( vector3_subtracted( a, b ) ),
154                                                                    vector3_length( vector3_added( a, b ) )
155                                                                    ) );
156 }
157
158
159 #if defined( _DEBUG )
160 class test_quat
161 {
162 public:
163 test_quat( const Vector3& from, const Vector3& to ){
164         Vector4 quaternion( quaternion_for_unit_vectors( from, to ) );
165         Matrix4 matrix( matrix4_rotation_for_quaternion( quaternion_multiplied_by_quaternion( quaternion, c_quaternion_identity ) ) );
166 }
167 private:
168 };
169
170 static test_quat bleh( g_vector3_axis_x, g_vector3_axis_y );
171 #endif
172
173 //! axis is a unit vector
174 inline void constrain_to_axis( Vector3& vec, const Vector3& axis ){
175         vec = vector3_normalised( vector3_added( vec, vector3_scaled( axis, -vector3_dot( vec, axis ) ) ) );
176 }
177
178 //! a and b are unit vectors .. a and b must be orthogonal to axis .. returns angle in radians
179 float angle_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){
180         if ( vector3_dot( axis, vector3_cross( a, b ) ) > 0.0 ) {
181                 return angle_between( a, b );
182         }
183         else{
184                 return -angle_between( a, b );
185         }
186 }
187
188 float distance_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){
189         return static_cast<float>( vector3_dot( b, axis ) - vector3_dot( a, axis ) );
190 }
191
192 class Manipulatable
193 {
194 public:
195 virtual void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ) = 0;
196 virtual void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ) = 0;
197 };
198
199 void transform_local2object( Matrix4& object, const Matrix4& local, const Matrix4& local2object ){
200         object = matrix4_multiplied_by_matrix4(
201                 matrix4_multiplied_by_matrix4( local2object, local ),
202                 matrix4_full_inverse( local2object )
203                 );
204 }
205
206 class Rotatable
207 {
208 public:
209 virtual void rotate( const Quaternion& rotation ) = 0;
210 };
211
212 class RotateFree : public Manipulatable
213 {
214 Vector3 m_start;
215 Rotatable& m_rotatable;
216 public:
217 RotateFree( Rotatable& rotatable )
218         : m_rotatable( rotatable ){
219 }
220 void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ){
221         point_on_sphere( m_start, device2manip, x, y );
222         vector3_normalise( m_start );
223 }
224 void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ){
225         Vector3 current;
226         point_on_sphere( current, device2manip, x, y );
227
228         if( snap ){
229                 Vector3 axis( 0, 0, 0 );
230                 for( std::size_t i = 0; i < 3; ++i ){
231                         if( current[i] == 0.0f ){
232                                 axis[i] = 1.0f;
233                                 break;
234                         }
235                 }
236                 if( vector3_length_squared( axis ) != 0 ){
237                         constrain_to_axis( current, axis );
238                         m_rotatable.rotate( quaternion_for_axisangle( axis, float_snapped( angle_for_axis( m_start, current, axis ), static_cast<float>( c_pi / 12.0 ) ) ) );
239                         return;
240                 }
241         }
242
243         vector3_normalise( current );
244         m_rotatable.rotate( quaternion_for_unit_vectors( m_start, current ) );
245 }
246 };
247
248 class RotateAxis : public Manipulatable
249 {
250 Vector3 m_axis;
251 Vector3 m_start;
252 Rotatable& m_rotatable;
253 public:
254 RotateAxis( Rotatable& rotatable )
255         : m_rotatable( rotatable ){
256 }
257 void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ){
258         point_on_sphere( m_start, device2manip, x, y );
259         constrain_to_axis( m_start, m_axis );
260 }
261 /// \brief Converts current position to a normalised vector orthogonal to axis.
262 void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ){
263         Vector3 current;
264         point_on_sphere( current, device2manip, x, y );
265         constrain_to_axis( current, m_axis );
266
267         if( snap ){
268                 m_rotatable.rotate( quaternion_for_axisangle( m_axis, float_snapped( angle_for_axis( m_start, current, m_axis ), static_cast<float>( c_pi / 12.0 ) ) ) );
269         }
270         else{
271                 m_rotatable.rotate( quaternion_for_axisangle( m_axis, angle_for_axis( m_start, current, m_axis ) ) );
272         }
273 }
274
275 void SetAxis( const Vector3& axis ){
276         m_axis = axis;
277 }
278 };
279
280 void translation_local2object( Vector3& object, const Vector3& local, const Matrix4& local2object ){
281         object = matrix4_get_translation_vec3(
282                 matrix4_multiplied_by_matrix4(
283                         matrix4_translated_by_vec3( local2object, local ),
284                         matrix4_full_inverse( local2object )
285                         )
286                 );
287 }
288
289 class Translatable
290 {
291 public:
292 virtual void translate( const Vector3& translation ) = 0;
293 };
294
295 class TranslateAxis : public Manipulatable
296 {
297 Vector3 m_start;
298 Vector3 m_axis;
299 Translatable& m_translatable;
300 AABB m_bounds;
301 public:
302 TranslateAxis( Translatable& translatable )
303         : m_translatable( translatable ){
304 }
305 void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ){
306         point_on_axis( m_start, m_axis, device2manip, x, y );
307         m_bounds = bounds;
308 }
309 void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ){
310         Vector3 current;
311         point_on_axis( current, m_axis, device2manip, x, y );
312         current = vector3_scaled( m_axis, distance_for_axis( m_start, current, m_axis ) );
313
314         translation_local2object( current, current, manip2object );
315         if( snapbbox ){
316                 float grid = GetSnapGridSize();
317                 Vector3 maxs( m_bounds.origin + m_bounds.extents );
318                 Vector3 mins( m_bounds.origin - m_bounds.extents );
319 //              globalOutputStream() << "current: " << current << "\n";
320                 for( std::size_t i = 0; i < 3; ++i ){
321                         if( m_axis[i] != 0.f ){
322                                 float snapto1 = float_snapped( maxs[i] + current[i] , grid );
323                                 float snapto2 = float_snapped( mins[i] + current[i] , grid );
324
325                                 float dist1 = fabs( fabs( maxs[i] + current[i] ) - fabs( snapto1 ) );
326                                 float dist2 = fabs( fabs( mins[i] + current[i] ) - fabs( snapto2 ) );
327
328 //                              globalOutputStream() << "maxs[i] + current[i]: " << maxs[i] + current[i]  << "    snapto1: " << snapto1 << "   dist1: " << dist1 << "\n";
329 //                              globalOutputStream() << "mins[i] + current[i]: " << mins[i] + current[i]  << "    snapto2: " << snapto2 << "   dist2: " << dist2 << "\n";
330                                 current[i] = dist2 > dist1 ? snapto1 - maxs[i] : snapto2 - mins[i];
331                         }
332                 }
333         }
334         else{
335                 vector3_snap( current, GetSnapGridSize() );
336         }
337
338         m_translatable.translate( current );
339 }
340
341 void SetAxis( const Vector3& axis ){
342         m_axis = axis;
343 }
344 };
345
346 class TranslateFree : public Manipulatable
347 {
348 private:
349 Vector3 m_start;
350 Translatable& m_translatable;
351 AABB m_bounds;
352 public:
353 TranslateFree( Translatable& translatable )
354         : m_translatable( translatable ){
355 }
356 void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ){
357         point_on_plane( m_start, device2manip, x, y );
358         m_bounds = bounds;
359 }
360 void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ){
361         Vector3 current;
362         point_on_plane( current, device2manip, x, y );
363         current = vector3_subtracted( current, m_start );
364
365         if( snap ){
366                 for ( std::size_t i = 0; i < 3 ; ++i ){
367                         if( fabs( current[i] ) >= fabs( current[(i + 1) % 3] ) ){
368                                 current[(i + 1) % 3] = 0.0f;
369                         }
370                         else{
371                                 current[i] = 0.0f;
372                         }
373                 }
374         }
375
376         translation_local2object( current, current, manip2object );
377         if( snapbbox ){
378                 float grid = GetSnapGridSize();
379                 Vector3 maxs( m_bounds.origin + m_bounds.extents );
380                 Vector3 mins( m_bounds.origin - m_bounds.extents );
381                 //globalOutputStream() << "current: " << current << "\n";
382                 for( std::size_t i = 0; i < 3; ++i ){
383                         if( fabs( current[i] ) > 0.000001f ){
384                                 float snapto1 = float_snapped( maxs[i] + current[i] , grid );
385                                 float snapto2 = float_snapped( mins[i] + current[i] , grid );
386
387                                 float dist1 = fabs( fabs( maxs[i] + current[i] ) - fabs( snapto1 ) );
388                                 float dist2 = fabs( fabs( mins[i] + current[i] ) - fabs( snapto2 ) );
389
390                                 current[i] = dist2 > dist1 ? snapto1 - maxs[i] : snapto2 - mins[i];
391                         }
392                 }
393         }
394         else{
395                 vector3_snap( current, GetSnapGridSize() );
396         }
397
398         m_translatable.translate( current );
399 }
400 };
401
402 class Scalable
403 {
404 public:
405 virtual void scale( const Vector3& scaling ) = 0;
406 };
407
408
409 class ScaleAxis : public Manipulatable
410 {
411 private:
412 Vector3 m_start;
413 Vector3 m_axis;
414 Scalable& m_scalable;
415
416 Vector3 m_choosen_extent;
417 AABB m_bounds;
418
419 public:
420 ScaleAxis( Scalable& scalable )
421         : m_scalable( scalable ){
422 }
423 void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ){
424         point_on_axis( m_start, m_axis, device2manip, x, y );
425
426         m_choosen_extent = Vector3(
427                                         std::max( bounds.origin[0] + bounds.extents[0] - transform_origin[0], - bounds.origin[0] + bounds.extents[0] + transform_origin[0] ),
428                                         std::max( bounds.origin[1] + bounds.extents[1] - transform_origin[1], - bounds.origin[1] + bounds.extents[1] + transform_origin[1] ),
429                                         std::max( bounds.origin[2] + bounds.extents[2] - transform_origin[2], - bounds.origin[2] + bounds.extents[2] + transform_origin[2] )
430                                                         );
431         m_bounds = bounds;
432 }
433 void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ){
434         //globalOutputStream() << "manip2object: " << manip2object << "  device2manip: " << device2manip << "  x: " << x << "  y:" << y <<"\n";
435         Vector3 current;
436         point_on_axis( current, m_axis, device2manip, x, y );
437         Vector3 delta = vector3_subtracted( current, m_start );
438
439         translation_local2object( delta, delta, manip2object );
440         vector3_snap( delta, GetSnapGridSize() );
441
442         Vector3 start( vector3_snapped( m_start, GetSnapGridSize() != 0.0f ? GetSnapGridSize() : 0.001f ) );
443         for ( std::size_t i = 0; i < 3 ; ++i ){ //prevent snapping to 0 with big gridsize
444                 if( float_snapped( m_start[i], 0.001f ) != 0.0f && start[i] == 0.0f ){
445                         start[i] = GetSnapGridSize();
446                 }
447         }
448         //globalOutputStream() << "m_start: " << m_start << "   start: " << start << "   delta: " << delta <<"\n";
449         Vector3 scale(
450                 start[0] == 0 ? 1 : 1 + delta[0] / start[0],
451                 start[1] == 0 ? 1 : 1 + delta[1] / start[1],
452                 start[2] == 0 ? 1 : 1 + delta[2] / start[2]
453                 );
454
455         for( std::size_t i = 0; i < 3; i++ ){
456                 if( m_choosen_extent[i] > 0.0625f && m_axis[i] != 0.f ){ //epsilon to prevent super high scale for set of models, having really small extent, formed by origins
457                         scale[i] = ( m_choosen_extent[i] + delta[i] ) / m_choosen_extent[i];
458                         if( snapbbox ){
459                                 float snappdwidth = float_snapped( scale[i] * m_bounds.extents[i] * 2.f, GetSnapGridSize() );
460                                 scale[i] = snappdwidth / ( m_bounds.extents[i] * 2.f );
461                         }
462                 }
463         }
464         if( snap ){
465                 for( std::size_t i = 0; i < 3; i++ ){
466                         if( scale[i] == 1.0f ){
467                                 scale[i] = vector3_dot( scale, m_axis );
468                         }
469                 }
470         }
471         //globalOutputStream() << "scale: " << scale <<"\n";
472         m_scalable.scale( scale );
473 }
474
475 void SetAxis( const Vector3& axis ){
476         m_axis = axis;
477 }
478 };
479
480 class ScaleFree : public Manipulatable
481 {
482 private:
483 Vector3 m_start;
484 Scalable& m_scalable;
485
486 Vector3 m_choosen_extent;
487 AABB m_bounds;
488
489 public:
490 ScaleFree( Scalable& scalable )
491         : m_scalable( scalable ){
492 }
493 void Construct( const Matrix4& device2manip, const float x, const float y, const AABB bounds, const Vector3 transform_origin ){
494         point_on_plane( m_start, device2manip, x, y );
495
496         m_choosen_extent = Vector3(
497                                         std::max( bounds.origin[0] + bounds.extents[0] - transform_origin[0], - bounds.origin[0] + bounds.extents[0] + transform_origin[0] ),
498                                         std::max( bounds.origin[1] + bounds.extents[1] - transform_origin[1], - bounds.origin[1] + bounds.extents[1] + transform_origin[1] ),
499                                         std::max( bounds.origin[2] + bounds.extents[2] - transform_origin[2], - bounds.origin[2] + bounds.extents[2] + transform_origin[2] )
500                                                         );
501         m_bounds = bounds;
502 }
503 void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox ){
504         Vector3 current;
505         point_on_plane( current, device2manip, x, y );
506         Vector3 delta = vector3_subtracted( current, m_start );
507
508         translation_local2object( delta, delta, manip2object );
509         vector3_snap( delta, GetSnapGridSize() );
510
511         Vector3 start( vector3_snapped( m_start, GetSnapGridSize() != 0.0f ? GetSnapGridSize() : 0.001f ) );
512         for ( std::size_t i = 0; i < 3 ; ++i ){ //prevent snapping to 0 with big gridsize
513                 if( float_snapped( m_start[i], 0.001f ) != 0.0f && start[i] == 0.0f ){
514                         start[i] = GetSnapGridSize();
515                 }
516         }
517         Vector3 scale(
518                 start[0] == 0 ? 1 : 1 + delta[0] / start[0],
519                 start[1] == 0 ? 1 : 1 + delta[1] / start[1],
520                 start[2] == 0 ? 1 : 1 + delta[2] / start[2]
521                 );
522
523         //globalOutputStream() << "m_start: " << m_start << "   start: " << start << "   delta: " << delta <<"\n";
524         for( std::size_t i = 0; i < 3; i++ ){
525                 if( m_choosen_extent[i] > 0.0625f ){
526                         scale[i] = ( m_choosen_extent[i] + delta[i] ) / m_choosen_extent[i];
527                         if( snapbbox && start[i] != 0.f ){
528                                 float snappdwidth = float_snapped( scale[i] * m_bounds.extents[i] * 2.f, GetSnapGridSize() );
529                                 scale[i] = snappdwidth / ( m_bounds.extents[i] * 2.f );
530                         }
531                 }
532         }
533         //globalOutputStream() << "pre snap scale: " << scale <<"\n";
534         if( snap ){
535                 float bestscale = scale[0];
536                 for( std::size_t i = 1; i < 3; i++ ){
537                         //if( fabs( 1.0f - fabs( scale[i] ) ) > fabs( 1.0f - fabs( bestscale ) ) ){
538                         if( fabs( scale[i] ) > fabs( bestscale ) && scale[i] != 1.0f ){ //harder to scale down with this, but glitchier with upper one
539                                 bestscale = scale[i];
540                         }
541                         //globalOutputStream() << "bestscale: " << bestscale <<"\n";
542                 }
543                 for( std::size_t i = 0; i < 3; i++ ){
544                         if( start[i] != 0.0f ){ // !!!!check grid == 0 case
545                                 scale[i] = ( scale[i] < 0.0f ) ? -fabs( bestscale ) : fabs( bestscale );
546                         }
547                 }
548         }
549         //globalOutputStream() << "scale: " << scale <<"\n";
550         m_scalable.scale( scale );
551 }
552 };
553
554
555
556
557
558
559
560
561
562
563 class RenderableClippedPrimitive : public OpenGLRenderable
564 {
565 struct primitive_t
566 {
567         PointVertex m_points[9];
568         std::size_t m_count;
569 };
570 Matrix4 m_inverse;
571 std::vector<primitive_t> m_primitives;
572 public:
573 Matrix4 m_world;
574
575 void render( RenderStateFlags state ) const {
576         for ( std::size_t i = 0; i < m_primitives.size(); ++i )
577         {
578                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_primitives[i].m_points[0].colour );
579                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_primitives[i].m_points[0].vertex );
580                 switch ( m_primitives[i].m_count )
581                 {
582                 case 1: break;
583                 case 2: glDrawArrays( GL_LINES, 0, GLsizei( m_primitives[i].m_count ) ); break;
584                 default: glDrawArrays( GL_POLYGON, 0, GLsizei( m_primitives[i].m_count ) ); break;
585                 }
586         }
587 }
588
589 void construct( const Matrix4& world2device ){
590         m_inverse = matrix4_full_inverse( world2device );
591         m_world = g_matrix4_identity;
592 }
593
594 void insert( const Vector4 clipped[9], std::size_t count ){
595         add_one();
596
597         m_primitives.back().m_count = count;
598         for ( std::size_t i = 0; i < count; ++i )
599         {
600                 Vector3 world_point( vector4_projected( matrix4_transformed_vector4( m_inverse, clipped[i] ) ) );
601                 m_primitives.back().m_points[i].vertex = vertex3f_for_vector3( world_point );
602         }
603 }
604
605 void destroy(){
606         m_primitives.clear();
607 }
608 private:
609 void add_one(){
610         m_primitives.push_back( primitive_t() );
611
612         const Colour4b colour_clipped( 255, 127, 0, 255 );
613
614         for ( std::size_t i = 0; i < 9; ++i )
615                 m_primitives.back().m_points[i].colour = colour_clipped;
616 }
617 };
618
619 #if defined( _DEBUG )
620 #define DEBUG_SELECTION
621 #endif
622
623 #if defined( DEBUG_SELECTION )
624 Shader* g_state_clipped;
625 RenderableClippedPrimitive g_render_clipped;
626 #endif
627
628
629 #if 0
630 // dist_Point_to_Line(): get the distance of a point to a line.
631 //    Input:  a Point P and a Line L (in any dimension)
632 //    Return: the shortest distance from P to L
633 float
634 dist_Point_to_Line( Point P, Line L ){
635         Vector v = L.P1 - L.P0;
636         Vector w = P - L.P0;
637
638         double c1 = dot( w,v );
639         double c2 = dot( v,v );
640         double b = c1 / c2;
641
642         Point Pb = L.P0 + b * v;
643         return d( P, Pb );
644 }
645 #endif
646
647 class Segment3D
648 {
649 typedef Vector3 point_type;
650 public:
651 Segment3D( const point_type& _p0, const point_type& _p1 )
652         : p0( _p0 ), p1( _p1 ){
653 }
654
655 point_type p0, p1;
656 };
657
658 typedef Vector3 Point3D;
659
660 inline double vector3_distance_squared( const Point3D& a, const Point3D& b ){
661         return vector3_length_squared( b - a );
662 }
663
664 // get the distance of a point to a segment.
665 Point3D segment_closest_point_to_point( const Segment3D& segment, const Point3D& point ){
666         Vector3 v = segment.p1 - segment.p0;
667         Vector3 w = point - segment.p0;
668
669         double c1 = vector3_dot( w,v );
670         if ( c1 <= 0 ) {
671                 return segment.p0;
672         }
673
674         double c2 = vector3_dot( v,v );
675         if ( c2 <= c1 ) {
676                 return segment.p1;
677         }
678
679         return Point3D( segment.p0 + v * ( c1 / c2 ) );
680 }
681
682 double segment_dist_to_point_3d( const Segment3D& segment, const Point3D& point ){
683         return vector3_distance_squared( point, segment_closest_point_to_point( segment, point ) );
684 }
685
686 typedef Vector3 point_t;
687 typedef const Vector3* point_iterator_t;
688
689 // crossing number test for a point in a polygon
690 // This code is patterned after [Franklin, 2000]
691 bool point_test_polygon_2d( const point_t& P, point_iterator_t start, point_iterator_t finish ){
692         std::size_t crossings = 0;
693
694         // loop through all edges of the polygon
695         for ( point_iterator_t prev = finish - 1, cur = start; cur != finish; prev = cur, ++cur )
696         {  // edge from (*prev) to (*cur)
697                 if ( ( ( ( *prev )[1] <= P[1] ) && ( ( *cur )[1] > P[1] ) ) // an upward crossing
698                          || ( ( ( *prev )[1] > P[1] ) && ( ( *cur )[1] <= P[1] ) ) ) { // a downward crossing
699                                                                                       // compute the actual edge-ray intersect x-coordinate
700                         float vt = (float)( P[1] - ( *prev )[1] ) / ( ( *cur )[1] - ( *prev )[1] );
701                         if ( P[0] < ( *prev )[0] + vt * ( ( *cur )[0] - ( *prev )[0] ) ) { // P[0] < intersect
702                                 ++crossings; // a valid crossing of y=P[1] right of P[0]
703                         }
704                 }
705         }
706         return ( crossings & 0x1 ) != 0; // 0 if even (out), and 1 if odd (in)
707 }
708
709 inline double triangle_signed_area_XY( const Vector3& p0, const Vector3& p1, const Vector3& p2 ){
710         return ( ( p1[0] - p0[0] ) * ( p2[1] - p0[1] ) ) - ( ( p2[0] - p0[0] ) * ( p1[1] - p0[1] ) );
711 }
712
713 enum clipcull_t
714 {
715         eClipCullNone,
716         eClipCullCW,
717         eClipCullCCW,
718 };
719
720
721 inline SelectionIntersection select_point_from_clipped( Vector4& clipped ){
722         return SelectionIntersection( clipped[2] / clipped[3], static_cast<float>( vector3_length_squared( Vector3( clipped[0] / clipped[3], clipped[1] / clipped[3], 0 ) ) ) );
723 }
724
725 void BestPoint( std::size_t count, Vector4 clipped[9], SelectionIntersection& best, clipcull_t cull ){
726         Vector3 normalised[9];
727
728         {
729                 for ( std::size_t i = 0; i < count; ++i )
730                 {
731                         normalised[i][0] = clipped[i][0] / clipped[i][3];
732                         normalised[i][1] = clipped[i][1] / clipped[i][3];
733                         normalised[i][2] = clipped[i][2] / clipped[i][3];
734                 }
735         }
736
737         if ( cull != eClipCullNone && count > 2 ) {
738                 double signed_area = triangle_signed_area_XY( normalised[0], normalised[1], normalised[2] );
739
740                 if ( ( cull == eClipCullCW && signed_area > 0 )
741                          || ( cull == eClipCullCCW && signed_area < 0 ) ) {
742                         return;
743                 }
744         }
745
746         if ( count == 2 ) {
747                 Segment3D segment( normalised[0], normalised[1] );
748                 Point3D point = segment_closest_point_to_point( segment, Vector3( 0, 0, 0 ) );
749                 assign_if_closer( best, SelectionIntersection( point.z(), 0 ) );
750         }
751         else if ( count > 2 && !point_test_polygon_2d( Vector3( 0, 0, 0 ), normalised, normalised + count ) ) {
752                 point_iterator_t end = normalised + count;
753                 for ( point_iterator_t previous = end - 1, current = normalised; current != end; previous = current, ++current )
754                 {
755                         Segment3D segment( *previous, *current );
756                         Point3D point = segment_closest_point_to_point( segment, Vector3( 0, 0, 0 ) );
757                         float depth = point.z();
758                         point.z() = 0;
759                         float distance = static_cast<float>( vector3_length_squared( point ) );
760
761                         assign_if_closer( best, SelectionIntersection( depth, distance ) );
762                 }
763         }
764         else if ( count > 2 ) {
765                 assign_if_closer(
766                         best,
767                         SelectionIntersection(
768                                 static_cast<float>( ray_distance_to_plane(
769                                                                                 Ray( Vector3( 0, 0, 0 ), Vector3( 0, 0, 1 ) ),
770                                                                                 plane3_for_points( normalised[0], normalised[1], normalised[2] )
771                                                                                 ) ),
772                                 0
773                                 )
774                         );
775         }
776
777 #if defined( DEBUG_SELECTION )
778         if ( count >= 2 ) {
779                 g_render_clipped.insert( clipped, count );
780         }
781 #endif
782 }
783
784 void LineStrip_BestPoint( const Matrix4& local2view, const PointVertex* vertices, const std::size_t size, SelectionIntersection& best ){
785         Vector4 clipped[2];
786         for ( std::size_t i = 0; ( i + 1 ) < size; ++i )
787         {
788                 const std::size_t count = matrix4_clip_line( local2view, vertex3f_to_vector3( vertices[i].vertex ), vertex3f_to_vector3( vertices[i + 1].vertex ), clipped );
789                 BestPoint( count, clipped, best, eClipCullNone );
790         }
791 }
792
793 void LineLoop_BestPoint( const Matrix4& local2view, const PointVertex* vertices, const std::size_t size, SelectionIntersection& best ){
794         Vector4 clipped[2];
795         for ( std::size_t i = 0; i < size; ++i )
796         {
797                 const std::size_t count = matrix4_clip_line( local2view, vertex3f_to_vector3( vertices[i].vertex ), vertex3f_to_vector3( vertices[( i + 1 ) % size].vertex ), clipped );
798                 BestPoint( count, clipped, best, eClipCullNone );
799         }
800 }
801
802 void Line_BestPoint( const Matrix4& local2view, const PointVertex vertices[2], SelectionIntersection& best ){
803         Vector4 clipped[2];
804         const std::size_t count = matrix4_clip_line( local2view, vertex3f_to_vector3( vertices[0].vertex ), vertex3f_to_vector3( vertices[1].vertex ), clipped );
805         BestPoint( count, clipped, best, eClipCullNone );
806 }
807
808 void Circle_BestPoint( const Matrix4& local2view, clipcull_t cull, const PointVertex* vertices, const std::size_t size, SelectionIntersection& best ){
809         Vector4 clipped[9];
810         for ( std::size_t i = 0; i < size; ++i )
811         {
812                 const std::size_t count = matrix4_clip_triangle( local2view, g_vector3_identity, vertex3f_to_vector3( vertices[i].vertex ), vertex3f_to_vector3( vertices[( i + 1 ) % size].vertex ), clipped );
813                 BestPoint( count, clipped, best, cull );
814         }
815 }
816
817 void Quad_BestPoint( const Matrix4& local2view, clipcull_t cull, const PointVertex* vertices, SelectionIntersection& best ){
818         Vector4 clipped[9];
819         {
820                 const std::size_t count = matrix4_clip_triangle( local2view, vertex3f_to_vector3( vertices[0].vertex ), vertex3f_to_vector3( vertices[1].vertex ), vertex3f_to_vector3( vertices[3].vertex ), clipped );
821                 BestPoint( count, clipped, best, cull );
822         }
823         {
824                 const std::size_t count = matrix4_clip_triangle( local2view, vertex3f_to_vector3( vertices[1].vertex ), vertex3f_to_vector3( vertices[2].vertex ), vertex3f_to_vector3( vertices[3].vertex ), clipped );
825                 BestPoint( count, clipped, best, cull );
826         }
827 }
828
829 struct FlatShadedVertex
830 {
831         Vertex3f vertex;
832         Colour4b colour;
833         Normal3f normal;
834
835         FlatShadedVertex(){
836         }
837 };
838
839
840 typedef FlatShadedVertex* FlatShadedVertexIterator;
841 void Triangles_BestPoint( const Matrix4& local2view, clipcull_t cull, FlatShadedVertexIterator first, FlatShadedVertexIterator last, SelectionIntersection& best ){
842         for ( FlatShadedVertexIterator x( first ), y( first + 1 ), z( first + 2 ); x != last; x += 3, y += 3, z += 3 )
843         {
844                 Vector4 clipped[9];
845                 BestPoint(
846                         matrix4_clip_triangle(
847                                 local2view,
848                                 reinterpret_cast<const Vector3&>( ( *x ).vertex ),
849                                 reinterpret_cast<const Vector3&>( ( *y ).vertex ),
850                                 reinterpret_cast<const Vector3&>( ( *z ).vertex ),
851                                 clipped
852                                 ),
853                         clipped,
854                         best,
855                         cull
856                         );
857         }
858 }
859
860
861 typedef std::multimap<SelectionIntersection, Selectable*> SelectableSortedSet;
862
863 class SelectionPool : public Selector
864 {
865 SelectableSortedSet m_pool;
866 SelectionIntersection m_intersection;
867 Selectable* m_selectable;
868
869 public:
870 void pushSelectable( Selectable& selectable ){
871         m_intersection = SelectionIntersection();
872         m_selectable = &selectable;
873 }
874 void popSelectable(){
875         addSelectable( m_intersection, m_selectable );
876         m_intersection = SelectionIntersection();
877 }
878 void addIntersection( const SelectionIntersection& intersection ){
879         assign_if_closer( m_intersection, intersection );
880 }
881 void addSelectable( const SelectionIntersection& intersection, Selectable* selectable ){
882         if ( intersection.valid() ) {
883                 m_pool.insert( SelectableSortedSet::value_type( intersection, selectable ) );
884         }
885 }
886
887 typedef SelectableSortedSet::iterator iterator;
888
889 iterator begin(){
890         return m_pool.begin();
891 }
892 iterator end(){
893         return m_pool.end();
894 }
895
896 bool failed(){
897         return m_pool.empty();
898 }
899 };
900
901
902 const Colour4b g_colour_sphere( 0, 0, 0, 255 );
903 const Colour4b g_colour_screen( 0, 255, 255, 255 );
904 const Colour4b g_colour_selected( 255, 255, 0, 255 );
905
906 inline const Colour4b& colourSelected( const Colour4b& colour, bool selected ){
907         return ( selected ) ? g_colour_selected : colour;
908 }
909
910 template<typename remap_policy>
911 inline void draw_semicircle( const std::size_t segments, const float radius, PointVertex* vertices, remap_policy remap ){
912         const double increment = c_pi / double(segments << 2);
913
914         std::size_t count = 0;
915         float x = radius;
916         float y = 0;
917         remap_policy::set( vertices[segments << 2].vertex, -radius, 0, 0 );
918         while ( count < segments )
919         {
920                 PointVertex* i = vertices + count;
921                 PointVertex* j = vertices + ( ( segments << 1 ) - ( count + 1 ) );
922
923                 PointVertex* k = i + ( segments << 1 );
924                 PointVertex* l = j + ( segments << 1 );
925
926 #if 0
927                 PointVertex* m = i + ( segments << 2 );
928                 PointVertex* n = j + ( segments << 2 );
929                 PointVertex* o = k + ( segments << 2 );
930                 PointVertex* p = l + ( segments << 2 );
931 #endif
932
933                 remap_policy::set( i->vertex, x,-y, 0 );
934                 remap_policy::set( k->vertex,-y,-x, 0 );
935 #if 0
936                 remap_policy::set( m->vertex,-x, y, 0 );
937                 remap_policy::set( o->vertex, y, x, 0 );
938 #endif
939
940                 ++count;
941
942                 {
943                         const double theta = increment * count;
944                         x = static_cast<float>( radius * cos( theta ) );
945                         y = static_cast<float>( radius * sin( theta ) );
946                 }
947
948                 remap_policy::set( j->vertex, y,-x, 0 );
949                 remap_policy::set( l->vertex,-x,-y, 0 );
950 #if 0
951                 remap_policy::set( n->vertex,-y, x, 0 );
952                 remap_policy::set( p->vertex, x, y, 0 );
953 #endif
954         }
955 }
956
957 class Manipulator
958 {
959 public:
960 virtual Manipulatable* GetManipulatable() = 0;
961 virtual void testSelect( const View& view, const Matrix4& pivot2world ){
962 }
963 virtual void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){
964 }
965 virtual void setSelected( bool select ) = 0;
966 virtual bool isSelected() const = 0;
967 };
968
969
970 inline Vector3 normalised_safe( const Vector3& self ){
971         if ( vector3_equal( self, g_vector3_identity ) ) {
972                 return g_vector3_identity;
973         }
974         return vector3_normalised( self );
975 }
976
977
978 class RotateManipulator : public Manipulator
979 {
980 struct RenderableCircle : public OpenGLRenderable
981 {
982         Array<PointVertex> m_vertices;
983
984         RenderableCircle( std::size_t size ) : m_vertices( size ){
985         }
986         void render( RenderStateFlags state ) const {
987                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices.data()->colour );
988                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices.data()->vertex );
989                 glDrawArrays( GL_LINE_LOOP, 0, GLsizei( m_vertices.size() ) );
990         }
991         void setColour( const Colour4b& colour ){
992                 for ( Array<PointVertex>::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i )
993                 {
994                         ( *i ).colour = colour;
995                 }
996         }
997 };
998
999 struct RenderableSemiCircle : public OpenGLRenderable
1000 {
1001         Array<PointVertex> m_vertices;
1002
1003         RenderableSemiCircle( std::size_t size ) : m_vertices( size ){
1004         }
1005         void render( RenderStateFlags state ) const {
1006                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices.data()->colour );
1007                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices.data()->vertex );
1008                 glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_vertices.size() ) );
1009         }
1010         void setColour( const Colour4b& colour ){
1011                 for ( Array<PointVertex>::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i )
1012                 {
1013                         ( *i ).colour = colour;
1014                 }
1015         }
1016 };
1017
1018 RotateFree m_free;
1019 RotateAxis m_axis;
1020 Vector3 m_axis_screen;
1021 RenderableSemiCircle m_circle_x;
1022 RenderableSemiCircle m_circle_y;
1023 RenderableSemiCircle m_circle_z;
1024 RenderableCircle m_circle_screen;
1025 RenderableCircle m_circle_sphere;
1026 SelectableBool m_selectable_x;
1027 SelectableBool m_selectable_y;
1028 SelectableBool m_selectable_z;
1029 SelectableBool m_selectable_screen;
1030 SelectableBool m_selectable_sphere;
1031 Pivot2World m_pivot;
1032 Matrix4 m_local2world_x;
1033 Matrix4 m_local2world_y;
1034 Matrix4 m_local2world_z;
1035 bool m_circle_x_visible;
1036 bool m_circle_y_visible;
1037 bool m_circle_z_visible;
1038 public:
1039 static Shader* m_state_outer;
1040
1041 RotateManipulator( Rotatable& rotatable, std::size_t segments, float radius ) :
1042         m_free( rotatable ),
1043         m_axis( rotatable ),
1044         m_circle_x( ( segments << 2 ) + 1 ),
1045         m_circle_y( ( segments << 2 ) + 1 ),
1046         m_circle_z( ( segments << 2 ) + 1 ),
1047         m_circle_screen( segments << 3 ),
1048         m_circle_sphere( segments << 3 ){
1049         draw_semicircle( segments, radius, m_circle_x.m_vertices.data(), RemapYZX() );
1050         draw_semicircle( segments, radius, m_circle_y.m_vertices.data(), RemapZXY() );
1051         draw_semicircle( segments, radius, m_circle_z.m_vertices.data(), RemapXYZ() );
1052
1053         draw_circle( segments, radius * 1.15f, m_circle_screen.m_vertices.data(), RemapXYZ() );
1054         draw_circle( segments, radius, m_circle_sphere.m_vertices.data(), RemapXYZ() );
1055
1056         m_selectable_sphere.setSelected( true );
1057 }
1058
1059
1060 void UpdateColours(){
1061         m_circle_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) );
1062         m_circle_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) );
1063         m_circle_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) );
1064         m_circle_screen.setColour( colourSelected( g_colour_screen, m_selectable_screen.isSelected() ) );
1065         m_circle_sphere.setColour( colourSelected( g_colour_sphere, false ) );
1066 }
1067
1068 void updateCircleTransforms(){
1069         Vector3 localViewpoint( matrix4_transformed_direction( matrix4_transposed( m_pivot.m_worldSpace ), vector4_to_vector3( m_pivot.m_viewpointSpace.z() ) ) );
1070
1071         m_circle_x_visible = !vector3_equal_epsilon( g_vector3_axis_x, localViewpoint, 1e-6f );
1072         if ( m_circle_x_visible ) {
1073                 m_local2world_x = g_matrix4_identity;
1074                 vector4_to_vector3( m_local2world_x.y() ) = normalised_safe(
1075                         vector3_cross( g_vector3_axis_x, localViewpoint )
1076                         );
1077                 vector4_to_vector3( m_local2world_x.z() ) = normalised_safe(
1078                         vector3_cross( vector4_to_vector3( m_local2world_x.x() ), vector4_to_vector3( m_local2world_x.y() ) )
1079                         );
1080                 matrix4_premultiply_by_matrix4( m_local2world_x, m_pivot.m_worldSpace );
1081         }
1082
1083         m_circle_y_visible = !vector3_equal_epsilon( g_vector3_axis_y, localViewpoint, 1e-6f );
1084         if ( m_circle_y_visible ) {
1085                 m_local2world_y = g_matrix4_identity;
1086                 vector4_to_vector3( m_local2world_y.z() ) = normalised_safe(
1087                         vector3_cross( g_vector3_axis_y, localViewpoint )
1088                         );
1089                 vector4_to_vector3( m_local2world_y.x() ) = normalised_safe(
1090                         vector3_cross( vector4_to_vector3( m_local2world_y.y() ), vector4_to_vector3( m_local2world_y.z() ) )
1091                         );
1092                 matrix4_premultiply_by_matrix4( m_local2world_y, m_pivot.m_worldSpace );
1093         }
1094
1095         m_circle_z_visible = !vector3_equal_epsilon( g_vector3_axis_z, localViewpoint, 1e-6f );
1096         if ( m_circle_z_visible ) {
1097                 m_local2world_z = g_matrix4_identity;
1098                 vector4_to_vector3( m_local2world_z.x() ) = normalised_safe(
1099                         vector3_cross( g_vector3_axis_z, localViewpoint )
1100                         );
1101                 vector4_to_vector3( m_local2world_z.y() ) = normalised_safe(
1102                         vector3_cross( vector4_to_vector3( m_local2world_z.z() ), vector4_to_vector3( m_local2world_z.x() ) )
1103                         );
1104                 matrix4_premultiply_by_matrix4( m_local2world_z, m_pivot.m_worldSpace );
1105         }
1106 }
1107
1108 void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){
1109         m_pivot.update( pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport() );
1110         updateCircleTransforms();
1111
1112         // temp hack
1113         UpdateColours();
1114
1115         renderer.SetState( m_state_outer, Renderer::eWireframeOnly );
1116         renderer.SetState( m_state_outer, Renderer::eFullMaterials );
1117
1118         renderer.addRenderable( m_circle_screen, m_pivot.m_viewpointSpace );
1119         renderer.addRenderable( m_circle_sphere, m_pivot.m_viewpointSpace );
1120
1121         if ( m_circle_x_visible ) {
1122                 renderer.addRenderable( m_circle_x, m_local2world_x );
1123         }
1124         if ( m_circle_y_visible ) {
1125                 renderer.addRenderable( m_circle_y, m_local2world_y );
1126         }
1127         if ( m_circle_z_visible ) {
1128                 renderer.addRenderable( m_circle_z, m_local2world_z );
1129         }
1130 }
1131 void testSelect( const View& view, const Matrix4& pivot2world ){
1132         m_pivot.update( pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport() );
1133         updateCircleTransforms();
1134
1135         SelectionPool selector;
1136
1137         {
1138                 {
1139                         Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_local2world_x ) );
1140
1141 #if defined( DEBUG_SELECTION )
1142                         g_render_clipped.construct( view.GetViewMatrix() );
1143 #endif
1144
1145                         SelectionIntersection best;
1146                         LineStrip_BestPoint( local2view, m_circle_x.m_vertices.data(), m_circle_x.m_vertices.size(), best );
1147                         selector.addSelectable( best, &m_selectable_x );
1148                 }
1149
1150                 {
1151                         Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_local2world_y ) );
1152
1153 #if defined( DEBUG_SELECTION )
1154                         g_render_clipped.construct( view.GetViewMatrix() );
1155 #endif
1156
1157                         SelectionIntersection best;
1158                         LineStrip_BestPoint( local2view, m_circle_y.m_vertices.data(), m_circle_y.m_vertices.size(), best );
1159                         selector.addSelectable( best, &m_selectable_y );
1160                 }
1161
1162                 {
1163                         Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_local2world_z ) );
1164
1165 #if defined( DEBUG_SELECTION )
1166                         g_render_clipped.construct( view.GetViewMatrix() );
1167 #endif
1168
1169                         SelectionIntersection best;
1170                         LineStrip_BestPoint( local2view, m_circle_z.m_vertices.data(), m_circle_z.m_vertices.size(), best );
1171                         selector.addSelectable( best, &m_selectable_z );
1172                 }
1173         }
1174
1175         {
1176                 Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_viewpointSpace ) );
1177
1178                 {
1179                         SelectionIntersection best;
1180                         LineLoop_BestPoint( local2view, m_circle_screen.m_vertices.data(), m_circle_screen.m_vertices.size(), best );
1181                         selector.addSelectable( best, &m_selectable_screen );
1182                 }
1183
1184                 {
1185                         SelectionIntersection best;
1186                         Circle_BestPoint( local2view, eClipCullCW, m_circle_sphere.m_vertices.data(), m_circle_sphere.m_vertices.size(), best );
1187                         selector.addSelectable( best, &m_selectable_sphere );
1188                 }
1189         }
1190
1191         m_axis_screen = m_pivot.m_axis_screen;
1192
1193         if ( !selector.failed() ) {
1194                 ( *selector.begin() ).second->setSelected( true );
1195         }
1196 }
1197
1198 Manipulatable* GetManipulatable(){
1199         if ( m_selectable_x.isSelected() ) {
1200                 m_axis.SetAxis( g_vector3_axis_x );
1201                 return &m_axis;
1202         }
1203         else if ( m_selectable_y.isSelected() ) {
1204                 m_axis.SetAxis( g_vector3_axis_y );
1205                 return &m_axis;
1206         }
1207         else if ( m_selectable_z.isSelected() ) {
1208                 m_axis.SetAxis( g_vector3_axis_z );
1209                 return &m_axis;
1210         }
1211         else if ( m_selectable_screen.isSelected() ) {
1212                 m_axis.SetAxis( m_axis_screen );
1213                 return &m_axis;
1214         }
1215         else{
1216                 return &m_free;
1217         }
1218 }
1219
1220 void setSelected( bool select ){
1221         m_selectable_x.setSelected( select );
1222         m_selectable_y.setSelected( select );
1223         m_selectable_z.setSelected( select );
1224         m_selectable_screen.setSelected( select );
1225 }
1226 bool isSelected() const {
1227         return m_selectable_x.isSelected()
1228                    | m_selectable_y.isSelected()
1229                    | m_selectable_z.isSelected()
1230                    | m_selectable_screen.isSelected()
1231                    | m_selectable_sphere.isSelected();
1232 }
1233 };
1234
1235 Shader* RotateManipulator::m_state_outer;
1236
1237
1238 const float arrowhead_length = 16;
1239 const float arrowhead_radius = 4;
1240
1241 inline void draw_arrowline( const float length, PointVertex* line, const std::size_t axis ){
1242         ( *line++ ).vertex = vertex3f_identity;
1243         ( *line ).vertex = vertex3f_identity;
1244         vertex3f_to_array( ( *line ).vertex )[axis] = length - arrowhead_length;
1245 }
1246
1247 template<typename VertexRemap, typename NormalRemap>
1248 inline void draw_arrowhead( const std::size_t segments, const float length, FlatShadedVertex* vertices, VertexRemap, NormalRemap ){
1249         std::size_t head_tris = ( segments << 3 );
1250         const double head_segment = c_2pi / head_tris;
1251         for ( std::size_t i = 0; i < head_tris; ++i )
1252         {
1253                 {
1254                         FlatShadedVertex& point = vertices[i * 6 + 0];
1255                         VertexRemap::x( point.vertex ) = length - arrowhead_length;
1256                         VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast<float>( cos( i * head_segment ) );
1257                         VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast<float>( sin( i * head_segment ) );
1258                         NormalRemap::x( point.normal ) = arrowhead_radius / arrowhead_length;
1259                         NormalRemap::y( point.normal ) = static_cast<float>( cos( i * head_segment ) );
1260                         NormalRemap::z( point.normal ) = static_cast<float>( sin( i * head_segment ) );
1261                 }
1262                 {
1263                         FlatShadedVertex& point = vertices[i * 6 + 1];
1264                         VertexRemap::x( point.vertex ) = length;
1265                         VertexRemap::y( point.vertex ) = 0;
1266                         VertexRemap::z( point.vertex ) = 0;
1267                         NormalRemap::x( point.normal ) = arrowhead_radius / arrowhead_length;
1268                         NormalRemap::y( point.normal ) = static_cast<float>( cos( ( i + 0.5 ) * head_segment ) );
1269                         NormalRemap::z( point.normal ) = static_cast<float>( sin( ( i + 0.5 ) * head_segment ) );
1270                 }
1271                 {
1272                         FlatShadedVertex& point = vertices[i * 6 + 2];
1273                         VertexRemap::x( point.vertex ) = length - arrowhead_length;
1274                         VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast<float>( cos( ( i + 1 ) * head_segment ) );
1275                         VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast<float>( sin( ( i + 1 ) * head_segment ) );
1276                         NormalRemap::x( point.normal ) = arrowhead_radius / arrowhead_length;
1277                         NormalRemap::y( point.normal ) = static_cast<float>( cos( ( i + 1 ) * head_segment ) );
1278                         NormalRemap::z( point.normal ) = static_cast<float>( sin( ( i + 1 ) * head_segment ) );
1279                 }
1280
1281                 {
1282                         FlatShadedVertex& point = vertices[i * 6 + 3];
1283                         VertexRemap::x( point.vertex ) = length - arrowhead_length;
1284                         VertexRemap::y( point.vertex ) = 0;
1285                         VertexRemap::z( point.vertex ) = 0;
1286                         NormalRemap::x( point.normal ) = -1;
1287                         NormalRemap::y( point.normal ) = 0;
1288                         NormalRemap::z( point.normal ) = 0;
1289                 }
1290                 {
1291                         FlatShadedVertex& point = vertices[i * 6 + 4];
1292                         VertexRemap::x( point.vertex ) = length - arrowhead_length;
1293                         VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast<float>( cos( i * head_segment ) );
1294                         VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast<float>( sin( i * head_segment ) );
1295                         NormalRemap::x( point.normal ) = -1;
1296                         NormalRemap::y( point.normal ) = 0;
1297                         NormalRemap::z( point.normal ) = 0;
1298                 }
1299                 {
1300                         FlatShadedVertex& point = vertices[i * 6 + 5];
1301                         VertexRemap::x( point.vertex ) = length - arrowhead_length;
1302                         VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast<float>( cos( ( i + 1 ) * head_segment ) );
1303                         VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast<float>( sin( ( i + 1 ) * head_segment ) );
1304                         NormalRemap::x( point.normal ) = -1;
1305                         NormalRemap::y( point.normal ) = 0;
1306                         NormalRemap::z( point.normal ) = 0;
1307                 }
1308         }
1309 }
1310
1311 template<typename Triple>
1312 class TripleRemapXYZ
1313 {
1314 public:
1315 static float& x( Triple& triple ){
1316         return triple.x();
1317 }
1318 static float& y( Triple& triple ){
1319         return triple.y();
1320 }
1321 static float& z( Triple& triple ){
1322         return triple.z();
1323 }
1324 };
1325
1326 template<typename Triple>
1327 class TripleRemapYZX
1328 {
1329 public:
1330 static float& x( Triple& triple ){
1331         return triple.y();
1332 }
1333 static float& y( Triple& triple ){
1334         return triple.z();
1335 }
1336 static float& z( Triple& triple ){
1337         return triple.x();
1338 }
1339 };
1340
1341 template<typename Triple>
1342 class TripleRemapZXY
1343 {
1344 public:
1345 static float& x( Triple& triple ){
1346         return triple.z();
1347 }
1348 static float& y( Triple& triple ){
1349         return triple.x();
1350 }
1351 static float& z( Triple& triple ){
1352         return triple.y();
1353 }
1354 };
1355
1356 void vector3_print( const Vector3& v ){
1357         globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )";
1358 }
1359
1360 class TranslateManipulator : public Manipulator
1361 {
1362 struct RenderableArrowLine : public OpenGLRenderable
1363 {
1364         PointVertex m_line[2];
1365
1366         RenderableArrowLine(){
1367         }
1368         void render( RenderStateFlags state ) const {
1369                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_line[0].colour );
1370                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_line[0].vertex );
1371                 glDrawArrays( GL_LINES, 0, 2 );
1372         }
1373         void setColour( const Colour4b& colour ){
1374                 m_line[0].colour = colour;
1375                 m_line[1].colour = colour;
1376         }
1377 };
1378 struct RenderableArrowHead : public OpenGLRenderable
1379 {
1380         Array<FlatShadedVertex> m_vertices;
1381
1382         RenderableArrowHead( std::size_t size )
1383                 : m_vertices( size ){
1384         }
1385         void render( RenderStateFlags state ) const {
1386                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( FlatShadedVertex ), &m_vertices.data()->colour );
1387                 glVertexPointer( 3, GL_FLOAT, sizeof( FlatShadedVertex ), &m_vertices.data()->vertex );
1388                 glNormalPointer( GL_FLOAT, sizeof( FlatShadedVertex ), &m_vertices.data()->normal );
1389                 glDrawArrays( GL_TRIANGLES, 0, GLsizei( m_vertices.size() ) );
1390         }
1391         void setColour( const Colour4b& colour ){
1392                 for ( Array<FlatShadedVertex>::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i )
1393                 {
1394                         ( *i ).colour = colour;
1395                 }
1396         }
1397 };
1398 struct RenderableQuad : public OpenGLRenderable
1399 {
1400         PointVertex m_quad[4];
1401         void render( RenderStateFlags state ) const {
1402                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_quad[0].colour );
1403                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_quad[0].vertex );
1404                 glDrawArrays( GL_LINE_LOOP, 0, 4 );
1405         }
1406         void setColour( const Colour4b& colour ){
1407                 m_quad[0].colour = colour;
1408                 m_quad[1].colour = colour;
1409                 m_quad[2].colour = colour;
1410                 m_quad[3].colour = colour;
1411         }
1412 };
1413
1414 TranslateFree m_free;
1415 TranslateAxis m_axis;
1416 RenderableArrowLine m_arrow_x;
1417 RenderableArrowLine m_arrow_y;
1418 RenderableArrowLine m_arrow_z;
1419 RenderableArrowHead m_arrow_head_x;
1420 RenderableArrowHead m_arrow_head_y;
1421 RenderableArrowHead m_arrow_head_z;
1422 RenderableQuad m_quad_screen;
1423 SelectableBool m_selectable_x;
1424 SelectableBool m_selectable_y;
1425 SelectableBool m_selectable_z;
1426 SelectableBool m_selectable_screen;
1427 Pivot2World m_pivot;
1428 public:
1429 static Shader* m_state_wire;
1430 static Shader* m_state_fill;
1431
1432 TranslateManipulator( Translatable& translatable, std::size_t segments, float length ) :
1433         m_free( translatable ),
1434         m_axis( translatable ),
1435         m_arrow_head_x( 3 * 2 * ( segments << 3 ) ),
1436         m_arrow_head_y( 3 * 2 * ( segments << 3 ) ),
1437         m_arrow_head_z( 3 * 2 * ( segments << 3 ) ){
1438         draw_arrowline( length, m_arrow_x.m_line, 0 );
1439         draw_arrowhead( segments, length, m_arrow_head_x.m_vertices.data(), TripleRemapXYZ<Vertex3f>(), TripleRemapXYZ<Normal3f>() );
1440         draw_arrowline( length, m_arrow_y.m_line, 1 );
1441         draw_arrowhead( segments, length, m_arrow_head_y.m_vertices.data(), TripleRemapYZX<Vertex3f>(), TripleRemapYZX<Normal3f>() );
1442         draw_arrowline( length, m_arrow_z.m_line, 2 );
1443         draw_arrowhead( segments, length, m_arrow_head_z.m_vertices.data(), TripleRemapZXY<Vertex3f>(), TripleRemapZXY<Normal3f>() );
1444
1445         draw_quad( 16, m_quad_screen.m_quad );
1446 }
1447
1448 void UpdateColours(){
1449         m_arrow_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) );
1450         m_arrow_head_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) );
1451         m_arrow_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) );
1452         m_arrow_head_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) );
1453         m_arrow_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) );
1454         m_arrow_head_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) );
1455         m_quad_screen.setColour( colourSelected( g_colour_screen, m_selectable_screen.isSelected() ) );
1456 }
1457
1458 bool manipulator_show_axis( const Pivot2World& pivot, const Vector3& axis ){
1459         return fabs( vector3_dot( pivot.m_axis_screen, axis ) ) < 0.95;
1460 }
1461
1462 void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){
1463         m_pivot.update( pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport() );
1464
1465         // temp hack
1466         UpdateColours();
1467
1468         Vector3 x = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.x() ) );
1469         bool show_x = manipulator_show_axis( m_pivot, x );
1470
1471         Vector3 y = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.y() ) );
1472         bool show_y = manipulator_show_axis( m_pivot, y );
1473
1474         Vector3 z = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.z() ) );
1475         bool show_z = manipulator_show_axis( m_pivot, z );
1476
1477         renderer.SetState( m_state_wire, Renderer::eWireframeOnly );
1478         renderer.SetState( m_state_wire, Renderer::eFullMaterials );
1479
1480         if ( show_x ) {
1481                 renderer.addRenderable( m_arrow_x, m_pivot.m_worldSpace );
1482         }
1483         if ( show_y ) {
1484                 renderer.addRenderable( m_arrow_y, m_pivot.m_worldSpace );
1485         }
1486         if ( show_z ) {
1487                 renderer.addRenderable( m_arrow_z, m_pivot.m_worldSpace );
1488         }
1489
1490         renderer.addRenderable( m_quad_screen, m_pivot.m_viewplaneSpace );
1491
1492         renderer.SetState( m_state_fill, Renderer::eWireframeOnly );
1493         renderer.SetState( m_state_fill, Renderer::eFullMaterials );
1494
1495         if ( show_x ) {
1496                 renderer.addRenderable( m_arrow_head_x, m_pivot.m_worldSpace );
1497         }
1498         if ( show_y ) {
1499                 renderer.addRenderable( m_arrow_head_y, m_pivot.m_worldSpace );
1500         }
1501         if ( show_z ) {
1502                 renderer.addRenderable( m_arrow_head_z, m_pivot.m_worldSpace );
1503         }
1504 }
1505 void testSelect( const View& view, const Matrix4& pivot2world ){
1506         m_pivot.update( pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport() );
1507
1508         SelectionPool selector;
1509
1510         Vector3 x = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.x() ) );
1511         bool show_x = manipulator_show_axis( m_pivot, x );
1512
1513         Vector3 y = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.y() ) );
1514         bool show_y = manipulator_show_axis( m_pivot, y );
1515
1516         Vector3 z = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.z() ) );
1517         bool show_z = manipulator_show_axis( m_pivot, z );
1518
1519         {
1520                 Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_viewpointSpace ) );
1521
1522                 {
1523                         SelectionIntersection best;
1524                         Quad_BestPoint( local2view, eClipCullCW, m_quad_screen.m_quad, best );
1525                         if ( best.valid() ) {
1526                                 best = SelectionIntersection( 0, 0 );
1527                                 selector.addSelectable( best, &m_selectable_screen );
1528                         }
1529                 }
1530         }
1531
1532         {
1533                 Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_worldSpace ) );
1534
1535 #if defined( DEBUG_SELECTION )
1536                 g_render_clipped.construct( view.GetViewMatrix() );
1537 #endif
1538
1539                 if ( show_x ) {
1540                         SelectionIntersection best;
1541                         Line_BestPoint( local2view, m_arrow_x.m_line, best );
1542                         Triangles_BestPoint( local2view, eClipCullCW, m_arrow_head_x.m_vertices.begin(), m_arrow_head_x.m_vertices.end(), best );
1543                         selector.addSelectable( best, &m_selectable_x );
1544                 }
1545
1546                 if ( show_y ) {
1547                         SelectionIntersection best;
1548                         Line_BestPoint( local2view, m_arrow_y.m_line, best );
1549                         Triangles_BestPoint( local2view, eClipCullCW, m_arrow_head_y.m_vertices.begin(), m_arrow_head_y.m_vertices.end(), best );
1550                         selector.addSelectable( best, &m_selectable_y );
1551                 }
1552
1553                 if ( show_z ) {
1554                         SelectionIntersection best;
1555                         Line_BestPoint( local2view, m_arrow_z.m_line, best );
1556                         Triangles_BestPoint( local2view, eClipCullCW, m_arrow_head_z.m_vertices.begin(), m_arrow_head_z.m_vertices.end(), best );
1557                         selector.addSelectable( best, &m_selectable_z );
1558                 }
1559         }
1560
1561         if ( !selector.failed() ) {
1562                 ( *selector.begin() ).second->setSelected( true );
1563         }
1564 }
1565
1566 Manipulatable* GetManipulatable(){
1567         if ( m_selectable_x.isSelected() ) {
1568                 m_axis.SetAxis( g_vector3_axis_x );
1569                 return &m_axis;
1570         }
1571         else if ( m_selectable_y.isSelected() ) {
1572                 m_axis.SetAxis( g_vector3_axis_y );
1573                 return &m_axis;
1574         }
1575         else if ( m_selectable_z.isSelected() ) {
1576                 m_axis.SetAxis( g_vector3_axis_z );
1577                 return &m_axis;
1578         }
1579         else
1580         {
1581                 return &m_free;
1582         }
1583 }
1584
1585 void setSelected( bool select ){
1586         m_selectable_x.setSelected( select );
1587         m_selectable_y.setSelected( select );
1588         m_selectable_z.setSelected( select );
1589         m_selectable_screen.setSelected( select );
1590 }
1591 bool isSelected() const {
1592         return m_selectable_x.isSelected()
1593                    | m_selectable_y.isSelected()
1594                    | m_selectable_z.isSelected()
1595                    | m_selectable_screen.isSelected();
1596 }
1597 };
1598
1599 Shader* TranslateManipulator::m_state_wire;
1600 Shader* TranslateManipulator::m_state_fill;
1601
1602 class ScaleManipulator : public Manipulator
1603 {
1604 struct RenderableArrow : public OpenGLRenderable
1605 {
1606         PointVertex m_line[2];
1607
1608         void render( RenderStateFlags state ) const {
1609                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_line[0].colour );
1610                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_line[0].vertex );
1611                 glDrawArrays( GL_LINES, 0, 2 );
1612         }
1613         void setColour( const Colour4b& colour ){
1614                 m_line[0].colour = colour;
1615                 m_line[1].colour = colour;
1616         }
1617 };
1618 struct RenderableQuad : public OpenGLRenderable
1619 {
1620         PointVertex m_quad[4];
1621         void render( RenderStateFlags state ) const {
1622                 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_quad[0].colour );
1623                 glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_quad[0].vertex );
1624                 glDrawArrays( GL_QUADS, 0, 4 );
1625         }
1626         void setColour( const Colour4b& colour ){
1627                 m_quad[0].colour = colour;
1628                 m_quad[1].colour = colour;
1629                 m_quad[2].colour = colour;
1630                 m_quad[3].colour = colour;
1631         }
1632 };
1633
1634 ScaleFree m_free;
1635 ScaleAxis m_axis;
1636 RenderableArrow m_arrow_x;
1637 RenderableArrow m_arrow_y;
1638 RenderableArrow m_arrow_z;
1639 RenderableQuad m_quad_screen;
1640 SelectableBool m_selectable_x;
1641 SelectableBool m_selectable_y;
1642 SelectableBool m_selectable_z;
1643 SelectableBool m_selectable_screen;
1644 Pivot2World m_pivot;
1645 public:
1646 ScaleManipulator( Scalable& scalable, std::size_t segments, float length ) :
1647         m_free( scalable ),
1648         m_axis( scalable ){
1649         draw_arrowline( length, m_arrow_x.m_line, 0 );
1650         draw_arrowline( length, m_arrow_y.m_line, 1 );
1651         draw_arrowline( length, m_arrow_z.m_line, 2 );
1652
1653         draw_quad( 16, m_quad_screen.m_quad );
1654 }
1655
1656 Pivot2World& getPivot(){
1657         return m_pivot;
1658 }
1659
1660 void UpdateColours(){
1661         m_arrow_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) );
1662         m_arrow_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) );
1663         m_arrow_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) );
1664         m_quad_screen.setColour( colourSelected( g_colour_screen, m_selectable_screen.isSelected() ) );
1665 }
1666
1667 void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){
1668         m_pivot.update( pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport() );
1669
1670         // temp hack
1671         UpdateColours();
1672
1673         renderer.addRenderable( m_arrow_x, m_pivot.m_worldSpace );
1674         renderer.addRenderable( m_arrow_y, m_pivot.m_worldSpace );
1675         renderer.addRenderable( m_arrow_z, m_pivot.m_worldSpace );
1676
1677         renderer.addRenderable( m_quad_screen, m_pivot.m_viewpointSpace );
1678 }
1679 void testSelect( const View& view, const Matrix4& pivot2world ){
1680         m_pivot.update( pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport() );
1681
1682         SelectionPool selector;
1683
1684         {
1685                 Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_worldSpace ) );
1686
1687 #if defined( DEBUG_SELECTION )
1688                 g_render_clipped.construct( view.GetViewMatrix() );
1689 #endif
1690
1691                 {
1692                         SelectionIntersection best;
1693                         Line_BestPoint( local2view, m_arrow_x.m_line, best );
1694                         selector.addSelectable( best, &m_selectable_x );
1695                 }
1696
1697                 {
1698                         SelectionIntersection best;
1699                         Line_BestPoint( local2view, m_arrow_y.m_line, best );
1700                         selector.addSelectable( best, &m_selectable_y );
1701                 }
1702
1703                 {
1704                         SelectionIntersection best;
1705                         Line_BestPoint( local2view, m_arrow_z.m_line, best );
1706                         selector.addSelectable( best, &m_selectable_z );
1707                 }
1708         }
1709
1710         {
1711                 Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_viewpointSpace ) );
1712
1713                 {
1714                         SelectionIntersection best;
1715                         Quad_BestPoint( local2view, eClipCullCW, m_quad_screen.m_quad, best );
1716                         selector.addSelectable( best, &m_selectable_screen );
1717                 }
1718         }
1719
1720         if ( !selector.failed() ) {
1721                 ( *selector.begin() ).second->setSelected( true );
1722         }
1723 }
1724
1725 Manipulatable* GetManipulatable(){
1726         if ( m_selectable_x.isSelected() ) {
1727                 m_axis.SetAxis( g_vector3_axis_x );
1728                 return &m_axis;
1729         }
1730         else if ( m_selectable_y.isSelected() ) {
1731                 m_axis.SetAxis( g_vector3_axis_y );
1732                 return &m_axis;
1733         }
1734         else if ( m_selectable_z.isSelected() ) {
1735                 m_axis.SetAxis( g_vector3_axis_z );
1736                 return &m_axis;
1737         }
1738         else{
1739                 return &m_free;
1740         }
1741 }
1742
1743 void setSelected( bool select ){
1744         m_selectable_x.setSelected( select );
1745         m_selectable_y.setSelected( select );
1746         m_selectable_z.setSelected( select );
1747         m_selectable_screen.setSelected( select );
1748 }
1749 bool isSelected() const {
1750         return m_selectable_x.isSelected()
1751                    | m_selectable_y.isSelected()
1752                    | m_selectable_z.isSelected()
1753                    | m_selectable_screen.isSelected();
1754 }
1755 };
1756
1757
1758 inline PlaneSelectable* Instance_getPlaneSelectable( scene::Instance& instance ){
1759         return InstanceTypeCast<PlaneSelectable>::cast( instance );
1760 }
1761
1762 class PlaneSelectableSelectPlanes : public scene::Graph::Walker
1763 {
1764 Selector& m_selector;
1765 SelectionTest& m_test;
1766 PlaneCallback m_selectedPlaneCallback;
1767 public:
1768 PlaneSelectableSelectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback )
1769         : m_selector( selector ), m_test( test ), m_selectedPlaneCallback( selectedPlaneCallback ){
1770 }
1771 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1772         if ( path.top().get().visible() ) {
1773                 Selectable* selectable = Instance_getSelectable( instance );
1774                 if ( selectable != 0 && selectable->isSelected() ) {
1775                         PlaneSelectable* planeSelectable = Instance_getPlaneSelectable( instance );
1776                         if ( planeSelectable != 0 ) {
1777                                 planeSelectable->selectPlanes( m_selector, m_test, m_selectedPlaneCallback );
1778                         }
1779                 }
1780         }
1781         return true;
1782 }
1783 };
1784
1785 class PlaneSelectableSelectReversedPlanes : public scene::Graph::Walker
1786 {
1787 Selector& m_selector;
1788 const SelectedPlanes& m_selectedPlanes;
1789 public:
1790 PlaneSelectableSelectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes )
1791         : m_selector( selector ), m_selectedPlanes( selectedPlanes ){
1792 }
1793 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1794         if ( path.top().get().visible() ) {
1795                 Selectable* selectable = Instance_getSelectable( instance );
1796                 if ( selectable != 0 && selectable->isSelected() ) {
1797                         PlaneSelectable* planeSelectable = Instance_getPlaneSelectable( instance );
1798                         if ( planeSelectable != 0 ) {
1799                                 planeSelectable->selectReversedPlanes( m_selector, m_selectedPlanes );
1800                         }
1801                 }
1802         }
1803         return true;
1804 }
1805 };
1806
1807 void Scene_forEachPlaneSelectable_selectPlanes( scene::Graph& graph, Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){
1808         graph.traverse( PlaneSelectableSelectPlanes( selector, test, selectedPlaneCallback ) );
1809 }
1810
1811 void Scene_forEachPlaneSelectable_selectReversedPlanes( scene::Graph& graph, Selector& selector, const SelectedPlanes& selectedPlanes ){
1812         graph.traverse( PlaneSelectableSelectReversedPlanes( selector, selectedPlanes ) );
1813 }
1814
1815
1816 class PlaneLess
1817 {
1818 public:
1819 bool operator()( const Plane3& plane, const Plane3& other ) const {
1820         if ( plane.a < other.a ) {
1821                 return true;
1822         }
1823         if ( other.a < plane.a ) {
1824                 return false;
1825         }
1826
1827         if ( plane.b < other.b ) {
1828                 return true;
1829         }
1830         if ( other.b < plane.b ) {
1831                 return false;
1832         }
1833
1834         if ( plane.c < other.c ) {
1835                 return true;
1836         }
1837         if ( other.c < plane.c ) {
1838                 return false;
1839         }
1840
1841         if ( plane.d < other.d ) {
1842                 return true;
1843         }
1844         if ( other.d < plane.d ) {
1845                 return false;
1846         }
1847
1848         return false;
1849 }
1850 };
1851
1852 typedef std::set<Plane3, PlaneLess> PlaneSet;
1853
1854 inline void PlaneSet_insert( PlaneSet& self, const Plane3& plane ){
1855         self.insert( plane );
1856 }
1857
1858 inline bool PlaneSet_contains( const PlaneSet& self, const Plane3& plane ){
1859         return self.find( plane ) != self.end();
1860 }
1861
1862
1863 class SelectedPlaneSet : public SelectedPlanes
1864 {
1865 PlaneSet m_selectedPlanes;
1866 public:
1867 bool empty() const {
1868         return m_selectedPlanes.empty();
1869 }
1870
1871 void insert( const Plane3& plane ){
1872         PlaneSet_insert( m_selectedPlanes, plane );
1873 }
1874 bool contains( const Plane3& plane ) const {
1875         return PlaneSet_contains( m_selectedPlanes, plane );
1876 }
1877 typedef MemberCaller1<SelectedPlaneSet, const Plane3&, &SelectedPlaneSet::insert> InsertCaller;
1878 };
1879
1880
1881 bool Scene_forEachPlaneSelectable_selectPlanes( scene::Graph& graph, Selector& selector, SelectionTest& test ){
1882         SelectedPlaneSet selectedPlanes;
1883
1884         Scene_forEachPlaneSelectable_selectPlanes( graph, selector, test, SelectedPlaneSet::InsertCaller( selectedPlanes ) );
1885         Scene_forEachPlaneSelectable_selectReversedPlanes( graph, selector, selectedPlanes );
1886
1887         return !selectedPlanes.empty();
1888 }
1889
1890
1891 #include "brush.h"
1892 /*
1893 class TestedBrushPlanesSelectVeritces : public scene::Graph::Walker
1894 {
1895 SelectionTest& m_test;
1896 public:
1897 TestedBrushPlanesSelectVeritces( SelectionTest& test )
1898         : m_test( test ){
1899 }
1900 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1901         if ( path.top().get().visible() ) {
1902                 Selectable* selectable = Instance_getSelectable( instance );
1903                 if ( selectable != 0 && selectable->isSelected() ) {
1904                         BrushInstance* brushInstance = Instance_getBrush( instance );
1905                         if ( brushInstance != 0 ) {
1906                                 brushInstance->selectVerticesOnPlanes( m_test );
1907                         }
1908                 }
1909         }
1910         return true;
1911 }
1912 };
1913
1914 void Scene_forEachTestedBrushPlane_selectVertices( scene::Graph& graph, SelectionTest& test ){
1915         graph.traverse( TestedBrushPlanesSelectVeritces( test ) );
1916 }
1917 */
1918 class BrushPlanesSelectVeritces : public scene::Graph::Walker
1919 {
1920 SelectionTest& m_test;
1921 public:
1922 BrushPlanesSelectVeritces( SelectionTest& test )
1923         : m_test( test ){
1924 }
1925 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1926         if ( path.top().get().visible() ) {
1927                 Selectable* selectable = Instance_getSelectable( instance );
1928                 if ( selectable != 0 && selectable->isSelected() ) {
1929                         BrushInstance* brushInstance = Instance_getBrush( instance );
1930                         if ( brushInstance != 0 ) {
1931                                 brushInstance->selectVerticesOnPlanes( m_test );
1932                         }
1933                 }
1934         }
1935         return true;
1936 }
1937 };
1938
1939 void Scene_forEachBrushPlane_selectVertices( scene::Graph& graph, SelectionTest& test ){
1940         graph.traverse( BrushPlanesSelectVeritces( test ) );
1941 }
1942
1943 void Scene_Translate_Component_Selected( scene::Graph& graph, const Vector3& translation );
1944 void Scene_Translate_Selected( scene::Graph& graph, const Vector3& translation );
1945 void Scene_TestSelect_Primitive( Selector& selector, SelectionTest& test, const VolumeTest& volume );
1946 void Scene_TestSelect_Component( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode );
1947 void Scene_TestSelect_Component_Selected( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode );
1948 void Scene_SelectAll_Component( bool select, SelectionSystem::EComponentMode componentMode );
1949
1950 class ResizeTranslatable : public Translatable
1951 {
1952 void translate( const Vector3& translation ){
1953         Scene_Translate_Component_Selected( GlobalSceneGraph(), translation );
1954 }
1955 };
1956
1957 class DragTranslatable : public Translatable
1958 {
1959 void translate( const Vector3& translation ){
1960         if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) {
1961                 Scene_Translate_Component_Selected( GlobalSceneGraph(), translation );
1962         }
1963         else
1964         {
1965                 Scene_Translate_Selected( GlobalSceneGraph(), translation );
1966         }
1967 }
1968 };
1969
1970 class SelectionVolume : public SelectionTest
1971 {
1972 Matrix4 m_local2view;
1973 const View& m_view;
1974 clipcull_t m_cull;
1975 Vector3 m_near;
1976 Vector3 m_far;
1977 public:
1978 SelectionVolume( const View& view )
1979         : m_view( view ){
1980 }
1981
1982 const VolumeTest& getVolume() const {
1983         return m_view;
1984 }
1985
1986 const Vector3& getNear() const {
1987         return m_near;
1988 }
1989 const Vector3& getFar() const {
1990         return m_far;
1991 }
1992
1993 void BeginMesh( const Matrix4& localToWorld, bool twoSided ){
1994         m_local2view = matrix4_multiplied_by_matrix4( m_view.GetViewMatrix(), localToWorld );
1995
1996         // Cull back-facing polygons based on winding being clockwise or counter-clockwise.
1997         // Don't cull if the view is wireframe and the polygons are two-sided.
1998         m_cull = twoSided && !m_view.fill() ? eClipCullNone : ( matrix4_handedness( localToWorld ) == MATRIX4_RIGHTHANDED ) ? eClipCullCW : eClipCullCCW;
1999
2000         {
2001                 Matrix4 screen2world( matrix4_full_inverse( m_local2view ) );
2002
2003                 m_near = vector4_projected(
2004                         matrix4_transformed_vector4(
2005                                 screen2world,
2006                                 Vector4( 0, 0, -1, 1 )
2007                                 )
2008                         );
2009
2010                 m_far = vector4_projected(
2011                         matrix4_transformed_vector4(
2012                                 screen2world,
2013                                 Vector4( 0, 0, 1, 1 )
2014                                 )
2015                         );
2016         }
2017
2018 #if defined( DEBUG_SELECTION )
2019         g_render_clipped.construct( m_view.GetViewMatrix() );
2020 #endif
2021 }
2022 void TestPoint( const Vector3& point, SelectionIntersection& best ){
2023         Vector4 clipped;
2024         if ( matrix4_clip_point( m_local2view, point, clipped ) == c_CLIP_PASS ) {
2025                 best = select_point_from_clipped( clipped );
2026         }
2027 }
2028 void TestPolygon( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){
2029         Vector4 clipped[9];
2030         for ( std::size_t i = 0; i + 2 < count; ++i )
2031         {
2032                 BestPoint(
2033                         matrix4_clip_triangle(
2034                                 m_local2view,
2035                                 reinterpret_cast<const Vector3&>( vertices[0] ),
2036                                 reinterpret_cast<const Vector3&>( vertices[i + 1] ),
2037                                 reinterpret_cast<const Vector3&>( vertices[i + 2] ),
2038                                 clipped
2039                                 ),
2040                         clipped,
2041                         best,
2042                         m_cull
2043                         );
2044         }
2045 }
2046 void TestLineLoop( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){
2047         if ( count == 0 ) {
2048                 return;
2049         }
2050         Vector4 clipped[9];
2051         for ( VertexPointer::iterator i = vertices.begin(), end = i + count, prev = i + ( count - 1 ); i != end; prev = i, ++i )
2052         {
2053                 BestPoint(
2054                         matrix4_clip_line(
2055                                 m_local2view,
2056                                 reinterpret_cast<const Vector3&>( ( *prev ) ),
2057                                 reinterpret_cast<const Vector3&>( ( *i ) ),
2058                                 clipped
2059                                 ),
2060                         clipped,
2061                         best,
2062                         m_cull
2063                         );
2064         }
2065 }
2066 void TestLineStrip( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){
2067         if ( count == 0 ) {
2068                 return;
2069         }
2070         Vector4 clipped[9];
2071         for ( VertexPointer::iterator i = vertices.begin(), end = i + count, next = i + 1; next != end; i = next, ++next )
2072         {
2073                 BestPoint(
2074                         matrix4_clip_line(
2075                                 m_local2view,
2076                                 reinterpret_cast<const Vector3&>( ( *i ) ),
2077                                 reinterpret_cast<const Vector3&>( ( *next ) ),
2078                                 clipped
2079                                 ),
2080                         clipped,
2081                         best,
2082                         m_cull
2083                         );
2084         }
2085 }
2086 void TestLines( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){
2087         if ( count == 0 ) {
2088                 return;
2089         }
2090         Vector4 clipped[9];
2091         for ( VertexPointer::iterator i = vertices.begin(), end = i + count; i != end; i += 2 )
2092         {
2093                 BestPoint(
2094                         matrix4_clip_line(
2095                                 m_local2view,
2096                                 reinterpret_cast<const Vector3&>( ( *i ) ),
2097                                 reinterpret_cast<const Vector3&>( ( *( i + 1 ) ) ),
2098                                 clipped
2099                                 ),
2100                         clipped,
2101                         best,
2102                         m_cull
2103                         );
2104         }
2105 }
2106 void TestTriangles( const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best ){
2107         Vector4 clipped[9];
2108         for ( IndexPointer::iterator i( indices.begin() ); i != indices.end(); i += 3 )
2109         {
2110                 BestPoint(
2111                         matrix4_clip_triangle(
2112                                 m_local2view,
2113                                 reinterpret_cast<const Vector3&>( vertices[*i] ),
2114                                 reinterpret_cast<const Vector3&>( vertices[*( i + 1 )] ),
2115                                 reinterpret_cast<const Vector3&>( vertices[*( i + 2 )] ),
2116                                 clipped
2117                                 ),
2118                         clipped,
2119                         best,
2120                         m_cull
2121                         );
2122         }
2123 }
2124 void TestQuads( const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best ){
2125         Vector4 clipped[9];
2126         for ( IndexPointer::iterator i( indices.begin() ); i != indices.end(); i += 4 )
2127         {
2128                 BestPoint(
2129                         matrix4_clip_triangle(
2130                                 m_local2view,
2131                                 reinterpret_cast<const Vector3&>( vertices[*i] ),
2132                                 reinterpret_cast<const Vector3&>( vertices[*( i + 1 )] ),
2133                                 reinterpret_cast<const Vector3&>( vertices[*( i + 3 )] ),
2134                                 clipped
2135                                 ),
2136                         clipped,
2137                         best,
2138                         m_cull
2139                         );
2140                 BestPoint(
2141                         matrix4_clip_triangle(
2142                                 m_local2view,
2143                                 reinterpret_cast<const Vector3&>( vertices[*( i + 1 )] ),
2144                                 reinterpret_cast<const Vector3&>( vertices[*( i + 2 )] ),
2145                                 reinterpret_cast<const Vector3&>( vertices[*( i + 3 )] ),
2146                                 clipped
2147                                 ),
2148                         clipped,
2149                         best,
2150                         m_cull
2151                         );
2152         }
2153 }
2154 void TestQuadStrip( const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best ){
2155         Vector4 clipped[9];
2156         for ( IndexPointer::iterator i( indices.begin() ); i + 2 != indices.end(); i += 2 )
2157         {
2158                 BestPoint(
2159                         matrix4_clip_triangle(
2160                                 m_local2view,
2161                                 reinterpret_cast<const Vector3&>( vertices[*i] ),
2162                                 reinterpret_cast<const Vector3&>( vertices[*( i + 1 )] ),
2163                                 reinterpret_cast<const Vector3&>( vertices[*( i + 2 )] ),
2164                                 clipped
2165                                 ),
2166                         clipped,
2167                         best,
2168                         m_cull
2169                         );
2170                 BestPoint(
2171                         matrix4_clip_triangle(
2172                                 m_local2view,
2173                                 reinterpret_cast<const Vector3&>( vertices[*( i + 2 )] ),
2174                                 reinterpret_cast<const Vector3&>( vertices[*( i + 1 )] ),
2175                                 reinterpret_cast<const Vector3&>( vertices[*( i + 3 )] ),
2176                                 clipped
2177                                 ),
2178                         clipped,
2179                         best,
2180                         m_cull
2181                         );
2182         }
2183 }
2184 };
2185
2186 class SelectionCounter
2187 {
2188 public:
2189 typedef const Selectable& first_argument_type;
2190
2191 SelectionCounter( const SelectionChangeCallback& onchanged )
2192         : m_count( 0 ), m_onchanged( onchanged ){
2193 }
2194 void operator()( const Selectable& selectable ){
2195         if ( selectable.isSelected() ) {
2196                 ++m_count;
2197         }
2198         else
2199         {
2200                 ASSERT_MESSAGE( m_count != 0, "selection counter underflow" );
2201                 --m_count;
2202         }
2203
2204         m_onchanged( selectable );
2205 }
2206 bool empty() const {
2207         return m_count == 0;
2208 }
2209 std::size_t size() const {
2210         return m_count;
2211 }
2212 private:
2213 std::size_t m_count;
2214 SelectionChangeCallback m_onchanged;
2215 };
2216
2217 inline void ConstructSelectionTest( View& view, const rect_t selection_box ){
2218         view.EnableScissor( selection_box.min[0], selection_box.max[0], selection_box.min[1], selection_box.max[1] );
2219 }
2220
2221 inline const rect_t SelectionBoxForPoint( const float device_point[2], const float device_epsilon[2] ){
2222         rect_t selection_box;
2223         selection_box.min[0] = device_point[0] - device_epsilon[0];
2224         selection_box.min[1] = device_point[1] - device_epsilon[1];
2225         selection_box.max[0] = device_point[0] + device_epsilon[0];
2226         selection_box.max[1] = device_point[1] + device_epsilon[1];
2227         return selection_box;
2228 }
2229
2230 inline const rect_t SelectionBoxForArea( const float device_point[2], const float device_delta[2] ){
2231         rect_t selection_box;
2232         selection_box.min[0] = ( device_delta[0] < 0 ) ? ( device_point[0] + device_delta[0] ) : ( device_point[0] );
2233         selection_box.min[1] = ( device_delta[1] < 0 ) ? ( device_point[1] + device_delta[1] ) : ( device_point[1] );
2234         selection_box.max[0] = ( device_delta[0] > 0 ) ? ( device_point[0] + device_delta[0] ) : ( device_point[0] );
2235         selection_box.max[1] = ( device_delta[1] > 0 ) ? ( device_point[1] + device_delta[1] ) : ( device_point[1] );
2236         return selection_box;
2237 }
2238
2239 Quaternion construct_local_rotation( const Quaternion& world, const Quaternion& localToWorld ){
2240         return quaternion_normalised( quaternion_multiplied_by_quaternion(
2241                                                                           quaternion_normalised( quaternion_multiplied_by_quaternion(
2242                                                                                                                                  quaternion_inverse( localToWorld ),
2243                                                                                                                                  world
2244                                                                                                                                  ) ),
2245                                                                           localToWorld
2246                                                                           ) );
2247 }
2248
2249 inline void matrix4_assign_rotation( Matrix4& matrix, const Matrix4& other ){
2250         matrix[0] = other[0];
2251         matrix[1] = other[1];
2252         matrix[2] = other[2];
2253         matrix[4] = other[4];
2254         matrix[5] = other[5];
2255         matrix[6] = other[6];
2256         matrix[8] = other[8];
2257         matrix[9] = other[9];
2258         matrix[10] = other[10];
2259 }
2260
2261 void matrix4_assign_rotation_for_pivot( Matrix4& matrix, scene::Instance& instance ){
2262         Editable* editable = Node_getEditable( instance.path().top() );
2263         if ( editable != 0 ) {
2264                 matrix4_assign_rotation( matrix, matrix4_multiplied_by_matrix4( instance.localToWorld(), editable->getLocalPivot() ) );
2265         }
2266         else
2267         {
2268                 matrix4_assign_rotation( matrix, instance.localToWorld() );
2269         }
2270 }
2271
2272 inline bool Instance_isSelectedComponents( scene::Instance& instance ){
2273         ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance );
2274         return componentSelectionTestable != 0
2275                    && componentSelectionTestable->isSelectedComponents();
2276 }
2277
2278 class TranslateSelected : public SelectionSystem::Visitor
2279 {
2280 const Vector3& m_translate;
2281 public:
2282 TranslateSelected( const Vector3& translate )
2283         : m_translate( translate ){
2284 }
2285 void visit( scene::Instance& instance ) const {
2286         Transformable* transform = Instance_getTransformable( instance );
2287         if ( transform != 0 ) {
2288                 transform->setType( TRANSFORM_PRIMITIVE );
2289                 transform->setTranslation( m_translate );
2290         }
2291 }
2292 };
2293
2294 void Scene_Translate_Selected( scene::Graph& graph, const Vector3& translation ){
2295         if ( GlobalSelectionSystem().countSelected() != 0 ) {
2296                 GlobalSelectionSystem().foreachSelected( TranslateSelected( translation ) );
2297         }
2298 }
2299
2300 Vector3 get_local_pivot( const Vector3& world_pivot, const Matrix4& localToWorld ){
2301         return Vector3(
2302                            matrix4_transformed_point(
2303                                    matrix4_full_inverse( localToWorld ),
2304                                    world_pivot
2305                                    )
2306                            );
2307 }
2308
2309 void translation_for_pivoted_matrix_transform( Vector3& parent_translation, const Matrix4& local_transform, const Vector3& world_pivot, const Matrix4& localToWorld, const Matrix4& localToParent ){
2310         // we need a translation inside the parent system to move the origin of this object to the right place
2311
2312         // mathematically, it must fulfill:
2313         //
2314         //   local_translation local_transform local_pivot = local_pivot
2315         //   local_translation = local_pivot - local_transform local_pivot
2316         //
2317         //   or maybe?
2318         //   local_transform local_translation local_pivot = local_pivot
2319         //                   local_translation local_pivot = local_transform^-1 local_pivot
2320         //                 local_translation + local_pivot = local_transform^-1 local_pivot
2321         //                   local_translation             = local_transform^-1 local_pivot - local_pivot
2322
2323         Vector3 local_pivot( get_local_pivot( world_pivot, localToWorld ) );
2324
2325         Vector3 local_translation(
2326                 vector3_subtracted(
2327                         local_pivot,
2328                         matrix4_transformed_point(
2329                                 local_transform,
2330                                 local_pivot
2331                                 )
2332                 /*
2333                     matrix4_transformed_point(
2334                         matrix4_full_inverse(local_transform),
2335                         local_pivot
2336                     ),
2337                     local_pivot
2338                  */
2339                         )
2340                 );
2341
2342         translation_local2object( parent_translation, local_translation, localToParent );
2343
2344         /*
2345            // verify it!
2346            globalOutputStream() << "World pivot is at " << world_pivot << "\n";
2347            globalOutputStream() << "Local pivot is at " << local_pivot << "\n";
2348            globalOutputStream() << "Transformation " << local_transform << " moves it to: " << matrix4_transformed_point(local_transform, local_pivot) << "\n";
2349            globalOutputStream() << "Must move by " << local_translation << " in the local system" << "\n";
2350            globalOutputStream() << "Must move by " << parent_translation << " in the parent system" << "\n";
2351          */
2352 }
2353
2354 void translation_for_pivoted_rotation( Vector3& parent_translation, const Quaternion& local_rotation, const Vector3& world_pivot, const Matrix4& localToWorld, const Matrix4& localToParent ){
2355         translation_for_pivoted_matrix_transform( parent_translation, matrix4_rotation_for_quaternion_quantised( local_rotation ), world_pivot, localToWorld, localToParent );
2356 }
2357
2358 void translation_for_pivoted_scale( Vector3& parent_translation, const Vector3& world_scale, const Vector3& world_pivot, const Matrix4& localToWorld, const Matrix4& localToParent ){
2359         Matrix4 local_transform(
2360                 matrix4_multiplied_by_matrix4(
2361                         matrix4_full_inverse( localToWorld ),
2362                         matrix4_multiplied_by_matrix4(
2363                                 matrix4_scale_for_vec3( world_scale ),
2364                                 localToWorld
2365                                 )
2366                         )
2367                 );
2368         local_transform.tx() = local_transform.ty() = local_transform.tz() = 0; // cancel translation parts
2369         translation_for_pivoted_matrix_transform( parent_translation, local_transform, world_pivot, localToWorld, localToParent );
2370 }
2371
2372 class rotate_selected : public SelectionSystem::Visitor
2373 {
2374 const Quaternion& m_rotate;
2375 const Vector3& m_world_pivot;
2376 public:
2377 rotate_selected( const Quaternion& rotation, const Vector3& world_pivot )
2378         : m_rotate( rotation ), m_world_pivot( world_pivot ){
2379 }
2380 void visit( scene::Instance& instance ) const {
2381         TransformNode* transformNode = Node_getTransformNode( instance.path().top() );
2382         if ( transformNode != 0 ) {
2383                 Transformable* transform = Instance_getTransformable( instance );
2384                 if ( transform != 0 ) {
2385                         transform->setType( TRANSFORM_PRIMITIVE );
2386                         transform->setScale( c_scale_identity );
2387                         transform->setTranslation( c_translation_identity );
2388
2389                         transform->setType( TRANSFORM_PRIMITIVE );
2390                         transform->setRotation( m_rotate );
2391
2392                         {
2393                                 Editable* editable = Node_getEditable( instance.path().top() );
2394                                 const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : g_matrix4_identity;
2395
2396                                 Vector3 parent_translation;
2397                                 translation_for_pivoted_rotation(
2398                                         parent_translation,
2399                                         m_rotate,
2400                                         m_world_pivot,
2401                                         matrix4_multiplied_by_matrix4( instance.localToWorld(), localPivot ),
2402                                         matrix4_multiplied_by_matrix4( transformNode->localToParent(), localPivot )
2403                                         );
2404
2405                                 transform->setTranslation( parent_translation );
2406                         }
2407                 }
2408         }
2409 }
2410 };
2411
2412 void Scene_Rotate_Selected( scene::Graph& graph, const Quaternion& rotation, const Vector3& world_pivot ){
2413         if ( GlobalSelectionSystem().countSelected() != 0 ) {
2414                 GlobalSelectionSystem().foreachSelected( rotate_selected( rotation, world_pivot ) );
2415         }
2416 }
2417
2418 class scale_selected : public SelectionSystem::Visitor
2419 {
2420 const Vector3& m_scale;
2421 const Vector3& m_world_pivot;
2422 public:
2423 scale_selected( const Vector3& scaling, const Vector3& world_pivot )
2424         : m_scale( scaling ), m_world_pivot( world_pivot ){
2425 }
2426 void visit( scene::Instance& instance ) const {
2427         TransformNode* transformNode = Node_getTransformNode( instance.path().top() );
2428         if ( transformNode != 0 ) {
2429                 Transformable* transform = Instance_getTransformable( instance );
2430                 if ( transform != 0 ) {
2431                         transform->setType( TRANSFORM_PRIMITIVE );
2432                         transform->setScale( c_scale_identity );
2433                         transform->setTranslation( c_translation_identity );
2434
2435                         transform->setType( TRANSFORM_PRIMITIVE );
2436                         transform->setScale( m_scale );
2437                         {
2438                                 Editable* editable = Node_getEditable( instance.path().top() );
2439                                 const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : g_matrix4_identity;
2440
2441                                 Vector3 parent_translation;
2442                                 translation_for_pivoted_scale(
2443                                         parent_translation,
2444                                         m_scale,
2445                                         m_world_pivot,
2446                                         matrix4_multiplied_by_matrix4( instance.localToWorld(), localPivot ),
2447                                         matrix4_multiplied_by_matrix4( transformNode->localToParent(), localPivot )
2448                                         );
2449
2450                                 transform->setTranslation( parent_translation );
2451                         }
2452                 }
2453         }
2454 }
2455 };
2456
2457 void Scene_Scale_Selected( scene::Graph& graph, const Vector3& scaling, const Vector3& world_pivot ){
2458         if ( GlobalSelectionSystem().countSelected() != 0 ) {
2459                 GlobalSelectionSystem().foreachSelected( scale_selected( scaling, world_pivot ) );
2460         }
2461 }
2462
2463
2464 class translate_component_selected : public SelectionSystem::Visitor
2465 {
2466 const Vector3& m_translate;
2467 public:
2468 translate_component_selected( const Vector3& translate )
2469         : m_translate( translate ){
2470 }
2471 void visit( scene::Instance& instance ) const {
2472         Transformable* transform = Instance_getTransformable( instance );
2473         if ( transform != 0 ) {
2474                 transform->setType( TRANSFORM_COMPONENT );
2475                 transform->setTranslation( m_translate );
2476         }
2477 }
2478 };
2479
2480 void Scene_Translate_Component_Selected( scene::Graph& graph, const Vector3& translation ){
2481         if ( GlobalSelectionSystem().countSelected() != 0 ) {
2482                 GlobalSelectionSystem().foreachSelectedComponent( translate_component_selected( translation ) );
2483         }
2484 }
2485
2486 class rotate_component_selected : public SelectionSystem::Visitor
2487 {
2488 const Quaternion& m_rotate;
2489 const Vector3& m_world_pivot;
2490 public:
2491 rotate_component_selected( const Quaternion& rotation, const Vector3& world_pivot )
2492         : m_rotate( rotation ), m_world_pivot( world_pivot ){
2493 }
2494 void visit( scene::Instance& instance ) const {
2495         Transformable* transform = Instance_getTransformable( instance );
2496         if ( transform != 0 ) {
2497                 Vector3 parent_translation;
2498                 translation_for_pivoted_rotation( parent_translation, m_rotate, m_world_pivot, instance.localToWorld(), Node_getTransformNode( instance.path().top() )->localToParent() );
2499
2500                 transform->setType( TRANSFORM_COMPONENT );
2501                 transform->setRotation( m_rotate );
2502                 transform->setTranslation( parent_translation );
2503         }
2504 }
2505 };
2506
2507 void Scene_Rotate_Component_Selected( scene::Graph& graph, const Quaternion& rotation, const Vector3& world_pivot ){
2508         if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) {
2509                 GlobalSelectionSystem().foreachSelectedComponent( rotate_component_selected( rotation, world_pivot ) );
2510         }
2511 }
2512
2513 class scale_component_selected : public SelectionSystem::Visitor
2514 {
2515 const Vector3& m_scale;
2516 const Vector3& m_world_pivot;
2517 public:
2518 scale_component_selected( const Vector3& scaling, const Vector3& world_pivot )
2519         : m_scale( scaling ), m_world_pivot( world_pivot ){
2520 }
2521 void visit( scene::Instance& instance ) const {
2522         Transformable* transform = Instance_getTransformable( instance );
2523         if ( transform != 0 ) {
2524                 Vector3 parent_translation;
2525                 translation_for_pivoted_scale( parent_translation, m_scale, m_world_pivot, instance.localToWorld(), Node_getTransformNode( instance.path().top() )->localToParent() );
2526
2527                 transform->setType( TRANSFORM_COMPONENT );
2528                 transform->setScale( m_scale );
2529                 transform->setTranslation( parent_translation );
2530         }
2531 }
2532 };
2533
2534 void Scene_Scale_Component_Selected( scene::Graph& graph, const Vector3& scaling, const Vector3& world_pivot ){
2535         if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) {
2536                 GlobalSelectionSystem().foreachSelectedComponent( scale_component_selected( scaling, world_pivot ) );
2537         }
2538 }
2539
2540
2541 class BooleanSelector : public Selector
2542 {
2543 bool m_selected;
2544 SelectionIntersection m_intersection;
2545 Selectable* m_selectable;
2546 public:
2547 BooleanSelector() : m_selected( false ){
2548 }
2549
2550 void pushSelectable( Selectable& selectable ){
2551         m_intersection = SelectionIntersection();
2552         m_selectable = &selectable;
2553 }
2554 void popSelectable(){
2555         if ( m_intersection.valid() ) {
2556                 m_selected = true;
2557         }
2558         m_intersection = SelectionIntersection();
2559 }
2560 void addIntersection( const SelectionIntersection& intersection ){
2561         if ( m_selectable->isSelected() ) {
2562                 assign_if_closer( m_intersection, intersection );
2563         }
2564 }
2565
2566 bool isSelected(){
2567         return m_selected;
2568 }
2569 };
2570
2571 class BestSelector : public Selector
2572 {
2573 SelectionIntersection m_intersection;
2574 Selectable* m_selectable;
2575 SelectionIntersection m_bestIntersection;
2576 std::list<Selectable*> m_bestSelectable;
2577 public:
2578 BestSelector() : m_bestIntersection( SelectionIntersection() ), m_bestSelectable( 0 ){
2579 }
2580
2581 void pushSelectable( Selectable& selectable ){
2582         m_intersection = SelectionIntersection();
2583         m_selectable = &selectable;
2584 }
2585 void popSelectable(){
2586         if ( m_intersection.equalEpsilon( m_bestIntersection, 0.25f, 0.001f ) ) {
2587                 m_bestSelectable.push_back( m_selectable );
2588                 m_bestIntersection = m_intersection;
2589         }
2590         else if ( m_intersection < m_bestIntersection ) {
2591                 m_bestSelectable.clear();
2592                 m_bestSelectable.push_back( m_selectable );
2593                 m_bestIntersection = m_intersection;
2594         }
2595         m_intersection = SelectionIntersection();
2596 }
2597 void addIntersection( const SelectionIntersection& intersection ){
2598         assign_if_closer( m_intersection, intersection );
2599 }
2600
2601 std::list<Selectable*>& best(){
2602         return m_bestSelectable;
2603 }
2604 };
2605
2606 class DeepBestSelector : public Selector
2607 {
2608 SelectionIntersection m_intersection;
2609 Selectable* m_selectable;
2610 SelectionIntersection m_bestIntersection;
2611 std::list<Selectable*> m_bestSelectable;
2612 public:
2613 DeepBestSelector() : m_bestIntersection( SelectionIntersection() ), m_bestSelectable( 0 ){
2614 }
2615
2616 void pushSelectable( Selectable& selectable ){
2617         m_intersection = SelectionIntersection();
2618         m_selectable = &selectable;
2619 }
2620 void popSelectable(){
2621         if ( m_intersection.equalEpsilon( m_bestIntersection, 0.25f, 2.f ) ) {
2622                 m_bestSelectable.push_back( m_selectable );
2623                 m_bestIntersection = m_intersection;
2624         }
2625         else if ( m_intersection < m_bestIntersection ) {
2626                 m_bestSelectable.clear();
2627                 m_bestSelectable.push_back( m_selectable );
2628                 m_bestIntersection = m_intersection;
2629         }
2630         m_intersection = SelectionIntersection();
2631 }
2632 void addIntersection( const SelectionIntersection& intersection ){
2633         assign_if_closer( m_intersection, intersection );
2634 }
2635
2636 std::list<Selectable*>& best(){
2637         return m_bestSelectable;
2638 }
2639 };
2640
2641 bool g_bAltDragManipulatorResize = false;
2642 bool g_bTmpComponentMode = false;
2643
2644 class DragManipulator : public Manipulator
2645 {
2646 TranslateFree m_freeResize;
2647 TranslateFree m_freeDrag;
2648 ResizeTranslatable m_resize;
2649 DragTranslatable m_drag;
2650 SelectableBool m_dragSelectable; //drag already selected stuff
2651 public:
2652
2653 bool m_selected; //selected temporally for drag
2654
2655 DragManipulator() : m_freeResize( m_resize ), m_freeDrag( m_drag ), m_selected( false ){
2656 }
2657
2658 Manipulatable* GetManipulatable(){
2659         return m_dragSelectable.isSelected() ? &m_freeDrag : &m_freeResize;
2660 }
2661
2662 void testSelect( const View& view, const Matrix4& pivot2world ){
2663         SelectionPool selector;
2664
2665         SelectionVolume test( view );
2666
2667         if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) {
2668                 BooleanSelector booleanSelector;
2669
2670                 Scene_TestSelect_Primitive( booleanSelector, test, view );
2671
2672                 if ( booleanSelector.isSelected() ) {
2673                         if( g_bAltDragManipulatorResize ){
2674                                 DeepBestSelector deepSelector;
2675                                 Scene_TestSelect_Component_Selected( deepSelector, test, view, SelectionSystem::eVertex );
2676                                 for ( std::list<Selectable*>::iterator i = deepSelector.best().begin(); i != deepSelector.best().end(); ++i )
2677                                 {
2678                                         if ( !( *i )->isSelected() ) {
2679                                                 GlobalSelectionSystem().setSelectedAllComponents( false );
2680                                         }
2681                                         selector.addSelectable( SelectionIntersection( 0, 0 ), ( *i ) );
2682                                         m_selected = true;
2683                                         m_dragSelectable.setSelected( false );
2684                                 }
2685                                 if( deepSelector.best().empty() ){
2686                                         //Scene_forEachTestedBrushPlane_selectVertices( GlobalSceneGraph(), test );     //todo? drag clicked face
2687                                         Scene_forEachBrushPlane_selectVertices( GlobalSceneGraph(), test );
2688                                         m_selected = true;
2689                                 }
2690                         }
2691                         else{
2692                                 selector.addSelectable( SelectionIntersection( 0, 0 ), &m_dragSelectable );
2693                                 m_selected = false;
2694                         }
2695                 }
2696                 else
2697                 {
2698                         if( g_bAltDragManipulatorResize ){
2699                                 Scene_forEachBrushPlane_selectVertices( GlobalSceneGraph(), test );
2700                                 m_selected = true;
2701                         }
2702                         else{
2703                                 m_selected = Scene_forEachPlaneSelectable_selectPlanes( GlobalSceneGraph(), selector, test );
2704                         }
2705                 }
2706         }
2707         else
2708         {
2709                 BestSelector bestSelector;
2710                 Scene_TestSelect_Component_Selected( bestSelector, test, view, GlobalSelectionSystem().ComponentMode() );
2711                 for ( std::list<Selectable*>::iterator i = bestSelector.best().begin(); i != bestSelector.best().end(); ++i )
2712                 {
2713                         if ( !( *i )->isSelected() ) {
2714                                 GlobalSelectionSystem().setSelectedAllComponents( false );
2715                         }
2716                         m_selected = false;
2717                         selector.addSelectable( SelectionIntersection( 0, 0 ), ( *i ) );
2718                         m_dragSelectable.setSelected( true );
2719                 }
2720                 if( GlobalSelectionSystem().countSelectedComponents() != 0 ){
2721                         m_dragSelectable.setSelected( true );
2722                 }
2723         }
2724
2725         for ( SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i )
2726         {
2727                 ( *i ).second->setSelected( true );
2728         }
2729         g_bTmpComponentMode = m_selected;
2730 }
2731
2732 void setSelected( bool select ){
2733         m_selected = select;
2734         m_dragSelectable.setSelected( select );
2735 }
2736 bool isSelected() const {
2737         return m_selected || m_dragSelectable.isSelected();
2738 }
2739 };
2740
2741 class ClipManipulator : public Manipulator
2742 {
2743 public:
2744
2745 Manipulatable* GetManipulatable(){
2746         ERROR_MESSAGE( "clipper is not manipulatable" );
2747         return 0;
2748 }
2749
2750 void setSelected( bool select ){
2751 }
2752 bool isSelected() const {
2753         return false;
2754 }
2755 };
2756
2757 class select_all : public scene::Graph::Walker
2758 {
2759 bool m_select;
2760 public:
2761 select_all( bool select )
2762         : m_select( select ){
2763 }
2764 bool pre( const scene::Path& path, scene::Instance& instance ) const {
2765         Selectable* selectable = Instance_getSelectable( instance );
2766         if ( selectable != 0 ) {
2767                 selectable->setSelected( m_select );
2768         }
2769         return true;
2770 }
2771 };
2772
2773 class select_all_component : public scene::Graph::Walker
2774 {
2775 bool m_select;
2776 SelectionSystem::EComponentMode m_mode;
2777 public:
2778 select_all_component( bool select, SelectionSystem::EComponentMode mode )
2779         : m_select( select ), m_mode( mode ){
2780 }
2781 bool pre( const scene::Path& path, scene::Instance& instance ) const {
2782         ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance );
2783         if ( componentSelectionTestable ) {
2784                 componentSelectionTestable->setSelectedComponents( m_select, m_mode );
2785         }
2786         return true;
2787 }
2788 };
2789
2790 void Scene_SelectAll_Component( bool select, SelectionSystem::EComponentMode componentMode ){
2791         GlobalSceneGraph().traverse( select_all_component( select, componentMode ) );
2792 }
2793
2794
2795 // RadiantSelectionSystem
2796 class RadiantSelectionSystem :
2797         public SelectionSystem,
2798         public Translatable,
2799         public Rotatable,
2800         public Scalable,
2801         public Renderable
2802 {
2803 mutable Matrix4 m_pivot2world;
2804 Matrix4 m_pivot2world_start;
2805 Matrix4 m_manip2pivot_start;
2806 Translation m_translation;
2807 Rotation m_rotation;
2808 Scale m_scale;
2809 public:
2810 static Shader* m_state;
2811 bool m_bPreferPointEntsIn2D;
2812 private:
2813 EManipulatorMode m_manipulator_mode;
2814 Manipulator* m_manipulator;
2815
2816 // state
2817 bool m_undo_begun;
2818 EMode m_mode;
2819 EComponentMode m_componentmode;
2820
2821 SelectionCounter m_count_primitive;
2822 SelectionCounter m_count_component;
2823
2824 TranslateManipulator m_translate_manipulator;
2825 RotateManipulator m_rotate_manipulator;
2826 ScaleManipulator m_scale_manipulator;
2827 DragManipulator m_drag_manipulator;
2828 ClipManipulator m_clip_manipulator;
2829
2830 typedef SelectionList<scene::Instance> selection_t;
2831 selection_t m_selection;
2832 selection_t m_component_selection;
2833
2834 Signal1<const Selectable&> m_selectionChanged_callbacks;
2835
2836 void ConstructPivot() const;
2837 void setCustomPivotOrigin( Vector3& point ) const;
2838 public:
2839 AABB getSelectionAABB() const;
2840 private:
2841 mutable bool m_pivotChanged;
2842 bool m_pivot_moving;
2843 mutable bool m_pivotIsCustom;
2844
2845 void Scene_TestSelect( Selector& selector, SelectionTest& test, const View& view, SelectionSystem::EMode mode, SelectionSystem::EComponentMode componentMode );
2846
2847 bool nothingSelected() const {
2848         return ( Mode() == eComponent && m_count_component.empty() )
2849                    || ( Mode() == ePrimitive && m_count_primitive.empty() );
2850 }
2851
2852
2853 public:
2854 enum EModifier
2855 {
2856         eManipulator,
2857         eToggle,
2858         eReplace,
2859         eCycle,
2860         eSelect,
2861         eDeselect,
2862 };
2863
2864 RadiantSelectionSystem() :
2865         m_bPreferPointEntsIn2D( true ),
2866         m_undo_begun( false ),
2867         m_mode( ePrimitive ),
2868         m_componentmode( eDefault ),
2869         m_count_primitive( SelectionChangedCaller( *this ) ),
2870         m_count_component( SelectionChangedCaller( *this ) ),
2871         m_translate_manipulator( *this, 2, 64 ),
2872         m_rotate_manipulator( *this, 8, 64 ),
2873         m_scale_manipulator( *this, 0, 64 ),
2874         m_pivotChanged( false ),
2875         m_pivot_moving( false ),
2876         m_pivotIsCustom( false ){
2877         SetManipulatorMode( eTranslate );
2878         pivotChanged();
2879         addSelectionChangeCallback( PivotChangedSelectionCaller( *this ) );
2880         AddGridChangeCallback( PivotChangedCaller( *this ) );
2881 }
2882 void pivotChanged() const {
2883         m_pivotChanged = true;
2884         SceneChangeNotify();
2885 }
2886 typedef ConstMemberCaller<RadiantSelectionSystem, &RadiantSelectionSystem::pivotChanged> PivotChangedCaller;
2887 void pivotChangedSelection( const Selectable& selectable ){
2888         pivotChanged();
2889 }
2890 typedef MemberCaller1<RadiantSelectionSystem, const Selectable&, &RadiantSelectionSystem::pivotChangedSelection> PivotChangedSelectionCaller;
2891
2892 void SetMode( EMode mode ){
2893         if ( m_mode != mode ) {
2894                 m_mode = mode;
2895                 pivotChanged();
2896         }
2897 }
2898 EMode Mode() const {
2899         return m_mode;
2900 }
2901 void SetComponentMode( EComponentMode mode ){
2902         m_componentmode = mode;
2903 }
2904 EComponentMode ComponentMode() const {
2905         return m_componentmode;
2906 }
2907 void SetManipulatorMode( EManipulatorMode mode ){
2908         m_pivotIsCustom = false;
2909         m_manipulator_mode = mode;
2910         switch ( m_manipulator_mode )
2911         {
2912         case eTranslate: m_manipulator = &m_translate_manipulator; break;
2913         case eRotate: m_manipulator = &m_rotate_manipulator; break;
2914         case eScale: m_manipulator = &m_scale_manipulator; break;
2915         case eDrag: m_manipulator = &m_drag_manipulator; break;
2916         case eClip: m_manipulator = &m_clip_manipulator; break;
2917         }
2918         pivotChanged();
2919 }
2920 EManipulatorMode ManipulatorMode() const {
2921         return m_manipulator_mode;
2922 }
2923
2924 SelectionChangeCallback getObserver( EMode mode ){
2925         if ( mode == ePrimitive ) {
2926                 return makeCallback1( m_count_primitive );
2927         }
2928         else
2929         {
2930                 return makeCallback1( m_count_component );
2931         }
2932 }
2933 std::size_t countSelected() const {
2934         return m_count_primitive.size();
2935 }
2936 std::size_t countSelectedComponents() const {
2937         return m_count_component.size();
2938 }
2939 void onSelectedChanged( scene::Instance& instance, const Selectable& selectable ){
2940         if ( selectable.isSelected() ) {
2941                 m_selection.append( instance );
2942         }
2943         else
2944         {
2945                 m_selection.erase( instance );
2946         }
2947
2948         ASSERT_MESSAGE( m_selection.size() == m_count_primitive.size(), "selection-tracking error" );
2949 }
2950 void onComponentSelection( scene::Instance& instance, const Selectable& selectable ){
2951         if ( selectable.isSelected() ) {
2952                 m_component_selection.append( instance );
2953         }
2954         else
2955         {
2956                 m_component_selection.erase( instance );
2957         }
2958
2959         ASSERT_MESSAGE( m_component_selection.size() == m_count_component.size(), "selection-tracking error" );
2960 }
2961 scene::Instance& ultimateSelected() const {
2962         ASSERT_MESSAGE( m_selection.size() > 0, "no instance selected" );
2963         return m_selection.back();
2964 }
2965 scene::Instance& penultimateSelected() const {
2966         ASSERT_MESSAGE( m_selection.size() > 1, "only one instance selected" );
2967         return *( *( --( --m_selection.end() ) ) );
2968 }
2969 void setSelectedAll( bool selected ){
2970         GlobalSceneGraph().traverse( select_all( selected ) );
2971
2972         m_manipulator->setSelected( selected );
2973 }
2974 void setSelectedAllComponents( bool selected ){
2975         Scene_SelectAll_Component( selected, SelectionSystem::eVertex );
2976         Scene_SelectAll_Component( selected, SelectionSystem::eEdge );
2977         Scene_SelectAll_Component( selected, SelectionSystem::eFace );
2978
2979         m_manipulator->setSelected( selected );
2980 }
2981
2982 void foreachSelected( const Visitor& visitor ) const {
2983         selection_t::const_iterator i = m_selection.begin();
2984         while ( i != m_selection.end() )
2985         {
2986                 visitor.visit( *( *( i++ ) ) );
2987         }
2988 }
2989 void foreachSelectedComponent( const Visitor& visitor ) const {
2990         selection_t::const_iterator i = m_component_selection.begin();
2991         while ( i != m_component_selection.end() )
2992         {
2993                 visitor.visit( *( *( i++ ) ) );
2994         }
2995 }
2996
2997 void addSelectionChangeCallback( const SelectionChangeHandler& handler ){
2998         m_selectionChanged_callbacks.connectLast( handler );
2999 }
3000 void selectionChanged( const Selectable& selectable ){
3001         m_selectionChanged_callbacks( selectable );
3002 }
3003 typedef MemberCaller1<RadiantSelectionSystem, const Selectable&, &RadiantSelectionSystem::selectionChanged> SelectionChangedCaller;
3004
3005
3006 void startMove(){
3007         m_pivot2world_start = GetPivot2World();
3008 }
3009
3010 bool SelectManipulator( const View& view, const float device_point[2], const float device_epsilon[2] ){
3011         if ( !nothingSelected() || ( ManipulatorMode() == eDrag && Mode() == eComponent ) ) {
3012 #if defined ( DEBUG_SELECTION )
3013                 g_render_clipped.destroy();
3014 #endif
3015
3016                 m_manipulator->setSelected( false );
3017
3018                 if ( !nothingSelected() || ( ManipulatorMode() == eDrag && Mode() == eComponent ) ) {
3019                         View scissored( view );
3020                         ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, device_epsilon ) );
3021                         m_manipulator->testSelect( scissored, GetPivot2World() );
3022                 }
3023
3024                 startMove();
3025
3026                 m_pivot_moving = m_manipulator->isSelected();
3027
3028                 if ( m_pivot_moving ) {
3029                         Pivot2World pivot;
3030                         pivot.update( GetPivot2World(), view.GetModelview(), view.GetProjection(), view.GetViewport() );
3031
3032                         m_manip2pivot_start = matrix4_multiplied_by_matrix4( matrix4_full_inverse( m_pivot2world_start ), pivot.m_worldSpace );
3033
3034                         Matrix4 device2manip;
3035                         ConstructDevice2Manip( device2manip, m_pivot2world_start, view.GetModelview(), view.GetProjection(), view.GetViewport() );
3036                         m_manipulator->GetManipulatable()->Construct( device2manip, device_point[0], device_point[1], getSelectionAABB(), vector4_to_vector3( GetPivot2World().t() ) );
3037
3038                         m_undo_begun = false;
3039                 }
3040
3041                 SceneChangeNotify();
3042         }
3043
3044         return m_pivot_moving;
3045 }
3046
3047 void deselectAll(){
3048         if ( Mode() == eComponent ) {
3049                 setSelectedAllComponents( false );
3050         }
3051         else
3052         {
3053                 setSelectedAll( false );
3054         }
3055 }
3056
3057 void deselectComponentsOrAll( bool components ){
3058         if ( components ) {
3059                 setSelectedAllComponents( false );
3060         }
3061         else
3062         {
3063                 deselectAll();
3064         }
3065 }
3066
3067 void SelectPoint( const View& view, const float device_point[2], const float device_epsilon[2], RadiantSelectionSystem::EModifier modifier, bool face ){
3068         //globalOutputStream() << device_point[0] << "   " << device_point[1] << "\n";
3069         ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" );
3070
3071         if ( modifier == eReplace ) {
3072                 deselectComponentsOrAll( face );
3073         }
3074 /*
3075 //nothingSelected() doesn't consider faces, selected in non-component mode, m
3076         if ( modifier == eCycle && nothingSelected() ){
3077                 modifier = eReplace;
3078         }
3079 */
3080   #if defined ( DEBUG_SELECTION )
3081         g_render_clipped.destroy();
3082   #endif
3083
3084         {
3085                 View scissored( view );
3086                 ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, device_epsilon ) );
3087
3088                 SelectionVolume volume( scissored );
3089                 SelectionPool selector;
3090                 SelectionPool selector_point_ents;
3091                 const bool prefer_point_ents = m_bPreferPointEntsIn2D && Mode() == ePrimitive && !view.fill() && !face
3092                         && ( modifier == RadiantSelectionSystem::eReplace || modifier == RadiantSelectionSystem::eSelect || modifier == RadiantSelectionSystem::eDeselect );
3093
3094                 if( prefer_point_ents ){
3095                         Scene_TestSelect( selector_point_ents, volume, scissored, eEntity, ComponentMode() );
3096                 }
3097                 if( prefer_point_ents && !selector_point_ents.failed() ){
3098                         switch ( modifier )
3099                         {
3100                         // if cycle mode not enabled, enable it
3101                         case RadiantSelectionSystem::eReplace:
3102                         {
3103                                 // select closest
3104                                 ( *selector_point_ents.begin() ).second->setSelected( true );
3105                         }
3106                         break;
3107                         case RadiantSelectionSystem::eSelect:
3108                         {
3109                                 SelectionPool::iterator best = selector_point_ents.begin();
3110                                 if( !( *best ).second->isSelected() ){
3111                                         ( *best ).second->setSelected( true );
3112                                 }
3113                                 SelectionPool::iterator i = best;
3114                                 ++i;
3115                                 while ( i != selector_point_ents.end() )
3116                                 {
3117                                         if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
3118                                                 if( !( *i ).second->isSelected() ){
3119                                                         ( *i ).second->setSelected( true );
3120                                                 }
3121                                         }
3122                                         else{
3123                                                 break;
3124                                         }
3125                                         ++i;
3126                                 }
3127                         }
3128                         break;
3129                         case RadiantSelectionSystem::eDeselect:
3130                         {
3131                                 SelectionPool::iterator best = selector_point_ents.begin();
3132                                 if( ( *best ).second->isSelected() ){
3133                                         ( *best ).second->setSelected( false );
3134                                 }
3135                                 SelectionPool::iterator i = best;
3136                                 ++i;
3137                                 while ( i != selector_point_ents.end() )
3138                                 {
3139                                         if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
3140                                                 if( ( *i ).second->isSelected() ){
3141                                                         ( *i ).second->setSelected( false );
3142                                                 }
3143                                         }
3144                                         else{
3145                                                 break;
3146                                         }
3147                                         ++i;
3148                                 }
3149                         }
3150                         break;
3151                         default:
3152                                 break;
3153                         }
3154                 }
3155                 else{
3156                         if ( face ){
3157                                 Scene_TestSelect_Component( selector, volume, scissored, eFace );
3158                         }
3159                         else{
3160                                 Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
3161                         }
3162
3163                         if ( !selector.failed() ) {
3164                                 switch ( modifier )
3165                                 {
3166                                 case RadiantSelectionSystem::eToggle:
3167                                 {
3168                                         SelectableSortedSet::iterator best = selector.begin();
3169                                         // toggle selection of the object with least depth
3170                                         if ( ( *best ).second->isSelected() ) {
3171                                                 ( *best ).second->setSelected( false );
3172                                         }
3173                                         else{
3174                                                 ( *best ).second->setSelected( true );
3175                                         }
3176                                 }
3177                                 break;
3178                                 // if cycle mode not enabled, enable it
3179                                 case RadiantSelectionSystem::eReplace:
3180                                 {
3181                                         // select closest
3182                                         ( *selector.begin() ).second->setSelected( true );
3183                                 }
3184                                 break;
3185                                 // select the next object in the list from the one already selected
3186                                 case RadiantSelectionSystem::eCycle:
3187                                 {
3188                                         bool CycleSelectionOccured = false;
3189                                         SelectionPool::iterator i = selector.begin();
3190                                         while ( i != selector.end() )
3191                                         {
3192                                                 if ( ( *i ).second->isSelected() ) {
3193                                                         deselectComponentsOrAll( face );
3194                                                         ++i;
3195                                                         if ( i != selector.end() ) {
3196                                                                 i->second->setSelected( true );
3197                                                         }
3198                                                         else
3199                                                         {
3200                                                                 selector.begin()->second->setSelected( true );
3201                                                         }
3202                                                         CycleSelectionOccured = true;
3203                                                         break;
3204                                                 }
3205                                                 ++i;
3206                                         }
3207                                         if( !CycleSelectionOccured ){
3208                                                 deselectComponentsOrAll( face );
3209                                                 ( *selector.begin() ).second->setSelected( true );
3210                                         }
3211                                 }
3212                                 break;
3213                                 case RadiantSelectionSystem::eSelect:
3214                                 {
3215                                         SelectionPool::iterator best = selector.begin();
3216                                         if( !( *best ).second->isSelected() ){
3217                                                 ( *best ).second->setSelected( true );
3218                                         }
3219                                         SelectionPool::iterator i = best;
3220                                         ++i;
3221                                         while ( i != selector.end() )
3222                                         {
3223                                                 if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
3224                                                         if( !( *i ).second->isSelected() ){
3225                                                                 ( *i ).second->setSelected( true );
3226                                                         }
3227                                                 }
3228                                                 else{
3229                                                         break;
3230                                                 }
3231                                                 ++i;
3232                                         }
3233                                 }
3234                                 break;
3235                                 case RadiantSelectionSystem::eDeselect:
3236                                 {
3237                                         SelectionPool::iterator best = selector.begin();
3238                                         if( ( *best ).second->isSelected() ){
3239                                                 ( *best ).second->setSelected( false );
3240                                         }
3241                                         SelectionPool::iterator i = best;
3242                                         ++i;
3243                                         while ( i != selector.end() )
3244                                         {
3245                                                 if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
3246                                                         if( ( *i ).second->isSelected() ){
3247                                                                 ( *i ).second->setSelected( false );
3248                                                         }
3249                                                 }
3250                                                 else{
3251                                                         break;
3252                                                 }
3253                                                 ++i;
3254                                         }
3255                                 }
3256                                 break;
3257                                 default:
3258                                         break;
3259                                 }
3260                         }
3261                         else if( modifier == eCycle ){
3262                                 deselectComponentsOrAll( face );
3263                         }
3264                 }
3265         }
3266 }
3267
3268 bool SelectPoint_InitPaint( const View& view, const float device_point[2], const float device_epsilon[2], bool face ){
3269         ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" );
3270   #if defined ( DEBUG_SELECTION )
3271         g_render_clipped.destroy();
3272   #endif
3273
3274         {
3275                 View scissored( view );
3276                 ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, device_epsilon ) );
3277
3278                 SelectionVolume volume( scissored );
3279                 SelectionPool selector;
3280                 SelectionPool selector_point_ents;
3281                 const bool prefer_point_ents = m_bPreferPointEntsIn2D && Mode() == ePrimitive && !view.fill() && !face;
3282
3283                 if( prefer_point_ents ){
3284                         Scene_TestSelect( selector_point_ents, volume, scissored, eEntity, ComponentMode() );
3285                 }
3286                 if( prefer_point_ents && !selector_point_ents.failed() ){
3287                         SelectableSortedSet::iterator best = selector_point_ents.begin();
3288                         const bool wasSelected = ( *best ).second->isSelected();
3289                         ( *best ).second->setSelected( !wasSelected );
3290                         SelectableSortedSet::iterator i = best;
3291                         ++i;
3292                         while ( i != selector_point_ents.end() )
3293                         {
3294                                 if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
3295                                         ( *i ).second->setSelected( !wasSelected );
3296                                 }
3297                                 else{
3298                                         break;
3299                                 }
3300                                 ++i;
3301                         }
3302                         return !wasSelected;
3303                 }
3304                 else{//do primitives, if ents failed
3305                         if ( face ){
3306                                 Scene_TestSelect_Component( selector, volume, scissored, eFace );
3307                         }
3308                         else{
3309                                 Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
3310                         }
3311                         if ( !selector.failed() ){
3312                                 SelectableSortedSet::iterator best = selector.begin();
3313                                 const bool wasSelected = ( *best ).second->isSelected();
3314                                 ( *best ).second->setSelected( !wasSelected );
3315                                 SelectableSortedSet::iterator i = best;
3316                                 ++i;
3317                                 while ( i != selector.end() )
3318                                 {
3319                                         if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
3320                                                 ( *i ).second->setSelected( !wasSelected );
3321                                         }
3322                                         else{
3323                                                 break;
3324                                         }
3325                                         ++i;
3326                                 }
3327                                 return !wasSelected;
3328                         }
3329                         else{
3330                                 return true;
3331                         }
3332                 }
3333         }
3334 }
3335
3336 void SelectArea( const View& view, const float device_point[2], const float device_delta[2], RadiantSelectionSystem::EModifier modifier, bool face ){
3337         if ( modifier == eReplace ) {
3338                 deselectComponentsOrAll( face );
3339         }
3340
3341   #if defined ( DEBUG_SELECTION )
3342         g_render_clipped.destroy();
3343   #endif
3344
3345         {
3346                 View scissored( view );
3347                 ConstructSelectionTest( scissored, SelectionBoxForArea( device_point, device_delta ) );
3348
3349                 SelectionVolume volume( scissored );
3350                 SelectionPool pool;
3351                 if ( face ) {
3352                         Scene_TestSelect_Component( pool, volume, scissored, eFace );
3353                 }
3354                 else
3355                 {
3356                         Scene_TestSelect( pool, volume, scissored, Mode(), ComponentMode() );
3357                 }
3358
3359                 for ( SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i )
3360                 {
3361                         ( *i ).second->setSelected( !( modifier == RadiantSelectionSystem::eToggle && ( *i ).second->isSelected() ) );
3362                 }
3363         }
3364 }
3365
3366
3367 void translate( const Vector3& translation ){
3368         if ( !nothingSelected() ) {
3369                 //ASSERT_MESSAGE(!m_pivotChanged, "pivot is invalid");
3370
3371                 m_translation = translation;
3372
3373                 m_pivot2world = m_pivot2world_start;
3374                 matrix4_translate_by_vec3( m_pivot2world, translation );
3375
3376                 if ( Mode() == eComponent ) {
3377                         Scene_Translate_Component_Selected( GlobalSceneGraph(), m_translation );
3378                 }
3379                 else
3380                 {
3381                         Scene_Translate_Selected( GlobalSceneGraph(), m_translation );
3382                 }
3383
3384                 SceneChangeNotify();
3385         }
3386 }
3387 void outputTranslation( TextOutputStream& ostream ){
3388         ostream << " -xyz " << m_translation.x() << " " << m_translation.y() << " " << m_translation.z();
3389 }
3390 void rotate( const Quaternion& rotation ){
3391         if ( !nothingSelected() ) {
3392                 //ASSERT_MESSAGE(!m_pivotChanged, "pivot is invalid");
3393
3394                 m_rotation = rotation;
3395
3396                 if ( Mode() == eComponent ) {
3397                         Scene_Rotate_Component_Selected( GlobalSceneGraph(), m_rotation, vector4_to_vector3( m_pivot2world.t() ) );
3398
3399                         matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
3400                 }
3401                 else
3402                 {
3403                         Scene_Rotate_Selected( GlobalSceneGraph(), m_rotation, vector4_to_vector3( m_pivot2world.t() ) );
3404
3405                         matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
3406                 }
3407
3408                 SceneChangeNotify();
3409         }
3410 }
3411 void outputRotation( TextOutputStream& ostream ){
3412         ostream << " -eulerXYZ " << m_rotation.x() << " " << m_rotation.y() << " " << m_rotation.z();
3413 }
3414 void scale( const Vector3& scaling ){
3415         if ( !nothingSelected() ) {
3416                 m_scale = scaling;
3417
3418                 if ( Mode() == eComponent ) {
3419                         Scene_Scale_Component_Selected( GlobalSceneGraph(), m_scale, vector4_to_vector3( m_pivot2world.t() ) );
3420                 }
3421                 else
3422                 {
3423                         Scene_Scale_Selected( GlobalSceneGraph(), m_scale, vector4_to_vector3( m_pivot2world.t() ) );
3424                 }
3425
3426                 SceneChangeNotify();
3427         }
3428 }
3429 void outputScale( TextOutputStream& ostream ){
3430         ostream << " -scale " << m_scale.x() << " " << m_scale.y() << " " << m_scale.z();
3431 }
3432
3433 void rotateSelected( const Quaternion& rotation, bool snapOrigin ){
3434         if( snapOrigin && !m_pivotIsCustom ){
3435                 m_pivot2world.tx() = float_snapped( m_pivot2world.tx(), GetSnapGridSize() );
3436                 m_pivot2world.ty() = float_snapped( m_pivot2world.ty(), GetSnapGridSize() );
3437                 m_pivot2world.tz() = float_snapped( m_pivot2world.tz(), GetSnapGridSize() );
3438         }
3439         startMove();
3440         rotate( rotation );
3441         freezeTransforms();
3442 }
3443 void translateSelected( const Vector3& translation ){
3444         startMove();
3445         translate( translation );
3446         freezeTransforms();
3447 }
3448 void scaleSelected( const Vector3& scaling ){
3449         startMove();
3450         scale( scaling );
3451         freezeTransforms();
3452 }
3453
3454 void MoveSelected( const View& view, const float device_point[2], bool snap, bool snapbbox ){
3455         if ( m_manipulator->isSelected() ) {
3456                 if ( !m_undo_begun ) {
3457                         m_undo_begun = true;
3458                         GlobalUndoSystem().start();
3459                 }
3460
3461                 Matrix4 device2manip;
3462                 ConstructDevice2Manip( device2manip, m_pivot2world_start, view.GetModelview(), view.GetProjection(), view.GetViewport() );
3463                 m_manipulator->GetManipulatable()->Transform( m_manip2pivot_start, device2manip, device_point[0], device_point[1], snap, snapbbox );
3464         }
3465 }
3466
3467 /// \todo Support view-dependent nudge.
3468 void NudgeManipulator( const Vector3& nudge, const Vector3& view ){
3469         if ( ManipulatorMode() == eTranslate || ManipulatorMode() == eDrag ) {
3470                 translateSelected( nudge );
3471         }
3472 }
3473
3474 void endMove();
3475 void freezeTransforms();
3476
3477 void renderSolid( Renderer& renderer, const VolumeTest& volume ) const;
3478 void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
3479         renderSolid( renderer, volume );
3480 }
3481
3482 const Matrix4& GetPivot2World() const {
3483         ConstructPivot();
3484         return m_pivot2world;
3485 }
3486
3487 static void constructStatic(){
3488         m_state = GlobalShaderCache().capture( "$POINT" );
3489   #if defined( DEBUG_SELECTION )
3490         g_state_clipped = GlobalShaderCache().capture( "$DEBUG_CLIPPED" );
3491   #endif
3492         TranslateManipulator::m_state_wire = GlobalShaderCache().capture( "$WIRE_OVERLAY" );
3493         TranslateManipulator::m_state_fill = GlobalShaderCache().capture( "$FLATSHADE_OVERLAY" );
3494         RotateManipulator::m_state_outer = GlobalShaderCache().capture( "$WIRE_OVERLAY" );
3495 }
3496
3497 static void destroyStatic(){
3498   #if defined( DEBUG_SELECTION )
3499         GlobalShaderCache().release( "$DEBUG_CLIPPED" );
3500   #endif
3501         GlobalShaderCache().release( "$WIRE_OVERLAY" );
3502         GlobalShaderCache().release( "$FLATSHADE_OVERLAY" );
3503         GlobalShaderCache().release( "$WIRE_OVERLAY" );
3504         GlobalShaderCache().release( "$POINT" );
3505 }
3506 };
3507
3508 Shader* RadiantSelectionSystem::m_state = 0;
3509
3510
3511 namespace
3512 {
3513 RadiantSelectionSystem* g_RadiantSelectionSystem;
3514
3515 inline RadiantSelectionSystem& getSelectionSystem(){
3516         return *g_RadiantSelectionSystem;
3517 }
3518 }
3519
3520 #include "map.h"
3521
3522 class testselect_entity_visible : public scene::Graph::Walker
3523 {
3524 Selector& m_selector;
3525 SelectionTest& m_test;
3526 public:
3527 testselect_entity_visible( Selector& selector, SelectionTest& test )
3528         : m_selector( selector ), m_test( test ){
3529 }
3530 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3531         if( path.top().get_pointer() == Map_GetWorldspawn( g_map ) ||
3532                 node_is_group( path.top().get() ) ){
3533                 return false;
3534         }
3535         Selectable* selectable = Instance_getSelectable( instance );
3536         if ( selectable != 0
3537                  && Node_isEntity( path.top() ) ) {
3538                 m_selector.pushSelectable( *selectable );
3539         }
3540
3541         SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance );
3542         if ( selectionTestable ) {
3543                 selectionTestable->testSelect( m_selector, m_test );
3544         }
3545
3546         return true;
3547 }
3548 void post( const scene::Path& path, scene::Instance& instance ) const {
3549         Selectable* selectable = Instance_getSelectable( instance );
3550         if ( selectable != 0
3551                  && Node_isEntity( path.top() ) ) {
3552                 m_selector.popSelectable();
3553         }
3554 }
3555 };
3556
3557 class testselect_primitive_visible : public scene::Graph::Walker
3558 {
3559 Selector& m_selector;
3560 SelectionTest& m_test;
3561 public:
3562 testselect_primitive_visible( Selector& selector, SelectionTest& test )
3563         : m_selector( selector ), m_test( test ){
3564 }
3565 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3566         Selectable* selectable = Instance_getSelectable( instance );
3567         if ( selectable != 0 ) {
3568                 m_selector.pushSelectable( *selectable );
3569         }
3570
3571         SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance );
3572         if ( selectionTestable ) {
3573                 selectionTestable->testSelect( m_selector, m_test );
3574         }
3575
3576         return true;
3577 }
3578 void post( const scene::Path& path, scene::Instance& instance ) const {
3579         Selectable* selectable = Instance_getSelectable( instance );
3580         if ( selectable != 0 ) {
3581                 m_selector.popSelectable();
3582         }
3583 }
3584 };
3585
3586 class testselect_component_visible : public scene::Graph::Walker
3587 {
3588 Selector& m_selector;
3589 SelectionTest& m_test;
3590 SelectionSystem::EComponentMode m_mode;
3591 public:
3592 testselect_component_visible( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode )
3593         : m_selector( selector ), m_test( test ), m_mode( mode ){
3594 }
3595 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3596         ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance );
3597         if ( componentSelectionTestable ) {
3598                 componentSelectionTestable->testSelectComponents( m_selector, m_test, m_mode );
3599         }
3600
3601         return true;
3602 }
3603 };
3604
3605
3606 class testselect_component_visible_selected : public scene::Graph::Walker
3607 {
3608 Selector& m_selector;
3609 SelectionTest& m_test;
3610 SelectionSystem::EComponentMode m_mode;
3611 public:
3612 testselect_component_visible_selected( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode )
3613         : m_selector( selector ), m_test( test ), m_mode( mode ){
3614 }
3615 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3616         Selectable* selectable = Instance_getSelectable( instance );
3617         if ( selectable != 0 && selectable->isSelected() ) {
3618                 ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance );
3619                 if ( componentSelectionTestable ) {
3620                         componentSelectionTestable->testSelectComponents( m_selector, m_test, m_mode );
3621                 }
3622         }
3623
3624         return true;
3625 }
3626 };
3627
3628 void Scene_TestSelect_Primitive( Selector& selector, SelectionTest& test, const VolumeTest& volume ){
3629         Scene_forEachVisible( GlobalSceneGraph(), volume, testselect_primitive_visible( selector, test ) );
3630 }
3631
3632 void Scene_TestSelect_Component_Selected( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode ){
3633         Scene_forEachVisible( GlobalSceneGraph(), volume, testselect_component_visible_selected( selector, test, componentMode ) );
3634 }
3635
3636 void Scene_TestSelect_Component( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode ){
3637         Scene_forEachVisible( GlobalSceneGraph(), volume, testselect_component_visible( selector, test, componentMode ) );
3638 }
3639
3640 void RadiantSelectionSystem::Scene_TestSelect( Selector& selector, SelectionTest& test, const View& view, SelectionSystem::EMode mode, SelectionSystem::EComponentMode componentMode ){
3641         switch ( mode )
3642         {
3643         case eEntity:
3644         {
3645                 Scene_forEachVisible( GlobalSceneGraph(), view, testselect_entity_visible( selector, test ) );
3646         }
3647         break;
3648         case ePrimitive:
3649                 Scene_TestSelect_Primitive( selector, test, view );
3650                 break;
3651         case eComponent:
3652                 Scene_TestSelect_Component_Selected( selector, test, view, componentMode );
3653                 break;
3654         }
3655 }
3656
3657 class FreezeTransforms : public scene::Graph::Walker
3658 {
3659 public:
3660 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3661         TransformNode* transformNode = Node_getTransformNode( path.top() );
3662         if ( transformNode != 0 ) {
3663                 Transformable* transform = Instance_getTransformable( instance );
3664                 if ( transform != 0 ) {
3665                         transform->freezeTransform();
3666                 }
3667         }
3668         return true;
3669 }
3670 };
3671
3672 void RadiantSelectionSystem::freezeTransforms(){
3673         GlobalSceneGraph().traverse( FreezeTransforms() );
3674 }
3675
3676
3677 void RadiantSelectionSystem::endMove(){
3678         freezeTransforms();
3679
3680         if ( Mode() == ePrimitive ) {
3681                 if ( ManipulatorMode() == eDrag ) {
3682                         g_bTmpComponentMode = false;
3683                         if( g_bAltDragManipulatorResize ){
3684                                 Scene_SelectAll_Component( false, SelectionSystem::eVertex );
3685                         }
3686                         else{
3687                                 Scene_SelectAll_Component( false, SelectionSystem::eFace );
3688                         }
3689                 }
3690         }
3691
3692         m_pivot_moving = false;
3693         pivotChanged();
3694
3695         SceneChangeNotify();
3696
3697         if ( m_undo_begun ) {
3698                 StringOutputStream command;
3699
3700                 if ( ManipulatorMode() == eTranslate ) {
3701                         command << "translateTool";
3702                         outputTranslation( command );
3703                 }
3704                 else if ( ManipulatorMode() == eRotate ) {
3705                         command << "rotateTool";
3706                         outputRotation( command );
3707                 }
3708                 else if ( ManipulatorMode() == eScale ) {
3709                         command << "scaleTool";
3710                         outputScale( command );
3711                 }
3712                 else if ( ManipulatorMode() == eDrag ) {
3713                         command << "dragTool";
3714                 }
3715
3716                 GlobalUndoSystem().finish( command.c_str() );
3717         }
3718
3719 }
3720
3721 inline AABB Instance_getPivotBounds( scene::Instance& instance ){
3722         Entity* entity = Node_getEntity( instance.path().top() );
3723         if ( entity != 0
3724                  && ( entity->getEntityClass().fixedsize
3725                           || !node_is_group( instance.path().top() ) ) ) {
3726                 Editable* editable = Node_getEditable( instance.path().top() );
3727                 if ( editable != 0 ) {
3728                         return AABB( vector4_to_vector3( matrix4_multiplied_by_matrix4( instance.localToWorld(), editable->getLocalPivot() ).t() ), Vector3( 0, 0, 0 ) );
3729                 }
3730                 else
3731                 {
3732                         return AABB( vector4_to_vector3( instance.localToWorld().t() ), Vector3( 0, 0, 0 ) );
3733                 }
3734         }
3735
3736         return instance.worldAABB();
3737 }
3738
3739 class bounds_selected : public scene::Graph::Walker
3740 {
3741 AABB& m_bounds;
3742 public:
3743 bounds_selected( AABB& bounds )
3744         : m_bounds( bounds ){
3745         m_bounds = AABB();
3746 }
3747 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3748         Selectable* selectable = Instance_getSelectable( instance );
3749         if ( selectable != 0
3750                  && selectable->isSelected() ) {
3751                 aabb_extend_by_aabb_safe( m_bounds, Instance_getPivotBounds( instance ) );
3752         }
3753         return true;
3754 }
3755 };
3756
3757 class bounds_selected_component : public scene::Graph::Walker
3758 {
3759 AABB& m_bounds;
3760 public:
3761 bounds_selected_component( AABB& bounds )
3762         : m_bounds( bounds ){
3763         m_bounds = AABB();
3764 }
3765 bool pre( const scene::Path& path, scene::Instance& instance ) const {
3766         Selectable* selectable = Instance_getSelectable( instance );
3767         if ( selectable != 0
3768                  && selectable->isSelected() ) {
3769                 ComponentEditable* componentEditable = Instance_getComponentEditable( instance );
3770                 if ( componentEditable ) {
3771                         aabb_extend_by_aabb_safe( m_bounds, aabb_for_oriented_aabb_safe( componentEditable->getSelectedComponentsBounds(), instance.localToWorld() ) );
3772                 }
3773         }
3774         return true;
3775 }
3776 };
3777
3778 void Scene_BoundsSelected( scene::Graph& graph, AABB& bounds ){
3779         graph.traverse( bounds_selected( bounds ) );
3780 }
3781
3782 void Scene_BoundsSelectedComponent( scene::Graph& graph, AABB& bounds ){
3783         graph.traverse( bounds_selected_component( bounds ) );
3784 }
3785
3786 #if 0
3787 inline void pivot_for_node( Matrix4& pivot, scene::Node& node, scene::Instance& instance ){
3788         ComponentEditable* componentEditable = Instance_getComponentEditable( instance );
3789         if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent
3790                  && componentEditable != 0 ) {
3791                 pivot = matrix4_translation_for_vec3( componentEditable->getSelectedComponentsBounds().origin );
3792         }
3793         else
3794         {
3795                 Bounded* bounded = Instance_getBounded( instance );
3796                 if ( bounded != 0 ) {
3797                         pivot = matrix4_translation_for_vec3( bounded->localAABB().origin );
3798                 }
3799                 else
3800                 {
3801                         pivot = g_matrix4_identity;
3802                 }
3803         }
3804 }
3805 #endif
3806
3807 void RadiantSelectionSystem::ConstructPivot() const {
3808         if ( !m_pivotChanged || m_pivot_moving || m_pivotIsCustom ) {
3809                 return;
3810         }
3811         m_pivotChanged = false;
3812
3813         Vector3 m_object_pivot;
3814
3815         if ( !nothingSelected() ) {
3816                 {
3817                         AABB bounds;
3818                         if ( Mode() == eComponent ) {
3819                                 Scene_BoundsSelectedComponent( GlobalSceneGraph(), bounds );
3820                         }
3821                         else
3822                         {
3823                                 Scene_BoundsSelected( GlobalSceneGraph(), bounds );
3824                         }
3825                         m_object_pivot = bounds.origin;
3826                 }
3827
3828                 //vector3_snap( m_object_pivot, GetSnapGridSize() );
3829                 //globalOutputStream() << m_object_pivot << "\n";
3830                 m_pivot2world = matrix4_translation_for_vec3( m_object_pivot );
3831
3832                 switch ( m_manipulator_mode )
3833                 {
3834                 case eTranslate:
3835                         break;
3836                 case eRotate:
3837                         if ( Mode() == eComponent ) {
3838                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
3839                         }
3840                         else
3841                         {
3842                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
3843                         }
3844                         break;
3845                 case eScale:
3846                         if ( Mode() == eComponent ) {
3847                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
3848                         }
3849                         else
3850                         {
3851                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
3852                         }
3853                         break;
3854                 default:
3855                         break;
3856                 }
3857         }
3858 }
3859
3860 void RadiantSelectionSystem::setCustomPivotOrigin( Vector3& point ) const {
3861         if ( !nothingSelected() && ( m_manipulator_mode == eTranslate || m_manipulator_mode == eRotate || m_manipulator_mode == eScale ) ) {
3862                 AABB bounds;
3863                 if ( Mode() == eComponent ) {
3864                         Scene_BoundsSelectedComponent( GlobalSceneGraph(), bounds );
3865                 }
3866                 else
3867                 {
3868                         Scene_BoundsSelected( GlobalSceneGraph(), bounds );
3869                 }
3870                 //globalOutputStream() << point << "\n";
3871                 for( std::size_t i = 0; i < 3; i++ ){
3872                         if( point[i] < 900000.0f ){
3873                                 float bestsnapDist = fabs( bounds.origin[i] - point[i] );
3874                                 float bestsnapTo = bounds.origin[i];
3875                                 float othersnapDist = fabs( bounds.origin[i] + bounds.extents[i] - point[i] );
3876                                 if( othersnapDist < bestsnapDist ){
3877                                         bestsnapDist = othersnapDist;
3878                                         bestsnapTo = bounds.origin[i] + bounds.extents[i];
3879                                 }
3880                                 othersnapDist = fabs( bounds.origin[i] - bounds.extents[i] - point[i] );
3881                                 if( othersnapDist < bestsnapDist ){
3882                                         bestsnapDist = othersnapDist;
3883                                         bestsnapTo = bounds.origin[i] - bounds.extents[i];
3884                                 }
3885                                 othersnapDist = fabs( float_snapped( point[i], GetSnapGridSize() ) - point[i] );
3886                                 if( othersnapDist < bestsnapDist ){
3887                                         bestsnapDist = othersnapDist;
3888                                         bestsnapTo = float_snapped( point[i], GetSnapGridSize() );
3889                                 }
3890                                 point[i] = bestsnapTo;
3891
3892                                 m_pivot2world[i + 12] = point[i]; //m_pivot2world.tx() .ty() .tz()
3893                         }
3894                 }
3895
3896                 switch ( m_manipulator_mode )
3897                 {
3898                 case eTranslate:
3899                         break;
3900                 case eRotate:
3901                         if ( Mode() == eComponent ) {
3902                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
3903                         }
3904                         else
3905                         {
3906                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
3907                         }
3908                         break;
3909                 case eScale:
3910                         if ( Mode() == eComponent ) {
3911                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
3912                         }
3913                         else
3914                         {
3915                                 matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
3916                         }
3917                         break;
3918                 default:
3919                         break;
3920                 }
3921
3922                 m_pivotIsCustom = true;
3923         }
3924 }
3925
3926 AABB RadiantSelectionSystem::getSelectionAABB() const {
3927         AABB bounds;
3928         if ( !nothingSelected() ) {
3929                 if ( Mode() == eComponent || g_bTmpComponentMode ) {
3930                         Scene_BoundsSelectedComponent( GlobalSceneGraph(), bounds );
3931                 }
3932                 else
3933                 {
3934                         Scene_BoundsSelected( GlobalSceneGraph(), bounds );
3935                 }
3936         }
3937         return bounds;
3938 }
3939
3940 void RadiantSelectionSystem::renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
3941         //if(view->TestPoint(m_object_pivot))
3942         if ( !nothingSelected() ) {
3943                 renderer.Highlight( Renderer::ePrimitive, false );
3944                 renderer.Highlight( Renderer::eFace, false );
3945
3946                 renderer.SetState( m_state, Renderer::eWireframeOnly );
3947                 renderer.SetState( m_state, Renderer::eFullMaterials );
3948
3949                 m_manipulator->render( renderer, volume, GetPivot2World() );
3950         }
3951
3952 #if defined( DEBUG_SELECTION )
3953         renderer.SetState( g_state_clipped, Renderer::eWireframeOnly );
3954         renderer.SetState( g_state_clipped, Renderer::eFullMaterials );
3955         renderer.addRenderable( g_render_clipped, g_render_clipped.m_world );
3956 #endif
3957 }
3958
3959 #include "preferencesystem.h"
3960 #include "preferences.h"
3961
3962 void SelectionSystem_constructPreferences( PreferencesPage& page ){
3963         page.appendCheckBox( "", "Prefer point entities in 2D", getSelectionSystem().m_bPreferPointEntsIn2D );
3964 }
3965 void SelectionSystem_constructPage( PreferenceGroup& group ){
3966         PreferencesPage page( group.createPage( "Selection", "Selection System Settings" ) );
3967         SelectionSystem_constructPreferences( page );
3968 }
3969 void SelectionSystem_registerPreferencesPage(){
3970         PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, SelectionSystem_constructPage>() );
3971 }
3972
3973
3974
3975 void SelectionSystem_OnBoundsChanged(){
3976         getSelectionSystem().pivotChanged();
3977 }
3978
3979 SignalHandlerId SelectionSystem_boundsChanged;
3980
3981 void SelectionSystem_Construct(){
3982         RadiantSelectionSystem::constructStatic();
3983
3984         g_RadiantSelectionSystem = new RadiantSelectionSystem;
3985
3986         SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( FreeCaller<SelectionSystem_OnBoundsChanged>() );
3987
3988         GlobalShaderCache().attachRenderable( getSelectionSystem() );
3989
3990         GlobalPreferenceSystem().registerPreference( "PreferPointEntsIn2D", BoolImportStringCaller( getSelectionSystem().m_bPreferPointEntsIn2D ), BoolExportStringCaller( getSelectionSystem().m_bPreferPointEntsIn2D ) );
3991         SelectionSystem_registerPreferencesPage();
3992 }
3993
3994 void SelectionSystem_Destroy(){
3995         GlobalShaderCache().detachRenderable( getSelectionSystem() );
3996
3997         GlobalSceneGraph().removeBoundsChangedCallback( SelectionSystem_boundsChanged );
3998
3999         delete g_RadiantSelectionSystem;
4000
4001         RadiantSelectionSystem::destroyStatic();
4002 }
4003
4004
4005
4006
4007 inline float screen_normalised( float pos, std::size_t size ){
4008         return ( ( 2.0f * pos ) / size ) - 1.0f;
4009 }
4010
4011 typedef Vector2 DeviceVector;
4012
4013 inline DeviceVector window_to_normalised_device( WindowVector window, std::size_t width, std::size_t height ){
4014         return DeviceVector( screen_normalised( window.x(), width ), screen_normalised( height - 1 - window.y(), height ) );
4015 }
4016
4017 inline float device_constrained( float pos ){
4018         return std::min( 1.0f, std::max( -1.0f, pos ) );
4019 }
4020
4021 inline DeviceVector device_constrained( DeviceVector device ){
4022         return DeviceVector( device_constrained( device.x() ), device_constrained( device.y() ) );
4023 }
4024
4025 inline float window_constrained( float pos, std::size_t origin, std::size_t size ){
4026         return std::min( static_cast<float>( origin + size ), std::max( static_cast<float>( origin ), pos ) );
4027 }
4028
4029 inline WindowVector window_constrained( WindowVector window, std::size_t x, std::size_t y, std::size_t width, std::size_t height ){
4030         return WindowVector( window_constrained( window.x(), x, width ), window_constrained( window.y(), y, height ) );
4031 }
4032
4033 typedef Callback1<DeviceVector> MouseEventCallback;
4034
4035 Single<MouseEventCallback> g_mouseMovedCallback;
4036 Single<MouseEventCallback> g_mouseUpCallback;
4037
4038 #if 1
4039 const ButtonIdentifier c_button_select = c_buttonLeft;
4040 const ButtonIdentifier c_button_select2 = c_buttonRight;
4041 const ModifierFlags c_modifier_manipulator = c_modifierNone;
4042 const ModifierFlags c_modifier_toggle = c_modifierShift;
4043 const ModifierFlags c_modifier_replace = c_modifierShift | c_modifierAlt;
4044 const ModifierFlags c_modifier_face = c_modifierControl;
4045 #else
4046 const ButtonIdentifier c_button_select = c_buttonLeft;
4047 const ModifierFlags c_modifier_manipulator = c_modifierNone;
4048 const ModifierFlags c_modifier_toggle = c_modifierControl;
4049 const ModifierFlags c_modifier_replace = c_modifierNone;
4050 const ModifierFlags c_modifier_face = c_modifierShift;
4051 #endif
4052 const ModifierFlags c_modifier_toggle_face = c_modifier_toggle | c_modifier_face;
4053 const ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_face;
4054
4055 const ButtonIdentifier c_button_texture = c_buttonMiddle;
4056 const ModifierFlags c_modifier_apply_texture1 = c_modifierControl | c_modifierShift;
4057 const ModifierFlags c_modifier_apply_texture2 = c_modifierControl;
4058 const ModifierFlags c_modifier_apply_texture3 =                     c_modifierShift;
4059 const ModifierFlags c_modifier_copy_texture = c_modifierNone;
4060
4061 class Selector_
4062 {
4063 RadiantSelectionSystem::EModifier modifier_for_state( ModifierFlags state ){
4064         if ( ( state == c_modifier_toggle || state == c_modifier_toggle_face || state == c_modifier_face ) ) {
4065                 if( m_mouse2 ){
4066                         return RadiantSelectionSystem::eReplace;
4067                 }
4068                 else{
4069                         return RadiantSelectionSystem::eToggle;
4070                 }
4071         }
4072         return RadiantSelectionSystem::eManipulator;
4073 }
4074
4075 rect_t getDeviceArea() const {
4076         DeviceVector delta( m_current - m_start );
4077         if ( selecting() && fabs( delta.x() ) > m_epsilon.x() && fabs( delta.y() ) > m_epsilon.y() ) {
4078                 return SelectionBoxForArea( &m_start[0], &delta[0] );
4079         }
4080         else
4081         {
4082                 rect_t default_area = { { 0, 0, }, { 0, 0, }, };
4083                 return default_area;
4084         }
4085 }
4086
4087 public:
4088 DeviceVector m_start;
4089 DeviceVector m_current;
4090 DeviceVector m_epsilon;
4091 ModifierFlags m_state;
4092 bool m_mouse2;
4093 bool m_mouseMoved;
4094 bool m_mouseMovedWhilePressed;
4095 bool m_paintSelect;
4096 const View* m_view;
4097 RectangleCallback m_window_update;
4098
4099 Selector_() : m_start( 0.0f, 0.0f ), m_current( 0.0f, 0.0f ), m_state( c_modifierNone ), m_mouse2( false ), m_mouseMoved( false ), m_mouseMovedWhilePressed( false ){
4100 }
4101
4102 void draw_area(){
4103         m_window_update( getDeviceArea() );
4104 }
4105
4106 void testSelect( DeviceVector position ){
4107         RadiantSelectionSystem::EModifier modifier = modifier_for_state( m_state );
4108         if ( modifier != RadiantSelectionSystem::eManipulator ) {
4109                 DeviceVector delta( position - m_start );
4110                 if ( fabs( delta.x() ) > m_epsilon.x() && fabs( delta.y() ) > m_epsilon.y() ) {
4111                         DeviceVector delta( position - m_start );
4112                         //getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
4113                         getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], RadiantSelectionSystem::eToggle, ( m_state & c_modifier_face ) != c_modifierNone );
4114                 }
4115                 else if( !m_mouseMovedWhilePressed ){
4116                         if ( modifier == RadiantSelectionSystem::eReplace && !m_mouseMoved ) {
4117                                 modifier = RadiantSelectionSystem::eCycle;
4118                         }
4119                         getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
4120                 }
4121         }
4122
4123         m_start = m_current = DeviceVector( 0.0f, 0.0f );
4124         draw_area();
4125 }
4126
4127 void testSelect_simpleM1( DeviceVector position ){
4128         /*RadiantSelectionSystem::EModifier modifier = RadiantSelectionSystem::eReplace;
4129         DeviceVector delta( position - m_start );
4130         if ( fabs( delta.x() ) < m_epsilon.x() && fabs( delta.y() ) < m_epsilon.y() ) {
4131                 modifier = RadiantSelectionSystem::eCycle;
4132         }
4133         getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, false );*/
4134         getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], m_mouseMoved ? RadiantSelectionSystem::eReplace : RadiantSelectionSystem::eCycle, false );
4135         m_start = m_current = device_constrained( position );
4136 }
4137
4138
4139 bool selecting() const {
4140         return m_state != c_modifier_manipulator && m_mouse2;
4141 }
4142
4143 void setState( ModifierFlags state ){
4144         bool was_selecting = selecting();
4145         m_state = state;
4146         if ( was_selecting ^ selecting() ) {
4147                 draw_area();
4148         }
4149 }
4150
4151 ModifierFlags getState() const {
4152         return m_state;
4153 }
4154
4155 void modifierEnable( ModifierFlags type ){
4156         setState( bitfield_enable( getState(), type ) );
4157 }
4158 void modifierDisable( ModifierFlags type ){
4159         setState( bitfield_disable( getState(), type ) );
4160 }
4161
4162 void mouseDown( DeviceVector position ){
4163         m_start = m_current = device_constrained( position );
4164         if( !m_mouse2 && m_state != c_modifierNone ){
4165                 m_paintSelect = getSelectionSystem().SelectPoint_InitPaint( *m_view, &position[0], &m_epsilon[0], ( m_state & c_modifier_face ) != c_modifierNone );
4166         }
4167 }
4168
4169 void mouseMoved( DeviceVector position ){
4170         m_current = device_constrained( position );
4171         m_mouseMovedWhilePressed = true;
4172         if( m_mouse2 ){
4173                 draw_area();
4174         }
4175         else if( m_state != c_modifier_manipulator ){
4176                 getSelectionSystem().SelectPoint( *m_view, &m_current[0], &m_epsilon[0],
4177                                                                                 m_paintSelect ? RadiantSelectionSystem::eSelect : RadiantSelectionSystem::eDeselect,
4178                                                                                 ( m_state & c_modifier_face ) != c_modifierNone );
4179         }
4180 }
4181 typedef MemberCaller1<Selector_, DeviceVector, &Selector_::mouseMoved> MouseMovedCaller;
4182
4183 void mouseUp( DeviceVector position ){
4184         if( m_mouse2 ){
4185                 testSelect( device_constrained( position ) );
4186         }
4187         else{
4188                 m_start = m_current = DeviceVector( 0.0f, 0.0f );
4189         }
4190
4191         g_mouseMovedCallback.clear();
4192         g_mouseUpCallback.clear();
4193 }
4194 typedef MemberCaller1<Selector_, DeviceVector, &Selector_::mouseUp> MouseUpCaller;
4195 };
4196
4197
4198 class Manipulator_
4199 {
4200 public:
4201 DeviceVector m_epsilon;
4202 const View* m_view;
4203 ModifierFlags m_state;
4204
4205 Manipulator_() : m_state( c_modifierNone ){
4206 }
4207
4208 bool mouseDown( DeviceVector position ){
4209         return getSelectionSystem().SelectManipulator( *m_view, &position[0], &m_epsilon[0] );
4210 }
4211
4212 void mouseMoved( DeviceVector position ){
4213         getSelectionSystem().MoveSelected( *m_view, &position[0], ( m_state & c_modifierShift ) == c_modifierShift, ( m_state & c_modifierControl ) == c_modifierControl );
4214 }
4215 typedef MemberCaller1<Manipulator_, DeviceVector, &Manipulator_::mouseMoved> MouseMovedCaller;
4216
4217 void mouseUp( DeviceVector position ){
4218         getSelectionSystem().endMove();
4219         g_mouseMovedCallback.clear();
4220         g_mouseUpCallback.clear();
4221 }
4222 typedef MemberCaller1<Manipulator_, DeviceVector, &Manipulator_::mouseUp> MouseUpCaller;
4223
4224 void setState( ModifierFlags state ){
4225         m_state = state;
4226 }
4227
4228 ModifierFlags getState() const {
4229         return m_state;
4230 }
4231
4232 void modifierEnable( ModifierFlags type ){
4233         setState( bitfield_enable( getState(), type ) );
4234 }
4235 void modifierDisable( ModifierFlags type ){
4236         setState( bitfield_disable( getState(), type ) );
4237 }
4238 };
4239
4240 void Scene_copyClosestTexture( SelectionTest& test );
4241 void Scene_applyClosestTexture( SelectionTest& test );
4242
4243 class RadiantWindowObserver : public SelectionSystemWindowObserver
4244 {
4245 enum
4246 {
4247         SELECT_EPSILON = 8,
4248 };
4249
4250 int m_width;
4251 int m_height;
4252
4253 bool m_mouse_down;
4254
4255 public:
4256 Selector_ m_selector;
4257 Manipulator_ m_manipulator;
4258
4259 RadiantWindowObserver() : m_mouse_down( false ){
4260 }
4261 void release(){
4262         delete this;
4263 }
4264 void setView( const View& view ){
4265         m_selector.m_view = &view;
4266         m_manipulator.m_view = &view;
4267 }
4268 void setRectangleDrawCallback( const RectangleCallback& callback ){
4269         m_selector.m_window_update = callback;
4270 }
4271 void onSizeChanged( int width, int height ){
4272         m_width = width;
4273         m_height = height;
4274         DeviceVector epsilon( SELECT_EPSILON / static_cast<float>( m_width ), SELECT_EPSILON / static_cast<float>( m_height ) );
4275         m_selector.m_epsilon = m_manipulator.m_epsilon = epsilon;
4276 }
4277 void onMouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){
4278         if ( button == c_button_select || ( button == c_button_select2 && modifiers != c_modifierNone ) ) {
4279                 m_mouse_down = true;
4280                 //m_selector.m_mouseMoved = false;
4281
4282                 DeviceVector devicePosition( window_to_normalised_device( position, m_width, m_height ) );
4283                 g_bAltDragManipulatorResize = ( modifiers == c_modifierAlt ) ? true : false;
4284                 if ( ( modifiers == c_modifier_manipulator || modifiers == c_modifierAlt ) && m_manipulator.mouseDown( devicePosition ) ) {
4285                         g_mouseMovedCallback.insert( MouseEventCallback( Manipulator_::MouseMovedCaller( m_manipulator ) ) );
4286                         g_mouseUpCallback.insert( MouseEventCallback( Manipulator_::MouseUpCaller( m_manipulator ) ) );
4287                 }
4288                 else
4289                 {
4290                         if ( button == c_button_select ) {
4291                                 m_selector.m_mouse2 = false;
4292                         }
4293                         else{
4294                                 m_selector.m_mouse2 = true;
4295                         }
4296                         m_selector.mouseDown( devicePosition );
4297                         g_mouseMovedCallback.insert( MouseEventCallback( Selector_::MouseMovedCaller( m_selector ) ) );
4298                         g_mouseUpCallback.insert( MouseEventCallback( Selector_::MouseUpCaller( m_selector ) ) );
4299                 }
4300         }
4301         else if ( button == c_button_texture ) {
4302                 DeviceVector devicePosition( device_constrained( window_to_normalised_device( position, m_width, m_height ) ) );
4303
4304                 View scissored( *m_selector.m_view );
4305                 ConstructSelectionTest( scissored, SelectionBoxForPoint( &devicePosition[0], &m_selector.m_epsilon[0] ) );
4306                 SelectionVolume volume( scissored );
4307
4308                 if ( modifiers == c_modifier_apply_texture1 || modifiers == c_modifier_apply_texture2 || modifiers == c_modifier_apply_texture3 ) {
4309                         Scene_applyClosestTexture( volume );
4310                 }
4311                 else if ( modifiers == c_modifier_copy_texture ) {
4312                         Scene_copyClosestTexture( volume );
4313                 }
4314         }
4315 }
4316 void onMouseMotion( const WindowVector& position, ModifierFlags modifiers ){
4317         m_selector.m_mouseMoved = true;
4318         if ( m_mouse_down && !g_mouseMovedCallback.empty() ) {
4319                 m_selector.m_mouseMovedWhilePressed = true;
4320                 g_mouseMovedCallback.get() ( window_to_normalised_device( position, m_width, m_height ) );
4321         }
4322 }
4323 void onMouseUp( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){
4324         if ( ( button == c_button_select || button == c_button_select2 ) && !g_mouseUpCallback.empty() ) {
4325                 m_mouse_down = false;
4326
4327                 g_mouseUpCallback.get() ( window_to_normalised_device( position, m_width, m_height ) );
4328         }
4329         //L button w/o scene changed = tunnel selection
4330         if( // !getSelectionSystem().m_undo_begun &&
4331                 modifiers == c_modifierNone && button == c_button_select &&
4332                 //( !m_selector.m_mouseMoved || !m_mouse_down ) &&
4333                 !m_selector.m_mouseMovedWhilePressed &&
4334                 ( getSelectionSystem().Mode() != SelectionSystem::eComponent || getSelectionSystem().ManipulatorMode() != SelectionSystem::eDrag ) ){
4335                 m_selector.testSelect_simpleM1( device_constrained( window_to_normalised_device( position, m_width, m_height ) ) );
4336         }
4337         //getSelectionSystem().m_undo_begun = false;
4338         m_selector.m_mouseMoved = false;
4339         m_selector.m_mouseMovedWhilePressed = false;
4340 }
4341 void onModifierDown( ModifierFlags type ){
4342         m_selector.modifierEnable( type );
4343         m_manipulator.modifierEnable( type );
4344 }
4345 void onModifierUp( ModifierFlags type ){
4346         m_selector.modifierDisable( type );
4347         m_manipulator.modifierDisable( type );
4348 }
4349 };
4350
4351
4352
4353 SelectionSystemWindowObserver* NewWindowObserver(){
4354         return new RadiantWindowObserver;
4355 }
4356
4357
4358
4359 #include "modulesystem/singletonmodule.h"
4360 #include "modulesystem/moduleregistry.h"
4361
4362 class SelectionDependencies :
4363         public GlobalSceneGraphModuleRef,
4364         public GlobalShaderCacheModuleRef,
4365         public GlobalOpenGLModuleRef
4366 {
4367 };
4368
4369 class SelectionAPI : public TypeSystemRef
4370 {
4371 SelectionSystem* m_selection;
4372 public:
4373 typedef SelectionSystem Type;
4374 STRING_CONSTANT( Name, "*" );
4375
4376 SelectionAPI(){
4377         SelectionSystem_Construct();
4378
4379         m_selection = &getSelectionSystem();
4380 }
4381 ~SelectionAPI(){
4382         SelectionSystem_Destroy();
4383 }
4384 SelectionSystem* getTable(){
4385         return m_selection;
4386 }
4387 };
4388
4389 typedef SingletonModule<SelectionAPI, SelectionDependencies> SelectionModule;
4390 typedef Static<SelectionModule> StaticSelectionModule;
4391 StaticRegisterModule staticRegisterSelection( StaticSelectionModule::instance() );