/* greebo: This gets called by the SelectObserver if the user drags a box and holds down
 * any of the selection modifiers. Possible selection candidates are determined and selected/deselected
 */
void RadiantSelectionSystem::SelectArea(const View& view,
                                        const Vector2& device_point,
                                        const Vector2& device_delta,
                                        SelectionSystem::EModifier modifier, bool face)
{
    // If we are in replace mode, deselect all the components or previous selections
    if (modifier == SelectionSystem::eReplace) {
        if (face) {
            setSelectedAllComponents(false);
        }
        else {
            deselectAll();
        }
    }

    {
        // Construct the selection test according to the area the user covered with his drag
        View scissored(view);
        ConstructSelectionTest(scissored, Rectangle::ConstructFromArea(device_point, device_delta));

        SelectionVolume volume(scissored);
        // The posssible candidates go here
        SelectionPool pool;

        SelectablesList candidates;

        if (face)
        {
            ComponentSelector selectionTester(pool, volume, eFace);
            GlobalSceneGraph().foreachVisibleNodeInVolume(scissored, selectionTester);

            // Load them all into the vector
            for (SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i)
            {
                candidates.push_back(i->second);
            }
        }
        else {
            testSelectScene(candidates, volume, scissored, Mode(), ComponentMode());
        }

        // Cycle through the selection pool and toggle the candidates, but only if we are in toggle mode
        for (SelectablesList::iterator i = candidates.begin(); i != candidates.end(); i++) {
            (*i)->setSelected(!(modifier == SelectionSystem::eToggle && (*i)->isSelected()));
        }
    }
}
示例#2
0
void RotateManipulator::testSelect (const View& view, const Matrix4& pivot2world)
{
    m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());
    updateCircleTransforms();

    SelectionPool selector;

    {
        {
            Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_x));

            SelectionIntersection best;
            LineStrip_BestPoint(local2view, m_circle_x.m_vertices.data(), m_circle_x.m_vertices.size(), best);
            selector.addSelectable(best, &m_selectable_x);
        }

        {
            Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_y));

            SelectionIntersection best;
            LineStrip_BestPoint(local2view, m_circle_y.m_vertices.data(), m_circle_y.m_vertices.size(), best);
            selector.addSelectable(best, &m_selectable_y);
        }

        {
            Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_z));

            SelectionIntersection best;
            LineStrip_BestPoint(local2view, m_circle_z.m_vertices.data(), m_circle_z.m_vertices.size(), best);
            selector.addSelectable(best, &m_selectable_z);
        }
    }

    {
        Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace));

        {
            SelectionIntersection best;
            LineLoop_BestPoint(local2view, m_circle_screen.m_vertices.data(), m_circle_screen.m_vertices.size(), best);
            selector.addSelectable(best, &m_selectable_screen);
        }

        {
            SelectionIntersection best;
            Circle_BestPoint(local2view, eClipCullCW, m_circle_sphere.m_vertices.data(),
                             m_circle_sphere.m_vertices.size(), best);
            selector.addSelectable(best, &m_selectable_sphere);
        }
    }

    m_axis_screen = m_pivot.m_axis_screen;

    if (!selector.failed()) {
        (*selector.begin()).second->setSelected(true);
    }
}
示例#3
0
/* greebo: This gets called by the SelectObserver if the user drags a box and holds down
 * any of the selection modifiers. Possible selection candidates are determined and selected/deselected
 */
