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); } }
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; }
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 ); } } } }
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; }
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; }
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; }
void SelectableGroup::unselectAll() { Selectable* selected = this->getSelection(); if(selected != NULL) selected->setSelected(false); this->notifySelectionChanged(); }
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; }
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; }
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); } } }
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; }
// 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; }
void FaceInstance::selectedChanged (const Selectable& selectable) { if (selectable.isSelected()) { g_SelectedFaceInstances.insert(*this); } else { g_SelectedFaceInstances.erase(*this); } m_selectionChanged(selectable); }
void SelectorImpl::changed( Selectable& s ) { if( s.avail() ) { _avail.insert(&s); } else { _avail.erase(&s); } }
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; }
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
// 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; }
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); } }
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; }
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); } } }