1
0
forked from 0ad/0ad

Allocated rally point flag entity on-demand instead of at initialization time. Fixes #1042.

This was SVN commit r10722.
This commit is contained in:
vts 2011-12-13 14:14:41 +00:00
parent df7d3afd64
commit 292ed1d9e0

View File

@ -101,6 +101,7 @@ protected:
bool m_SmoothPath; ///< Smooth the path before rendering? bool m_SmoothPath; ///< Smooth the path before rendering?
entity_id_t m_MarkerEntityId; ///< Entity ID of the rally point marker. Allocated when first displayed. entity_id_t m_MarkerEntityId; ///< Entity ID of the rally point marker. Allocated when first displayed.
player_id_t m_LastOwner; ///< Last seen owner of this entity (used to keep track of ownership changes).
std::wstring m_MarkerTemplate; ///< Template name of the rally point marker. std::wstring m_MarkerTemplate; ///< Template name of the rally point marker.
/// Marker connector line settings (loaded from XML) /// Marker connector line settings (loaded from XML)
@ -230,8 +231,7 @@ public:
break; break;
case MT_OwnershipChanged: case MT_OwnershipChanged:
{ {
CreateMarker(); // change marker actor to new owner's civilization UpdateMarker(); // update marker variation to new player's civilization
UpdateMarkerPosition(); // the new marker doesn't have a position yet, so let's make sure to update it
} }
break; break;
case MT_TurnStart: case MT_TurnStart:
@ -247,7 +247,7 @@ public:
if (m_RallyPoint != pos) if (m_RallyPoint != pos)
{ {
m_RallyPoint = pos; m_RallyPoint = pos;
UpdateMarkerPosition(); UpdateMarker(); // reposition the marker
RecomputeRallyPointPath(); RecomputeRallyPointPath();
} }
} }
@ -259,7 +259,7 @@ public:
m_Displayed = displayed; m_Displayed = displayed;
// move the marker out of oblivion and back into the real world, or vice-versa // move the marker out of oblivion and back into the real world, or vice-versa
UpdateMarkerPosition(); UpdateMarker();
// Check for changes to the SoD and update the overlay lines accordingly. We need to do this here because this method // Check for changes to the SoD and update the overlay lines accordingly. We need to do this here because this method
// only takes effect when the display flag is active; we need to pick up changes to the SoD that might have occurred // only takes effect when the display flag is active; we need to pick up changes to the SoD that might have occurred
@ -279,17 +279,13 @@ private:
} }
/** /**
* (Re)creates the rally point marker entity. Called upon initialization and whenever the ownership of this entity changes, as * Repositions the rally point marker; moves it outside of the world (ie. hides it), or positions it at the currently set rally
* the marker actor depends on the owner's civilization. If a marker entity already exists, it will be destroyed first. * point. Also updates the actor's variation according to the entity's current owning player's civilization.
*/ *
void CreateMarker();
/**
* Repositions the rally point marker; moves it outside of the world (ie. hides it), or positions it at the rally point.
* Should be called whenever either the position of the rally point changes (including whether it is set or not), or the display * Should be called whenever either the position of the rally point changes (including whether it is set or not), or the display
* flag changes. * flag changes, or the ownership of the entity changes.
*/ */
void UpdateMarkerPosition(); void UpdateMarker();
/** /**
* Recomputes the full path from this entity to the rally point, and does all the necessary post-processing to make it prettier. * Recomputes the full path from this entity to the rally point, and does all the necessary post-processing to make it prettier.
@ -359,6 +355,7 @@ void CCmpRallyPointRenderer::Init(const CParamNode& paramNode)
{ {
m_Displayed = false; m_Displayed = false;
m_SmoothPath = true; m_SmoothPath = true;
m_LastOwner = INVALID_PLAYER;
m_MarkerEntityId = INVALID_ENTITY; m_MarkerEntityId = INVALID_ENTITY;
m_EnableDebugNodeOverlay = false; m_EnableDebugNodeOverlay = false;
@ -406,62 +403,27 @@ void CCmpRallyPointRenderer::Init(const CParamNode& paramNode)
texturePropsMask.SetMaxAnisotropy(4.f); texturePropsMask.SetMaxAnisotropy(4.f);
m_TextureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask); m_TextureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask);
} }
// ---------------------------------------------------------------------------------------------
CreateMarker(); // TODO: evaluate how much load this puts on the entity IDs, if it's too high then we can do this on-demand)
} }
void CCmpRallyPointRenderer::CreateMarker() void CCmpRallyPointRenderer::UpdateMarker()
{
CComponentManager& componentMgr = GetSimContext().GetComponentManager();
// if a marker entity already exists, kill it first
if (m_MarkerEntityId != INVALID_ENTITY)
{
CmpPtr<ICmpPosition> markerCmpPosition(GetSimContext(), m_MarkerEntityId);
if (!markerCmpPosition.null())
markerCmpPosition->MoveOutOfWorld();
componentMgr.DestroyComponentsSoon(m_MarkerEntityId); // queue entity for destruction
m_MarkerEntityId = INVALID_ENTITY; // make sure any code below doesn't try to access the soon-to-be-destroyed entity anymore
}
// allocate a new entity for the marker
if (!m_MarkerTemplate.empty())
{
m_MarkerEntityId = componentMgr.AllocateNewLocalEntity();
if (m_MarkerEntityId != INVALID_ENTITY)
m_MarkerEntityId = componentMgr.AddEntity(m_MarkerTemplate, m_MarkerEntityId);
}
// set rally point flag selection based on player civilization
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
if (!cmpOwnership.null())
{
player_id_t ownerId = cmpOwnership->GetOwner();
if (ownerId != INVALID_PLAYER)
{
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
ENSURE(!cmpPlayerManager.null());
CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(ownerId));
if (!cmpPlayer.null())
{
CmpPtr<ICmpVisual> cmpVisualActor(GetSimContext(), m_MarkerEntityId);
if (!cmpVisualActor.null())
{
cmpVisualActor->SetUnitEntitySelection(CStrW(cmpPlayer->GetCiv()).ToUTF8());
}
}
}
}
}
void CCmpRallyPointRenderer::UpdateMarkerPosition()
{ {
if (m_MarkerEntityId == INVALID_ENTITY) if (m_MarkerEntityId == INVALID_ENTITY)
return; // there is no valid marker entity, no use trying to position it {
// no marker exists yet, create one first
CComponentManager& componentMgr = GetSimContext().GetComponentManager();
// allocate a new entity for the marker
if (!m_MarkerTemplate.empty())
{
m_MarkerEntityId = componentMgr.AllocateNewLocalEntity();
if (m_MarkerEntityId != INVALID_ENTITY)
m_MarkerEntityId = componentMgr.AddEntity(m_MarkerTemplate, m_MarkerEntityId);
}
}
// the marker entity should be valid at this point, otherwise something went wrong trying to allocate it
if (m_MarkerEntityId == INVALID_ENTITY)
LOGERROR(L"Failed to create rally point marker entity");
CmpPtr<ICmpPosition> markerCmpPosition(GetSimContext(), m_MarkerEntityId); CmpPtr<ICmpPosition> markerCmpPosition(GetSimContext(), m_MarkerEntityId);
if (!markerCmpPosition.null()) if (!markerCmpPosition.null())
@ -475,6 +437,32 @@ void CCmpRallyPointRenderer::UpdateMarkerPosition()
markerCmpPosition->MoveOutOfWorld(); // hide it markerCmpPosition->MoveOutOfWorld(); // hide it
} }
} }
// set rally point flag selection based on player civilization
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
if (!cmpOwnership.null())
{
player_id_t ownerId = cmpOwnership->GetOwner();
if (ownerId != INVALID_PLAYER && ownerId != m_LastOwner)
{
m_LastOwner = ownerId;
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
// cmpPlayerManager should not be null as long as this method is called on-demand instead of at Init() time
// (we can't rely on component initialization order in Init())
if (!cmpPlayerManager.null())
{
CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(ownerId));
if (!cmpPlayer.null())
{
CmpPtr<ICmpVisual> cmpVisualActor(GetSimContext(), m_MarkerEntityId);
if (!cmpVisualActor.null())
{
cmpVisualActor->SetUnitEntitySelection(CStrW(cmpPlayer->GetCiv()).ToUTF8());
}
}
}
}
}
} }
void CCmpRallyPointRenderer::RecomputeRallyPointPath() void CCmpRallyPointRenderer::RecomputeRallyPointPath()
@ -745,7 +733,6 @@ void CCmpRallyPointRenderer::UpdateOverlayLines()
m_VisibilitySegments = newVisibilitySegments; // save the new visibility segments to compare against next time m_VisibilitySegments = newVisibilitySegments; // save the new visibility segments to compare against next time
ConstructOverlayLines(); ConstructOverlayLines();
} }
} }
void CCmpRallyPointRenderer::FixFootprintWaypoints(std::vector<CVector2D>& coords, CmpPtr<ICmpPosition> cmpPosition, CmpPtr<ICmpFootprint> cmpFootprint) void CCmpRallyPointRenderer::FixFootprintWaypoints(std::vector<CVector2D>& coords, CmpPtr<ICmpPosition> cmpPosition, CmpPtr<ICmpFootprint> cmpFootprint)