void RadiantSelectionSystem::SelectArea(const View& view,
										const float device_point[2],
										const float device_delta[2],
										SelectionSystem::EModifier modifier, bool face)
{
	// If we are in replace mode, deselect all the components or previous selections
	if (modifier == SelectionSystem::eReplace) {
		if (face) {
			setSelectedAllComponents(false);
		}
		else {
			deselectAll();
		}
	}

#if defined (DEBUG_SELECTION)
	g_render_clipped.destroy();
#endif

	{
		// Construct the selection test according to the area the user covered with his drag
		View scissored(view);
		ConstructSelectionTest(scissored, SelectionBoxForArea(device_point, device_delta));

		SelectionVolume volume(scissored);
		// The posssible candidates go here
		SelectionPool pool;
		if (face) {
			Scene_TestSelect_Component(pool, volume, scissored, eFace);
		}
		else {
			Scene_TestSelect(pool, volume, scissored, Mode(), ComponentMode());
		}

		// Cycle through the selection pool and toggle the candidates, but only if we are in toggle mode
		for (SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i) {
			(*i).second->setSelected(!(modifier == SelectionSystem::eToggle && (*i).second->isSelected()));
		}
	}
}
示例#4
0
void DragManipulator::testSelect(const View& view, const Matrix4& pivot2world) {
    SelectionPool selector;

    SelectionVolume test(view);

    if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) {
        BooleanSelector booleanSelector;

        Scene_TestSelect_Primitive(booleanSelector, test, view);

        if (booleanSelector.isSelected()) {
            selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
            _selected = false;
        } else {
            _selected = Scene_forEachPlaneSelectable_selectPlanes(GlobalSceneGraph(), selector, test);
        }
    }
    // Check for entities that can be selected
    else if (GlobalSelectionSystem().Mode() == SelectionSystem::eEntity) {
        // Create a boolean selection pool (can have exactly one selectable or none)
        BooleanSelector booleanSelector;

        // Find the visible entities
        Scene_forEachVisible(GlobalSceneGraph(), view, testselect_entity_visible(booleanSelector, test));

        // Check, if an entity could be found
        if (booleanSelector.isSelected()) {
            selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
            _selected = false;
        }
    } else {
        BestSelector bestSelector;
        Scene_TestSelect_Component_Selected(bestSelector, test, view, GlobalSelectionSystem().ComponentMode());
        for (std::list<Selectable*>::iterator i = bestSelector.best().begin(); i != bestSelector.best().end(); ++i) {
            if (!(*i)->isSelected()) {
                GlobalSelectionSystem().setSelectedAllComponents(false);
            }
            _selected = false;
            selector.addSelectable(SelectionIntersection(0, 0), (*i));
            _dragSelectable.setSelected(true);
        }
    }

    for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i) {
        (*i).second->setSelected(true);
    }
}
示例#5
0
void ScaleManipulator::testSelect (const View& view, const Matrix4& pivot2world)
{
    m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());

    SelectionPool selector;

    {
        Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_worldSpace));

        {
            SelectionIntersection best;
            Line_BestPoint(local2view, m_arrow_x.m_line, best);
            selector.addSelectable(best, &m_selectable_x);
        }

        {
            SelectionIntersection best;
            Line_BestPoint(local2view, m_arrow_y.m_line, best);
            selector.addSelectable(best, &m_selectable_y);
        }

        {
            SelectionIntersection best;
            Line_BestPoint(local2view, m_arrow_z.m_line, best);
            selector.addSelectable(best, &m_selectable_z);
        }
    }

    {
        Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace));

        {
            SelectionIntersection best;
            Quad_BestPoint(local2view, eClipCullCW, m_quad_screen.m_quad, best);
            selector.addSelectable(best, &m_selectable_screen);
        }
    }

    if (!selector.failed()) {
        (*selector.begin()).second->setSelected(true);
    }
}
/* greebo: This gets called by SelectObserver if the user just clicks into the scene (without dragging)
 * It checks for any possible targets (in the "line of click") and takes the actions according
 * to the modifiers that are held down (Alt-Shift, etc.)
 */
