LCOV - code coverage report
Current view: top level - source/simulation2/components - CCmpRallyPointRenderer.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 1 7 14.3 %
Date: 2022-06-14 00:41:00 Functions: 1 5 20.0 %

          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             : #ifndef INCLUDED_CCMPRALLYPOINTRENDERER
      19             : #define INCLUDED_CCMPRALLYPOINTRENDERER
      20             : 
      21             : #include "ICmpRallyPointRenderer.h"
      22             : 
      23             : #include "graphics/Overlay.h"
      24             : #include "graphics/TextureManager.h"
      25             : #include "ps/CLogger.h"
      26             : #include "renderer/Renderer.h"
      27             : #include "simulation2/MessageTypes.h"
      28             : #include "simulation2/components/ICmpFootprint.h"
      29             : #include "simulation2/components/ICmpIdentity.h"
      30             : #include "simulation2/components/ICmpObstructionManager.h"
      31             : #include "simulation2/components/ICmpOwnership.h"
      32             : #include "simulation2/components/ICmpPathfinder.h"
      33             : #include "simulation2/components/ICmpPlayer.h"
      34             : #include "simulation2/components/ICmpPlayerManager.h"
      35             : #include "simulation2/components/ICmpPosition.h"
      36             : #include "simulation2/components/ICmpTerrain.h"
      37             : #include "simulation2/components/ICmpVisual.h"
      38             : #include "simulation2/components/ICmpWaterManager.h"
      39             : #include "simulation2/helpers/Render.h"
      40             : #include "simulation2/helpers/Geometry.h"
      41             : #include "simulation2/system/Component.h"
      42             : 
      43             : struct SVisibilitySegment
      44             : {
      45             :     bool m_Visible;
      46             :     size_t m_StartIndex;
      47             :     size_t m_EndIndex; // Inclusive
      48             : 
      49             :     SVisibilitySegment(bool visible, size_t startIndex, size_t endIndex)
      50           0 :         : m_Visible(visible), m_StartIndex(startIndex), m_EndIndex(endIndex)
      51             :     {}
      52             : 
      53             :     bool operator==(const SVisibilitySegment& other) const
      54             :     {
      55           0 :         return m_Visible == other.m_Visible && m_StartIndex == other.m_StartIndex && m_EndIndex == other.m_EndIndex;
      56             :     }
      57             : 
      58             :     bool operator!=(const SVisibilitySegment& other) const
      59             :     {
      60             :         return !(*this == other);
      61             :     }
      62             : 
      63           0 :     bool IsSinglePoint() const
      64             :     {
      65           0 :         return m_StartIndex == m_EndIndex;
      66             :     }
      67             : };
      68             : 
      69           0 : class CCmpRallyPointRenderer final : public ICmpRallyPointRenderer
      70             : {
      71             : public:
      72             :     static std::string GetSchema();
      73             :     static void ClassInit(CComponentManager& componentManager);
      74             : 
      75             :     void Init(const CParamNode& paramNode) override;
      76             :     void Deinit() override;
      77             : 
      78             :     void Serialize(ISerializer& UNUSED(serialize)) override;
      79             :     void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) override;
      80             : 
      81             :     void HandleMessage(const CMessage& msg, bool UNUSED(global)) override;
      82             : 
      83             :     /*
      84             :      * Must be called whenever m_Displayed or the size of m_RallyPoints change,
      85             :      * to determine whether we need to respond to render messages.
      86             :      */
      87             :     virtual void UpdateMessageSubscriptions();
      88             : 
      89             :     void AddPosition_wrapper(const CFixedVector2D& pos) override;
      90             : 
      91             :     void SetPosition(const CFixedVector2D& pos) override;
      92             : 
      93             :     void UpdatePosition(u32 rallyPointId, const CFixedVector2D& pos) override;
      94             : 
      95             :     void SetDisplayed(bool displayed) override;
      96             : 
      97             :     void Reset() override;
      98             : 
      99             :     void UpdateColor() override;
     100             : 
     101             :     /**
     102             :      * Returns true if at least one display rally point is set; i.e., if we have a point to render our marker/line at.
     103             :      */
     104             :     bool IsSet() const override;
     105             : 
     106           0 :     DEFAULT_COMPONENT_ALLOCATOR(RallyPointRenderer)
     107             : 
     108             : protected:
     109             :     /**
     110             :      * Display position of the rally points. Note that this are merely the display positions; they not necessarily the same as the
     111             :      * actual positions used in the simulation at any given time. In particular, we need this separate copy to support
     112             :      * instantaneously rendering the rally point markers/lines when the user sets one in-game (instead of waiting until the
     113             :      * network-synchronization code sets it on the RallyPoint component, which might take up to half a second).
     114             :      */
     115             :     std::vector<CFixedVector2D> m_RallyPoints;
     116             :     /**
     117             :      * Full path to the rally points as returned by the pathfinder, with some post-processing applied to reduce zig/zagging.
     118             :      */
     119             :     std::vector<std::vector<CVector2D> > m_Path;
     120             :     /**
     121             :      * Visibility segments of the rally point paths; splits the path into SoD/non-SoD segments.
     122             :      */
     123             :     std::vector<std::vector<SVisibilitySegment> > m_VisibilitySegments;
     124             :     /**
     125             :      * Should we render the rally points and the path lines? (set from JS when e.g. the unit is selected/deselected)
     126             :      */
     127             :     bool m_Displayed;
     128             :     /**
     129             :      * Smooth the path before rendering?
     130             :      */
     131             :     bool m_SmoothPath;
     132             :     /**
     133             :      * Entity IDs of the rally point markers.
     134             :      */
     135             :     std::vector<entity_id_t> m_MarkerEntityIds;
     136             : 
     137             :     size_t m_LastMarkerCount;
     138             :     /**
     139             :      * Last seen owner of this entity (used to keep track of ownership changes).
     140             :      */
     141             :     player_id_t m_LastOwner;
     142             :     /**
     143             :      * Template name of the rally point markers.
     144             :      */
     145             :     std::wstring m_MarkerTemplate;
     146             : 
     147             :     /**
     148             :      * Marker connector line settings (loaded from XML)
     149             :      */
     150             :     float m_LineThickness;
     151             :     CColor m_LineColor;
     152             :     CColor m_LineDashColor;
     153             :     SOverlayTexturedLine::LineCapType m_LineStartCapType;
     154             :     SOverlayTexturedLine::LineCapType m_LineEndCapType;
     155             :     std::wstring m_LineTexturePath;
     156             :     std::wstring m_LineTextureMaskPath;
     157             :     /**
     158             :      * Pathfinder passability class to use for computing the (long-range) marker line path.
     159             :      */
     160             :     std::string m_LinePassabilityClass;
     161             : 
     162             :     CTexturePtr m_Texture;
     163             :     CTexturePtr m_TextureMask;
     164             : 
     165             :     /**
     166             :      * Textured overlay lines to be used for rendering the marker line. There can be multiple because we may need to render
     167             :      * dashes for segments that are inside the SoD.
     168             :      */
     169             :     std::vector<std::vector<SOverlayTexturedLine> > m_TexturedOverlayLines;
     170             : 
     171             :     /**
     172             :      * Draw little overlay circles to indicate where the exact path points are.
     173             :      */
     174             :     bool m_EnableDebugNodeOverlay;
     175             :     std::vector<std::vector<SOverlayLine> > m_DebugNodeOverlays;
     176             : 
     177             : private:
     178             :     /**
     179             :      * Helper function for AddPosition_wrapper and SetPosition.
     180             :      */
     181             :     void AddPosition(CFixedVector2D pos, bool recompute);
     182             : 
     183             :     /**
     184             :     * Helper function to set the line color to its owner's color.
     185             :     */
     186             :     void UpdateLineColor();
     187             : 
     188             :     /**
     189             :      * Repositions the rally point markers; moves them outside of the world (ie. hides them), or positions them at the currently
     190             :      * set rally points. Also updates the actor's variation according to the entity's current owning player's civilization.
     191             :      *
     192             :      * Should be called whenever either the position of a rally point changes (including whether it is set or not), or the display
     193             :      * flag changes, or the ownership of the entity changes.
     194             :      */
     195             :     void UpdateMarkers();
     196             : 
     197             :     /**
     198             :      * Recomputes all the full paths from this entity to the rally point and from the rally point to the next, and does all the necessary
     199             :      * post-processing to make them prettier.
     200             :      *
     201             :      * Should be called whenever all rally points' position changes.
     202             :      */
     203             :     void RecomputeAllRallyPointPaths();
     204             : 
     205             :     /**
     206             :      * Recomputes the full path for m_Path[ @p index], and does all the necessary post-processing to make it prettier.
     207             :      *
     208             :      * Should be called whenever either the starting position or the rally point's position changes.
     209             :      */
     210             :     void RecomputeRallyPointPath_wrapper(size_t index);
     211             : 
     212             :     /**
     213             :      * Recomputes the full path from this entity/the previous rally point to the next rally point, and does all the necessary
     214             :      * post-processing to make it prettier. This doesn't check if we have a valid position or if a rally point is set.
     215             :      *
     216             :      * You shouldn't need to call this method directly.
     217             :      */
     218             :     void RecomputeRallyPointPath(size_t index, CmpPtr<ICmpPosition>& cmpPosition, CmpPtr<ICmpFootprint>& cmpFootprint, CmpPtr<ICmpPathfinder> cmpPathfinder);
     219             : 
     220             :     /**
     221             :      * Checks for changes to the SoD to the previously saved state, and reconstructs the visibility segments and overlay lines to
     222             :      * match if necessary. Does nothing if the rally point lines are not currently set to be displayed, or if no rally point is set.
     223             :      */
     224             :     void UpdateOverlayLines();
     225             : 
     226             :     /**
     227             :      * Sets up all overlay lines for rendering according to the current full path and visibility segments. Splits the line into solid
     228             :      * and dashed pieces (for the SoD). Should be called whenever the SoD has changed. If no full path is currently set, this method
     229             :      * does nothing.
     230             :      */
     231             :     void ConstructAllOverlayLines();
     232             : 
     233             :     /**
     234             :      * Sets up the overlay lines for rendering according to the full path and visibility segments at @p index. Splits the line into
     235             :      * solid and dashed pieces (for the SoD). Should be called whenever the SoD of the path at @p index has changed.
     236             :      */
     237             :     void ConstructOverlayLines(size_t index);
     238             : 
     239             :     /**
     240             :      * Get the point on the footprint edge that's as close from "start" as possible.
     241             :      */
     242             :     void GetClosestsEdgePointFrom(CFixedVector2D& result, CFixedVector2D& start, CmpPtr<ICmpPosition> cmpPosition, CmpPtr<ICmpFootprint> cmpFootprint) const;
     243             : 
     244             :     /**
     245             :      * Returns a list of indices of waypoints in the current path (m_Path[index]) where the LOS visibility changes, ordered from
     246             :      * building/previous rally point to rally point. Used to construct the overlay line segments and track changes to the SoD.
     247             :      */
     248             :     void GetVisibilitySegments(std::vector<SVisibilitySegment>& out, size_t index) const;
     249             : 
     250             :     /**
     251             :      * Simplifies the path by removing waypoints that lie between two points that are visible from one another. This is primarily
     252             :      * intended to reduce some unnecessary curviness of the path; the pathfinder returns a mathematically (near-)optimal path, which
     253             :      * will happily curve and bend to reduce costs. Visually, it doesn't make sense for a rally point path to curve and bend when it
     254             :      * could just as well have gone in a straight line; that's why we have this, to make it look more natural.
     255             :      *
     256             :      * @p coords array of path coordinates to simplify
     257             :      * @p maxSegmentLinks if non-zero, indicates the maximum amount of consecutive node-to-node links that can be joined into a
     258             :      *                    single link. If this value is set to e.g. 1, then no reductions will be performed. A value of 3 means that
     259             :      *                    at most 3 consecutive node links will be joined into a single link.
     260             :      * @p floating whether to consider nodes who are under the water level as floating on top of the water
     261             :      */
     262             :     void ReduceSegmentsByVisibility(std::vector<CVector2D>& coords, unsigned maxSegmentLinks = 0, bool floating = true) const;
     263             : 
     264             :     /**
     265             :      * Helper function to GetVisibilitySegments, factored out for testing. Merges single-point segments with its neighbouring
     266             :      * segments. You should not have to call this method directly.
     267             :      */
     268             :     static void MergeVisibilitySegments(std::vector<SVisibilitySegment>& segments);
     269             : 
     270             :     void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling);
     271             : };
     272             : 
     273         230 : REGISTER_COMPONENT_TYPE(RallyPointRenderer)
     274             : 
     275             : #endif // INCLUDED_CCMPRALLYPOINTRENDERER

Generated by: LCOV version 1.13