private bool SaveNodes(string fileName, DialogueContainer dialogueContainerObject) { if (!Edges.Any()) { return(false); } var connectedSockets = Edges.Where(x => x.input.node != null).ToArray(); for (var i = 0; i < connectedSockets.Count(); i++) { var outputNode = (connectedSockets[i].output.node as DialogueNode); var inputNode = (connectedSockets[i].input.node as DialogueNode); dialogueContainerObject.NodeLinks.Add(new NodeLinkData { BaseNodeGUID = outputNode.GUID, PortName = connectedSockets[i].output.portName, TargetNodeGUID = inputNode.GUID }); } foreach (var node in Nodes.Where(node => !node.EntyPoint)) { dialogueContainerObject.DialogueNodeData.Add(new DialogueNodeData { NodeGUID = node.GUID, DialogueText = node.DialogueText, Position = node.GetPosition().position }); } return(true); }
/// <summary> /// Removes all edges between vertices. /// Vertices still remains in graph but any of them are connected. /// </summary> public void ClearEdges() { while (Edges.Any()) { RemoveEdge(Edges.First()); } }
public void AddEdge(Edge <T> edge, double weight = 0) { bool existsInGraph = !(Edges.Any((i => i.Node1.Id == edge.Node1.Id && i.Node2.Id == edge.Node2.Id)) || (Edges.Any(i => i.Node1.Id == edge.Node2.Id && i.Node2.Id == edge.Node1.Id))); if (existsInGraph) { Edges.Add(edge); } if (!_graphSet.ContainsKey(edge.Node1.Id)) { _graphSet.Add(edge.Node1.Id, new HashSet <Node <T> >()); } if (!_graphSet.ContainsKey(edge.Node2.Id)) { _graphSet.Add(edge.Node2.Id, new HashSet <Node <T> >()); } if (_graphSet.ContainsKey(edge.Node1.Id)) { _graphSet[edge.Node1.Id].Add(edge.Node2); } if (_graphSet.ContainsKey(edge.Node2.Id)) { _graphSet[edge.Node2.Id].Add(edge.Node1); } SetEdgeWeight(edge, weight); }
public void AddEdge(T from, T to) { if (from == null) { throw new ArgumentNullException(nameof(from)); } if (to == null) { throw new ArgumentNullException(nameof(to)); } if (!Vertices.Contains(from, EqualityComparer)) { throw new ArgumentException($"Cannot add edge from nonexistant vertex {from}"); } if (!Vertices.Contains(to, EqualityComparer)) { throw new ArgumentException($"Cannot add edge to nonexistant vertex {to}"); } if (Edges.Any(edge => EqualityComparer.Equals(edge.From, from) && EqualityComparer.Equals(edge.To, to))) { throw new ArgumentException($"Edge from vertex {from} to vertex {to} already exists"); } _edges.Add(new Edge <T>(from, to)); }
protected void ValidatePrintEdges() { if (!Edges.Any()) { throw new Exception("There's no edges."); } }
public void SortVertices() { if (!Edges.Any()) { return; } Vertices.Clear(); List <Line> sortedLines = new List <Line>(); List <Line> edgesCopy = new List <Line>(); foreach (Line e in Edges) { Line tmp = new Line(e.StartPoint, e.EndPoint); edgesCopy.Add(tmp); } bool closed = false; Line currLine = edgesCopy.First(); Line toRemove = null; while (!closed) { foreach (Line line in edgesCopy) { //if (l.GetPoints().Contains(currLine.EndPoint)) if (containsPoint(line.GetPoints(), currLine.EndPoint, 5)) { Vector3 vtmp = line.GetPoints().Where(o => !almostEqual(o, currLine.EndPoint, 5)).First(); Line tmp = new Line(currLine.EndPoint, vtmp); toRemove = line; sortedLines.Add(tmp); currLine = tmp; break; } else { toRemove = null; } } if (toRemove == null) { break; } else { edgesCopy.Remove(toRemove); } if (edgesCopy.Count == 0) { closed = true; } } Edges = sortedLines; }
public bool ContainsEdge(Edge edge, bool compareByPos = false) { if (compareByPos) { return(ContainsVertex(edge.P1.Position) && ContainsVertex(edge.P2.Position)); } return(Edges.Any(x => x.Equals(edge, compareByPos))); }
private bool SaveNodes(FrpGraphContainer frpGraphContainer) { if (!Edges.Any()) { return(false); } var edges = Edges.ToArray(); for (var i = 0; i < edges.Length; ++i) { var outputNode = edges[i].output.node as FrpNode; var inputNode = edges[i].input.node as FrpNode; var basePortName = edges[i].output.portName; var basePortNames = new List <string>(); for (int j = 0; j < outputNode.outputContainer.childCount; ++j) { basePortNames.Add(outputNode.outputContainer[j].Q <Port>().portName); } var basePortIndex = basePortNames.FindIndex(x => x == basePortName); var targetPortName = edges[i].input.portName; var targetPortNames = new List <string>(); for (int j = 0; j < inputNode.inputContainer.childCount; ++j) { targetPortNames.Add(inputNode.inputContainer[j].Q <Port>().portName); } var targetPortIndex = targetPortNames.FindIndex(x => x == targetPortName); var connectionName = edges[i].Q <TextField>().value; frpGraphContainer.NodeLinks.Add(new NodeLinkData { ConnectionName = connectionName, BaseNodeGuid = outputNode.frpNodeData.Guid, BasePortName = basePortName, BasePortNum = basePortIndex, TargetNodeGuid = inputNode.frpNodeData.Guid, TargetPortName = targetPortName, TargetPortNum = targetPortIndex }); } foreach (var node in Nodes) { node.frpNodeData.Position = node.GetPosition().position; frpGraphContainer.FrpNodeData.Add(node.frpNodeData.Clone()); } return(true); }
/// <inheritdoc /> public bool ContainsVertex(TVertex vertex) { if (vertex == null) { throw new ArgumentNullException(nameof(vertex)); } return(Edges.Any( edge => edge.Source.Equals(vertex) || edge.Target.Equals(vertex))); }
/// <inheritdoc /> public bool ContainsVertex(TVertex vertex) { if (vertex == null) { throw new ArgumentNullException(nameof(vertex)); } return(Edges.Any( edge => EqualityComparer <TVertex> .Default.Equals(edge.Source, vertex) || EqualityComparer <TVertex> .Default.Equals(edge.Target, vertex))); }
public void AddEdge(Vertex to) { if (!Edges.Any( t => t.Name.Equals( to.Name, StringComparison.InvariantCultureIgnoreCase))) { Edges.AddLast(to); } }
bool CanAdd() { if (!Edges.Any()) { return(true); } var edge = Edges[Edges.Count - 1]; return(!string.IsNullOrEmpty(edge.From) && !string.IsNullOrEmpty(edge.To)); }
private bool FCheckEasy(out IEnumerable <Vector> ptsToBeClipped) { ptsToBeClipped = null; if (!Edges.Any(e => e.VtxStart.FAtInfinity || e.VtxEnd.FAtInfinity)) { ptsToBeClipped = Vertices.Select(v => v.Pt); return(true); } return(false); }
public List <Triangle> CreateTriangles(Vector3 normal) { if (!Edges.Any()) { return(new List <Triangle>()); } List <Triangle> triangles = new List <Triangle>(); //Clear the vertices Vertices.Clear(); UV.Clear(); //Create the new vertices with the uv foreach (Line l in Edges) { Vertices.Add(l.StartPoint); UV.Add(new Vector2()); } Vertices.Add(Edges.Last().EndPoint); UV.Add(new Vector2()); //Create the triangles for (int i = 1; i < Vertices.Count - 1; i++) { if (Vertices[0] == Vertices[i] || Vertices[0] == Vertices[i + 1]) { continue; } List <Vector3> vertices = new List <Vector3> { Vertices[0], Vertices[i], Vertices[i + 1] }; List <Vector3> normals = new List <Vector3> { normal, normal, normal }; List <Vector2> uvs = new List <Vector2> { UV[0], UV[i], UV[i + 1] }; triangles.Add(new Triangle(vertices, normals, uvs)); } return(triangles); }
private void InitializeIds() { if (Edges.Any()) { nextEdgeId = edges.Keys.Max() + 1; } if (Vertices.Any()) { nextVertexId = vertices.Keys.Max() + 1; } idsAreInitialized = true; }
public int CountTrees() { int treeCount = 0; List <Edge> tree = new List <Edge>(); var fGroup = Edges.GroupBy(e => e.From); // 1, 3, 4, 6 var tGroup = Edges.GroupBy(e => e.To); // 2, 4, 5, 7, 8, 9 for (int i = 0; i < Nodes; i++) { int fCount = fGroup.Count(f => f.Key == i); int tCount = tGroup.Count(f => f.Key == i); if (fCount == 0 && tCount == 0) { treeCount++; tree.Add(new Edge(i, i)); continue; } if (fCount > 0 && tCount > 0) { continue; //Do not add to tree since it found in both direction. } if (fCount > 0) { foreach (var e in fGroup.Where(g => g.Key == i)) { List <int> tos = e.Select(f => f.To).ToList(); if (!Edges.Any(f => tos.Contains(f.From))) { treeCount++; tree.AddRange(e.Select(f => f)); } } } if (tCount > 0) { foreach (var e in tGroup.Where(g => g.Key == i)) { List <int> froms = e.Select(f => f.From).ToList(); if (!Edges.Any(f => froms.Contains(f.To))) { treeCount++; tree.AddRange(e.Select(f => f)); } } } } treeCount = tree.Distinct().Select(d => d.From).Distinct().Count(); return(treeCount); }
public void AddEdge(Edge edge) { if (!Edges.Any(current => current.FirstVertex.Equals(edge.FirstVertex) || current.SecondVertex.Equals(edge.FirstVertex))) { VertexCount++; } if (!Edges.Any(current => current.FirstVertex.Equals(edge.SecondVertex) || current.SecondVertex.Equals(edge.SecondVertex))) { VertexCount++; } Edges.Add(edge); }
// todo: not cut by rhythm private SliderTick[] GetBezierDiscreteBallData(double interval) { if (Math.Round(interval - _singleElapsedTime) >= 0) { return(Array.Empty <SliderTick>()); } var totalLength = RawBezierLengthData.Sum(); var ticks = new List <SliderTick>(); for (int i = 1; i *interval < _singleElapsedTime; i++) { var offset = i * interval; // 当前tick的相对时间 if (Edges.Any(k => Math.Abs(k.Offset - _offset - offset) < 0.01)) { continue; } var ratio = offset / _singleElapsedTime; // 相对整个滑条的时间比例,=距离比例 var relativeLen = totalLength * ratio; // 至滑条头的距离 var(index, lenInPart) = CalculateWhichPart(relativeLen); // can be optimized var len = RawBezierLengthData[index]; var tickPoint = Bezier.CalcPoint((float)(lenInPart / len), RawGroupedBezierData[index]); ticks.Add(new SliderTick(_offset + offset, tickPoint)); } if (Repeat > 1) { var firstSingleCopy = ticks.ToArray(); for (int i = 2; i <= Repeat; i++) { var reverse = i % 2 == 0; if (reverse) { ticks.AddRange(firstSingleCopy.Reverse().Select(k => new SliderTick((_singleElapsedTime - (k.Offset - _offset)) + (i - 1) * _singleElapsedTime + _offset, k.Point))); } else { ticks.AddRange(firstSingleCopy.Select(k => new SliderTick(k.Offset + (i - 1) * _singleElapsedTime, k.Point))); } } } return(ticks.ToArray()); }
public void AddToMesh(IEnumerable <GroundPointBuilder> newPoints, IEnumerable <GroundEdgeBuilder> newEdges) { IEnumerable <GroundPoint> points = newPoints.Select(item => new GroundPoint(this, item.Index, item.Position)).ToArray(); AddPoints(points); IEnumerable <GroundEdge> edges = newEdges.Select(item => new GroundEdge(this, Points[item.PointAIndex], Points[item.PointBIndex])).ToArray(); AddEdges(edges); BorderEdges = Edges.Where(item => item.IsBorder).ToArray(); if (Edges.Any(edge => edge.Quads.Count() == 0 || edge.Quads.Count() > 2)) { throw new Exception("Malformed data."); } UpdateVoxelVisuals(); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Identical to BoxVertices if there are any infinite polygons/vertices involved. In the case /// of a purely finite polygon, we return it unaltered. /// </summary> /// <remarks> /// This overload of RealVertices ensures that all vertices are finite in a foolproof way. The /// overload of RealVertices that takes a double as a raylength relies on the caller guessing as /// to a sufficient ray length to ensure that our rays extend outside of whatever area they're /// interested in. That's usually not possible to do in a foolproof way. Also, it has problems /// with doubly infinite lines when the return value is interpreted as a polygon. This routine /// doesn't necessarily clip to the box in question, but does guarantee that the finite polygon /// returned will properly cover it's assigned area in the box passed in. On interior cells, it /// avoids the overhead of a clipping operation which is liable to happen outside of this call /// anyway. This is the safest way of covering a box without necessarily clipping to it. /// Darrellp, 2/28/2011. /// </remarks> /// <param name="ptUL"> The upper left point of the box. </param> /// <param name="ptLR"> The lower right point of the box. </param> /// <returns> An enumerable of real points representing the polygon. </returns> //////////////////////////////////////////////////////////////////////////////////////////////////// public IEnumerable <Vector> RealVertices(Vector ptUL, Vector ptLR) { if (!Edges.Any(e => e.VtxStart.FAtInfinity || e.VtxEnd.FAtInfinity)) { foreach (var pt in Vertices.Select(v => v.Pt)) { yield return(pt); } } else { foreach (var pt in BoxVertices(ptUL, ptLR)) { yield return(pt); } } }
/// <summary> /// Defines the face curvature. Depends on DefineEdgeAngle /// </summary> public void DefineFaceCurvature() { if (Edges.Any(e => e == null || e.Curvature == CurvatureType.Undefined)) { Curvature = CurvatureType.Undefined; } else if (Edges.All(e => e.Curvature != CurvatureType.Concave)) { Curvature = CurvatureType.Convex; } else if (Edges.All(e => e.Curvature != CurvatureType.Convex)) { Curvature = CurvatureType.Concave; } else { Curvature = CurvatureType.SaddleOrFlat; } }
/// <summary> /// Creates the connection to the annex node. /// </summary> public override void CreateConnections(List <PathfindingNodeMaster> Objects) { var annexZoneLocProp = export.GetProperty <ObjectProperty>("AnnexZoneLocation"); if (annexZoneLocProp != null) { //ExportEntry annexzonelocexp = pcc.Exports[annexZoneLocProp.Value - 1]; PathfindingNodeMaster othernode = null; int othernodeidx = annexZoneLocProp.Value; if (othernodeidx != 0) { foreach (PathfindingNodeMaster node in Objects) { if (node.export.UIndex == othernodeidx) { othernode = node; break; } } } if (othernode != null) { PathfindingEditorEdge edge = new PathfindingEditorEdge { Pen = annexZoneLocPen, EndPoints = { [0] = this, [1] = othernode } }; if (!Edges.Any(x => x.DoesEdgeConnectSameNodes(edge)) && !othernode.Edges.Any(x => x.DoesEdgeConnectSameNodes(edge))) { Edges.Add(edge); othernode.Edges.Add(edge); g.edgeLayer.AddChild(edge); } } } }
internal void Refresh(bool switchBackFront) { UpdateNormalVector(); if (mIsTransparent || Edges.Any <Edge>(e => e.OtherFace == null)) { mIsFrontFacing = true; } else { //the face may no longer be front-facing (or no longer back-facing) double dotProduct = NormalVector.DotProduct(new Coord(0, 0, 1)); int dotSign = Math.Sign(dotProduct); mIsFrontFacing = switchBackFront ? (dotSign == -1) : (dotSign == 1); } //update the bounding box mBoundingBox = Global.GetRectangleWithGivenCorners(Vertices[0].ViewCoord.ToPointD(), Vertices[1].ViewCoord.ToPointD()); for (int i = 1; i < Vertices.Count; i++) { mBoundingBox = Rectangle.Union(mBoundingBox, Global.GetRectangleWithGivenCorners(Vertices[i - 1].ViewCoord.ToPointD(), Vertices[i].ViewCoord.ToPointD())); } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Ensure that all edges connect to each other. </summary> /// <remarks> Darrellp, 2/18/2011. </remarks> /// <returns> True if all edges connect in order, else false. </returns> //////////////////////////////////////////////////////////////////////////////////////////////////// internal bool FValidateEdgesInOrder() { // If it's a single infinite polygon if (!Edges.Any()) { // There are no edges so skip this check return(true); } // Declarations var fFirstTimeThroughLoop = true; var edgePrev = new WeEdge(); var edgeFirst = new WeEdge(); // For each edge in the polygon foreach (var edgeCur in Edges) { if (fFirstTimeThroughLoop) { // Initialize fFirstTimeThroughLoop = false; edgePrev = edgeFirst = edgeCur; } else { // If this edge doesn't connect to the previous one if (!edgeCur.FConnectsToEdge(edgePrev)) { // there is a problem return(Failure()); } edgePrev = edgeCur; } } // Make sure the last edge cycles back to the first one return(edgePrev.FConnectsToEdge(edgeFirst) || Failure()); }
/// <summary> /// Defines vertex curvature /// </summary> private void DefineCurvature() { if (Edges.Any(e => e.Curvature == CurvatureType.Undefined)) { _curvature = CurvatureType.Undefined; } else if (Edges.All(e => e.Curvature == CurvatureType.SaddleOrFlat)) { _curvature = CurvatureType.SaddleOrFlat; } else if (Edges.Any(e => e.Curvature != CurvatureType.Convex)) { _curvature = CurvatureType.Concave; } else if (Edges.Any(e => e.Curvature != CurvatureType.Concave)) { _curvature = CurvatureType.Convex; } else { _curvature = CurvatureType.SaddleOrFlat; } }
private void DefineAdvancedPlanarFace() { MinX = PlanarFace.GetMinX(); MaxX = PlanarFace.GetMaxX(); MinY = PlanarFace.GetMinY(); MaxY = PlanarFace.GetMaxY(); MinZ = PlanarFace.GetMinZ(); MaxZ = PlanarFace.GetMaxZ(); Edges = GetEdges(); if (!Edges.Any()) { IsDefined = false; return; } IsHorizontal = PlanarFace.IsHorizontal(); IsVertical = PlanarFace.IsVertical(); if (!IsVertical && !IsHorizontal) { IsDefined = false; } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Clip this voronoi cell with a passed in bounding box. /// </summary> /// <remarks> /// <para> /// I'm trying to handle all the exceptional cases. There is one incredibly exceptional /// case which I'm ignoring. That is the case where there are two vertices at infinity which are /// at such nearly opposite directions without being completely collinear that we can't push /// their points at infinity out far enough to encompass the rest of the box within the range of /// a double. If this is important to you, then see the comments below, but it's hard to imagine /// it ever arising. /// </para> /// <para> /// Editorial comment - The annoying thing about all of this is that, like in so much of /// computational geometry, the rarer and less significant the exceptional cases are, the more /// difficult they are to handle. It's both a blessing and a curse - it means that the normal /// cases are generally faster, but it also makes it difficult to get excited about slogging /// through the tedious details of situations that will probably never arise in practice. Still, /// in order to keep our noses clean, we press on regardless. /// </para> /// Darrellp, 2/26/2011. /// </remarks> /// <param name="ptUL"> The upper left point of the box. </param> /// <param name="ptLR"> The lower right point of the box. </param> /// <returns> An enumerable of real points representing the voronoi cell clipped to the box. </returns> //////////////////////////////////////////////////////////////////////////////////////////////////// public IEnumerable <Vector> BoxVertices(Vector ptUL, Vector ptLR) { // If no edges, then it's just the entire box if (!Edges.Any()) { foreach (var pt in BoxPoints(ptUL, ptLR)) { yield return(pt); } yield break; } var ptsBox = BoxPoints(ptUL, ptLR); var fFound = FCheckEasy(out var ptsToBeClipped); if (!fFound) { fFound = FCheckParallelLines(ptsBox, out ptsToBeClipped); } if (!fFound) { fFound = FCheckDoublyInfinite(ptsBox, out ptsToBeClipped); } if (!fFound) { ptsToBeClipped = RealVertices(CalcRayLength(ptsBox)); } foreach (var pt in ConvexPolyIntersection.FindIntersection(ptsToBeClipped, ptsBox)) { yield return(pt); } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Converts vertices to real vertices. </summary> /// <remarks> /// This routine does nothing for polygons with no infinite vertices. If there are no doubly /// infinite lines, it uses raylength to extend the rays. If there are doubly infinite lines it /// uses the machinery above to produce a region. No clipping is done but it's guaranteed is /// that the resultant polygon is finite and covers the polygon's portion which intersects the /// passed in box (assuming that rayLength is long enough). This routine is fairly fast, works /// with doubly infinite lines but could fail for infinite regions in which rayLength is of /// insufficient size. If you feel like raylength will handle all non-doubly infinite lines but /// you still have to deal with the doubly infinite case, this is a good choice - especially if /// perfomance is an issue. /// Darrellp, 3/1/2011. /// </remarks> /// <param name="rayLength"> Length of the ray. </param> /// <param name="ptUL"> The upper left point of the box. </param> /// <param name="ptLR"> The lower right point of the box. </param> /// <returns> An enumerable of real points representing the polygon. </returns> //////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: share code between this and BoxVertices public IEnumerable <Vector> RealVertices(double rayLength, Vector ptUL, Vector ptLR) { // If no edges, then it's just the entire box if (!Edges.Any()) { foreach (var pt in BoxPoints(ptUL, ptLR)) { yield return(pt); } yield break; } var ptsBox = BoxPoints(ptUL, ptLR); var fFound = FCheckEasy(out var points); if (!fFound) { fFound = FCheckParallelLines(ptsBox, out points); } if (!fFound) { fFound = FCheckDoublyInfinite(ptsBox, out points); } if (!fFound) { points = RealVertices(rayLength); } foreach (var pt in points) { yield return(pt); } }
// todo: not cut by rhythm // todo: i forget math private SliderTick[] GetPerfectDiscreteBallData(double interval) { if (Math.Round(interval - _singleElapsedTime) >= 0) { return(Array.Empty <SliderTick>()); } Vector2 <float> p1; Vector2 <float> p2; Vector2 <float> p3; try { p1 = StartPoint; p2 = CurvePoints[0]; p3 = CurvePoints[1]; } catch (IndexOutOfRangeException) { this.SliderType = SliderType.Linear; return(GetBezierDiscreteBallData(interval)); } var circle = GetCircle(p1, p2, p3); var radStart = Math.Atan2(p1.Y - circle.p.Y, p1.X - circle.p.X); var radMid = Math.Atan2(p2.Y - circle.p.Y, p2.X - circle.p.X); var radEnd = Math.Atan2(p3.Y - circle.p.Y, p3.X - circle.p.X); if (radMid - radStart > Math.PI) { radMid -= Math.PI * 2; } else if (radMid - radStart < -Math.PI) { radMid += Math.PI * 2; } if (radEnd - radMid > Math.PI) { radEnd -= Math.PI * 2; } else if (radEnd - radMid < -Math.PI) { radEnd += Math.PI * 2; } var ticks = new List <SliderTick>(); for (int i = 1; i *interval < _singleElapsedTime; i++) { var offset = i * interval; // 当前tick的相对时间 if (Edges.Any(k => Math.Abs(k.Offset - _offset - offset) < 0.01)) { continue; } var ratio = offset / _singleElapsedTime; // 相对整个滑条的时间比例,=距离比例 var relativeRad = (radEnd - radStart) * ratio; // 至滑条头的距离 var offsetRad = radStart + relativeRad; var x = circle.p.X + circle.r * Math.Cos(offsetRad); var y = circle.p.Y + circle.r * Math.Sin(offsetRad); ticks.Add(new SliderTick(_offset + offset, new Vector2 <float>((float)x, (float)y))); } if (Repeat > 1) { var firstSingleCopy = ticks.ToArray(); for (int i = 2; i <= Repeat; i++) { var reverse = i % 2 == 0; if (reverse) { ticks.AddRange(firstSingleCopy.Reverse().Select(k => new SliderTick((_singleElapsedTime - (k.Offset - _offset)) + (i - 1) * _singleElapsedTime + _offset, k.Point))); } else { ticks.AddRange(firstSingleCopy.Select(k => new SliderTick(k.Offset + (i - 1) * _singleElapsedTime, k.Point))); } } } return(ticks.ToArray()); //var degStart = radStart / Math.PI * 180; //var degMid = radMid / Math.PI * 180; //var degEnd = radEnd / Math.PI * 180; //return Array.Empty<SliderTick>(); }
/// <summary> /// Creates the reachspec connections from this pathfinding node to others. /// </summary> public override void CreateConnections(List <PathfindingNodeMaster> graphNodes) { ReachSpecs = (SharedPathfinding.GetReachspecExports(export)); foreach (ExportEntry spec in ReachSpecs) { Pen penToUse = blackPen; switch (spec.ObjectName.Name) { case "SlotToSlotReachSpec": penToUse = slotToSlotPen; break; case "CoverSlipReachSpec": penToUse = coverSlipPen; break; case "SFXLadderReachSpec": penToUse = sfxLadderPen; break; case "SFXLargeBoostReachSpec": penToUse = sfxLargeBoostPen; break; case "SFXBoostReachSpec": penToUse = sfxBoostPen; break; case "SFXJumpDownReachSpec": penToUse = sfxJumpDownPen; break; } //Get ending PropertyCollection props = spec.GetProperties(); ExportEntry otherEndExport = SharedPathfinding.GetReachSpecEndExport(spec, props); /* * if (props.GetProp<StructProperty>("End") is StructProperty endProperty && * endProperty.GetProp<ObjectProperty>(SharedPathfinding.GetReachSpecEndName(spec)) is ObjectProperty otherNodeValue) * { * othernodeidx = otherNodeValue.Value; * }*/ if (otherEndExport != null) { bool isTwoWay = false; PathfindingNodeMaster othernode = graphNodes.FirstOrDefault(x => x.export == otherEndExport); if (othernode != null) { //Check for returning reachspec for pen drawing. This is going to incur a significant performance penalty... var othernodeSpecs = SharedPathfinding.GetReachspecExports(otherEndExport); foreach (var path in othernodeSpecs) { if (SharedPathfinding.GetReachSpecEndExport(path) == export) { isTwoWay = true; break; } } //var // PropertyCollection otherSpecProperties = possibleIncomingSpec.GetProperties(); // if (otherSpecProperties.GetProp<StructProperty>("End") is StructProperty endStruct) // { // if (endStruct.GetProp<ObjectProperty>(SharedPathfinding.GetReachSpecEndName(possibleIncomingSpec)) is ObjectProperty incomingTargetIdx) // { // if (incomingTargetIdx.Value == export.UIndex) // { // isTwoWay = true; // break; // } // } // } //} //if (othernode != null) //{ var radius = props.GetProp <IntProperty>("CollisionRadius"); var height = props.GetProp <IntProperty>("CollisionHeight"); bool penCloned = false; if (radius != null && height != null && (radius >= ReachSpecSize.MINIBOSS_RADIUS || height >= ReachSpecSize.MINIBOSS_HEIGHT)) { penCloned = true; penToUse = (Pen)penToUse.Clone(); if (radius >= ReachSpecSize.BOSS_RADIUS && height >= ReachSpecSize.BOSS_HEIGHT) { penToUse.Width = 3; } else { penToUse.Width = 2; } } if (!isTwoWay) { if (!penCloned) { penToUse = (Pen)penToUse.Clone(); penCloned = true; } penToUse.DashStyle = DashStyle.Dash; } if (!penCloned) { //This will prevent immutable modifications later if we delete or modify reachspecs without a full //graph redraw penToUse = (Pen)penToUse.Clone(); penCloned = true; } PathfindingEditorEdge edge = new PathfindingEditorEdge { Pen = penToUse, EndPoints = { [0] = this, [1] = othernode }, OutboundConnections = { [0] = true, [1] = isTwoWay } }; if (!Edges.Any(x => x.DoesEdgeConnectSameNodes(edge)) && !othernode.Edges.Any(x => x.DoesEdgeConnectSameNodes(edge))) { //Only add edge if neither node contains this edge Edges.Add(edge); othernode.Edges.Add(edge); g.edgeLayer.AddChild(edge); } } } } }