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