void RadiantSelectionSystem::SelectPoint(const View& view,
                                         const Vector2& device_point,
                                         const Vector2& device_epsilon,
                                         SelectionSystem::EModifier modifier,
                                         bool face)
{
    ASSERT_MESSAGE(fabs(device_point[0]) <= 1.0f && fabs(device_point[1]) <= 1.0f, "point-selection error");
    // If the user is holding the replace modifiers (default: Alt-Shift), deselect the current selection
    if (modifier == SelectionSystem::eReplace) {
        if (face) {
            setSelectedAllComponents(false);
        }
        else {
            deselectAll();
        }
    }

    {
        View scissored(view);
        // Construct a selection test according to a small box with 2*epsilon edge length
        ConstructSelectionTest(scissored, Rectangle::ConstructFromPoint(device_point, device_epsilon));

        // Create a new SelectionPool instance and fill it with possible candidates
        SelectionVolume volume(scissored);
        // The possible candidates are stored in the SelectablesSet
        SelectablesList candidates;

        if (face)
        {
            SelectionPool selector;

            ComponentSelector selectionTester(selector, volume, eFace);
            GlobalSceneGraph().foreachVisibleNodeInVolume(scissored, selectionTester);

            // Load them all into the vector
            for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i)
            {
                candidates.push_back(i->second);
            }
        }
        else {
            testSelectScene(candidates, volume, scissored, Mode(), ComponentMode());
        }

        // Was the selection test successful (have we found anything to select)?
        if (candidates.size() > 0) {
            // Yes, now determine how we should interpret the click
            switch (modifier) {
                // If we are in toggle mode (Shift-Left-Click by default), just toggle the
                // selection of the "topmost" item
                case SelectionSystem::eToggle: {
                    Selectable* best = *candidates.begin();
                    // toggle selection of the object with least depth (=first in the list)
                    best->setSelected(!best->isSelected());
                }
                break;
                // greebo: eReplace mode gets active as soon as the user holds the replace modifiers down
                // and clicks (by default: Alt-Shift). eReplace is only active during the first click
                // afterwards we are in cycle mode.
                // if cycle mode not enabled, enable it
                case SelectionSystem::eReplace: {
                    // select closest (=first in the list)
                    (*candidates.begin())->setSelected(true);
                }
                break;
                // select the next object in the list from the one already selected
                // greebo: eCycle is set if the user keeps holding the replace modifiers (Alt-Shift)
                // and does NOT move the mouse between the clicks, otherwise we fall back into eReplace mode
                // Note: The mode is set in SelectObserver::testSelect()
                case SelectionSystem::eCycle: {
                    // Cycle through the selection pool and activate the item right after the currently selected
                    SelectablesList::iterator i = candidates.begin();

                    while (i != candidates.end()) {
                        if ((*i)->isSelected()) {
                            // unselect the currently selected one
                            (*i)->setSelected(false);
                            // check if there is a "next" item in the list, if not: select the first item
                            ++i;
                            if (i != candidates.end()) {
                                (*i)->setSelected(true);
                            }
                            else {
                                (*candidates.begin())->setSelected(true);
                            }
                            break;
                        }
                        ++i;
                    } // while
                } // case
                break;
                default:
                break;
            } // switch
        }
    }
}
void RadiantSelectionSystem::testSelectScene(SelectablesList& targetList, SelectionTest& test,
                                             const View& view, SelectionSystem::EMode mode,
                                             SelectionSystem::EComponentMode componentMode)
{
    // The (temporary) storage pool
    SelectionPool selector;
    SelectionPool sel2;

    switch(mode)
    {
        case eEntity:
        {
            // Instantiate a walker class which is specialised for selecting entities
            EntitySelector entityTester(selector, test);
            GlobalSceneGraph().foreachVisibleNodeInVolume(view, entityTester);

            for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i)
            {
                targetList.push_back(i->second);
            }
        }
        break;

        case ePrimitive:
        {
            // Do we have a camera view (filled rendering?)
            if (view.fill() || !GlobalXYWnd().higherEntitySelectionPriority())
            {
                // Test for any visible elements (primitives, entities), but don't select child primitives
                AnySelector anyTester(selector, test);
                GlobalSceneGraph().foreachVisibleNodeInVolume(view, anyTester);
            }
            else
            {
                // We have an orthoview, here, select entities first

                // First, obtain all the selectable entities
                EntitySelector entityTester(selector, test);
                GlobalSceneGraph().foreachVisibleNodeInVolume(view, entityTester);

                // Now retrieve all the selectable primitives
                PrimitiveSelector primitiveTester(sel2, test);
                GlobalSceneGraph().foreachVisibleNodeInVolume(view, primitiveTester);
            }

            // Add the first selection crop to the target vector
            for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i) {
                targetList.push_back(i->second);
            }

            // Add the secondary crop to the vector (if it has any entries)
            for (SelectionPool::iterator i = sel2.begin(); i != sel2.end(); ++i) {
                // Check for duplicates
                SelectablesList::iterator j;
                for (j = targetList.begin(); j != targetList.end(); ++j) {
                    if (*j == i->second) break;
                }
                // Insert if not yet in the list
                if (j == targetList.end()) {
                    targetList.push_back(i->second);
                }
            }
        }
        break;

        case eGroupPart:
        {
            // Retrieve all the selectable primitives of group nodes
            GroupChildPrimitiveSelector primitiveTester(selector, test);
            GlobalSceneGraph().foreachVisibleNodeInVolume(view, primitiveTester);

            // Add the selection crop to the target vector
            for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i)
            {
                targetList.push_back(i->second);
            }
        }
        break;

        case eComponent:
        {
            ComponentSelector selectionTester(selector, test, componentMode);
            foreachSelected(selectionTester);

            for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i)
            {
                targetList.push_back(i->second);
            }
        }
        break;
    } // switch
}
示例#8
0
/* greebo: This gets called by SelectObserver if the user just clicks into the scene (without dragging)
 * It checks for any possible targets (in the "line of click") and takes the actions according
 * to the modifiers that are held down (Alt-Shift, etc.)
 */
