Пример #1
0
void ScanningControl::next()
{
    Scanning *scanning = Scanning::instance();

    if (!scanning)
        return;

    if (!scanning->m_scanning.contains(scanning->m_selected))
        return;

    QList<Selectable *> *list = scanning->m_scanning.value(scanning->m_selected);

    if (list->size() == 0) {
        scanning->select(scanning->m_root);
    } else {
        Selectable *nowSelected = list->at(m_index);

        m_index = nowSelected->selected() ? (m_index + 1) % list->size() : 0;

        Selectable *nextSelected = list->at(m_index);

        nowSelected->setSelected(false);
        nextSelected->setSelected(true);
    }
}
Пример #2
0
void ScanningControl::select()
{
    Scanning *scanning = Scanning::instance();

    if (!scanning)
        return;

    if (!scanning->m_scanning.contains(scanning->m_selected))
        return;

    QList<Selectable *> *list = scanning->m_scanning.value(scanning->m_selected);

    Selectable *selected = list->at(m_index);
    selected->setSelected(false);

    QList<Selectable *> *listSelected = scanning->m_scanning.value(selected);
    if (listSelected->size() == 0) {
        qDebug() << "Action from " << selected;
        scanning->select(scanning->m_root);
    } else {
        scanning->select(selected);
    }

    m_index = 0;
}
Пример #3
0
void post( const scene::Path& path, scene::Instance& instance ) const {
	Selectable *selectable = Instance_getSelectable( instance );
	if ( selectable && selectable->isSelected() ) {
		Entity* entity = Node_getEntity( path.top() );
		if ( entity == 0 && Node_isPrimitive( path.top() ) ) {
			NodeSmartReference child( path.top().get() );
			NodeSmartReference parent( path.parent().get() );

			if ( path.size() >= 3 && parent != worldspawn ) {
				NodeSmartReference parentparent( path[path.size() - 3].get() );

				Node_getTraversable( parent )->erase( child );
				Node_getTraversable( group )->insert( child );

				if ( Node_getTraversable( parent )->empty() ) {
					//deleteme.push(DeletionPair(parentparent, parent));
					Node_getTraversable( parentparent )->erase( parent );
				}
			}
			else
			{
				Node_getTraversable( parent )->erase( child );
				Node_getTraversable( group )->insert( child );
			}
		}
	}
}
Пример #4
0
Selectable* SelectableWorld::rayIntersection(vec3 startPoint,
											vec3 endPoint)
{
	vec3 direction = endPoint - startPoint;
	float distance = glm::length(direction);
	Selectable* closest = NULL;
	
	for (SelectableList::const_iterator it = world.begin();
		 it != world.end();
		 it++)
	{
		Selectable* sel = (*it);
		vec3 pos = sel->getPosition();
		
		float rayDistance = pointToRayDistance(sel->getPosition(), startPoint, direction);
		
		if (rayDistance == -1)
			continue;
		
		if (rayDistance < (*it)->getRadius()) // hit!
		{
			float newDist = glm::length(startPoint - (*it)->getPosition());
			if (newDist < distance)
			{
				closest = *it;
				distance = newDist;
			}
		}
	}
	return closest;
}
// greebo: This should be called "onComponentSelectionChanged", as it is a similar function of the above one
// Updates the internal list of component nodes if the component selection gets changed
void RadiantSelectionSystem::onComponentSelection(const scene::INodePtr& node, const Selectable& selectable) {

    int delta = selectable.isSelected() ? +1 : -1;

    _countComponent += delta;
    _sigSelectionChanged(selectable);

    _selectionInfo.totalCount += delta;
    _selectionInfo.componentCount += delta;

    // If the instance got selected, add it to the list, otherwise remove it
    if (selectable.isSelected()) {
        _componentSelection.append(node);
    }
    else {
        _componentSelection.erase(node);
    }

    // Notify observers, TRUE => this is a component selection change
    notifyObservers(node, true);

    // Check if the number of selected components in the list matches the value of the selection counter
    ASSERT_MESSAGE(_componentSelection.size() == _countComponent, "component selection-tracking error");

    // Schedule an idle callback
    requestIdleCallback();

    _requestWorkZoneRecalculation = true;
    _requestSceneGraphChange = true;
}
Пример #6
0
bool MainLoopImpl::waitNext()
{
    std::size_t timeout = _timerQueue.processTimers();

    // check all selectables that did not require waiting
    while( true )
    {
        Pt::System::MutexLock lock(_mutex);

        if( _avail.empty() )
            break;

        timeout = 0;
        Selectable* s = _avail.back();
        _avail.pop_back();
        lock.unlock();

        s->run();
    }

    bool isActive = true;
    if( _selector.waitForWake(timeout) )
        isActive = _eventQueue.processEvents(*_event);

    return isActive;
}
Пример #7
0
static gboolean entitylist_tree_select(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data)
{
  GtkTreeIter iter;
  gtk_tree_model_get_iter(model, &iter, path);
  scene::Node* node;
  gtk_tree_model_get_pointer(model, &iter, 0, &node);
  scene::Instance* instance;
  gtk_tree_model_get_pointer(model, &iter, 1, &instance);
  Selectable* selectable = Instance_getSelectable(*instance);

  if(node == 0)
  {
    if(path_currently_selected != FALSE)
    {
      getEntityList().m_selection_disabled = true;
      GlobalSelectionSystem().setSelectedAll(false);
      getEntityList().m_selection_disabled = false;
    }
  }
  else if(selectable != 0)
  {
    getEntityList().m_selection_disabled = true;
    selectable->setSelected(path_currently_selected == FALSE);
    getEntityList().m_selection_disabled = false;
    return TRUE;
  }

  return FALSE;
}
Пример #8
0
void SelectableGroup::unselectAll()
{
	Selectable* selected = this->getSelection();
	
	if(selected != NULL)
		selected->setSelected(false);

	this->notifySelectionChanged();
}
Пример #9
0
gboolean EntityList::onSelection(GtkTreeSelection* selection, 
								GtkTreeModel* model, 
								GtkTreePath* path, 
								gboolean path_currently_selected, 
								gpointer data)
{
	// Get a pointer to the class instance
	EntityList* self = reinterpret_cast<EntityList*>(data);

	if (self->_callbackActive) return TRUE; // avoid loops

	bool shouldFocus = gtk_toggle_button_get_active(
		GTK_TOGGLE_BUTTON(self->_focusOnSelectedEntityToggle)) ? true : false;
	
	if (!shouldFocus) return TRUE;

	GtkTreeIter iter;
	gtk_tree_model_get_iter(model, &iter, path);
	
	// Load the instance pointer from the columns
	scene::INode* node = reinterpret_cast<scene::Node*>(
		gtkutil::TreeModel::getPointer(model, &iter, GraphTreeModel::COL_NODE_POINTER)
	);
	
	Selectable* selectable = dynamic_cast<Selectable*>(node);

	if (selectable != NULL) {
		// We've found a selectable instance
		
		// Disable update to avoid loopbacks
		self->_callbackActive = true;
		
		// Select the instance
		selectable->setSelected(path_currently_selected == FALSE);

		const AABB& aabb = node->worldAABB();
		Vector3 origin(aabb.origin);
		
		// Move the camera a bit off the AABB origin
		origin += Vector3(-50, 0, 50);

		// Rotate the camera a bit towards the "ground"
		Vector3 angles(0, 0, 0);
		angles[CAMERA_PITCH] = -30;

		GlobalCameraView().focusCamera(origin, angles);

		// Now reactivate the callbacks
		self->_callbackActive = false;
		
		return TRUE; // don't propagate
	}

	return FALSE;
}
    Selection ViewpointCursor::getCursor(const SelectableList& selectables) {
        Selectable* closestObject = NULL;
        Selection closestIntersection;
        if (updatePending) {

            closestIntersection.distance = std::numeric_limits<float>::max();

            glm::vec3 p = getUserPosition();
            glm::vec3 d = getCursorDirection();


            // First up, see if we intersect one of the objects.
            for (SelectableList::const_iterator it = selectables.begin(); it < selectables.end(); ++it) {
                Selectable* s = *it;
                Selection i = s->intersect(p, d);

                if (i.distance > 0 && i.distance < closestIntersection.distance)
                {
                    closestObject = s;
                    closestIntersection = i;
                }
            }
            updatePending = false;

            // Return the closest object, if there was one.
            if (closestObject != NULL) {
                cursorPlaced = true;
                cursor3D = closestIntersection.pos;
                cursorNormal = closestIntersection.normal;
                closestIntersection.rotationMatrix = getCursorRotation();
                closestIntersection.object = closestObject;
            }

            // intersect with magic plane so at least the cursor appears...
            else {
                glm::vec3 userDirection = getViewDirection();
                Plane plane(p + userDirection*planeDistance, userDirection);
                Plane::Intersection ip = plane.intersect(p, d);
                if (ip.intersects) {
                    cursorPlaced = true;
                    cursor3D = ip.intersectionPoint;
                    cursorNormal = userDirection*-1.0f;
                    cursorPlaced = true;

                    closestIntersection.pos = cursor3D;
                    closestIntersection.normal = cursorNormal;
                    closestIntersection.rotationMatrix = getCursorRotation();
                    closestIntersection.object = NULL;
                }
            }
        }
        return closestIntersection;
    }
