// 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;
	}
Пример #2
0
	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()));
						}
					}
				}

			}
		}
	}