1 #include "Manipulators.h"
2 #include "Remap.h"
3 #include "Selectors.h"
4 #include "BestPoint.h"
5 #include "TransformationVisitors.h"
6 #include "SelectionTest.h"
7 #include "Planes.h"
8 #include "../renderer.h"
9 
10 // ------------ Helper functions ---------------------------
11 
12 const Colour4b g_colour_sphere(0, 0, 0, 255);
13 const Colour4b g_colour_screen(0, 255, 255, 255);
14 const Colour4b g_colour_selected(255, 255, 0, 255);
15 
colourSelected(const Colour4b & colour,bool selected)16 inline const Colour4b& colourSelected (const Colour4b& colour, bool selected)
17 {
18 	return (selected) ? g_colour_selected : colour;
19 }
20 
21 template<typename remap_policy>
draw_semicircle(const std::size_t segments,const float radius,PointVertex * vertices,remap_policy remap)22 inline void draw_semicircle (const std::size_t segments, const float radius, PointVertex* vertices, remap_policy remap)
23 {
24 	const double increment = c_pi / double(segments << 2);
25 
26 	std::size_t count = 0;
27 	float x = radius;
28 	float y = 0;
29 	remap_policy::set(vertices[segments << 2].vertex, -radius, 0, 0);
30 	while (count < segments) {
31 		PointVertex* i = vertices + count;
32 		PointVertex* j = vertices + ((segments << 1) - (count + 1));
33 
34 		PointVertex* k = i + (segments << 1);
35 		PointVertex* l = j + (segments << 1);
36 
37 		remap_policy::set(i->vertex, x, -y, 0);
38 		remap_policy::set(k->vertex, -y, -x, 0);
39 
40 		++count;
41 
42 		{
43 			const double theta = increment * count;
44 			x = static_cast<float> (radius * cos(theta));
45 			y = static_cast<float> (radius * sin(theta));
46 		}
47 
48 		remap_policy::set(j->vertex, y, -x, 0);
49 		remap_policy::set(l->vertex, -x, -y, 0);
50 #if 0
51 		remap_policy::set(n->vertex,-y, x, 0);
52 		remap_policy::set(p->vertex, x, y, 0);
53 #endif
54 	}
55 }
56 
~Manipulator()57 Manipulator::~Manipulator()
58 {
59 }
60 
61 // ------------ RotateManipulator methods ------------------
62 
63 // Constructor
RotateManipulator(Rotatable & rotatable,std::size_t segments,float radius)64 RotateManipulator::RotateManipulator (Rotatable& rotatable, std::size_t segments, float radius) :
65 	m_free(rotatable), m_axis(rotatable), m_circle_x((segments << 2) + 1), m_circle_y((segments << 2) + 1), m_circle_z(
66 			(segments << 2) + 1), m_circle_screen(segments << 3), m_circle_sphere(segments << 3)
67 {
68 	draw_semicircle(segments, radius, m_circle_x.m_vertices.data(), RemapYZX());
69 	draw_semicircle(segments, radius, m_circle_y.m_vertices.data(), RemapZXY());
70 	draw_semicircle(segments, radius, m_circle_z.m_vertices.data(), RemapXYZ());
71 
72 	draw_circle(segments, radius * 1.15f, m_circle_screen.m_vertices.data(), RemapXYZ());
73 	draw_circle(segments, radius, m_circle_sphere.m_vertices.data(), RemapXYZ());
74 }
75 
UpdateColours()76 void RotateManipulator::UpdateColours ()
77 {
78 	m_circle_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected()));
79 	m_circle_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected()));
80 	m_circle_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected()));
81 	m_circle_screen.setColour(colourSelected(g_colour_screen, m_selectable_screen.isSelected()));
82 	m_circle_sphere.setColour(colourSelected(g_colour_sphere, false));
83 }
84 
updateCircleTransforms()85 void RotateManipulator::updateCircleTransforms ()
86 {
87 	Vector3 localViewpoint(matrix4_transformed_direction(m_pivot.m_worldSpace.getTransposed(),
88 			m_pivot.m_viewpointSpace.z().getVector3()));
89 
90 	m_circle_x_visible = !vector3_equal_epsilon(g_vector3_axis_x, localViewpoint, 1e-6f);
91 	if (m_circle_x_visible) {
92 		m_local2world_x = Matrix4::getIdentity();
93 		m_local2world_x.y().getVector3() = g_vector3_axis_x.crossProduct(localViewpoint).getNormalised();
94 		m_local2world_x.z().getVector3() = m_local2world_x.x().getVector3().crossProduct(
95 				m_local2world_x.y().getVector3()).getNormalised();
96 		matrix4_premultiply_by_matrix4(m_local2world_x, m_pivot.m_worldSpace);
97 	}
98 
99 	m_circle_y_visible = !vector3_equal_epsilon(g_vector3_axis_y, localViewpoint, 1e-6f);
100 	if (m_circle_y_visible) {
101 		m_local2world_y = Matrix4::getIdentity();
102 		m_local2world_y.z().getVector3() = g_vector3_axis_y.crossProduct(localViewpoint).getNormalised();
103 		m_local2world_y.x().getVector3() = m_local2world_y.y().getVector3().crossProduct(
104 				m_local2world_y.z().getVector3()).getNormalised();
105 		matrix4_premultiply_by_matrix4(m_local2world_y, m_pivot.m_worldSpace);
106 	}
107 
108 	m_circle_z_visible = !vector3_equal_epsilon(g_vector3_axis_z, localViewpoint, 1e-6f);
109 	if (m_circle_z_visible) {
110 		m_local2world_z = Matrix4::getIdentity();
111 		m_local2world_z.x().getVector3() = g_vector3_axis_z.crossProduct(localViewpoint).getNormalised();
112 		m_local2world_z.y().getVector3() = m_local2world_z.z().getVector3().crossProduct(
113 				m_local2world_z.x().getVector3()).getNormalised();
114 		matrix4_premultiply_by_matrix4(m_local2world_z, m_pivot.m_worldSpace);
115 	}
116 }
117 
render(Renderer & renderer,const VolumeTest & volume,const Matrix4 & pivot2world)118 void RotateManipulator::render (Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world)
119 {
120 	m_pivot.update(pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
121 	updateCircleTransforms();
122 
123 	// temp hack
124 	UpdateColours();
125 
126 	renderer.SetState(m_state_outer, Renderer::eWireframeOnly);
127 	renderer.SetState(m_state_outer, Renderer::eFullMaterials);
128 
129 	renderer.addRenderable(m_circle_screen, m_pivot.m_viewpointSpace);
130 	renderer.addRenderable(m_circle_sphere, m_pivot.m_viewpointSpace);
131 
132 	if (m_circle_x_visible) {
133 		renderer.addRenderable(m_circle_x, m_local2world_x);
134 	}
135 	if (m_circle_y_visible) {
136 		renderer.addRenderable(m_circle_y, m_local2world_y);
137 	}
138 	if (m_circle_z_visible) {
139 		renderer.addRenderable(m_circle_z, m_local2world_z);
140 	}
141 }
142 
testSelect(const View & view,const Matrix4 & pivot2world)143 void RotateManipulator::testSelect (const View& view, const Matrix4& pivot2world)
144 {
145 	m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());
146 	updateCircleTransforms();
147 
148 	SelectionPool selector;
149 
150 	{
151 		{
152 			Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_x));
153 
154 			SelectionIntersection best;
155 			LineStrip_BestPoint(local2view, m_circle_x.m_vertices.data(), m_circle_x.m_vertices.size(), best);
156 			selector.addSelectable(best, &m_selectable_x);
157 		}
158 
159 		{
160 			Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_y));
161 
162 			SelectionIntersection best;
163 			LineStrip_BestPoint(local2view, m_circle_y.m_vertices.data(), m_circle_y.m_vertices.size(), best);
164 			selector.addSelectable(best, &m_selectable_y);
165 		}
166 
167 		{
168 			Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_z));
169 
170 			SelectionIntersection best;
171 			LineStrip_BestPoint(local2view, m_circle_z.m_vertices.data(), m_circle_z.m_vertices.size(), best);
172 			selector.addSelectable(best, &m_selectable_z);
173 		}
174 	}
175 
176 	{
177 		Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace));
178 
179 		{
180 			SelectionIntersection best;
181 			LineLoop_BestPoint(local2view, m_circle_screen.m_vertices.data(), m_circle_screen.m_vertices.size(), best);
182 			selector.addSelectable(best, &m_selectable_screen);
183 		}
184 
185 		{
186 			SelectionIntersection best;
187 			Circle_BestPoint(local2view, eClipCullCW, m_circle_sphere.m_vertices.data(),
188 					m_circle_sphere.m_vertices.size(), best);
189 			selector.addSelectable(best, &m_selectable_sphere);
190 		}
191 	}
192 
193 	m_axis_screen = m_pivot.m_axis_screen;
194 
195 	if (!selector.failed()) {
196 		(*selector.begin()).second->setSelected(true);
197 	}
198 }
199 
GetManipulatable()200 Manipulatable* RotateManipulator::GetManipulatable ()
201 {
202 	if (m_selectable_x.isSelected()) {
203 		m_axis.SetAxis(g_vector3_axis_x);
204 		return &m_axis;
205 	} else if (m_selectable_y.isSelected()) {
206 		m_axis.SetAxis(g_vector3_axis_y);
207 		return &m_axis;
208 	} else if (m_selectable_z.isSelected()) {
209 		m_axis.SetAxis(g_vector3_axis_z);
210 		return &m_axis;
211 	} else if (m_selectable_screen.isSelected()) {
212 		m_axis.SetAxis(m_axis_screen);
213 		return &m_axis;
214 	} else
215 		return &m_free;
216 }
217 
setSelected(bool select)218 void RotateManipulator::setSelected (bool select)
219 {
220 	m_selectable_x.setSelected(select);
221 	m_selectable_y.setSelected(select);
222 	m_selectable_z.setSelected(select);
223 	m_selectable_screen.setSelected(select);
224 }
225 
isSelected() const226 bool RotateManipulator::isSelected () const
227 {
228 	return m_selectable_x.isSelected() | m_selectable_y.isSelected() | m_selectable_z.isSelected()
229 			| m_selectable_screen.isSelected() | m_selectable_sphere.isSelected();
230 }
231 
232 // Initialise the shader of the RotateManipulator class
233 Shader* RotateManipulator::m_state_outer;
234 
235 // ------------ TranslateManipulator methods ------------------
236 
237 // Constructor
TranslateManipulator(Translatable & translatable,std::size_t segments,float length)238 TranslateManipulator::TranslateManipulator (Translatable& translatable, std::size_t segments, float length) :
239 	m_free(translatable), m_axis(translatable), m_arrow_head_x(3 * 2 * (segments << 3)), m_arrow_head_y(3 * 2
240 			* (segments << 3)), m_arrow_head_z(3 * 2 * (segments << 3))
241 {
242 	draw_arrowline(length, m_arrow_x.m_line, 0);
243 	draw_arrowhead(segments, length, m_arrow_head_x.m_vertices.data(), TripleRemapXYZ<Vertex3f> (), TripleRemapXYZ<
244 			Normal3f> ());
245 	draw_arrowline(length, m_arrow_y.m_line, 1);
246 	draw_arrowhead(segments, length, m_arrow_head_y.m_vertices.data(), TripleRemapYZX<Vertex3f> (), TripleRemapYZX<
247 			Normal3f> ());
248 	draw_arrowline(length, m_arrow_z.m_line, 2);
249 	draw_arrowhead(segments, length, m_arrow_head_z.m_vertices.data(), TripleRemapZXY<Vertex3f> (), TripleRemapZXY<
250 			Normal3f> ());
251 
252 	draw_quad(16, m_quad_screen.m_quad);
253 }
254 
UpdateColours()255 void TranslateManipulator::UpdateColours ()
256 {
257 	m_arrow_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected()));
258 	m_arrow_head_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected()));
259 	m_arrow_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected()));
260 	m_arrow_head_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected()));
261 	m_arrow_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected()));
262 	m_arrow_head_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected()));
263 	m_quad_screen.setColour(colourSelected(g_colour_screen, m_selectable_screen.isSelected()));
264 }
265 
manipulator_show_axis(const Pivot2World & pivot,const Vector3 & axis)266 bool TranslateManipulator::manipulator_show_axis (const Pivot2World& pivot, const Vector3& axis)
267 {
268 	return fabs(pivot.m_axis_screen.dot(axis)) < 0.95;
269 }
270 
render(Renderer & renderer,const VolumeTest & volume,const Matrix4 & pivot2world)271 void TranslateManipulator::render (Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world)
272 {
273 	m_pivot.update(pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
274 
275 	// temp hack
276 	UpdateColours();
277 
278 	Vector3 x = m_pivot.m_worldSpace.x().getVector3().getNormalised();
279 	bool show_x = manipulator_show_axis(m_pivot, x);
280 
281 	Vector3 y = m_pivot.m_worldSpace.y().getVector3().getNormalised();
282 	bool show_y = manipulator_show_axis(m_pivot, y);
283 
284 	Vector3 z = m_pivot.m_worldSpace.z().getVector3().getNormalised();
285 	bool show_z = manipulator_show_axis(m_pivot, z);
286 
287 	renderer.SetState(m_state_wire, Renderer::eWireframeOnly);
288 	renderer.SetState(m_state_wire, Renderer::eFullMaterials);
289 
290 	if (show_x) {
291 		renderer.addRenderable(m_arrow_x, m_pivot.m_worldSpace);
292 	}
293 	if (show_y) {
294 		renderer.addRenderable(m_arrow_y, m_pivot.m_worldSpace);
295 	}
296 	if (show_z) {
297 		renderer.addRenderable(m_arrow_z, m_pivot.m_worldSpace);
298 	}
299 
300 	renderer.addRenderable(m_quad_screen, m_pivot.m_viewplaneSpace);
301 
302 	renderer.SetState(m_state_fill, Renderer::eWireframeOnly);
303 	renderer.SetState(m_state_fill, Renderer::eFullMaterials);
304 
305 	if (show_x) {
306 		renderer.addRenderable(m_arrow_head_x, m_pivot.m_worldSpace);
307 	}
308 	if (show_y) {
309 		renderer.addRenderable(m_arrow_head_y, m_pivot.m_worldSpace);
310 	}
311 	if (show_z) {
312 		renderer.addRenderable(m_arrow_head_z, m_pivot.m_worldSpace);
313 	}
314 }
315 
testSelect(const View & view,const Matrix4 & pivot2world)316 void TranslateManipulator::testSelect (const View& view, const Matrix4& pivot2world)
317 {
318 	m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());
319 
320 	SelectionPool selector;
321 
322 	Vector3 x = m_pivot.m_worldSpace.x().getVector3().getNormalised();
323 	bool show_x = manipulator_show_axis(m_pivot, x);
324 
325 	Vector3 y = m_pivot.m_worldSpace.y().getVector3().getNormalised();
326 	bool show_y = manipulator_show_axis(m_pivot, y);
327 
328 	Vector3 z = m_pivot.m_worldSpace.z().getVector3().getNormalised();
329 	bool show_z = manipulator_show_axis(m_pivot, z);
330 
331 	{
332 		Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace));
333 
334 		{
335 			SelectionIntersection best;
336 			Quad_BestPoint(local2view, eClipCullCW, m_quad_screen.m_quad, best);
337 			if (best.valid()) {
338 				best = SelectionIntersection(0, 0);
339 				selector.addSelectable(best, &m_selectable_screen);
340 			}
341 		}
342 	}
343 
344 	{
345 		Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_worldSpace));
346 
347 #if defined(DEBUG_SELECTION)
348 		g_render_clipped.construct(view.GetViewMatrix());
349 #endif
350 
351 		if (show_x) {
352 			SelectionIntersection best;
353 			Line_BestPoint(local2view, m_arrow_x.m_line, best);
354 			Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_x.m_vertices.begin(),
355 					m_arrow_head_x.m_vertices.end(), best);
356 			selector.addSelectable(best, &m_selectable_x);
357 		}
358 
359 		if (show_y) {
360 			SelectionIntersection best;
361 			Line_BestPoint(local2view, m_arrow_y.m_line, best);
362 			Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_y.m_vertices.begin(),
363 					m_arrow_head_y.m_vertices.end(), best);
364 			selector.addSelectable(best, &m_selectable_y);
365 		}
366 
367 		if (show_z) {
368 			SelectionIntersection best;
369 			Line_BestPoint(local2view, m_arrow_z.m_line, best);
370 			Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_z.m_vertices.begin(),
371 					m_arrow_head_z.m_vertices.end(), best);
372 			selector.addSelectable(best, &m_selectable_z);
373 		}
374 	}
375 
376 	if (!selector.failed()) {
377 		(*selector.begin()).second->setSelected(true);
378 	}
379 }
380 
GetManipulatable()381 Manipulatable* TranslateManipulator::GetManipulatable ()
382 {
383 	if (m_selectable_x.isSelected()) {
384 		m_axis.SetAxis(g_vector3_axis_x);
385 		return &m_axis;
386 	} else if (m_selectable_y.isSelected()) {
387 		m_axis.SetAxis(g_vector3_axis_y);
388 		return &m_axis;
389 	} else if (m_selectable_z.isSelected()) {
390 		m_axis.SetAxis(g_vector3_axis_z);
391 		return &m_axis;
392 	} else {
393 		return &m_free;
394 	}
395 }
396 
setSelected(bool select)397 void TranslateManipulator::setSelected (bool select)
398 {
399 	m_selectable_x.setSelected(select);
400 	m_selectable_y.setSelected(select);
401 	m_selectable_z.setSelected(select);
402 	m_selectable_screen.setSelected(select);
403 }
404 
isSelected() const405 bool TranslateManipulator::isSelected () const
406 {
407 	return m_selectable_x.isSelected() | m_selectable_y.isSelected() | m_selectable_z.isSelected()
408 			| m_selectable_screen.isSelected();
409 }
410 
411 // Initialise the shaders of this class
412 Shader* TranslateManipulator::m_state_wire;
413 Shader* TranslateManipulator::m_state_fill;
414 
415 // ------------ ScaleManipulator methods ------------------
416 
417 // Constructor
ScaleManipulator(Scalable & scalable,std::size_t segments,float length)418 ScaleManipulator::ScaleManipulator (Scalable& scalable, std::size_t segments, float length) :
419 	m_free(scalable), m_axis(scalable)
420 {
421 	draw_arrowline(length, m_arrow_x.m_line, 0);
422 	draw_arrowline(length, m_arrow_y.m_line, 1);
423 	draw_arrowline(length, m_arrow_z.m_line, 2);
424 
425 	draw_quad(16, m_quad_screen.m_quad);
426 }
427 
UpdateColours()428 void ScaleManipulator::UpdateColours ()
429 {
430 	m_arrow_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected()));
431 	m_arrow_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected()));
432 	m_arrow_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected()));
433 	m_quad_screen.setColour(colourSelected(g_colour_screen, m_selectable_screen.isSelected()));
434 }
435 
render(Renderer & renderer,const VolumeTest & volume,const Matrix4 & pivot2world)436 void ScaleManipulator::render (Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world)
437 {
438 	m_pivot.update(pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
439 
440 	// temp hack
441 	UpdateColours();
442 
443 	renderer.addRenderable(m_arrow_x, m_pivot.m_worldSpace);
444 	renderer.addRenderable(m_arrow_y, m_pivot.m_worldSpace);
445 	renderer.addRenderable(m_arrow_z, m_pivot.m_worldSpace);
446 
447 	renderer.addRenderable(m_quad_screen, m_pivot.m_viewpointSpace);
448 }
449 
testSelect(const View & view,const Matrix4 & pivot2world)450 void ScaleManipulator::testSelect (const View& view, const Matrix4& pivot2world)
451 {
452 	m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());
453 
454 	SelectionPool selector;
455 
456 	{
457 		Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_worldSpace));
458 
459 		{
460 			SelectionIntersection best;
461 			Line_BestPoint(local2view, m_arrow_x.m_line, best);
462 			selector.addSelectable(best, &m_selectable_x);
463 		}
464 
465 		{
466 			SelectionIntersection best;
467 			Line_BestPoint(local2view, m_arrow_y.m_line, best);
468 			selector.addSelectable(best, &m_selectable_y);
469 		}
470 
471 		{
472 			SelectionIntersection best;
473 			Line_BestPoint(local2view, m_arrow_z.m_line, best);
474 			selector.addSelectable(best, &m_selectable_z);
475 		}
476 	}
477 
478 	{
479 		Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace));
480 
481 		{
482 			SelectionIntersection best;
483 			Quad_BestPoint(local2view, eClipCullCW, m_quad_screen.m_quad, best);
484 			selector.addSelectable(best, &m_selectable_screen);
485 		}
486 	}
487 
488 	if (!selector.failed()) {
489 		(*selector.begin()).second->setSelected(true);
490 	}
491 }
492 
GetManipulatable()493 Manipulatable* ScaleManipulator::GetManipulatable ()
494 {
495 	if (m_selectable_x.isSelected()) {
496 		m_axis.SetAxis(g_vector3_axis_x);
497 		return &m_axis;
498 	} else if (m_selectable_y.isSelected()) {
499 		m_axis.SetAxis(g_vector3_axis_y);
500 		return &m_axis;
501 	} else if (m_selectable_z.isSelected()) {
502 		m_axis.SetAxis(g_vector3_axis_z);
503 		return &m_axis;
504 	} else
505 		return &m_free;
506 }
507 
setSelected(bool select)508 void ScaleManipulator::setSelected (bool select)
509 {
510 	m_selectable_x.setSelected(select);
511 	m_selectable_y.setSelected(select);
512 	m_selectable_z.setSelected(select);
513 	m_selectable_screen.setSelected(select);
514 }
515 
isSelected() const516 bool ScaleManipulator::isSelected () const
517 {
518 	return m_selectable_x.isSelected() | m_selectable_y.isSelected() | m_selectable_z.isSelected()
519 			| m_selectable_screen.isSelected();
520 }
521 
522 // ------------ DragManipulator methods ------------------
523 
GetManipulatable()524 Manipulatable* DragManipulator::GetManipulatable() {
525     return _dragSelectable.isSelected() ? &_freeDrag : &_freeResize;
526 }
527 
testSelect(const View & view,const Matrix4 & pivot2world)528 void DragManipulator::testSelect(const View& view, const Matrix4& pivot2world) {
529 	SelectionPool selector;
530 
531 	SelectionVolume test(view);
532 
533 	if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) {
534 		BooleanSelector booleanSelector;
535 
536 		Scene_TestSelect_Primitive(booleanSelector, test, view);
537 
538 		if (booleanSelector.isSelected()) {
539 			selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
540 			_selected = false;
541 		} else {
542 			_selected = Scene_forEachPlaneSelectable_selectPlanes(GlobalSceneGraph(), selector, test);
543 		}
544 	}
545 	// Check for entities that can be selected
546 	else if (GlobalSelectionSystem().Mode() == SelectionSystem::eEntity) {
547 		// Create a boolean selection pool (can have exactly one selectable or none)
548 		BooleanSelector booleanSelector;
549 
550 		// Find the visible entities
551 		Scene_forEachVisible(GlobalSceneGraph(), view, testselect_entity_visible(booleanSelector, test));
552 
553 		// Check, if an entity could be found
554 		if (booleanSelector.isSelected()) {
555 			selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
556 			_selected = false;
557 		}
558 	} else {
559 		BestSelector bestSelector;
560 		Scene_TestSelect_Component_Selected(bestSelector, test, view, GlobalSelectionSystem().ComponentMode());
561 		for (std::list<Selectable*>::iterator i = bestSelector.best().begin(); i != bestSelector.best().end(); ++i) {
562 			if (!(*i)->isSelected()) {
563 				GlobalSelectionSystem().setSelectedAllComponents(false);
564 			}
565 			_selected = false;
566 			selector.addSelectable(SelectionIntersection(0, 0), (*i));
567 			_dragSelectable.setSelected(true);
568 		}
569 	}
570 
571 	for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i) {
572 		(*i).second->setSelected(true);
573 	}
574 }
575 
setSelected(bool select)576 void DragManipulator::setSelected(bool select) {
577     _selected = select;
578     _dragSelectable.setSelected(select);
579 }
580 
isSelected() const581 bool DragManipulator::isSelected() const  {
582 	return _selected || _dragSelectable.isSelected();
583 }
584