Пример #11
0
Buffer<Selectable *> UnixSelectorImpl::getSelected()
{
    AdvancedBuffer<Selectable *> result;
    
    for (int i = 0, j = selectableList.size() ; i < j ; i++) {
        Selectable *currentSelectable = selectableList[i];
        UnixSelectableImpl *currentImpl = static_cast<UnixSelectableImpl *>(currentSelectable->getSelectableImpl());
        if (FD_ISSET(currentImpl->getFd(), &readfds))
            result.add(currentSelectable);
    }
    result.flush();
    return result;
}
Пример #12
0
void deselectCB(void *data, SoPath *path)
{
	ManipMaster *master = static_cast<ManipMaster *>(data);

	LabObject *obj;
	if (LabObject::isLabObject(path->getTail(), &obj)) {
		if (obj->getTypeId() == Selectable::classTypeId) {
			Selectable *sel = static_cast<Selectable *>(obj);
			sel->setSelected(false);

			master->setSelected(NULL);
		}
	}
}
Пример #13
0
bool PlaneSelectableSelectPlanes::pre(const scene::Path& path, scene::Instance& instance) const {
    if(path.top().get().visible())
    {
      Selectable* selectable = Instance_getSelectable(instance);
      if(selectable != 0 && selectable->isSelected())
      {
        PlaneSelectable* planeSelectable = Instance_getPlaneSelectable(instance);
        if(planeSelectable != 0)
        {
          planeSelectable->selectPlanes(_selector, _test, _selectedPlaneCallback);
        }
      }
    }
    return true;
}
Пример #14
0
// This is called if the selection changes, so that the local list of selected instances can be updated
void RadiantSelectionSystem::onSelectedChanged(scene::Instance& instance, const Selectable& selectable) {
	// Cache the selection state
	bool isSelected = selectable.isSelected();

	_countPrimitive += (isSelected) ? +1 : -1;
	_selectionChangedCallbacks(selectable); // legacy

	_selectionInfo.totalCount += (isSelected) ? +1 : -1;

	if (Instance_getBrush(instance) != NULL) {
		_selectionInfo.brushCount += (isSelected) ? +1 : -1;
	}
	else {
		_selectionInfo.entityCount += (isSelected) ? +1 : -1;
	}

	// If the selectable is selected, add it to the local selection list, otherwise remove it
	if (isSelected) {
		_selection.append(instance);
	}
	else {
		_selection.erase(instance);
	}

	// Notify observers, FALSE = primitive selection change
	notifyObservers(instance, false);

	// Check if the number of selected primitives in the list matches the value of the selection counter
	ASSERT_MESSAGE(_selection.size() == _countPrimitive, "selection-tracking error");

	// Schedule an idle callback
	requestIdleCallback();

	_requestWorkZoneRecalculation = true;
}
Пример #15
0
void FaceInstance::selectedChanged (const Selectable& selectable)
{
	if (selectable.isSelected()) {
		g_SelectedFaceInstances.insert(*this);
	} else {
		g_SelectedFaceInstances.erase(*this);
	}
	m_selectionChanged(selectable);
}
Пример #16
0
void SelectorImpl::changed( Selectable& s )
{
    if( s.avail() )
    {
        _avail.insert(&s);
    }
    else
    {
        _avail.erase(&s);
    }
}
Пример #17
0
gboolean treemodel_update_selection(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer data)
{
  GtkTreeView* view = reinterpret_cast<GtkTreeView*>(data);

  scene::Instance* instance;
  gtk_tree_model_get_pointer(model, iter, 1, &instance);
  Selectable* selectable = Instance_getSelectable(*instance);

  if(selectable != 0)
  {
    GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
    if(selectable->isSelected())
    {
      gtk_tree_selection_select_path(selection, path);
    }
    else
    {
      gtk_tree_selection_unselect_path(selection, path);
    }
  }

  return FALSE;
}
Пример #18
0
bool
Canvas::OnDelete(void)
{
	bool deleted = false;
	
	Design::iterator element;
	for (element = design->begin(); element != design->end(); ++element) {
		while(true) {
			Selectable *elem = *element;
			if (element == design->end())
				return deleted;
			
			if (elem->IsSelected()) {
				element = design->erase(element);
				delete elem;
				deleted = true;
				continue;
			}
			break;
		}
	}
	
	return deleted;
} // Canvas::OnDelete
Пример #19
0
// greebo: This should be called "onComponentSelectionChanged", as it is a similar function of the above one
// Updates the internal list of component instances if the component selection gets changed
void RadiantSelectionSystem::onComponentSelection(scene::Instance& instance, const Selectable& selectable) {
	_countComponent += (selectable.isSelected()) ? +1 : -1;
	_selectionChangedCallbacks(selectable); // legacy

	_selectionInfo.totalCount += (selectable.isSelected()) ? +1 : -1;

	// If the instance got selected, add it to the list, otherwise remove it
	if (selectable.isSelected()) {
		_componentSelection.append(instance);
	}
	else {
		_componentSelection.erase(instance);
	}

	notifyObservers(instance, true);

	// Check if the number of selected components in the list matches the value of the selection counter
	ASSERT_MESSAGE(_componentSelection.size() == _countComponent, "selection-tracking error");

	// Schedule an idle callback
	requestIdleCallback();

	_requestWorkZoneRecalculation = true;
}
// This is called if the selection changes, so that the local list of selected nodes can be updated
void RadiantSelectionSystem::onSelectedChanged(const scene::INodePtr& node, const Selectable& selectable) {

    // Cache the selection state
    bool isSelected = selectable.isSelected();
    int delta = isSelected ? +1 : -1;

    _countPrimitive += delta;
    _sigSelectionChanged(selectable);

    _selectionInfo.totalCount += delta;

    if (Node_getPatch(node) != NULL) {
        _selectionInfo.patchCount += delta;
    }
    else if (Node_getBrush(node) != NULL) {
        _selectionInfo.brushCount += delta;
    }
    else {
        _selectionInfo.entityCount += delta;
    }

    // If the selectable is selected, add it to the local selection list, otherwise remove it
    if (isSelected) {
        _selection.append(node);
    }
    else {
        _selection.erase(node);
    }

    // Notify observers, FALSE = primitive selection change
    notifyObservers(node, false);

    // Check if the number of selected primitives in the list matches the value of the selection counter
    ASSERT_MESSAGE(_selection.size() == _countPrimitive, "selection-tracking error");

    // Schedule an idle callback
    requestIdleCallback();

    _requestWorkZoneRecalculation = true;
    _requestSceneGraphChange = true;
}
Пример #21
0
void FaceInstance::selectedChanged(const Selectable& selectable)
{
	if (selectable.isSelected())
	{
		Selection().push_back(this);
	}
	else
	{
		FaceInstanceSet::reverse_iterator found = std::find(Selection().rbegin(), Selection().rend(), this);

		// Emit an error if the instance is not in the list
		ASSERT_MESSAGE(found != Selection().rend(), "selection-tracking error");

		Selection().erase(--found.base());
	}

	if (m_selectionChanged)
	{
		m_selectionChanged(selectable);
	}
}
Пример #22
0
bool SelectorImpl::waitUntil(Timespan until)
{
    if (!_avail.empty())
        until = Timespan(0);

    if (_isDirty)
    {
        _pollfds.clear();

        // recalculate size
        size_t pollSize= 1;

        std::set<Selectable*>::iterator iter;
        for( iter= _devices.begin(); iter != _devices.end(); ++iter)
        {
            if( (*iter)->enabled() )
                pollSize+= (*iter)->simpl().pollSize();
        }

        pollfd pfd;
        pfd.fd = -1;
        pfd.events = 0;
        pfd.revents = 0;

        _pollfds.assign(pollSize, pfd);

        // add entries
        pollfd* pCurr= &_pollfds[0];

        // insert event pipe
        pCurr->fd = _wakePipe[0];
        pCurr->events = POLLIN;

        ++pCurr;

        for( iter= _devices.begin(); iter != _devices.end(); ++iter)
        {
            if( (*iter)->enabled() )
            {
                const size_t availableSpace= &_pollfds.back() - pCurr + 1;
                size_t required = (*iter)->simpl().pollSize();
                assert( required <= availableSpace);
                pCurr+= (*iter)->simpl().initializePoll( pCurr, required);
            }
        }

        _isDirty= false;
    }

#ifdef HAVE_PPOLL
    struct timespec pollTimeout = { 0, 0 };
    struct timespec* pollTimeoutP = 0;
    if (until >= Timespan(0))
        pollTimeoutP = &pollTimeout;
#else
    int pollTimeout = until == Timespan(0) ? 0 : -1;
#endif

    int ret = -1;
    while (true)
    {
        if (until > Timespan(0))
        {
            Timespan remaining = until - Timespan::gettimeofday();
            if (remaining < Timespan(0))
                remaining = Timespan(0);

#ifdef HAVE_PPOLL
            pollTimeout.tv_sec = remaining.totalUSecs() / 1000000;
            pollTimeout.tv_nsec = (remaining.totalUSecs() % 1000000) * 1000;
#else
            if (Milliseconds(remaining) >= std::numeric_limits<int>::max())
                pollTimeout = std::numeric_limits<int>::max();
            else
                pollTimeout = Milliseconds(remaining).ceil();
#endif

            log_debug("remaining " << remaining);
        }
        else
            log_debug("no timeout");

#ifdef HAVE_PPOLL
        log_debug("ppoll with " << _pollfds.size() << " fds, timeout=" << pollTimeout.tv_sec << "s " << pollTimeout.tv_nsec << "ns");
        ret = ::ppoll(&_pollfds[0], _pollfds.size(), pollTimeoutP, 0);
        log_debug("ppoll returns " << ret);
#else
        log_debug("poll with " << _pollfds.size() << " fds, timeout=" << pollTimeout << "ms");
        ret = ::poll(&_pollfds[0], _pollfds.size(), pollTimeout);
        log_debug("poll returns " << ret);
#endif
        if( ret != -1 )
            break;

        if( errno != EINTR )
            throw IOError("Could not poll on file descriptors");

    }

    if( ret == 0 && _avail.empty() )
        return false;

    bool avail = false;
    try
    {
        if (_pollfds[0].revents != 0)
        {

            if ( _pollfds[0].revents & POLL_ERROR_MASK)
            {
                throw IOError("poll error on event pipe");
            }

            static char buffer[1024];
            while(true)
            {
                int ret = ::read(_wakePipe[0], buffer, sizeof(buffer));
                if(ret > 0)
                {
                    avail = true;
                    continue;
                }

                if (ret == -1)
                {
                    if(errno == EINTR)
                        continue;

                    if(errno == EAGAIN)
                        break;
                }

                throw IOError("Could not read from pipe");
            }
        }

        for( _current = _devices.begin(); _current != _devices.end(); )
        {
            Selectable* dev = *_current;

            if ( dev->enabled() && dev->simpl().checkPollEvent() )
            {
                avail = true;
            }

            if (_current != _devices.end())
            {
                if (*_current == dev)
                {
                    ++_current;
                }
            }
        }
    }
    catch (...)
    {
        _current= _devices.end();
        throw;
    }

    return avail;
}
Пример #23
0
 void notify(const Selectable& arguments)
 {
   bool bleh = arguments.isSelected();
 }
/* 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 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);
    	}
    }
}