Example #1
0
	void RenderSubmit(SceneCollector& collector)
	{
		// (This is only called if a > 0)
		collector.Submit(&m_Overlay);

		if (ICmpSelectable::ms_EnableDebugOverlays)
		{
			// allocate debug overlays on-demand
			if (!m_DebugBoundingBoxOverlay) m_DebugBoundingBoxOverlay = new SOverlayLine;
			if (!m_DebugSelectionBoxOverlay) m_DebugSelectionBoxOverlay = new SOverlayLine;

			CmpPtr<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId()); 
			if (cmpVisual) 
			{
				SimRender::ConstructBoxOutline(cmpVisual->GetBounds(), *m_DebugBoundingBoxOverlay);
				m_DebugBoundingBoxOverlay->m_Thickness = 2; 
				m_DebugBoundingBoxOverlay->m_Color = CColor(1.f, 0.f, 0.f, 1.f);

				SimRender::ConstructBoxOutline(cmpVisual->GetSelectionBox(), *m_DebugSelectionBoxOverlay);
				m_DebugSelectionBoxOverlay->m_Thickness = 2;
				m_DebugSelectionBoxOverlay->m_Color = CColor(0.f, 1.f, 0.f, 1.f);

				collector.Submit(m_DebugBoundingBoxOverlay);
				collector.Submit(m_DebugSelectionBoxOverlay);
			}
		}
		else
		{
			// reclaim debug overlay line memory when no longer debugging (and make sure to set to zero after deletion)
			if (m_DebugBoundingBoxOverlay) SAFE_DELETE(m_DebugBoundingBoxOverlay);
			if (m_DebugSelectionBoxOverlay) SAFE_DELETE(m_DebugSelectionBoxOverlay);
		}
	}
Example #2
0
	float GetConstructionProgressOffset(const CVector3D& pos)
	{
		if (m_ConstructionProgress.IsZero())
			return 0.0f;

		CmpPtr<ICmpVisual> cmpVisual(GetEntityHandle());
		if (!cmpVisual)
			return 0.0f;

		// We use selection boxes to calculate the model size, since the model could be offset
		// TODO: this annoyingly shows decals, would be nice to hide them
		CBoundingBoxOriented bounds = cmpVisual->GetSelectionBox();
		if (bounds.IsEmpty())
			return 0.0f;

		float dy = 2.0f * bounds.m_HalfSizes.Y;

		// If this is a floating unit, we want it to start all the way under the terrain,
		// so find the difference between its current position and the terrain

		CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
		if (cmpTerrain && (m_Floating || m_ActorFloating))
		{
			float ground = cmpTerrain->GetExactGroundLevel(pos.X, pos.Z);
			dy += std::max(0.f, pos.Y - ground);
		}

		return (m_ConstructionProgress.ToFloat() - 1.0f) * dy;
	}