void RadiantSelectionSystem::SelectPoint(const View& view,
										 const float device_point[2],
										 const float device_epsilon[2],
										 SelectionSystem::EModifier modifier,
										 bool face)
{
	ASSERT_MESSAGE(fabs(device_point[0]) <= 1.0f && fabs(device_point[1]) <= 1.0f, "point-selection error");
	// If the user is holding the replace modifiers (default: Alt-Shift), deselect the current selection
	if (modifier == SelectionSystem::eReplace) {
		if (face) {
			setSelectedAllComponents(false);
		}
		else {
			deselectAll();
		}
	}

#if defined (DEBUG_SELECTION)
	g_render_clipped.destroy();
#endif

	{
		View scissored(view);
		// Construct a selection test according to a small box with 2*epsilon edge length
		ConstructSelectionTest(scissored, SelectionBoxForPoint(device_point, device_epsilon));

		// Create a new SelectionPool instance and fill it with possible candidates
		SelectionVolume volume(scissored);
		// The possible candidates are stored in the SelectionPool
		SelectionPool selector;
		if (face) {
			Scene_TestSelect_Component(selector, volume, scissored, eFace);
		}
		else {
			Scene_TestSelect(selector, volume, scissored, Mode(), ComponentMode());
		}

		// Was the selection test successful (have we found anything to select)?
		if (!selector.failed()) {
			// Yes, now determine how we should interpret the click
			switch (modifier) {
				// If we are in toggle mode (Shift-Left-Click by default), just toggle the
				// selection of the "topmost" item
				case SelectionSystem::eToggle: {
					SelectableSortedSet::iterator best = selector.begin();
					// toggle selection of the object with least depth (=first in the list)
					if ((*best).second->isSelected())
						(*best).second->setSelected(false);
					else
						(*best).second->setSelected(true);
				}
				break;
				// greebo: eReplace mode gets active as soon as the user holds the replace modifiers down
				// and clicks (by default: Alt-Shift). eReplace is only active during the first click
				// afterwards we are in cycle mode.
				// if cycle mode not enabled, enable it
				case SelectionSystem::eReplace: {
					// select closest (=first in the list)
					(*selector.begin()).second->setSelected(true);
				}
				break;
				// select the next object in the list from the one already selected
				// greebo: eCycle is set if the user keeps holding the replace modifiers (Alt-Shift)
				// and does NOT move the mouse between the clicks, otherwise we fall back into eReplace mode
				// Note: The mode is set in SelectObserver::testSelect()
				case SelectionSystem::eCycle: {
					// Cycle through the selection pool and activate the item right after the currently selected
					SelectionPool::iterator i = selector.begin();
					while (i != selector.end()) {
						if ((*i).second->isSelected()) {
							// unselect the currently selected one
							(*i).second->setSelected(false);
							// check if there is a "next" item in the list, if not: select the first item
							++i;
							if (i != selector.end()) {
								i->second->setSelected(true);
							}
							else {
								selector.begin()->second->setSelected(true);
							}
							break;
						}
						++i;
					} // while
				} // case
				break;
				default:
				break;
			} // switch
		}
	}
}
示例#9
0
void TranslateManipulator::testSelect (const View& view, const Matrix4& pivot2world)
{
    m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());

    SelectionPool selector;

    Vector3 x = m_pivot.m_worldSpace.x().getVector3().getNormalised();
    bool show_x = manipulator_show_axis(m_pivot, x);

    Vector3 y = m_pivot.m_worldSpace.y().getVector3().getNormalised();
    bool show_y = manipulator_show_axis(m_pivot, y);

    Vector3 z = m_pivot.m_worldSpace.z().getVector3().getNormalised();
    bool show_z = manipulator_show_axis(m_pivot, z);

    {
        Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace));

        {
            SelectionIntersection best;
            Quad_BestPoint(local2view, eClipCullCW, m_quad_screen.m_quad, best);
            if (best.valid()) {
                best = SelectionIntersection(0, 0);
                selector.addSelectable(best, &m_selectable_screen);
            }
        }
    }

    {
        Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_worldSpace));

