forked from mirrors/0ad
Dynamic message subscriptions.
Allow components to individually subscribe/unsubscribe to messages, instead of statically subscribing the entire component type. Use this for most Interpolate/RenderSubmit messages, to avoid the performance cost of passing those messages to a large number of components that will just ignore them anyway. On Azure Coast this reduces total time per frame by about 30% on a CPU-bound system. This was SVN commit r15400.
This commit is contained in:
@@ -53,14 +53,10 @@ class CCmpSelectable : public ICmpSelectable
|
||||
public:
|
||||
static void ClassInit(CComponentManager& componentManager)
|
||||
{
|
||||
componentManager.SubscribeToMessageType(MT_Interpolate);
|
||||
componentManager.SubscribeToMessageType(MT_RenderSubmit);
|
||||
componentManager.SubscribeToMessageType(MT_OwnershipChanged);
|
||||
componentManager.SubscribeToMessageType(MT_PositionChanged);
|
||||
componentManager.SubscribeToMessageType(MT_TerrainChanged);
|
||||
componentManager.SubscribeToMessageType(MT_WaterChanged);
|
||||
// TODO: it'd be nice if we didn't get these messages except in the rare
|
||||
// cases where we're actually drawing a selection highlight
|
||||
}
|
||||
|
||||
DEFAULT_COMPONENT_ALLOCATOR(Selectable)
|
||||
@@ -148,6 +144,10 @@ public:
|
||||
m_OverlayDescriptor.m_LineTextureMask = CStrIntern(textureBasePath + outlineNode.GetChild("LineTextureMask").ToUTF8());
|
||||
m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat();
|
||||
}
|
||||
|
||||
m_EnabledInterpolate = false;
|
||||
m_EnabledRenderSubmit = false;
|
||||
UpdateMessageSubscriptions();
|
||||
}
|
||||
|
||||
virtual void Deinit() { }
|
||||
@@ -200,11 +200,14 @@ public:
|
||||
m_FadeBaselineAlpha = m_Color.a;
|
||||
m_FadeDeltaAlpha = alpha - m_FadeBaselineAlpha;
|
||||
m_FadeProgress = 0.f;
|
||||
|
||||
UpdateMessageSubscriptions();
|
||||
}
|
||||
|
||||
virtual void SetVisibility(bool visible)
|
||||
{
|
||||
m_Visible = visible;
|
||||
UpdateMessageSubscriptions();
|
||||
}
|
||||
|
||||
virtual bool IsEditorOnly()
|
||||
@@ -230,6 +233,16 @@ public:
|
||||
/// Explicitly invalidates the static overlay.
|
||||
void InvalidateStaticOverlay();
|
||||
|
||||
/**
|
||||
* Subscribe/unsubscribe to MT_Interpolate, MT_RenderSubmit, depending on
|
||||
* whether we will do any actual work when receiving them. (This is to avoid
|
||||
* the performance cost of receiving messages in the typical case when the
|
||||
* entity is not selected.)
|
||||
*
|
||||
* Must be called after changing m_Visible, m_FadeDeltaAlpha, m_Color.a
|
||||
*/
|
||||
void UpdateMessageSubscriptions();
|
||||
|
||||
private:
|
||||
SOverlayDescriptor m_OverlayDescriptor;
|
||||
SOverlayTexturedLine* m_BuildingOverlay;
|
||||
@@ -238,6 +251,9 @@ private:
|
||||
SOverlayLine* m_DebugBoundingBoxOverlay;
|
||||
SOverlayLine* m_DebugSelectionBoxOverlay;
|
||||
|
||||
bool m_EnabledInterpolate;
|
||||
bool m_EnabledRenderSubmit;
|
||||
|
||||
// Whether the selectable will be rendered.
|
||||
bool m_Visible;
|
||||
// Whether the entity is only selectable in Atlas editor
|
||||
@@ -272,6 +288,8 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
||||
{
|
||||
case MT_Interpolate:
|
||||
{
|
||||
PROFILE3("Selectable::Interpolate");
|
||||
|
||||
const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
|
||||
|
||||
if (m_FadeDeltaAlpha != 0.f)
|
||||
@@ -297,6 +315,8 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
||||
if (m_Color.a > 0)
|
||||
UpdateDynamicOverlay(msgData.offset);
|
||||
|
||||
UpdateMessageSubscriptions();
|
||||
|
||||
break;
|
||||
}
|
||||
case MT_OwnershipChanged:
|
||||
@@ -333,6 +353,8 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
||||
}
|
||||
case MT_RenderSubmit:
|
||||
{
|
||||
PROFILE3("Selectable::RenderSubmit");
|
||||
|
||||
const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg);
|
||||
RenderSubmit(msgData.collector);
|
||||
|
||||
@@ -341,6 +363,30 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
||||
}
|
||||
}
|
||||
|
||||
void CCmpSelectable::UpdateMessageSubscriptions()
|
||||
{
|
||||
bool needInterpolate = false;
|
||||
bool needRenderSubmit = false;
|
||||
|
||||
if (m_FadeDeltaAlpha != 0.f || m_Color.a > 0)
|
||||
needInterpolate = true;
|
||||
|
||||
if (m_Visible && m_Color.a > 0)
|
||||
needRenderSubmit = true;
|
||||
|
||||
if (needInterpolate != m_EnabledInterpolate)
|
||||
{
|
||||
GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_Interpolate, this, needInterpolate);
|
||||
m_EnabledInterpolate = needInterpolate;
|
||||
}
|
||||
|
||||
if (needRenderSubmit != m_EnabledRenderSubmit)
|
||||
{
|
||||
GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, needRenderSubmit);
|
||||
m_EnabledRenderSubmit = needRenderSubmit;
|
||||
}
|
||||
}
|
||||
|
||||
void CCmpSelectable::InvalidateStaticOverlay()
|
||||
{
|
||||
SAFE_DELETE(m_BuildingOverlay);
|
||||
|
||||
Reference in New Issue
Block a user