Example #3
0
std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, player_id_t owner, bool allowEditorSelectables)
{
	PROFILE2("PickEntitiesInRect");
	// Make sure sx0 <= sx1, and sy0 <= sy1
	if (sx0 > sx1)
		std::swap(sx0, sx1);
	if (sy0 > sy1)
		std::swap(sy0, sy1);

	CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
	ENSURE(cmpRangeManager);

	std::vector<entity_id_t> hitEnts;

	const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
	for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
	{
		entity_id_t ent = it->first;
		CEntityHandle handle = it->second->GetEntityHandle();

		// Check if this entity is only selectable in Atlas
		if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !allowEditorSelectables)
			continue;

		// Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
		if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN)
			continue;

		// Ignore entities not owned by 'owner'
		CmpPtr<ICmpOwnership> cmpOwnership(handle);
		if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner))
			continue;

		// Find the current interpolated model position.
		// (We just use the centre position and not the whole bounding box, because maybe
		// that's better for users trying to select objects in busy areas)

		CmpPtr<ICmpVisual> cmpVisual(handle);
		if (!cmpVisual)
			continue;

		CVector3D position = cmpVisual->GetPosition();

		// Reject if it's not on-screen (e.g. it's behind the camera)
		if (!camera.GetFrustum().IsPointVisible(position))
			continue;

		// Compare screen-space coordinates
		float x, y;
		camera.GetScreenCoordinates(position, x, y);
		int ix = (int)x;
		int iy = (int)y;
		if (sx0 <= ix && ix <= sx1 && sy0 <= iy && iy <= sy1)
			hitEnts.push_back(ent);
	}

	return hitEnts;
}
Example #4
0
std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank)
{
	CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY);
	CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);

	std::vector<entity_id_t> hitEnts;

 	const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
	for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
	{
 		entity_id_t ent = it->first;

		if (matchRank)
		{
			// Exact template name matching
			if (cmpTemplateManager->GetCurrentTemplateName(ent) != templateName)
				continue;
		}

		// Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
		// In this case, the checking is done to avoid selecting garrisoned units
		if (cmpRangeManager->GetLosVisibility(ent, owner) == ICmpRangeManager::VIS_HIDDEN)
			continue;

 		// Ignore entities not owned by 'owner'
 		CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent);
 		if (!cmpOwnership || cmpOwnership->GetOwner() != owner)
 			continue;

		// Ignore off screen entities
 		if (!includeOffScreen)
 		{
 			// Find the current interpolated model position.
			CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
			if (!cmpVisual)
				continue;
			CVector3D position = cmpVisual->GetPosition();

			// Reject if it's not on-screen (e.g. it's behind the camera)
			if (!camera.GetFrustum().IsPointVisible(position))
				continue;
 		}

		if (!matchRank)
		{
			// Match by selection group name
			// (This is relatively expensive since it involves script calls, so do it after all other tests)
			CmpPtr<ICmpIdentity> cmpIdentity(simulation.GetSimContext(), ent);
			if (!cmpIdentity || cmpIdentity->GetSelectionGroupName() != templateName)
				continue;
		}

 		hitEnts.push_back(ent);
 	}

 	return hitEnts;
}
Example #5
0
std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner)
{
    // Make sure sx0 <= sx1, and sy0 <= sy1
    if (sx0 > sx1)
        std::swap(sx0, sx1);
    if (sy0 > sy1)
        std::swap(sy0, sy1);

    CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
    ENSURE(!cmpRangeManager.null());

    std::vector<entity_id_t> hitEnts;

    const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
    for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
    {
        entity_id_t ent = it->first;

        // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
        if (cmpRangeManager->GetLosVisibility(ent, owner) == ICmpRangeManager::VIS_HIDDEN)
            continue;

        // Ignore entities not owned by 'owner'
        CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent);
        if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner)
            continue;

        // Find the current interpolated model position.
        // (We just use the centre position and not the whole bounding box, because maybe
        // that's better for users trying to select objects in busy areas)

        CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
        if (cmpVisual.null())
            continue;

        CVector3D position = cmpVisual->GetPosition();

        // Reject if it's not on-screen (e.g. it's behind the camera)

        if (!camera.GetFrustum().IsPointVisible(position))
            continue;

        // Compare screen-space coordinates
        float x, y;
        camera.GetScreenCoordinates(position, x, y);
        int ix = (int)x;
        int iy = (int)y;
        if (sx0 <= ix && ix <= sx1 && sy0 <= iy && iy <= sy1)
            hitEnts.push_back(ent);
    }

    return hitEnts;
}
Example #6
0
void ActorViewer::Render()
{
	m.Terrain.MakeDirty(RENDERDATA_UPDATE_COLOR);

	g_Renderer.SetClearColor(m.Background);

	// Set shadows, sky and water locally (avoid clobbering global state)
	bool oldShadows = g_Renderer.GetOptionBool(CRenderer::OPT_SHADOWS);
	g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS, m.ShadowsEnabled);

	bool oldSky = g_Renderer.GetSkyManager()->m_RenderSky;
	g_Renderer.GetSkyManager()->m_RenderSky = false;

	bool oldWater = g_Renderer.GetWaterManager()->m_RenderWater;
	g_Renderer.GetWaterManager()->m_RenderWater = m.WaterEnabled;

	// Set simulation context for rendering purposes
	g_Renderer.SetSimulation(&m.Simulation2);

	g_Renderer.BeginFrame();

	// Find the centre of the interesting region, in the middle of the patch
	// and half way up the model (assuming there is one)
	CVector3D centre;
	CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity);
	if (cmpVisual)
		cmpVisual->GetBounds().GetCentre(centre);
	else
		centre.Y = 0.f;
	centre.X = centre.Z = TERRAIN_TILE_SIZE * m.Terrain.GetPatchesPerSide()*PATCH_SIZE/2;

	CCamera camera = AtlasView::GetView_Actor()->GetCamera();
	camera.m_Orientation.Translate(centre.X, centre.Y, centre.Z);
	camera.UpdateFrustum();

	g_Renderer.SetSceneCamera(camera, camera);

	g_Renderer.RenderScene(m);

	glDisable(GL_DEPTH_TEST);
	g_Logger->Render();
	g_ProfileViewer.RenderProfile();
	glEnable(GL_DEPTH_TEST);

	g_Renderer.EndFrame();

	// Restore the old renderer state
	g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS, oldShadows);
	g_Renderer.GetSkyManager()->m_RenderSky = oldSky;
	g_Renderer.GetWaterManager()->m_RenderWater = oldWater;

	ogl_WarnIfError();
}
Example #7
0
std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, int player)
{
    CVector3D origin, dir;
    camera.BuildCameraRay(screenX, screenY, origin, dir);

    CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
    ENSURE(!cmpRangeManager.null());

    std::vector<std::pair<float, entity_id_t> > hits; // (dist^2, entity) pairs

    const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
    for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
    {
        entity_id_t ent = it->first;

        // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
        if (cmpRangeManager->GetLosVisibility(ent, player) == ICmpRangeManager::VIS_HIDDEN)
            continue;

        CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
        if (cmpVisual.null())
            continue;

        CBound bounds = cmpVisual->GetBounds();

        float tmin, tmax;
        if (!bounds.RayIntersect(origin, dir, tmin, tmax))
            continue;

        // Find the perpendicular distance from the object's centre to the picker ray

        CVector3D centre;
        bounds.GetCentre(centre);

        CVector3D closest = origin + dir * (centre - origin).Dot(dir);
        float dist2 = (closest - centre).LengthSquared();

        hits.push_back(std::make_pair(dist2, ent));
    }

    // Sort hits by distance
    std::sort(hits.begin(), hits.end()); // lexicographic comparison

    // Extract the entity IDs
    std::vector<entity_id_t> hitEnts;
    hitEnts.reserve(hits.size());
    for (size_t i = 0; i < hits.size(); ++i)
        hitEnts.push_back(hits[i].second);
    return hitEnts;
}
Example #8
0
void ActorViewerImpl::UpdatePropList()
{
	Props.clear();

	CmpPtr<ICmpVisual> cmpVisual(Simulation2, Entity);
	if (cmpVisual)
	{
		CUnit* unit = cmpVisual->GetUnit();
		if (unit)
		{
			CModelAbstract& modelAbstract = unit->GetModel();
			UpdatePropListRecursive(&modelAbstract);
		}
	}
}
Example #9
0
void ActorViewer::SetActor(const CStrW& name, const CStrW& animation, player_id_t playerID)
{
	bool needsAnimReload = false;

	CStrW id = name;

	// Recreate the entity, if we don't have one or if the new one is different
	if (m.Entity == INVALID_ENTITY || id != m.CurrentUnitID)
	{
		// Delete the old entity (if any)
		if (m.Entity != INVALID_ENTITY)
		{
			m.Simulation2.DestroyEntity(m.Entity);
			m.Simulation2.FlushDestroyedEntities();
			m.Entity = INVALID_ENTITY;
		}

		// Clear particles associated with deleted entity
		g_Renderer.GetParticleManager().ClearUnattachedEmitters();

		// If there's no actor to display, return with nothing loaded
		if (id.empty())
			return;

		m.Entity = m.Simulation2.AddEntity(L"preview|" + id);
		if (m.Entity == INVALID_ENTITY)
			return;

		CmpPtr<ICmpPosition> cmpPosition(m.Simulation2, m.Entity);
		if (cmpPosition)
		{
			ssize_t c = TERRAIN_TILE_SIZE * m.Terrain.GetPatchesPerSide()*PATCH_SIZE/2;
			cmpPosition->JumpTo(entity_pos_t::FromInt(c), entity_pos_t::FromInt(c));
			cmpPosition->SetYRotation(entity_angle_t::Pi());
		}

		CmpPtr<ICmpOwnership> cmpOwnership(m.Simulation2, m.Entity);
		if (cmpOwnership)
			cmpOwnership->SetOwner(playerID);

		needsAnimReload = true;
	}

	if (animation != m.CurrentUnitAnim)
		needsAnimReload = true;

	if (needsAnimReload)
	{
		CStr anim = animation.ToUTF8().LowerCase();

		// Emulate the typical simulation animation behaviour
		float speed;
		float repeattime = 0.f;
		if (anim == "walk")
		{
			CmpPtr<ICmpUnitMotion> cmpUnitMotion(m.Simulation2, m.Entity);
			if (cmpUnitMotion)
				speed = cmpUnitMotion->GetWalkSpeed().ToFloat();
			else
				speed = 7.f; // typical unit speed

			m.CurrentSpeed = speed;
		}
		else if (anim == "run")
		{
			CmpPtr<ICmpUnitMotion> cmpUnitMotion(m.Simulation2, m.Entity);
			if (cmpUnitMotion)
				speed = cmpUnitMotion->GetRunSpeed().ToFloat();
			else
				speed = 12.f; // typical unit speed

			m.CurrentSpeed = speed;
		}
		else if (anim == "melee")
		{
			speed = 1.f; // speed will be ignored if we have a repeattime
			m.CurrentSpeed = 0.f;

			CStr code = "var cmp = Engine.QueryInterface("+CStr::FromUInt(m.Entity)+", IID_Attack); " +
				"if (cmp) cmp.GetTimers(cmp.GetBestAttack()).repeat; else 0;";
			m.Simulation2.GetScriptInterface().Eval(code.c_str(), repeattime);
		}
		else
		{
			// Play the animation at normal speed, but movement speed is zero
			speed = 1.f;
			m.CurrentSpeed = 0.f;
		}

		CStr sound;
		if (anim == "melee")
			sound = "attack";
		else if (anim == "build")
			sound = "build";
		else if (anim.Find("gather_") == 0)
			sound = anim;

		std::wstring soundgroup;
		if (!sound.empty())
		{
			CStr code = "var cmp = Engine.QueryInterface("+CStr::FromUInt(m.Entity)+", IID_Sound); " +
				"if (cmp) cmp.GetSoundGroup('"+sound+"'); else '';";
			m.Simulation2.GetScriptInterface().Eval(code.c_str(), soundgroup);
		}

		CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity);
		if (cmpVisual)
		{
			// TODO: SetEntitySelection(anim)
			cmpVisual->SelectAnimation(anim, false, fixed::FromFloat(speed), soundgroup);
			if (repeattime)
				cmpVisual->SetAnimationSyncRepeat(fixed::FromFloat(repeattime));
		}

		// update prop list for new entity/animation (relies on needsAnimReload also getting called for entire entity changes)
		m.UpdatePropList();
	}

	m.CurrentUnitID = id;
	m.CurrentUnitAnim = animation;
}
Example #10
0
std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, player_id_t player, bool allowEditorSelectables, int range)
{
	PROFILE2("PickEntitiesAtPoint");
	CVector3D origin, dir;
	camera.BuildCameraRay(screenX, screenY, origin, dir);

	CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
	ENSURE(cmpRangeManager);

	/* We try to approximate where the mouse is hovering by drawing a ray from
	 * the center of the camera and through the mouse then taking the position
	 * at which the ray intersects the terrain.                               */
	// TODO: Do this smarter without being slow.
	CVector3D pos3d = camera.GetWorldCoordinates(screenX, screenY, true);
	// Change the position to 2D by removing the terrain height.
	CFixedVector2D pos(fixed::FromFloat(pos3d.X), fixed::FromFloat(pos3d.Z));

	// Get a rough group of entities using our approximated origin.
	SpatialQueryArray ents;
	cmpRangeManager->GetSubdivision()->GetNear(ents, pos, entity_pos_t::FromInt(range));

	// Filter for relevent entities and calculate precise distances.
	std::vector<std::pair<float, entity_id_t> > hits; // (dist^2, entity) pairs
	for (int i = 0; i < ents.size(); ++i)
	{
		CmpPtr<ICmpSelectable> cmpSelectable(simulation, ents[i]);
		if (!cmpSelectable)
			continue;

		CEntityHandle handle = cmpSelectable->GetEntityHandle();

		// Check if this entity is only selectable in Atlas
		if (!allowEditorSelectables && cmpSelectable->IsEditorOnly())
			continue;

		// Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
		if (cmpRangeManager->GetLosVisibility(handle, player) == ICmpRangeManager::VIS_HIDDEN)
			continue;

		CmpPtr<ICmpVisual> cmpVisual(handle);
		if (!cmpVisual)
			continue;

		CVector3D center;
		float tmin, tmax;

		CBoundingBoxOriented selectionBox = cmpVisual->GetSelectionBox();
		if (selectionBox.IsEmpty())
		{
			if (!allowEditorSelectables)
				continue;

			// Fall back to using old AABB selection method for decals
			//	see: http://trac.wildfiregames.com/ticket/1032
			CBoundingBoxAligned aABBox = cmpVisual->GetBounds();
			if (aABBox.IsEmpty())
				continue;

			if (!aABBox.RayIntersect(origin, dir, tmin, tmax))
				continue;

			aABBox.GetCentre(center);
		}
		else
		{
			if (!selectionBox.RayIntersect(origin, dir, tmin, tmax))
				continue;

			center = selectionBox.m_Center;
		}

		// Find the perpendicular distance from the object's centre to the picker ray
		float dist2;
		CVector3D closest = origin + dir * (center - origin).Dot(dir);
		dist2 = (closest - center).LengthSquared();

		hits.push_back(std::make_pair(dist2, ents[i]));
	}

	// Sort hits by distance
	std::sort(hits.begin(), hits.end()); // lexicographic comparison

	// Extract the entity IDs
	std::vector<entity_id_t> hitEnts;
	hitEnts.reserve(hits.size());
	for (size_t i = 0; i < hits.size(); ++i)
		hitEnts.push_back(hits[i].second);
	return hitEnts;
}
Example #11
0
void ActorViewer::Render()
{
	m.Terrain.MakeDirty(RENDERDATA_UPDATE_COLOR);

	g_Renderer.SetClearColor(m.Background);

	// Disable shadows locally (avoid clobbering global state)
	bool oldShadows = g_Renderer.GetOptionBool(CRenderer::OPT_SHADOWS);
	g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS, m.ShadowsEnabled);

	bool oldSky = g_Renderer.GetSkyManager()->m_RenderSky;
	g_Renderer.GetSkyManager()->m_RenderSky = false;

	bool oldWater = g_Renderer.GetWaterManager()->m_RenderWater;
	g_Renderer.GetWaterManager()->m_RenderWater = false;

	g_Renderer.BeginFrame();

	// Find the centre of the interesting region, in the middle of the patch
	// and half way up the model (assuming there is one)
	CVector3D centre;
	CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity);
	if (!cmpVisual.null())
		cmpVisual->GetBounds().GetCentre(centre);
	else
		centre.Y = 0.f;
	centre.X = centre.Z = CELL_SIZE * m.Terrain.GetPatchesPerSide()*PATCH_SIZE/2;

	CCamera camera = View::GetView_Actor()->GetCamera();
	camera.m_Orientation.Translate(centre.X, centre.Y, centre.Z);
	camera.UpdateFrustum();
	
	g_Renderer.SetSceneCamera(camera, camera);

	g_Renderer.RenderScene(m);

	// ....

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glPushAttrib(GL_ENABLE_BIT);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_CULL_FACE);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glEnable(GL_TEXTURE_2D);

	g_ProfileViewer.RenderProfile();

	glPopAttrib();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	g_Renderer.EndFrame();

	// Restore the old renderer state
	g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS, oldShadows);
	g_Renderer.GetSkyManager()->m_RenderSky = oldSky;
	g_Renderer.GetWaterManager()->m_RenderWater = oldWater;

	ogl_WarnIfError();
}
Example #12
0
std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, player_id_t player, bool allowEditorSelectables)
{
	CVector3D origin, dir;
	camera.BuildCameraRay(screenX, screenY, origin, dir);

	CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
	ENSURE(cmpRangeManager);

	std::vector<std::pair<float, entity_id_t> > hits; // (dist^2, entity) pairs

	const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
	for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
	{
		entity_id_t ent = it->first;

		// Check if this entity is only selectable in Atlas
		if (!allowEditorSelectables && static_cast<ICmpSelectable*>(it->second)->IsEditorOnly())
			continue;

		// Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
		if (cmpRangeManager->GetLosVisibility(ent, player) == ICmpRangeManager::VIS_HIDDEN)
			continue;

		CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
		if (!cmpVisual)
			continue;

		CVector3D center;
		float tmin, tmax;

		CBoundingBoxOriented selectionBox = cmpVisual->GetSelectionBox();
		if (selectionBox.IsEmpty())
		{
			if (!allowEditorSelectables)
				continue;

			// Fall back to using old AABB selection method for decals
			//	see: http://trac.wildfiregames.com/ticket/1032
			CBoundingBoxAligned aABBox = cmpVisual->GetBounds();
			if (aABBox.IsEmpty())
				continue;

			if (!aABBox.RayIntersect(origin, dir, tmin, tmax))
				continue;

			aABBox.GetCentre(center);
		}
		else
		{
			if (!selectionBox.RayIntersect(origin, dir, tmin, tmax))
				continue;

			center = selectionBox.m_Center;
		}

		// Find the perpendicular distance from the object's centre to the picker ray

		float dist2;
		CVector3D closest = origin + dir * (center - origin).Dot(dir);
		dist2 = (closest - center).LengthSquared();

		hits.push_back(std::make_pair(dist2, ent));
	}

	// Sort hits by distance
	std::sort(hits.begin(), hits.end()); // lexicographic comparison

	// Extract the entity IDs
	std::vector<entity_id_t> hitEnts;
	hitEnts.reserve(hits.size());
	for (size_t i = 0; i < hits.size(); ++i)
		hitEnts.push_back(hits[i].second);
	return hitEnts;
}
Example #13
0
void CMapWriter::WriteXML(const VfsPath& filename,
						  WaterManager* pWaterMan, SkyManager* pSkyMan,
						  CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema,
						  CPostprocManager* pPostproc,
						  CSimulation2* pSimulation2)
{
	XML_Start();

	{
		XML_Element("Scenario");
		XML_Attribute("version", (int)FILE_VERSION);

		ENSURE(pSimulation2);
		CSimulation2& sim = *pSimulation2;

		if (!sim.GetStartupScript().empty())
		{
			XML_Element("Script");
			XML_CDATA(sim.GetStartupScript().c_str());
		}

		{
			XML_Element("Environment");

			XML_Setting("SkySet", pSkyMan->GetSkySet());
			{
				XML_Element("SunColor");
				XML_Attribute("r", pLightEnv->m_SunColor.X); // yes, it's X/Y/Z...
				XML_Attribute("g", pLightEnv->m_SunColor.Y);
				XML_Attribute("b", pLightEnv->m_SunColor.Z);
			}
			{
				XML_Element("SunElevation");
				XML_Attribute("angle", pLightEnv->m_Elevation);
			}
			{
				XML_Element("SunRotation");
				XML_Attribute("angle", pLightEnv->m_Rotation);
			}
			{
				XML_Element("TerrainAmbientColor");
				XML_Attribute("r", pLightEnv->m_TerrainAmbientColor.X);
				XML_Attribute("g", pLightEnv->m_TerrainAmbientColor.Y);
				XML_Attribute("b", pLightEnv->m_TerrainAmbientColor.Z);
			}
			{
				XML_Element("UnitsAmbientColor");
				XML_Attribute("r", pLightEnv->m_UnitsAmbientColor.X);
				XML_Attribute("g", pLightEnv->m_UnitsAmbientColor.Y);
				XML_Attribute("b", pLightEnv->m_UnitsAmbientColor.Z);
			}
			{
				XML_Element("Fog");
				XML_Setting("FogFactor", pLightEnv->m_FogFactor);
				XML_Setting("FogThickness", pLightEnv->m_FogMax);
				{
					XML_Element("FogColor");
					XML_Attribute("r", pLightEnv->m_FogColor.X);
					XML_Attribute("g", pLightEnv->m_FogColor.Y);
					XML_Attribute("b", pLightEnv->m_FogColor.Z);
				}
			}

			{
				XML_Element("Water");
				{
					XML_Element("WaterBody");
					CmpPtr<ICmpWaterManager> cmpWaterManager(sim, SYSTEM_ENTITY);
					ENSURE(cmpWaterManager);
					XML_Setting("Type", pWaterMan->m_WaterType);
					{
						XML_Element("Color");
						XML_Attribute("r", pWaterMan->m_WaterColor.r);
						XML_Attribute("g", pWaterMan->m_WaterColor.g);
						XML_Attribute("b", pWaterMan->m_WaterColor.b);
					}
					{
						XML_Element("Tint");
						XML_Attribute("r", pWaterMan->m_WaterTint.r);
						XML_Attribute("g", pWaterMan->m_WaterTint.g);
						XML_Attribute("b", pWaterMan->m_WaterTint.b);
					}
					XML_Setting("Height", cmpWaterManager->GetExactWaterLevel(0, 0));
					XML_Setting("Waviness", pWaterMan->m_Waviness);
					XML_Setting("Murkiness", pWaterMan->m_Murkiness);
					XML_Setting("WindAngle", pWaterMan->m_WindAngle);
				}
			}

			{
				XML_Element("Postproc");
				{
					XML_Setting("Brightness", pLightEnv->m_Brightness);
					XML_Setting("Contrast", pLightEnv->m_Contrast);
					XML_Setting("Saturation", pLightEnv->m_Saturation);
					XML_Setting("Bloom", pLightEnv->m_Bloom);
					XML_Setting("PostEffect", pPostproc->GetPostEffect());
				}
			}
		}

		{
			XML_Element("Camera");

			{
				XML_Element("Position");
				CVector3D pos = pCamera->m_Orientation.GetTranslation();
				XML_Attribute("x", pos.X);
				XML_Attribute("y", pos.Y);
				XML_Attribute("z", pos.Z);
			}

			CVector3D in = pCamera->m_Orientation.GetIn();
			// Convert to spherical coordinates
			float rotation = atan2(in.X, in.Z);
			float declination = atan2(sqrt(in.X*in.X + in.Z*in.Z), in.Y) - (float)M_PI/2;

			{
				XML_Element("Rotation");
				XML_Attribute("angle", rotation);
			}
			{
				XML_Element("Declination");
				XML_Attribute("angle", declination);
			}
		}

		{
			std::string settings = sim.GetMapSettingsString();
			if (!settings.empty())
			{
				XML_Element("ScriptSettings");
				XML_CDATA(("\n" + settings + "\n").c_str());
			}
		}

		{
			XML_Element("Entities");

			CmpPtr<ICmpTemplateManager> cmpTemplateManager(sim, SYSTEM_ENTITY);
			ENSURE(cmpTemplateManager);

			// This will probably need to be changed in the future, but for now we'll
			// just save all entities that have a position
			CSimulation2::InterfaceList ents = sim.GetEntitiesWithInterface(IID_Position);
			for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
			{
				entity_id_t ent = it->first;

				// Don't save local entities (placement previews etc)
				if (ENTITY_IS_LOCAL(ent))
					continue;

				XML_Element("Entity");
				XML_Attribute("uid", ent);

				XML_Setting("Template", cmpTemplateManager->GetCurrentTemplateName(ent));

				CmpPtr<ICmpOwnership> cmpOwnership(sim, ent);
				if (cmpOwnership)
					XML_Setting("Player", (int)cmpOwnership->GetOwner());

				CmpPtr<ICmpPosition> cmpPosition(sim, ent);
				if (cmpPosition)
				{
					CFixedVector3D pos;
					if (cmpPosition->IsInWorld())
						pos = cmpPosition->GetPosition();

					CFixedVector3D rot = cmpPosition->GetRotation();
					{
						XML_Element("Position");
						XML_Attribute("x", pos.X);
						XML_Attribute("z", pos.Z);
						// TODO: height offset etc
					}
					{
						XML_Element("Orientation");
						XML_Attribute("y", rot.Y);
						// TODO: X, Z maybe
					}
				}

				CmpPtr<ICmpObstruction> cmpObstruction(sim, ent);
				if (cmpObstruction)
				{
					// TODO: Currently only necessary because Atlas
					// does not set up control groups for its walls.
					cmpObstruction->ResolveFoundationCollisions();

					entity_id_t group = cmpObstruction->GetControlGroup();
					entity_id_t group2 = cmpObstruction->GetControlGroup2();

					// Don't waste space writing the default control groups.
					if (group != ent || group2 != INVALID_ENTITY)
					{
						XML_Element("Obstruction");
						if (group != ent)
							XML_Attribute("group", group);
						if (group2 != INVALID_ENTITY)
							XML_Attribute("group2", group2);
					}
				}

				CmpPtr<ICmpVisual> cmpVisual(sim, ent);
				if (cmpVisual)
				{
					u32 seed = cmpVisual->GetActorSeed();
					if (seed != (u32)ent)
					{
						XML_Element("Actor");
						XML_Attribute("seed", seed);
					}
					// TODO: variation/selection strings
				}
			}
		}

		const std::map<CStrW, CCinemaPath>& paths = pCinema->GetAllPaths();
		std::map<CStrW, CCinemaPath>::const_iterator it = paths.begin();

		{
			XML_Element("Paths");

			for ( ; it != paths.end(); ++it )
			{
				fixed timescale = it->second.GetTimescale();
				const std::vector<SplineData>& nodes = it->second.GetAllNodes();
				const std::vector<SplineData>& target_nodes = it->second.GetTargetSpline().GetAllNodes();
				const CCinemaData* data = it->second.GetData();
				
				XML_Element("Path");
				XML_Attribute("name", data->m_Name);
				XML_Attribute("timescale", timescale);
				XML_Attribute("orientation", data->m_Orientation);
				XML_Attribute("mode", data->m_Mode);
				XML_Attribute("style", data->m_Style);

				fixed last_target = fixed::Zero();
				for (size_t i = 0, j = 0; i < nodes.size(); ++i)
				{
					XML_Element("Node");
					fixed distance = i > 0 ? nodes[i - 1].Distance : fixed::Zero();
					last_target += distance;

					XML_Attribute("deltatime", distance);

					{
						XML_Element("Position");
						XML_Attribute("x", nodes[i].Position.X);
						XML_Attribute("y", nodes[i].Position.Y);
						XML_Attribute("z", nodes[i].Position.Z);
					}

					{
						XML_Element("Rotation");
						XML_Attribute("x", nodes[i].Rotation.X);
						XML_Attribute("y", nodes[i].Rotation.Y);
						XML_Attribute("z", nodes[i].Rotation.Z);
					}

					if (j >= target_nodes.size())
						continue;

					fixed target_distance = j > 0 ? target_nodes[j - 1].Distance : fixed::Zero();

					if (target_distance > last_target)
						continue;

					{
						XML_Element("Target");
						XML_Attribute("x", target_nodes[j].Position.X);
						XML_Attribute("y", target_nodes[j].Position.Y);
						XML_Attribute("z", target_nodes[j].Position.Z);
					}

					last_target = fixed::Zero();
					++j;
				}
			}
		}
	}
	if (!XML_StoreVFS(g_VFS, filename))
		LOGERROR("Failed to write map '%s'", filename.string8());
}
Example #14
0
	virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
	{
		switch (msg.GetType())
		{
		case MT_Interpolate:
		{
			if (!m_Active)
				break;

			const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);

			CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
			if (cmpPosition.null() || !cmpPosition->IsInWorld())
			{
				// If there's no position (this usually shouldn't happen), destroy the unit immediately
				GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
				break;
			}

			// Compute the depth the first time this is called
			// (This is a bit of an ugly place to do it but at least we'll be sure
			// the actor component was loaded already)
			if (m_TotalSinkDepth < 0.f)
			{
				m_TotalSinkDepth = 1.f; // minimum so we always sink at least a little

				CmpPtr<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId());
				if (!cmpVisual.null())
				{
					CBound bound = cmpVisual->GetBounds();
					m_TotalSinkDepth = std::max(m_TotalSinkDepth, bound[1].Y - bound[0].Y);
				}

				// If this is a floating unit, we want it to sink all the way under the terrain,
				// so find the difference between its current position and the terrain

				CFixedVector3D pos = cmpPosition->GetPosition();

				CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
				if (!cmpTerrain.null())
				{
					fixed ground = cmpTerrain->GetGroundLevel(pos.X, pos.Z);
					m_TotalSinkDepth += std::max(0.f, (pos.Y - ground).ToFloat());
				}
			}

			m_CurrentTime += msgData.frameTime;

			if (m_CurrentTime > m_DelayTime)
			{
				float t = m_CurrentTime - m_DelayTime;
				float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);

				cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));

				if (depth > m_TotalSinkDepth)
					GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
			}

			break;
		}
		}
	}
