LCOV - code coverage report
Current view: top level - source/simulation2/components - CCmpRangeOverlayRenderer.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 8 100 8.0 %
Date: 2023-01-19 00:18:29 Functions: 5 24 20.8 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "ICmpRangeOverlayRenderer.h"
      21             : 
      22             : #include "graphics/Overlay.h"
      23             : #include "graphics/TextureManager.h"
      24             : #include "renderer/Renderer.h"
      25             : #include "simulation2/MessageTypes.h"
      26             : #include "simulation2/components/ICmpOwnership.h"
      27             : #include "simulation2/components/ICmpPlayer.h"
      28             : #include "simulation2/components/ICmpPlayerManager.h"
      29             : #include "simulation2/components/ICmpPosition.h"
      30             : #include "simulation2/helpers/Render.h"
      31             : #include "simulation2/system/Component.h"
      32             : 
      33             : #include <memory>
      34             : 
      35             : class CCmpRangeOverlayRenderer final : public ICmpRangeOverlayRenderer
      36             : {
      37             : public:
      38         116 :     static void ClassInit(CComponentManager& componentManager)
      39             :     {
      40         116 :         componentManager.SubscribeToMessageType(MT_Deserialized);
      41         116 :         componentManager.SubscribeToMessageType(MT_OwnershipChanged);
      42         116 :         componentManager.SubscribeToMessageType(MT_PlayerColorChanged);
      43         116 :     }
      44             : 
      45           0 :     DEFAULT_COMPONENT_ALLOCATOR(RangeOverlayRenderer)
      46             : 
      47           0 :     CCmpRangeOverlayRenderer() : m_RangeOverlayData()
      48             :     {
      49           0 :         m_Color = CColor(0.f, 0.f, 0.f, 1.f);
      50           0 :     }
      51             : 
      52           0 :     ~CCmpRangeOverlayRenderer() = default;
      53             : 
      54         116 :     static std::string GetSchema()
      55             :     {
      56         116 :         return "<a:component type='system'/><empty/>";
      57             :     }
      58             : 
      59           0 :     void Init(const CParamNode& UNUSED(paramNode)) override
      60             :     {
      61           0 :         m_Enabled = m_LastEnabledState = false;
      62           0 :         UpdateMessageSubscriptions();
      63           0 :     }
      64             : 
      65           0 :     void Deinit() override { }
      66             : 
      67           0 :     void Serialize(ISerializer& UNUSED(serialize)) override
      68             :     {
      69           0 :     }
      70             : 
      71           0 :     void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) override
      72             :     {
      73           0 :         Init(paramNode);
      74           0 :     }
      75             : 
      76           0 :     void ResetRangeOverlays() override
      77             :     {
      78           0 :         m_RangeOverlayData.clear();
      79           0 :         UpdateMessageSubscriptions();
      80           0 :         m_Enabled = false;
      81           0 :     }
      82             : 
      83           0 :     void AddRangeOverlay(float radius, const std::string& texture, const std::string& textureMask, float thickness) override
      84             :     {
      85           0 :         if (!CRenderer::IsInitialised())
      86           0 :             return;
      87             : 
      88           0 :         SOverlayDescriptor rangeOverlayDescriptor;
      89           0 :         rangeOverlayDescriptor.m_Radius = radius;
      90           0 :         rangeOverlayDescriptor.m_LineTexture = CStrIntern(TEXTURE_BASE_PATH + texture);
      91           0 :         rangeOverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTURE_BASE_PATH + textureMask);
      92           0 :         rangeOverlayDescriptor.m_LineThickness = thickness;
      93             : 
      94           0 :         m_RangeOverlayData.push_back({
      95             :             rangeOverlayDescriptor, std::unique_ptr<SOverlayTexturedLine>()
      96             :         });
      97           0 :         m_Enabled = true;
      98           0 :         UpdateMessageSubscriptions();
      99             :     }
     100             : 
     101           0 :     void HandleMessage(const CMessage& msg, bool UNUSED(global)) override
     102             :     {
     103           0 :         switch (msg.GetType())
     104             :         {
     105           0 :         case MT_Interpolate:
     106             :         {
     107           0 :             const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
     108             : 
     109           0 :             for (RangeOverlayData& rangeOverlay : m_RangeOverlayData)
     110           0 :                 UpdateRangeOverlay(rangeOverlay, msgData.offset);
     111             : 
     112           0 :             UpdateMessageSubscriptions();
     113             : 
     114           0 :             break;
     115             :         }
     116           0 :         case MT_Deserialized:
     117             :         case MT_OwnershipChanged:
     118             :         case MT_PlayerColorChanged:
     119             :         {
     120           0 :             UpdateColor();
     121           0 :             break;
     122             :         }
     123           0 :         case MT_RenderSubmit:
     124             :         {
     125           0 :             const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg);
     126           0 :             RenderSubmit(msgData.collector, msgData.frustum, msgData.culling);
     127           0 :             break;
     128             :         }
     129             :         }
     130           0 :     }
     131             : 
     132             : private:
     133           0 :     struct RangeOverlayData {
     134             :         SOverlayDescriptor descriptor;
     135             :         std::unique_ptr<SOverlayTexturedLine> line;
     136             :     };
     137             : 
     138           0 :     void UpdateColor() override
     139             :     {
     140           0 :         CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
     141           0 :         if (!cmpOwnership)
     142           0 :             return;
     143             : 
     144           0 :         player_id_t owner = cmpOwnership->GetOwner();
     145           0 :         if (owner == INVALID_PLAYER)
     146           0 :             return;
     147             : 
     148           0 :         CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
     149           0 :         if (!cmpPlayerManager)
     150           0 :             return;
     151             : 
     152           0 :         CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(owner));
     153           0 :         if (!cmpPlayer)
     154           0 :             return;
     155             : 
     156           0 :         CColor color = cmpPlayer->GetDisplayedColor();
     157           0 :         m_Color = color;
     158             :     }
     159             : 
     160           0 :     void UpdateMessageSubscriptions()
     161             :     {
     162           0 :         if (m_Enabled == m_LastEnabledState)
     163           0 :             return;
     164             : 
     165           0 :         CComponentManager& cmpManager = GetSimContext().GetComponentManager();
     166           0 :         cmpManager.DynamicSubscriptionNonsync(MT_Interpolate, this, m_Enabled);
     167           0 :         cmpManager.DynamicSubscriptionNonsync(MT_RenderSubmit, this, m_Enabled);
     168           0 :         m_LastEnabledState = m_Enabled;
     169             :     }
     170             : 
     171           0 :     void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling)
     172             :     {
     173           0 :         if (!m_RangeOverlayData.size())
     174           0 :             return;
     175             : 
     176           0 :         for (const RangeOverlayData& rangeOverlay : m_RangeOverlayData)
     177             :         {
     178           0 :             if (!rangeOverlay.line)
     179           0 :                 continue;
     180           0 :             if (culling && !rangeOverlay.line->IsVisibleInFrustum(frustum))
     181           0 :                 continue;
     182           0 :             collector.Submit(rangeOverlay.line.get());
     183             :         }
     184             :     }
     185             : 
     186           0 :     void UpdateRangeOverlay(RangeOverlayData& rangeOverlay, const float frameOffset)
     187             :     {
     188           0 :         if (!CRenderer::IsInitialised())
     189           0 :             return;
     190             : 
     191           0 :         CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
     192           0 :         if (!cmpPosition || !cmpPosition->IsInWorld())
     193           0 :             return;
     194             : 
     195             :         float rotY;
     196           0 :         CVector2D origin;
     197           0 :         cmpPosition->GetInterpolatedPosition2D(frameOffset, origin.X, origin.Y, rotY);
     198             : 
     199           0 :         rangeOverlay.line = std::make_unique<SOverlayTexturedLine>();
     200           0 :         rangeOverlay.line->m_SimContext = &GetSimContext();
     201           0 :         rangeOverlay.line->m_Color = m_Color;
     202           0 :         rangeOverlay.line->CreateOverlayTexture(&rangeOverlay.descriptor);
     203             : 
     204           0 :         SimRender::ConstructTexturedLineCircle(*rangeOverlay.line.get(), origin, rangeOverlay.descriptor.m_Radius);
     205             :     }
     206             : 
     207             :     bool m_LastEnabledState;
     208             :     bool m_Enabled;
     209             : 
     210             :     const char* TEXTURE_BASE_PATH = "art/textures/selection/";
     211             :     std::vector<RangeOverlayData> m_RangeOverlayData;
     212             :     CColor m_Color;
     213             : };
     214             : 
     215         119 : REGISTER_COMPONENT_TYPE(RangeOverlayRenderer)

Generated by: LCOV version 1.13