forked from mirror/DotRecast
refactor: flags
This commit is contained in:
parent
17b3832297
commit
533afe49e2
|
@ -132,7 +132,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool offMeshConnection = ((corners[corners.Count - 1].flags
|
bool offMeshConnection = ((corners[corners.Count - 1].flags
|
||||||
& DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
if (offMeshConnection)
|
if (offMeshConnection)
|
||||||
|
@ -150,7 +150,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
if (0 == corners.Count)
|
if (0 == corners.Count)
|
||||||
return range;
|
return range;
|
||||||
|
|
||||||
bool endOfPath = ((corners[corners.Count - 1].flags & DtNavMeshQuery.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
bool endOfPath = ((corners[corners.Count - 1].flags & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
||||||
if (endOfPath)
|
if (endOfPath)
|
||||||
return Math.Min(RcVec3f.Dist2D(npos, corners[corners.Count - 1].pos), range);
|
return Math.Min(RcVec3f.Dist2D(npos, corners[corners.Count - 1].pos), range);
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
int start = 0;
|
int start = 0;
|
||||||
foreach (DtStraightPath spi in corners)
|
foreach (DtStraightPath spi in corners)
|
||||||
{
|
{
|
||||||
if ((spi.flags & DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|
if ((spi.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|
||||||
|| RcVec3f.Dist2DSqr(spi.pos, m_pos) > MIN_TARGET_DIST)
|
|| RcVec3f.Dist2DSqr(spi.pos, m_pos) > MIN_TARGET_DIST)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -137,7 +137,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
for (int i = start; i < corners.Count; i++)
|
for (int i = start; i < corners.Count; i++)
|
||||||
{
|
{
|
||||||
DtStraightPath spi = corners[i];
|
DtStraightPath spi = corners[i];
|
||||||
if ((spi.flags & DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
if ((spi.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
end = i + 1;
|
end = i + 1;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,23 +38,6 @@ namespace DotRecast.Detour
|
||||||
/** Raycast should calculate movement cost along the ray and fill RaycastHit::cost */
|
/** Raycast should calculate movement cost along the ray and fill RaycastHit::cost */
|
||||||
public const int DT_RAYCAST_USE_COSTS = 0x01;
|
public const int DT_RAYCAST_USE_COSTS = 0x01;
|
||||||
|
|
||||||
/// Vertex flags returned by findStraightPath.
|
|
||||||
/** The vertex is the start position in the path. */
|
|
||||||
public const int DT_STRAIGHTPATH_START = 0x01;
|
|
||||||
|
|
||||||
/** The vertex is the end position in the path. */
|
|
||||||
public const int DT_STRAIGHTPATH_END = 0x02;
|
|
||||||
|
|
||||||
/** The vertex is the start of an off-mesh connection. */
|
|
||||||
public const int DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04;
|
|
||||||
|
|
||||||
/// Options for findStraightPath.
|
|
||||||
public const int DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01;
|
|
||||||
|
|
||||||
/// < Add a vertex at every polygon edge crossing
|
|
||||||
/// where area changes.
|
|
||||||
public const int DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02;
|
|
||||||
|
|
||||||
/// < Add a vertex at every polygon edge crossing.
|
/// < Add a vertex at every polygon edge crossing.
|
||||||
protected readonly DtNavMesh m_nav;
|
protected readonly DtNavMesh m_nav;
|
||||||
|
|
||||||
|
@ -1448,7 +1431,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// If reached end of path or there is no space to append more vertices, return.
|
// If reached end of path or there is no space to append more vertices, return.
|
||||||
if (flags == DT_STRAIGHTPATH_END || straightPath.Count >= maxStraightPath)
|
if (flags == DtStraightPathFlags.DT_STRAIGHTPATH_END || straightPath.Count >= maxStraightPath)
|
||||||
{
|
{
|
||||||
return DtStatus.DT_SUCCSESS;
|
return DtStatus.DT_SUCCSESS;
|
||||||
}
|
}
|
||||||
|
@ -1486,7 +1469,7 @@ namespace DotRecast.Detour
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options & DT_STRAIGHTPATH_AREA_CROSSINGS) != 0)
|
if ((options & DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS) != 0)
|
||||||
{
|
{
|
||||||
// Skip intersection if only area crossings are requested.
|
// Skip intersection if only area crossings are requested.
|
||||||
if (fromPoly.GetArea() == toPoly.GetArea())
|
if (fromPoly.GetArea() == toPoly.GetArea())
|
||||||
|
@ -1562,7 +1545,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add start point.
|
// Add start point.
|
||||||
DtStatus stat = AppendVertex(closestStartPos, DT_STRAIGHTPATH_START, path[0], ref straightPath, maxStraightPath);
|
DtStatus stat = AppendVertex(closestStartPos, DtStraightPathFlags.DT_STRAIGHTPATH_START, path[0], ref straightPath, maxStraightPath);
|
||||||
if (!stat.InProgress())
|
if (!stat.InProgress())
|
||||||
{
|
{
|
||||||
return stat;
|
return stat;
|
||||||
|
@ -1606,7 +1589,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append portals along the current straight path segment.
|
// Append portals along the current straight path segment.
|
||||||
if ((options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
||||||
{
|
{
|
||||||
// Ignore status return value as we're just about to return anyway.
|
// Ignore status return value as we're just about to return anyway.
|
||||||
AppendPortals(apexIndex, i, closestEndPos, path, ref straightPath, maxStraightPath, options);
|
AppendPortals(apexIndex, i, closestEndPos, path, ref straightPath, maxStraightPath, options);
|
||||||
|
@ -1649,7 +1632,7 @@ namespace DotRecast.Detour
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Append portals along the current straight path segment.
|
// Append portals along the current straight path segment.
|
||||||
if ((options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
||||||
{
|
{
|
||||||
stat = AppendPortals(apexIndex, leftIndex, portalLeft, path, ref straightPath, maxStraightPath, options);
|
stat = AppendPortals(apexIndex, leftIndex, portalLeft, path, ref straightPath, maxStraightPath, options);
|
||||||
if (!stat.InProgress())
|
if (!stat.InProgress())
|
||||||
|
@ -1664,11 +1647,11 @@ namespace DotRecast.Detour
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (leftPolyRef == 0)
|
if (leftPolyRef == 0)
|
||||||
{
|
{
|
||||||
flags = DT_STRAIGHTPATH_END;
|
flags = DtStraightPathFlags.DT_STRAIGHTPATH_END;
|
||||||
}
|
}
|
||||||
else if (leftPolyType == DtPoly.DT_POLYTYPE_OFFMESH_CONNECTION)
|
else if (leftPolyType == DtPoly.DT_POLYTYPE_OFFMESH_CONNECTION)
|
||||||
{
|
{
|
||||||
flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION;
|
flags = DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
long refs = leftPolyRef;
|
long refs = leftPolyRef;
|
||||||
|
@ -1705,7 +1688,7 @@ namespace DotRecast.Detour
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Append portals along the current straight path segment.
|
// Append portals along the current straight path segment.
|
||||||
if ((options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
||||||
{
|
{
|
||||||
stat = AppendPortals(apexIndex, rightIndex, portalRight, path, ref straightPath, maxStraightPath, options);
|
stat = AppendPortals(apexIndex, rightIndex, portalRight, path, ref straightPath, maxStraightPath, options);
|
||||||
if (!stat.InProgress())
|
if (!stat.InProgress())
|
||||||
|
@ -1720,11 +1703,11 @@ namespace DotRecast.Detour
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (rightPolyRef == 0)
|
if (rightPolyRef == 0)
|
||||||
{
|
{
|
||||||
flags = DT_STRAIGHTPATH_END;
|
flags = DtStraightPathFlags.DT_STRAIGHTPATH_END;
|
||||||
}
|
}
|
||||||
else if (rightPolyType == DtPoly.DT_POLYTYPE_OFFMESH_CONNECTION)
|
else if (rightPolyType == DtPoly.DT_POLYTYPE_OFFMESH_CONNECTION)
|
||||||
{
|
{
|
||||||
flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION;
|
flags = DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
long refs = rightPolyRef;
|
long refs = rightPolyRef;
|
||||||
|
@ -1750,7 +1733,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append portals along the current straight path segment.
|
// Append portals along the current straight path segment.
|
||||||
if ((options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
||||||
{
|
{
|
||||||
stat = AppendPortals(apexIndex, path.Count - 1, closestEndPos, path, ref straightPath, maxStraightPath, options);
|
stat = AppendPortals(apexIndex, path.Count - 1, closestEndPos, path, ref straightPath, maxStraightPath, options);
|
||||||
if (!stat.InProgress())
|
if (!stat.InProgress())
|
||||||
|
@ -1761,7 +1744,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore status return value as we're just about to return anyway.
|
// Ignore status return value as we're just about to return anyway.
|
||||||
AppendVertex(closestEndPos, DT_STRAIGHTPATH_END, 0, ref straightPath, maxStraightPath);
|
AppendVertex(closestEndPos, DtStraightPathFlags.DT_STRAIGHTPATH_END, 0, ref straightPath, maxStraightPath);
|
||||||
return DtStatus.DT_SUCCSESS | (straightPath.Count >= maxStraightPath ? DtStatus.DT_BUFFER_TOO_SMALL : DtStatus.DT_STATUS_NOTHING);
|
return DtStatus.DT_SUCCSESS | (straightPath.Count >= maxStraightPath ? DtStatus.DT_BUFFER_TOO_SMALL : DtStatus.DT_STATUS_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace DotRecast.Detour
|
||||||
while (ns < straightPath.Count)
|
while (ns < straightPath.Count)
|
||||||
{
|
{
|
||||||
// Stop at Off-Mesh link or when point is further than slop away.
|
// Stop at Off-Mesh link or when point is further than slop away.
|
||||||
if (((straightPath[ns].flags & DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
if (((straightPath[ns].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
|| !InRange(straightPath[ns].pos, startPos, minTargetDist, 1000.0f))
|
|| !InRange(straightPath[ns].pos, startPos, minTargetDist, 1000.0f))
|
||||||
break;
|
break;
|
||||||
ns++;
|
ns++;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace DotRecast.Detour
|
||||||
|
{
|
||||||
|
/// Vertex flags returned by dtNavMeshQuery::findStraightPath.
|
||||||
|
public static class DtStraightPathFlags
|
||||||
|
{
|
||||||
|
public const int DT_STRAIGHTPATH_START = 0x01; //< The vertex is the start position in the path.
|
||||||
|
public const int DT_STRAIGHTPATH_END = 0x02; //< The vertex is the end position in the path.
|
||||||
|
public const int DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04; //< The vertex is the start of an off-mesh connection.
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,8 +5,8 @@ namespace DotRecast.Detour
|
||||||
public class DtStraightPathOption
|
public class DtStraightPathOption
|
||||||
{
|
{
|
||||||
public static readonly DtStraightPathOption None = new DtStraightPathOption(0, "None");
|
public static readonly DtStraightPathOption None = new DtStraightPathOption(0, "None");
|
||||||
public static readonly DtStraightPathOption AreaCrossings = new DtStraightPathOption(DtNavMeshQuery.DT_STRAIGHTPATH_AREA_CROSSINGS, "Area");
|
public static readonly DtStraightPathOption AreaCrossings = new DtStraightPathOption(DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS, "Area");
|
||||||
public static readonly DtStraightPathOption AllCrossings = new DtStraightPathOption(DtNavMeshQuery.DT_STRAIGHTPATH_ALL_CROSSINGS, "All");
|
public static readonly DtStraightPathOption AllCrossings = new DtStraightPathOption(DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS, "All");
|
||||||
|
|
||||||
public static readonly RcImmutableArray<DtStraightPathOption> Values = RcImmutableArray.Create(
|
public static readonly RcImmutableArray<DtStraightPathOption> Values = RcImmutableArray.Create(
|
||||||
None, AreaCrossings, AllCrossings
|
None, AreaCrossings, AllCrossings
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace DotRecast.Detour
|
||||||
|
{
|
||||||
|
/// Options for dtNavMeshQuery::findStraightPath.
|
||||||
|
public class DtStraightPathOptions
|
||||||
|
{
|
||||||
|
public const int DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01; //< Add a vertex at every polygon edge crossing where area changes.
|
||||||
|
public const int DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02; //< Add a vertex at every polygon edge crossing.
|
||||||
|
}
|
||||||
|
}
|
|
@ -263,7 +263,7 @@ public class CrowdSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag.corners[ag.corners.Count - 1].flags
|
if ((ag.corners[ag.corners.Count - 1].flags
|
||||||
& DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
RcVec3f v = ag.corners[ag.corners.Count - 1].pos;
|
RcVec3f v = ag.corners[ag.corners.Count - 1].pos;
|
||||||
dd.Vertex(v.x, v.y, v.z, DuRGBA(192, 0, 0, 192));
|
dd.Vertex(v.x, v.y, v.z, DuRGBA(192, 0, 0, 192));
|
||||||
|
|
|
@ -288,7 +288,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
||||||
int col;
|
int col;
|
||||||
if ((straightPathItem.flags & DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
if ((straightPathItem.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
col = offMeshCol;
|
col = offMeshCol;
|
||||||
}
|
}
|
||||||
|
@ -307,15 +307,15 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
int col;
|
int col;
|
||||||
if ((straightPathItem.flags & DtNavMeshQuery.DT_STRAIGHTPATH_START) != 0)
|
if ((straightPathItem.flags & DtStraightPathFlags.DT_STRAIGHTPATH_START) != 0)
|
||||||
{
|
{
|
||||||
col = startCol;
|
col = startCol;
|
||||||
}
|
}
|
||||||
else if ((straightPathItem.flags & DtNavMeshQuery.DT_STRAIGHTPATH_END) != 0)
|
else if ((straightPathItem.flags & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0)
|
||||||
{
|
{
|
||||||
col = endCol;
|
col = endCol;
|
||||||
}
|
}
|
||||||
else if ((straightPathItem.flags & DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
else if ((straightPathItem.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
col = offMeshCol;
|
col = offMeshCol;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,10 +64,10 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool endOfPath = (steerPosFlag & DtNavMeshQuery.DT_STRAIGHTPATH_END) != 0
|
bool endOfPath = (steerPosFlag & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
bool offMeshConnection = (steerPosFlag & DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|
bool offMeshConnection = (steerPosFlag & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
|
|
||||||
straightPath = new List<DtStraightPath>(MAX_POLYS);
|
straightPath = new List<DtStraightPath>(MAX_POLYS);
|
||||||
navQuery.FindStraightPath(startPos, epos, path, ref straightPath, MAX_POLYS, DtNavMeshQuery.DT_STRAIGHTPATH_ALL_CROSSINGS);
|
navQuery.FindStraightPath(startPos, epos, path, ref straightPath, MAX_POLYS, DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtStatus.DT_SUCCSESS;
|
return DtStatus.DT_SUCCSESS;
|
||||||
|
|
|
@ -74,8 +74,8 @@ public class PathCorridorTest
|
||||||
straightPath.Add(new DtStraightPath(RcVec3f.Of(10, 20, 30.00001f), 0, 0)); // too close
|
straightPath.Add(new DtStraightPath(RcVec3f.Of(10, 20, 30.00001f), 0, 0)); // too close
|
||||||
straightPath.Add(new DtStraightPath(RcVec3f.Of(10, 20, 30.00002f), 0, 0)); // too close
|
straightPath.Add(new DtStraightPath(RcVec3f.Of(10, 20, 30.00002f), 0, 0)); // too close
|
||||||
straightPath.Add(new DtStraightPath(RcVec3f.Of(11f, 21, 32f), 0, 0));
|
straightPath.Add(new DtStraightPath(RcVec3f.Of(11f, 21, 32f), 0, 0));
|
||||||
straightPath.Add(new DtStraightPath(RcVec3f.Of(12f, 22, 33f), DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
straightPath.Add(new DtStraightPath(RcVec3f.Of(12f, 22, 33f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
||||||
straightPath.Add(new DtStraightPath(RcVec3f.Of(11f, 21, 32f), DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
straightPath.Add(new DtStraightPath(RcVec3f.Of(11f, 21, 32f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
||||||
|
|
||||||
var mockQuery = new Mock<DtNavMeshQuery>(It.IsAny<DtNavMesh>());
|
var mockQuery = new Mock<DtNavMeshQuery>(It.IsAny<DtNavMesh>());
|
||||||
mockQuery.Setup(q => q.FindStraightPath(
|
mockQuery.Setup(q => q.FindStraightPath(
|
||||||
|
|
Loading…
Reference in New Issue