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