// pick a node using the mouse cursor location ISceneNode* CSLevel::selectNode(int screenX, int screenY, long objectflags) { // attempt to select a node. use the passed in mask ISceneNode* node = getCollMan()->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(screenX, screenY), objectflags, true); if (node) CS_LOG(CSLOGTYPE::CSL_DEBUG, "SELECTED NODE %i", node->getID()); return node; }
// Support function for finding collided nodes using a subset of nodes in the scene // recursive method for going through all scene nodes void getNodeRayBB(ISceneNode* root, const core::line3df& ray, s32 bits, bool recurse, f32& outbestdistance, ISceneNode*& outbestnode) { core::vector3df edges[8]; const core::list<ISceneNode*>& children = root->getChildren(); core::list<ISceneNode*>::ConstIterator it = children.begin(); for (; it != children.end(); ++it) { ISceneNode* current = *it; if (current->isVisible() && // (bNoDebugObjects ? !current->isDebugObject() : true) && (bits==0 || (bits != 0 && (current->getID() & bits)))) { // get world to object space transform core::matrix4 mat; if (!current->getAbsoluteTransformation().getInverse(mat)) continue; // transform vector from world space to object space core::line3df line(ray); mat.transformVect(line.start); mat.transformVect(line.end); const core::aabbox3df& box = current->getBoundingBox(); // do intersection test in object space if (box.intersectsWithLine(line)) { box.getEdges(edges); f32 distance = 0.0f; for (s32 e=0; e<8; ++e) { f32 t = edges[e].getDistanceFromSQ(line.start); if (t > distance) distance = t; } if (distance < outbestdistance) { outbestnode = current; outbestdistance = distance; } } } if ( recurse ) getNodeRayBB(current, ray, bits, recurse, outbestdistance, outbestnode); } }
bool GUIManager::updateNodeInformation(const INodeObject* obj) { ISceneNode* node = nullptr; if (!obj || !(node = obj->getNode()) || _currentObj == obj) return false; _currentObj = obj; _information->clear(); //Check id ? (this->*(_objDisplayers[static_cast<Ids>(node->getID())]))(obj); }
/// @param hitEntity the entity intersected by the ray /// @param hitPos the position of the intersection /// @param origin origin of the ray to cast /// @param target target of the ray to cast /// @param type bitmask of the objects to care about or 0 for 'check all' /// @param vis show rays? /// @param foundColor the color to use if vis is true and an intersection is found /// @param noneColor the color to use if vis is true /// @return first intersection info tuple(sim, hit) with SimEntityData sim and Vector3f hit (hit location) or () /// Find the first object that intersects the specified ray bool SimContext::FindInRay( SimEntityData& hitEntity, Vector3f& hitPos, const Vector3f& origin, const Vector3f& target, const uint32_t& type, const bool vis, const SColor& foundColor, const SColor& noneColor ) { ISceneCollisionManager* collider = mIrr.getSceneManager()->getSceneCollisionManager(); Assert(collider); Line3f ray(ConvertNeroToIrrlichtPosition(origin), ConvertNeroToIrrlichtPosition(target)); Triangle3f outTriangle; ISceneNode* node = collider->getSceneNodeAndCollisionPointFromRay (ray, hitPos, outTriangle, type); // convert back into our coord system hitPos = ConvertIrrlichtToNeroPosition(hitPos); if (node && node->getID() >= kFirstSimId) { // we found a sim node, so return its data SimEntityPtr ent = getSimulation()->FindBySceneObjectId(node->getID()); if (ent) { // return the result: (sim, hit) hitEntity = ent->GetState(); // draw a ray if requested if (vis) { LineSet::instance().AddSegment(origin, hitPos, foundColor); } return true; } } if (vis) { LineSet::instance().AddSegment(origin, target, noneColor); } return false; }
/// @param x screen x-coordinate for active camera /// @param y screen y-coordinate for active camera /// @return the SimEntity intersected first by the ray from the camera origin through the view plane SimEntityPtr SimContext::GetClickedEntity(const int32_t& x, const int32_t& y) { Pos2i pos(x,y); // get scene node ISceneNode* node = mIrr.getSceneManager()->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(pos); SimEntityPtr result; if (node != NULL) { result = getSimulation()->FindBySceneObjectId(node->getID()); } else { LOG_F_WARNING("core", "unable to find clicked entity at location " << x << ", " << y); } return result; }
/// @param x screen x-coordinate for active camera /// @param y screen y-coordinate for active camera /// @return Approximate 3d position of the click Vector3f SimContext::GetClickedPosition(const int32_t& x, const int32_t& y) { Pos2i pos(x,y); ISceneCollisionManager* collider = mIrr.getSceneManager()->getSceneCollisionManager(); // get ray Line3f ray = collider->getRayFromScreenCoordinates(pos); LOG_F_DEBUG("collision", "screen coordinates: " << pos << ", ray: " << ray.start << " - " << ray.end << ", length: " << ray.getLength()); Vector3f collision_point; Triangle3f collision_triangle; ISceneNode* collision = collider->getSceneNodeAndCollisionPointFromRay(ray, collision_point, collision_triangle); if (collision) { SimEntityPtr ent = mpSimulation->FindBySceneObjectId(collision->getID()); LOG_F_DEBUG("collision", "screen coordinates: " << pos << " colliding with: " << ent << " at: " << collision_point); return ConvertIrrlichtToNeroPosition(collision_point); } else { LOG_F_WARNING("collision", "screen coordinates: " << pos << " did not collide with any geometry!"); return ConvertIrrlichtToNeroPosition(ray.end); } }
// Support function for finding collided nodes using a subset of nodes in the scene // recursive method for going through all scene nodes and testing them against a point bool getNodePointBB(ISceneNode* root, vector3df point, s32 bits, bool recurse, ISceneNode*& outbestnode) { core::vector3df edges[8]; const core::list<ISceneNode*>& children = root->getChildren(); core::list<ISceneNode*>::ConstIterator it = children.begin(); for (; it != children.end(); ++it) { ISceneNode* current = *it; if (current->isVisible() && // (bNoDebugObjects ? !current->isDebugObject() : true) && (bits==0 || (bits != 0 && (current->getID() & bits)))) { // get world to object space transform core::matrix4 mat; if (!current->getAbsoluteTransformation().getInverse(mat)) continue; // transform vector from world space to object space vector3df currentPoint( point ); mat.transformVect(currentPoint); const core::aabbox3df& box = current->getBoundingBox(); // do intersection test in object space if (box.isPointInside( currentPoint )) { outbestnode = current; return true; } } if ( recurse ) if ( getNodePointBB(current, point, bits, recurse, outbestnode)) return true; } return false; }
void IdleBoard::Execute(BattleBoard* pField, u32 elapsedTime) { HandleEvent(pField, elapsedTime); // check if there are clicked card static EventReceiver* pEventReceiver = &(EventRcv); position2di posMouse; if (pEventReceiver->IsLeftMouseBtnDown(posMouse)) { pEventReceiver->SetLeftMouseBtnDown(false); ISceneCollisionManager* pCollisionManager = IrrDvc.GetSmgr()->getSceneCollisionManager(); ISceneNode* pSelectedCard = pCollisionManager->getSceneNodeFromScreenCoordinatesBB(posMouse); // send message Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY, pField->ID(), pSelectedCard->getID(), MSG_CARD_CLICKED, null); } }
// selectObject // detect list objs at mouse xy void CDocument::selectObject( int mouseX, int mouseY, bool isControlHold ) { ISceneManager *smgr = getIView()->getSceneMgr(); ICameraSceneNode *camera = smgr->getActiveCamera(); // if no camera if ( camera == NULL ) return; ISceneCollisionManager *collMan = smgr->getSceneCollisionManager(); // get select ray core::line3df selectRay = getIView()->getSelectRay(); // check hit test core::vector3df intersection; core::triangle3df hitTriangle; // check select ISceneNode *selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay ( selectRay, intersection, hitTriangle ); if ( selectedSceneNode ) { CGameObject *pObj = searchObject( selectedSceneNode->getID() ); // try find parent while ( pObj == NULL ) { selectedSceneNode = selectedSceneNode->getParent(); if ( selectedSceneNode == NULL ) break; pObj = searchObject( selectedSceneNode->getID() ); } // add to select list if ( pObj && pObj->isVisible() ) { if ( isControlHold == false || pObj->getObjectState() == CGameObject::Normal ) m_selectObjects.push_back( pObj ); else { pObj->setObjectState( CGameObject::Normal ); ArrayGameObjectIter i = m_selectObjects.begin(), iEnd = m_selectObjects.end(); while ( i != iEnd ) { if ( (*i) == pObj ) { m_selectObjects.erase( i ); break; } i++; } } } } }