#if defined(DEBUG_SELECTION)
        g_render_clipped.construct(view.GetViewMatrix());
#endif

        if (show_x) {
            SelectionIntersection best;
            Line_BestPoint(local2view, m_arrow_x.m_line, best);
            Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_x.m_vertices.begin(),
                                m_arrow_head_x.m_vertices.end(), best);
            selector.addSelectable(best, &m_selectable_x);
        }

        if (show_y) {
            SelectionIntersection best;
            Line_BestPoint(local2view, m_arrow_y.m_line, best);
            Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_y.m_vertices.begin(),
                                m_arrow_head_y.m_vertices.end(), best);
            selector.addSelectable(best, &m_selectable_y);
        }

        if (show_z) {
            SelectionIntersection best;
            Line_BestPoint(local2view, m_arrow_z.m_line, best);
            Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_z.m_vertices.begin(),
                                m_arrow_head_z.m_vertices.end(), best);
            selector.addSelectable(best, &m_selectable_z);
        }
    }

    if (!selector.failed()) {
        (*selector.begin()).second->setSelected(true);
    }
}
void TranslateManipulator::testSelect(const render::View& view, const Matrix4& pivot2world) {
    _pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport());

    SelectionPool selector;

    Vector3 x = _pivot._worldSpace.x().getVector3().getNormalised();
    bool show_x = manipulator_show_axis(_pivot, x);

    Vector3 y = _pivot._worldSpace.y().getVector3().getNormalised();
    bool show_y = manipulator_show_axis(_pivot, y);

    Vector3 z = _pivot._worldSpace.z().getVector3().getNormalised();
    bool show_z = manipulator_show_axis(_pivot, z);

    {
		Matrix4 local2view(view.GetViewMatrix().getMultipliedBy(_pivot._viewpointSpace));

      {
        SelectionIntersection best;
        Quad_BestPoint(local2view, eClipCullCW, &_quadScreen.front(), best);
        if(best.valid())
        {
          best = SelectionIntersection(0, 0);
          selector.addSelectable(best, &_selectableScreen);
        }
      }
    }

    {
		Matrix4 local2view(view.GetViewMatrix().getMultipliedBy(_pivot._worldSpace));

      if(show_x)
      {
        SelectionIntersection best;
        Line_BestPoint(local2view, &_arrowX.front(), best);
        Triangles_BestPoint(local2view, eClipCullCW, &_arrowHeadX._vertices.front(), &*(_arrowHeadX._vertices.end()-1)+1, best);
        selector.addSelectable(best, &_selectableX);
      }

      if(show_y)
      {
        SelectionIntersection best;
        Line_BestPoint(local2view, &_arrowY.front(), best);
        Triangles_BestPoint(local2view, eClipCullCW, &_arrowHeadY._vertices.front(), &*(_arrowHeadY._vertices.end()-1)+1, best);
        selector.addSelectable(best, &_selectableY);
      }

      if(show_z)
      {
        SelectionIntersection best;
        Line_BestPoint(local2view, &_arrowZ.front(), best);
        Triangles_BestPoint(local2view, eClipCullCW, &_arrowHeadZ._vertices.front(), &*(_arrowHeadZ._vertices.end()-1)+1, best);
        selector.addSelectable(best, &_selectableZ);
      }
    }

	// greebo: If any of the above arrows could be selected, select the first in the SelectionPool
    if(!selector.failed()) {
      (*selector.begin()).second->setSelected(true);
    } else {
    	Selectable* selectable = NULL;

    	if (registry::getValue<bool>(RKEY_TRANSLATE_CONSTRAINED)) {
	    	// None of the shown arrows (or quad) has been selected, select an axis based on the precedence
	    	Matrix4 local2view(view.GetViewMatrix().getMultipliedBy(_pivot._worldSpace));

	    	// Get the (relative?) distance from the mouse pointer to the manipulator
	    	Vector3 delta = local2view.t().getProjected();

	    	// Get the precedence (which axis has the absolute largest value in it)
	    	bool xGreaterY = (fabs(delta.x()) > fabs(delta.y()));

	    	// The precedence has to be interpreted according to which axes are visible
	    	if (show_z) {
	    		// Either XZ or YZ
	    		if (show_y) {
	    			// YZ
	    			selectable = (xGreaterY) ? &_selectableY : &_selectableZ;
	    		}
	    		else {
	    			// XZ
	    			selectable = (xGreaterY) ? &_selectableX : &_selectableZ;
	    		}
	    	}
	    	else {
	    		// XY
	    		selectable = (xGreaterY) ? &_selectableX : &_selectableY;
	    	}
    	}
    	else {
    		// Don't constrain to axis, choose the freemove translator
    		selectable = &_selectableScreen;
    	}

		// If everything went ok, there is a selectable available, add it
    	if (selectable != NULL) {
    		selector.addSelectable(SelectionIntersection(0,0), selectable);
    		selectable->setSelected(true);
    	}
    }
}
示例#11
0
void DragManipulator::testSelect(const render::View& view, const Matrix4& pivot2world)
{
    SelectionPool selector;

    SelectionVolume test(view);

    if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive)
	{
		// Find all entities
		BooleanSelector entitySelector;

		EntitySelector selectionTester(entitySelector, test);
		GlobalSceneGraph().foreachVisibleNodeInVolume(view, selectionTester);

    	if (entitySelector.isSelected())
		{
			// Found a selectable entity
			selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
			_selected = false;
		}
		else
		{
			// Find all primitives that are selectable
			BooleanSelector primitiveSelector;

			PrimitiveSelector primitiveTester(primitiveSelector, test);
			GlobalSceneGraph().foreachVisibleNodeInVolume(view, primitiveTester);

			if (primitiveSelector.isSelected())	
			{
				// Found a selectable primitive
				selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
				_selected = false;
			}
			else
			{
				// Entities and worldspawn primitives failed, so check for group children too
				// Find all group child primitives that are selectable
				BooleanSelector childPrimitiveSelector;

				GroupChildPrimitiveSelector childPrimitiveTester(childPrimitiveSelector, test);
				GlobalSceneGraph().foreachVisibleNodeInVolume(view, childPrimitiveTester);

				if (childPrimitiveSelector.isSelected())	
				{
					// Found a selectable group child primitive
					selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
					_selected = false;
				}
				else
				{
					// all direct hits failed, check for drag-selectable faces
					_selected = Scene_forEachPlaneSelectable_selectPlanes(selector, test);
				}
			}
		}
	}
	else if (GlobalSelectionSystem().Mode() == SelectionSystem::eGroupPart)
    {
    	// Find all primitives that are selectable
		BooleanSelector booleanSelector;

		GroupChildPrimitiveSelector childPrimitiveTester(booleanSelector, test);
		GlobalSceneGraph().foreachVisibleNodeInVolume(view, childPrimitiveTester);

		if (booleanSelector.isSelected())
		{
			// Found a selectable primitive
			selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
			_selected = false;
		}
		else
		{
			// Check for selectable faces
			_selected = Scene_forEachPlaneSelectable_selectPlanes(selector, test);
		}
    }
    // Check for entities that can be selected
    else if (GlobalSelectionSystem().Mode() == SelectionSystem::eEntity)
	{
    	// Create a boolean selection pool (can have exactly one selectable or none)
		BooleanSelector booleanSelector;

		// Find the visible entities
		EntitySelector selectionTester(booleanSelector, test);
		GlobalSceneGraph().foreachVisibleNodeInVolume(view, selectionTester);

		// Check, if an entity could be found
      	if (booleanSelector.isSelected()) {
        	selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
        	_selected = false;
		}
    }
    else
    {
		BestSelector bestSelector;

		ComponentSelector selectionTester(bestSelector, test, GlobalSelectionSystem().ComponentMode());
		GlobalSelectionSystem().foreachSelected(selectionTester);

		for (std::list<Selectable*>::iterator i = bestSelector.best().begin();
			 i != bestSelector.best().end(); ++i)
		{
			// greebo: Disabled this, it caused the currently selected patch vertices being deselected.
			if (registry::getValue<bool>(RKEY_TRANSIENT_COMPONENT_SELECTION))
			{
				if (!(*i)->isSelected())
				{
					GlobalSelectionSystem().setSelectedAllComponents(false);
				}
			}

			_selected = false;
			selector.addSelectable(SelectionIntersection(0, 0), (*i));
			_dragSelectable.setSelected(true);
		}
	}

	for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i)
	{
		i->second->setSelected(true);
	}
}