diff --git a/source/simulation2/components/CCmpOverlayRenderer.cpp b/source/simulation2/components/CCmpOverlayRenderer.cpp index 39c48d02f1..f9e2e2d45a 100644 --- a/source/simulation2/components/CCmpOverlayRenderer.cpp +++ b/source/simulation2/components/CCmpOverlayRenderer.cpp @@ -19,8 +19,8 @@ #include "simulation2/system/Component.h" #include "ICmpOverlayRenderer.h" - #include "ICmpPosition.h" +#include "ICmpRangeManager.h" #include "simulation2/MessageTypes.h" @@ -32,9 +32,21 @@ class CCmpOverlayRenderer final : public ICmpOverlayRenderer { -public: - static void ClassInit(CComponentManager& UNUSED(componentManager)) + enum class LocalLosVisibility : u8 { + HIDDEN = 0, + FOGGED = 1, + VISIBLE = 2, + DIRTY = 3, + }; + static_assert(LocalLosVisibility::HIDDEN == static_cast(LosVisibility::HIDDEN), "Desynced"); + static_assert(LocalLosVisibility::FOGGED == static_cast(LosVisibility::FOGGED), "Desynced"); + static_assert(LocalLosVisibility::VISIBLE == static_cast(LosVisibility::VISIBLE), "Desynced"); + +public: + static void ClassInit(CComponentManager &componentManager) + { + componentManager.SubscribeToMessageType(MT_VisibilityChanged); } DEFAULT_COMPONENT_ALLOCATOR(OverlayRenderer) @@ -49,12 +61,16 @@ public: // Whether the sprites should be drawn (only valid between Interpolate and RenderSubmit) bool m_Enabled; + // NOT SAFE TO SERIALIZE - used to hide status bars/auras of entities invisible to the player. + // We also can't just deserialize it because annoyingly the range manager computes LOS data on deserialize... + LocalLosVisibility m_VisibilityToCurrentPlayer = LocalLosVisibility::DIRTY; + static std::string GetSchema() { return ""; } - void Init(const CParamNode& UNUSED(paramNode)) override + void Init(const CParamNode &UNUSED(paramNode)) override { } @@ -62,36 +78,43 @@ public: { } - void Serialize(ISerializer& UNUSED(serialize)) override + void Serialize(ISerializer &UNUSED(serialize)) override { // TODO: should we do anything here? // or should we expect other components to reinitialise us // after deserialization? } - void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) override + void Deserialize(const CParamNode ¶mNode, IDeserializer &UNUSED(deserialize)) override { Init(paramNode); } - void HandleMessage(const CMessage& msg, bool UNUSED(global)) override + void HandleMessage(const CMessage &msg, bool UNUSED(global)) override { switch (msg.GetType()) { case MT_Interpolate: { PROFILE("OverlayRenderer::Interpolate"); - const CMessageInterpolate& msgData = static_cast (msg); + const CMessageInterpolate &msgData = static_cast(msg); Interpolate(msgData.deltaSimTime, msgData.offset); break; } case MT_RenderSubmit: { PROFILE("OverlayRenderer::RenderSubmit"); - const CMessageRenderSubmit& msgData = static_cast (msg); + const CMessageRenderSubmit &msgData = static_cast(msg); RenderSubmit(msgData.collector); break; } + case MT_VisibilityChanged: + { + const CMessageVisibilityChanged &msgData = static_cast(msg); + if (msgData.player == GetSimContext().GetCurrentDisplayedPlayer()) + m_VisibilityToCurrentPlayer = static_cast(msgData.newVisibility); + break; + } } } @@ -115,7 +138,7 @@ public: UpdateMessageSubscriptions(); } - void AddSprite(const VfsPath& textureName, const CFixedVector2D& corner0, const CFixedVector2D& corner1, const CFixedVector3D& position, const std::string& color) override + void AddSprite(const VfsPath &textureName, const CFixedVector2D &corner0, const CFixedVector2D &corner1, const CFixedVector3D &position, const std::string &color) override { CColor colorObj(1.0f, 1.0f, 1.0f, 1.0f); if (!colorObj.ParseString(color, 1)) @@ -134,13 +157,19 @@ public: m_Sprites.push_back(sprite); m_SpriteOffsets.push_back(CVector3D(position)); + if (m_VisibilityToCurrentPlayer == LocalLosVisibility::DIRTY) + { + CmpPtr cmpRangeManager(GetSystemEntity()); + m_VisibilityToCurrentPlayer = static_cast(cmpRangeManager->GetLosVisibility(GetEntityHandle(), GetSimContext().GetCurrentDisplayedPlayer())); + } + UpdateMessageSubscriptions(); } void Interpolate(float UNUSED(frameTime), float frameOffset) { // Skip all the following computations if we have no sprites - if (m_Sprites.empty()) + if (m_Sprites.empty() || m_VisibilityToCurrentPlayer == LocalLosVisibility::HIDDEN) { m_Enabled = false; return; @@ -165,7 +194,7 @@ public: m_Enabled = true; } - void RenderSubmit(SceneCollector& collector) + void RenderSubmit(SceneCollector &collector) { if (!m_Enabled || !ICmpOverlayRenderer::m_OverrideVisible) return;