Example #15
0
std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, 
	const std::string& templateName, player_id_t owner, bool includeOffScreen, bool matchRank,
	bool allowEditorSelectables, bool allowFoundations)
{
	PROFILE2("PickSimilarEntities");
	CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY);
	CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);

	std::vector<entity_id_t> hitEnts;

 	const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
	for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
	{
 		entity_id_t ent = it->first;
		CEntityHandle handle = it->second->GetEntityHandle();

		// Check if this entity is only selectable in Atlas
		if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !allowEditorSelectables)
			continue;

		if (matchRank)
		{
			// Exact template name matching, optionally also allowing foundations
			std::string curTemplateName = cmpTemplateManager->GetCurrentTemplateName(ent);
			bool matches = (curTemplateName == templateName ||
			                (allowFoundations && curTemplateName.substr(0, 11) == "foundation|" && curTemplateName.substr(11) == templateName));
			if (!matches)
				continue;
		}

		// Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
		// In this case, the checking is done to avoid selecting garrisoned units
		if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN)
			continue;

		// Ignore entities not owned by 'owner'
		CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent);
		if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner))
			continue;

		// Ignore off screen entities
		if (!includeOffScreen)
		{
 			// Find the current interpolated model position.
			CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
			if (!cmpVisual)
				continue;
			CVector3D position = cmpVisual->GetPosition();

			// Reject if it's not on-screen (e.g. it's behind the camera)
			if (!camera.GetFrustum().IsPointVisible(position))
				continue;
		}

		if (!matchRank)
		{
			// Match by selection group name
			// (This is relatively expensive since it involves script calls, so do it after all other tests)
			CmpPtr<ICmpIdentity> cmpIdentity(simulation.GetSimContext(), ent);
			if (!cmpIdentity || cmpIdentity->GetSelectionGroupName() != templateName)
				continue;
		}

 		hitEnts.push_back(ent);
 	}

 	return hitEnts;
}
Example #16
0
	// Simplistic implementation of the Scene interface
	virtual void EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
	{
		if (GroundEnabled)
		{
			for (ssize_t pj = 0; pj < Terrain.GetPatchesPerSide(); ++pj)
				for (ssize_t pi = 0; pi < Terrain.GetPatchesPerSide(); ++pi)
					c->Submit(Terrain.GetPatch(pi, pj));
		}

		CmpPtr<ICmpVisual> cmpVisual(Simulation2, Entity);
		if (cmpVisual)
		{
			// add selection box outlines manually
			if (SelectionBoxEnabled)
			{
				SelectionBoxOverlay.m_Color = CColor(35/255.f, 86/255.f, 188/255.f, .75f); // pretty blue
				SelectionBoxOverlay.m_Thickness = 2;

				SimRender::ConstructBoxOutline(cmpVisual->GetSelectionBox(), SelectionBoxOverlay);
				c->Submit(&SelectionBoxOverlay);
			}

			// add origin axis thingy
			if (AxesMarkerEnabled)
			{
				CMatrix3D worldSpaceAxes;
				// offset from the ground a little bit to prevent fighting with the floor texture (also note: SetTranslation
				// sets the identity 3x3 transformation matrix, which are the world axes)
				worldSpaceAxes.SetTranslation(cmpVisual->GetPosition() + CVector3D(0, 0.02f, 0));
				SimRender::ConstructAxesMarker(worldSpaceAxes, AxesMarkerOverlays[0], AxesMarkerOverlays[1], AxesMarkerOverlays[2]);

				c->Submit(&AxesMarkerOverlays[0]);
				c->Submit(&AxesMarkerOverlays[1]);
				c->Submit(&AxesMarkerOverlays[2]);
			}

			// add prop point overlays
			if (PropPointsMode > 0 && Props.size() > 0)
			{
				PropPointOverlays.clear(); // doesn't clear capacity, but should be ok since the number of prop points is usually pretty limited
				for (size_t i = 0; i < Props.size(); ++i)
				{
					CModel::Prop& prop = Props[i];
					if (prop.m_Model) // should always be the case
					{
						// prop point positions are automatically updated during animations etc. by CModel::ValidatePosition
						const CMatrix3D& propCoordSystem = prop.m_Model->GetTransform();
						
						SOverlayLine pointGimbal;
						pointGimbal.m_Color = CColor(1.f, 0.f, 1.f, 1.f);
						SimRender::ConstructGimbal(propCoordSystem.GetTranslation(), 0.05f, pointGimbal);
						PropPointOverlays.push_back(pointGimbal);

						if (PropPointsMode > 1)
						{
							// scale the prop axes coord system down a bit to distinguish them from the main world-space axes markers
							CMatrix3D displayCoordSystem = propCoordSystem;
							displayCoordSystem.Scale(0.5f, 0.5f, 0.5f);
							// revert translation scaling
							displayCoordSystem._14 = propCoordSystem._14;
							displayCoordSystem._24 = propCoordSystem._24;
							displayCoordSystem._34 = propCoordSystem._34;

							// construct an XYZ axes marker for the prop's coordinate system
							SOverlayLine xAxis, yAxis, zAxis;
							SimRender::ConstructAxesMarker(displayCoordSystem, xAxis, yAxis, zAxis);
							PropPointOverlays.push_back(xAxis);
							PropPointOverlays.push_back(yAxis);
							PropPointOverlays.push_back(zAxis);
						}
					}
				}

				for (size_t i = 0; i < PropPointOverlays.size(); ++i)
				{
					c->Submit(&PropPointOverlays[i]);
				}
			}
		}

		// send a RenderSubmit message so the components can submit their visuals to the renderer
		Simulation2.RenderSubmit(*c, frustum, false);
	}
