18 #include "precompiled.h"
59 return !(*
this == other);
136 "<a:help>Displays a rally point marker where created units will gather when spawned</a:help>"
138 "<MarkerTemplate>special/rallypoint</MarkerTemplate>"
139 "<LineThickness>0.75</LineThickness>"
140 "<LineStartCap>round</LineStartCap>"
141 "<LineEndCap>square</LineEndCap>"
142 "<LineColour r='20' g='128' b='240'></LineColour>"
143 "<LineDashColour r='158' g='11' b='15'></LineDashColour>"
144 "<LineCostClass>default</LineCostClass>"
145 "<LinePassabilityClass>default</LinePassabilityClass>"
147 "<element name='MarkerTemplate' a:help='Template name for the rally point marker entity (typically a waypoint flag actor)'>"
150 "<element name='LineTexture' a:help='Texture file to use for the rally point line'>"
153 "<element name='LineTextureMask' a:help='Texture mask to indicate where overlay colors are to be applied (see LineColour and LineDashColour)'>"
156 "<element name='LineThickness' a:help='Thickness of the marker line connecting the entity to the rally point marker'>"
157 "<data type='decimal'/>"
159 "<element name='LineColour'>"
160 "<attribute name='r'>"
161 "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
163 "<attribute name='g'>"
164 "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
166 "<attribute name='b'>"
167 "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
170 "<element name='LineDashColour'>"
171 "<attribute name='r'>"
172 "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
174 "<attribute name='g'>"
175 "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
177 "<attribute name='b'>"
178 "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
181 "<element name='LineStartCap'>"
183 "<value a:help='Abrupt line ending; line endings are not closed'>flat</value>"
184 "<value a:help='Semi-circular line end cap'>round</value>"
185 "<value a:help='Sharp, pointy line end cap'>sharp</value>"
186 "<value a:help='Square line end cap'>square</value>"
189 "<element name='LineEndCap'>"
191 "<value a:help='Abrupt line ending; line endings are not closed'>flat</value>"
192 "<value a:help='Semi-circular line end cap'>round</value>"
193 "<value a:help='Sharp, pointy line end cap'>sharp</value>"
194 "<value a:help='Square line end cap'>square</value>"
197 "<element name='LinePassabilityClass' a:help='The pathfinder passability class to use for computing the rally point marker line path'>"
200 "<element name='LineCostClass' a:help='The pathfinder cost class to use for computing the rally point marker line path'>"
420 m_LastMarkerCount = 0;
421 m_EnableDebugNodeOverlay =
false;
426 m_MarkerTemplate = paramNode.GetChild(
"MarkerTemplate").ToString();
438 lineDashColor.GetChild(
"@r").ToInt()/255.f,
439 lineDashColor.GetChild(
"@g").ToInt()/255.f,
440 lineDashColor.GetChild(
"@b").ToInt()/255.f,
444 m_LineThickness = paramNode.GetChild(
"LineThickness").ToFixed().ToFloat();
445 m_LineTexturePath = paramNode.GetChild(
"LineTexture").ToString();
446 m_LineTextureMaskPath = paramNode.GetChild(
"LineTextureMask").ToString();
449 m_LineCostClass = paramNode.GetChild(
"LineCostClass").ToUTF8();
450 m_LinePassabilityClass = paramNode.GetChild(
"LinePassabilityClass").ToUTF8();
458 texturePropsBase.
SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE);
460 m_Texture =
g_Renderer.GetTextureManager().CreateTexture(texturePropsBase);
463 texturePropsMask.
SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE);
465 m_TextureMask =
g_Renderer.GetTextureManager().CreateTexture(texturePropsMask);
493 LOGERROR(L
"Failed to create rally point marker entity");
496 if (markerCmpPosition)
519 if (cmpPlayerManager)
552 if (!cmpPosition || !cmpPosition->
IsInWorld())
570 if (!cmpPosition || !cmpPosition->
IsInWorld())
581 while (index >=
m_Path.size())
583 std::vector<CVector2D> tmp;
590 std::deque<SVisibilitySegment> tmp;
613 std::vector<Waypoint>& waypoints = path.
m_Waypoints;
642 Waypoint& lastWaypoint = waypoints.back();
643 if (lastWaypoint.
x != goal.
x || lastWaypoint.
z != goal.
z)
647 for (
size_t i = 0; i < waypoints.size(); ++i)
648 m_Path[index].push_back(
CVector2D(waypoints[i].x.ToFloat(), waypoints[i].z.ToFloat()));
661 for(
size_t i =
m_Path[index].size() - 2; i > 0; --i)
665 if (index == 0 && cmpFootprint)
677 std::vector<SOverlayLine> tmp;
686 for (
size_t j = 0; j <
m_Path[index].size(); ++j)
716 for (
size_t i = 0; i <
m_Path.size(); ++i)
727 std::vector<SOverlayTexturedLine> tmp;
732 if (
m_Path[index].size() < 2)
776 std::vector<CVector2D> straightLine;
784 float maxDashSize = 3.f;
785 float maxClearSize = 3.f;
787 float dashSize = maxDashSize;
788 float clearSize = maxClearSize;
789 float pairDashRatio = (dashSize / (dashSize + clearSize));
795 int numFitUnmodified = floor(distance/(dashSize + clearSize));
796 float remainderDistance = distance - (numFitUnmodified * (dashSize + clearSize));
805 numFitUnmodified = std::max(1, numFitUnmodified);
807 float pairwiseLengthDifference = (remainderDistance - maxDashSize)/numFitUnmodified;
808 dashSize += pairDashRatio * pairwiseLengthDifference;
809 clearSize += (1 - pairDashRatio) * pairwiseLengthDifference;
818 for (
size_t i=0; i < numDashes; i++)
835 ENSURE(dashEndIndex > dashStartIndex);
837 for (
size_t n = dashStartIndex; n < dashEndIndex; n++)
854 std::vector<SOverlayLine> tmp;
857 for (
size_t j = 0; j <
m_Path[index].size(); ++j)
877 std::deque<std::deque<SVisibilitySegment> > newVisibilitySegments;
878 for (
size_t i = 0; i <
m_Path.size(); ++i)
880 std::deque<SVisibilitySegment> tmp;
881 newVisibilitySegments.push_back(tmp);
915 entity_pos_t footprintSize0, footprintSize1, footprintHeight;
917 cmpFootprint->
GetShape(footprintShape, footprintSize0, footprintSize1, footprintHeight);
924 switch (footprintShape)
943 for(
int i = (
int)(coords.size() - 1); i >= 0; i--)
948 coords.erase(coords.begin() + i);
959 CVector2D footprintEdge((center.
X + footprintEdgePoint.
X).ToFloat(), (center.
Y + footprintEdgePoint.
Y).ToFloat());
960 coords.push_back(footprintEdge);
968 for(
int i = (
int)(coords.size() - 1); i >= 0; i--)
972 if (pointDistance <= footprintSize0)
974 coords.erase(coords.begin() + i);
984 CVector2D centerToLast(coords.back() - centerVec2D);
985 coords.push_back(centerVec2D + (centerToLast.Normalized() * footprintSize0.
ToFloat()));
996 ENSURE(cmpPathFinder && cmpTerrain && cmpWaterManager);
998 if (coords.size() < 3)
1005 std::vector<CVector2D> newCoords;
1010 newCoords.push_back(coords[0]);
1012 size_t baseNodeIdx = 0;
1013 size_t curNodeIdx = 1;
1022 baseNodeY = cmpTerrain->
GetExactGroundLevel(coords[baseNodeIdx].X, coords[baseNodeIdx].Y);
1024 baseNodeY = std::max(baseNodeY, cmpWaterManager->
GetExactWaterLevel(coords[baseNodeIdx].X, coords[baseNodeIdx].Y));
1026 while (curNodeIdx < coords.size())
1028 ENSURE(curNodeIdx > baseNodeIdx);
1032 float curNodeY = cmpTerrain->
GetExactGroundLevel(coords[curNodeIdx].X, coords[curNodeIdx].Y);
1034 curNodeY = std::max(curNodeY, cmpWaterManager->
GetExactWaterLevel(coords[curNodeIdx].X, coords[curNodeIdx].Y));
1037 bool curNodeVisible = cmpPathFinder->
CheckMovement(obstructionFilter, baseNodeX, baseNodeZ, curNodeX, curNodeZ, lineRadius, passabilityClass);
1041 curNodeVisible = curNodeVisible && (fabsf(curNodeY - baseNodeY) < 3.f);
1042 if (maxSegmentLinks > 0)
1044 curNodeVisible = curNodeVisible && ((curNodeIdx - baseNodeIdx) <= maxSegmentLinks);
1046 if (!curNodeVisible)
1053 if (curNodeIdx > baseNodeIdx + 1)
1055 baseNodeIdx = curNodeIdx - 1;
1060 baseNodeIdx = curNodeIdx;
1064 newCoords.push_back(coords[baseNodeIdx]);
1069 baseNodeY = cmpTerrain->
GetExactGroundLevel(coords[baseNodeIdx].X, coords[baseNodeIdx].Y);
1071 baseNodeY = std::max(baseNodeY, cmpWaterManager->
GetExactWaterLevel(coords[baseNodeIdx].X, coords[baseNodeIdx].Y));
1079 ENSURE(curNodeIdx == coords.size());
1080 newCoords.push_back(coords[coords.size() - 1]);
1082 coords.swap(newCoords);
1089 if (
m_Path[index].size() < 2)
1104 size_t curSegmentStartIndex = 0;
1106 for (
size_t k = 1; k <
m_Path[index].size(); ++k)
1112 bool nodeVisible = losQuerier.IsExplored(i, j);
1113 if (nodeVisible != lastVisible)
1119 curSegmentStartIndex = k - 1;
1120 lastVisible = nodeVisible;
1138 size_t numSegments = segments.size();
1141 for (
size_t i = 1; i < numSegments - 1;)
1147 ENSURE(segments[i-1].m_Visible == segments[i+1].m_Visible);
1149 segments[i-1].m_EndIndex = segments[i+1].m_EndIndex;
1150 segments.erase(segments.begin() + i);
1151 segments.erase(segments.begin() + i);
1162 ENSURE(numSegments == segments.size());
1165 if (segments.size() >= 2 && segments[0].IsSinglePoint())
1167 int firstSegmentStartIndex = segments.front().m_StartIndex;
1168 ENSURE(firstSegmentStartIndex == 0);
1169 ENSURE(!segments[1].IsSinglePoint());
1171 segments.erase(segments.begin());
1172 segments.front().m_StartIndex = firstSegmentStartIndex;
1177 if (segments.size() >= 2 && segments[segments.size()-1].IsSinglePoint())
1179 int lastSegmentEndIndex = segments.back().m_EndIndex;
1180 ENSURE(!segments[segments.size()-2].IsSinglePoint());
1182 segments.erase(segments.end());
1183 segments.back().m_EndIndex = lastSegmentEndIndex;
1188 for (
size_t i = 0; i < segments.size(); ++i)
1190 ENSURE(!segments[i].IsSinglePoint());
1191 ENSURE(segments[i].m_EndIndex > segments[i].m_StartIndex);
An entity initialisation parameter node.
virtual pass_class_t GetPassabilityClass(const std::string &name)=0
Get the tag for a given passability class name.
void SubscribeToMessageType(MessageTypeId mtid)
Subscribe the current component type to the given message type.
A simple fixed-point number class.
virtual void HandleMessage(const CMessage &msg, bool global)
virtual void AddPosition_wrapper(CFixedVector2D pos)
Add another position at which a marker should be displayed, connected to the previous one...
#define REGISTER_COMPONENT_TYPE(cname)
CTexturePtr m_TextureBase
float m_LineThickness
Marker connector line settings (loaded from XML)
virtual void Init(const CParamNode ¶mNode)
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
virtual CLosQuerier GetLosQuerier(player_id_t player)=0
Returns a CLosQuerier for checking whether vertex positions are visible to the given player (or other...
Line-based overlay, with world-space coordinates, rendered in the world potentially behind other obje...
SOverlayTexturedLine::LineCapType LineCapType
entity_id_t AddEntity(const std::wstring &templateName, entity_id_t ent)
Constructs an entity based on the given template, and adds it the world with entity ID ent...
const ssize_t TERRAIN_TILE_SIZE
metres [world space units] per tile in x and z
static LineCapType StrToLineCapType(const std::wstring &str)
Converts a string line cap type into its corresponding LineCap enum value, and returns the resulting ...
ICmpPathfinder::Goal Goal
SVisibilitySegment(bool visible, size_t startIndex, size_t endIndex)
std::string m_LineCostClass
Pathfinder cost class to use for computing the (long-range) marker line path.
Serialization interface; see serialization overview.
virtual float GetExactGroundLevel(float x, float z)=0
static void MergeVisibilitySegments(std::deque< SVisibilitySegment > &segments)
Helper function to GetVisibilitySegments, factored out for testing.
Represents the filename and GL parameters of a texture, for passing to CTextureManager::CreateTexture...
Add renderable objects to the scene collector.
void ConstructDashedLine(const std::vector< CVector2D > &linePoints, SDashedLine &dashedLineOut, const float dashLength, const float blankLength)
Creates a dashed line from the given line, dash length, and blank space between.
static void out(const wchar_t *fmt,...)
void UpdateOverlayLines()
Checks for changes to the SoD to the previously saved state, and reconstructs the visibility segments...
ICmpRangeManager::CLosQuerier CLosQuerier
virtual CFixedVector3D GetRotation()=0
Returns the current rotation (relative to the upwards axis), as Euler angles with X=pitch...
void InterpolatePointsRNS(std::vector< CVector2D > &points, bool closed, float offset, int segmentSamples=4)
Updates the given points to include intermediate points interpolating between the original control po...
virtual void SetPosition(CFixedVector2D pos)
Sets the position at which the rally point marker should be displayed.
std::vector< Waypoint > m_Waypoints
std::vector< CFixedVector2D > m_RallyPoints
Display position of the rally points.
bool m_AlwaysVisible
Should this line be rendered fully visible at all times, even under the SoD?
std::wstring m_LineTextureMaskPath
virtual cost_class_t GetCostClass(const std::string &name)=0
Get the tag for a given movement cost class name.
std::wstring m_LineTexturePath
int ToInt() const
Parses the content of this node as an integer.
bool operator!=(const SVisibilitySegment &other) const
std::wstring m_MarkerTemplate
Template name of the rally point markers.
virtual bool IsInWorld()=0
Returns true if the entity currently exists at a defined position in the world.
CFixedVector2D NearestPointOnSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize)
Find point closest to the given point on the edge of the given square or rectangle.
Obstruction test filter that will test only against stationary (i.e.
int32_t player_id_t
valid player IDs are non-negative (see ICmpOwnership)
bool m_Displayed
Should we render the rally points and the path lines? (set from JS when e.g. the unit is selected/des...
This interface accepts renderable objects.
size_t GetEndIndex(size_t i)
Returns the (exclusive) end point index (i.e. index within m_Points) of dash n.
bool IsSet()
Returns true iff at least one display rally point is set; i.e., if we have a point to render our mark...
std::vector< entity_id_t > m_MarkerEntityIds
Entity IDs of the rally point markers.
CEntityHandle GetEntityHandle() const
std::vector< std::vector< SOverlayTexturedLine > > m_TexturedOverlayLines
Textured overlay lines to be used for rendering the marker line.
LineCapType m_LineEndCapType
virtual void MoveOutOfWorld()=0
Causes IsInWorld to return false.
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
void ConstructCircleOnGround(const CSimContext &context, float x, float z, float radius, SOverlayLine &overlay, bool floating, float heightOffset=0.25f)
Constructs overlay line as a circle with given center and radius, conforming to terrain.
std::vector< std::vector< CVector2D > > m_Path
Full path to the rally points as returned by the pathfinder, with some post-processing applied to red...
void RecomputeAllRallyPointPaths()
Recomputes all the full paths from this entity to the rally point and from the rally point to the nex...
virtual int GetType() const =0
virtual void Reset()
Reset the positions of this rally point marker.
const CParamNode & GetChild(const char *name) const
Returns the (unique) child node with the given name, or a node with IsOk() == false if there is none...
virtual bool CheckMovement(const IObstructionTestFilter &filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, pass_class_t passClass)=0
Check whether the given movement line is valid and doesn't hit any obstructions or impassable terrain...
Textured line overlay, with world-space coordinates, rendered in the world onto the terrain...
bool m_Closed
Should this line be treated as a closed loop? If set, any end cap settings are ignored.
virtual void Serialize(ISerializer &serialize)
bool m_EnableDebugNodeOverlay
Draw little overlay circles to indicate where the exact path points are?
std::deque< std::deque< SVisibilitySegment > > m_VisibilitySegments
Visibility segments of the rally point paths; splits the path into SoD/non-SoD segments.
Semi-circular line ending.
virtual entity_id_t GetPlayerByID(int32_t id)=0
float ToFloat() const
Convert to float. May be lossy - float can't represent all values.
void ReduceSegmentsByVisibility(std::vector< CVector2D > &coords, unsigned maxSegmentLinks=0, bool floating=true)
Simplifies the path by removing waypoints that lie between two points that are visible from one anoth...
virtual CFixedVector2D GetPosition2D()=0
Returns the current x,z position (no interpolation).
virtual player_id_t GetOwner()=0
CColor m_Color
Color to apply to the line texture, where indicated by the mask.
virtual float GetExactWaterLevel(float x, float z)=0
Get the current water level at the given point.
std::string m_LinePassabilityClass
Pathfinder passability class to use for computing the (long-range) marker line path.
std::vector< CVector2D > m_Points
Packed array of consecutive dashes' points. Use m_StartIndices to navigate it.
std::vector< float > m_Coords
(x, z) vertex coordinate pairs; y is computed automatically.
std::vector< size_t > m_StartIndices
Start indices in m_Points of each dash.
#define DEFAULT_COMPONENT_ALLOCATOR(cname)
static void ClassInit(CComponentManager &componentManager)
const CSimContext & GetSimContext() const
ICmpPathfinder::Path Path
static bool IsInitialised()
CTexturePtr m_TextureMask
CTexturePtr m_TextureMask
entity_id_t AllocateNewLocalEntity()
Returns a new local entity ID that has never been used before.
A simplified syntax for accessing entity components.
bool operator==(const SVisibilitySegment &other) const
void FixFootprintWaypoints(std::vector< CVector2D > &coords, CmpPtr< ICmpPosition > cmpPosition, CmpPtr< ICmpFootprint > cmpFootprint)
Removes points from coords that are obstructed by the originating building's footprint, and links up the last point nicely to the edge of the building's footprint.
int GetCurrentDisplayedPlayer() const
Returns the player ID that the current display is being rendered for.
std::vector< std::vector< SOverlayLine > > m_DebugNodeOverlays
CEntityHandle GetSystemEntity() const
virtual void SetDisplayed(bool displayed)
Sets whether the rally point marker and line should be displayed.
Helper functions related to rendering.
bool IsExplored(ssize_t i, ssize_t j)
Returns whether the given vertex is explored (i.e.
void SetMaxAnisotropy(float aniso)
Set maximum anisotropy value.
player_id_t m_LastOwner
Last seen owner of this entity (used to keep track of ownership changes).
virtual void SetUnitEntitySelection(const CStr &selection)=0
Sets the specified entity selection on the underlying unit.
SceneCollector & collector
virtual void JumpTo(entity_pos_t x, entity_pos_t z)=0
Move immediately to the given location, with no interpolation.
Object providing efficient abstracted access to the LOS state.
virtual void ComputePath(entity_pos_t x0, entity_pos_t z0, const Goal &goal, pass_class_t passClass, cost_class_t costClass, Path &ret)=0
Compute a tile-based path from the given point to the goal, and return the set of waypoints...
void RenderSubmit(SceneCollector &collector)
void ConstructSquareOnGround(const CSimContext &context, float x, float z, float w, float h, float a, SOverlayLine &overlay, bool floating, float heightOffset=0.25f)
Constructs overlay line as rectangle with given center and dimensions, conforming to terrain...
void ConstructAllOverlayLines()
Sets up all overlay lines for rendering according to the current full path and visibility segments...
static CFixed FromFloat(float n)
void UpdateMarkers()
Repositions the rally point markers; moves them outside of the world (ie.
LineCapType m_LineStartCapType
void RecomputeRallyPointPath(size_t index, CmpPtr< ICmpPosition > &cmpPosition, CmpPtr< ICmpFootprint > &cmpFootprint, CmpPtr< ICmpPathfinder > cmpPathfinder)
Recomputes the full path from this entity/the previous rally point to the next rally point...
ICmpPathfinder::Waypoint Waypoint
void sincos_approx(CFixed_15_16 a, CFixed_15_16 &sin_out, CFixed_15_16 &cos_out)
Compute sin(a) and cos(a).
const CSimContext * m_SimContext
Simulation context applicable for this overlay line; used to obtain terrain information during automa...
void DestroyComponentsSoon(entity_id_t ent)
Destroys all the components belonging to the specified entity when FlushDestroyedComponents is called...
void ConstructOverlayLines(size_t index)
Sets up the overlay lines for rendering according to the full path and visibility segments at index...
LineCapType m_StartCapType
bool m_SmoothPath
Smooth the path before rendering?
bool PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize)
Checks if a point is inside the given rotated square or rectangle.
float m_Thickness
Half-width of the line, in world-space units.
static float Length(const SVec3 v)
const entity_id_t INVALID_ENTITY
Invalid entity ID.
void GetVisibilitySegments(std::deque< SVisibilitySegment > &out, size_t index)
Returns a list of indices of waypoints in the current path (m_Path[index]) where the LOS visibility c...
static std::string GetSchema()
void SetWrap(GLint wrap)
Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc).
u32 entity_id_t
Entity ID type.
virtual void Submit(CPatch *patch)=0
Submit a terrain patch that is part of the scene.
static const player_id_t INVALID_PLAYER
void RecomputeRallyPointPath_wrapper(size_t index)
Recomputes the full path for m_Path[ index], and does all the necessary post-processing to make it pr...
Helper functions related to geometry algorithms.
CComponentManager & GetComponentManager() const
void AddPosition(CFixedVector2D pos, bool recompute)
Helper function for AddPosition_wrapper and SetPosition.
Deserialization interface; see serialization overview.
virtual void Deserialize(const CParamNode ¶mNode, IDeserializer &deserialize)
shared_ptr< CTexture > CTexturePtr