// Since the modelviewmatrix is updated in the update, and flowgraph is updated in the preupdate, we need this postupdate virtual void OnPostUpdate(float fDeltaTime) { int invMouseY = gEnv->pRenderer->GetHeight() - m_mouseY; Vec3 vPos0(0,0,0); gEnv->pRenderer->UnProjectFromScreen((float)m_mouseX, (float)invMouseY, 0, &vPos0.x, &vPos0.y, &vPos0.z); Vec3 vPos1(0,0,0); gEnv->pRenderer->UnProjectFromScreen((float)m_mouseX, (float)invMouseY, 1, &vPos1.x, &vPos1.y, &vPos1.z); Vec3 vDir = vPos1 - vPos0; vDir.Normalize(); ray_hit hit; const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; IPhysicalEntity** pSkipEnts = NULL; int numSkipped = 0; int containerId = GetPortInt(&m_actInfo, EIP_EntitiesToIgnore); if(containerId != 0) { IFlowSystemContainerPtr container = gEnv->pFlowSystem->GetContainer(containerId); numSkipped = container->GetItemCount(); pSkipEnts = new IPhysicalEntity*[numSkipped]; for (int i = 0; i < numSkipped; i++) { EntityId id; container->GetItem(i).GetValueWithConversion(id); pSkipEnts[i] = gEnv->pEntitySystem->GetEntity(id)->GetPhysics(); } } if (gEnv->pPhysicalWorld && gEnv->pPhysicalWorld->RayWorldIntersection(vPos0, vDir * gEnv->p3DEngine->GetMaxViewDistance(), m_rayTypeFilter, flags, &hit, 1, pSkipEnts, numSkipped)) { ActivateOutput(&m_actInfo, EOP_HitPos, hit.pt); ActivateOutput(&m_actInfo, EOP_HitNormal, hit.n); if(hit.pCollider) { if(IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics(hit.pCollider)) { ActivateOutput(&m_actInfo, EOP_EntityId, pEntity->GetId()); } } } if(pSkipEnts) delete [] pSkipEnts; }
virtual void ProcessEvent( EFlowEvent event, SActivationInfo* pActInfo ) { switch(event) { case eFE_Activate: { if(IsPortActive(pActInfo, EIP_Start)) { m_currentIdx = 0; m_containerId = GetPortInt(pActInfo, EIP_Id); pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true); } } break; case eFE_Update: { IFlowSystemContainerPtr pContainer = gEnv->pFlowSystem->GetContainer(m_containerId); if(pContainer) { if(m_currentIdx < pContainer->GetItemCount()) { ActivateOutput(pActInfo, EOP_Out, pContainer->GetItem(m_currentIdx)); m_currentIdx++; } else { ActivateOutput(pActInfo, EOP_Done, 1); pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false); } } else { ActivateOutput(pActInfo, EOP_Error, 1); pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false); } } break; } }
virtual void OnPostUpdate(float fDeltaTime) { // Get it once, then unregister to prevent unnescessary updates if(!m_get) { gEnv->pGame->GetIGameFramework()->UnregisterListener(this); return; } m_get = false; // Grab the container, and make sure its valid (user has to create it for us and pass the valid ID) IFlowSystemContainerPtr pContainer = gEnv->pFlowSystem->GetContainer(GetPortInt(&m_actInfo, EIP_ContainerId)); if(!pContainer) return; IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator(); while (!pIt->IsEnd()) { if (IEntity *pEntity = pIt->Next()) { //skip Local player if (IPhysicalEntity *physEnt = pEntity->GetPhysics()) { IActor *pClientActor = gEnv->pGame->GetIGameFramework()->GetClientActor(); if (!pClientActor) return; //skip the client actor entity if (physEnt == pClientActor->GetEntity()->GetPhysics()) continue; AABB worldBounds; pEntity->GetWorldBounds(worldBounds); //skip further calculations if the entity is not visible at all... if (gEnv->pSystem->GetViewCamera().IsAABBVisible_F(worldBounds) == CULL_EXCLUSION) continue; Vec3 wpos = pEntity->GetWorldPos(); Quat rot = pEntity->GetWorldRotation(); AABB localBounds; pEntity->GetLocalBounds(localBounds); //get min and max values of the entity bounding box (local positions) Vec3 points[2]; points[0] = wpos + rot * localBounds.min; points[1] = wpos + rot * localBounds.max; Vec3 pointsProjected[2]; //project the bounding box min max values to screen positions for (int i=0; i<2; ++i) { gEnv->pRenderer->ProjectToScreen(points[i].x, points[i].y, points[i].z, &pointsProjected[i].x, &pointsProjected[i].y, &pointsProjected[i].z); const float fWidth = (float)gEnv->pRenderer->GetWidth(); const float fHeight = (float)gEnv->pRenderer->GetHeight(); //scale projected values to the actual screen resolution pointsProjected[i].x *= 0.01f * fWidth; pointsProjected[i].y *= 0.01f * fHeight; } //check if the projected bounding box min max values are fully or partly inside the screen selection if ((m_screenX <= pointsProjected[0].x && pointsProjected[0].x <= m_screenX2) || (m_screenX >= pointsProjected[0].x && m_screenX2 <= pointsProjected[1].x) || (m_screenX <= pointsProjected[1].x && m_screenX2 >= pointsProjected[1].x) || (m_screenX <= pointsProjected[0].x && m_screenX2 >= pointsProjected[1].x)) { if ((m_screenY <= pointsProjected[0].y && m_screenY2 >= pointsProjected[0].y) || (m_screenY <= pointsProjected[1].y && m_screenY2 >= pointsProjected[0].y) || (m_screenY <= pointsProjected[1].y && m_screenY2 >= pointsProjected[1].y)) { // Add entity to container pContainer->AddItem(TFlowInputData(pEntity->GetId())); } } } } } }