Example #17
0
    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
    {
        switch (msg.GetType())
        {
        case MT_Interpolate:
        {
            if (!m_Active)
                break;

            const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);

            CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
            if (!cmpPosition || !cmpPosition->IsInWorld())
            {
                // If there's no position (this usually shouldn't happen), destroy the unit immediately
                GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
                break;
            }

            // Compute the depth the first time this is called
            // (This is a bit of an ugly place to do it but at least we'll be sure
            // the actor component was loaded already)
            if (m_TotalSinkDepth < 0.f)
            {
                m_TotalSinkDepth = 1.f; // minimum so we always sink at least a little

                CmpPtr<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId());
                if (cmpVisual)
                {
                    CBoundingBoxAligned bound = cmpVisual->GetBounds();
                    m_TotalSinkDepth = std::max(m_TotalSinkDepth, bound[1].Y - bound[0].Y);
                }

                // If this is a floating unit, we want it to sink all the way under the terrain,
                // so find the difference between its current position and the terrain

                CFixedVector3D pos = cmpPosition->GetPosition();

                CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
                if (cmpTerrain)
                {
                    fixed ground = cmpTerrain->GetGroundLevel(pos.X, pos.Z);
                    m_TotalSinkDepth += std::max(0.f, (pos.Y - ground).ToFloat());
                }

                // Sink it further down if it sinks like a ship, as it will rotate.
                if (m_ShipSink)
                    m_TotalSinkDepth += 10.f;

                // probably 0 in both cases but we'll remember it anyway.
                m_InitialXRotation = cmpPosition->GetRotation().X;
                m_InitialZRotation = cmpPosition->GetRotation().Z;
            }

            m_CurrentTime += msgData.deltaSimTime;

            if (m_CurrentTime >= m_DelayTime)
            {
                float t = m_CurrentTime - m_DelayTime;
                float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);

                if (m_ShipSink)
                {
                    // exponential sinking with tilting
                    float tilt_time = t > 5.f ? 5.f : t;
                    float tiltSink = tilt_time * tilt_time / 5.f;
                    entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5.f - tiltSink)) + (1.5f * tiltSink)) / 5.f);
                    entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3.f - tilt_time)) + (-0.3f * tilt_time)) / 3.f);
                    cmpPosition->SetXZRotation(RotX,RotZ);

                    depth = m_SinkRate * (exp(t - 1.f) - 0.54881163609f) + (m_SinkAccel * exp(t - 4.f) - 0.01831563888f);
                    if (depth < 0.f)
                        depth = 0.f;
                }

                cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));

                if (depth > m_TotalSinkDepth)
                    GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
            }

            break;
        }
        }
    }