public void Draw(PathingGraphEditor g) { for (int i = 0; i < ReparamTable.Points.Count; i++) { InterpCurvePoint <float> reparamTablePoint = ReparamTable.Points[i]; (float x, float y, _) = SplineInfo.Eval(reparamTablePoint.OutVal, Vector3.Zero); var node = new SplineParambleNode(x, y, i == 6); nodes.Add(node); } if (nodes.Count > 7) { var directionVector = new Vector2(nodes[7].OffsetX, nodes[7].OffsetY) - new Vector2(nodes[5].OffsetX, nodes[5].OffsetY); directionVector.Normalize(); nodes[6].RotateBy((float)(Math.Atan2(directionVector.X, -directionVector.Y) * 180 / Math.PI)); } AddChildren(nodes); for (int i = 1; i < nodes.Count; i++) { PathfindingEditorEdge edge = new PathfindingEditorEdge { EndPoints = { [0] = nodes[i - 1], [1] = nodes[i] }, Pen = Pens.Purple }; edges.Add(edge); g.edgeLayer.AddChild(edge); } }
public PathfindingEditorEdge CreateConnection(PathingGraphEditor g) { if (Edge != null) { g.edgeLayer.RemoveChild(Edge); } return(Edge = new PathfindingEditorEdge { EndPoints = { [0] = this, [1] = splineActor }, Pen = Pens.White }); }
/// <summary> /// Creates straight edged lines, from the center of the node. /// </summary> /// <param name="edge"></param> public static void UpdateEdgeStraight(PathfindingEditorEdge edge) { // Note that the node's "FullBounds" must be used (instead of just the "Bound") // because the nodes have non-identity transforms which must be included when // determining their position. PNode node1 = edge.EndPoints[0]; PNode node2 = edge.EndPoints[1]; PointF start = node1.GlobalBounds.Location; PointF end = node2.GlobalBounds.Location; edge.Reset(); edge.AddLine(start.X + node1.GlobalBounds.Width * 0.5f, start.Y + node1.GlobalBounds.Height * 0.5f, end.X + node2.GlobalBounds.Width * 0.5f, end.Y + node2.GlobalBounds.Height * 0.5f); }
/// <summary> /// This beginning node of the spline connects to the destination point over a bezier curve. /// </summary> public override void CreateConnections(List <PathfindingNodeMaster> Objects) { PathfindingEditorEdge edge = new PathfindingEditorEdge(); edge.Pen = splineconnnectorPen; //TODO: Calculate where points B and C lie in actual space for calculating the overhead curve //edge.BezierPoints = new float[2]; //SharpDX.Vector2 b = a + tan1 / 3.0f; // Operator overloading is lovely. Java can go die in a hole. //SharpDX.Vector2 c = d - tan2 / 3.0f; ((ArrayList)Tag).Add(edge); ((ArrayList)destinationPoint.Tag).Add(edge); edge.Tag = new ArrayList(); ((ArrayList)edge.Tag).Add(this); ((ArrayList)edge.Tag).Add(destinationPoint); g.edgeLayer.AddChild(edge); }
/// <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); } } } }
public static void UpdateEdgeBezier(PathfindingEditorEdge edge) { // Note that the node's "FullBounds" must be used (instead of just the "Bound") // because the nodes have non-identity transforms which must be included when // determining their position. ArrayList nodes = (ArrayList)edge.Tag; PNode node1 = (PNode)nodes[0]; PNode node2 = (PNode)nodes[1]; PointF start = node1.GlobalBounds.Location; PointF end = node2.GlobalBounds.Location; float h1x, h1y, h2x; if (nodes.Count > 2 && (int)nodes[2] == -1) //var link { start.X += node1.GlobalBounds.Width * 0.5f; start.Y += node1.GlobalBounds.Height; h1x = h2x = 0; h1y = end.Y > start.Y ? 200 * (float)Math.Log10((end.Y - start.Y) / 200 + 1) : 200 * (float)Math.Log10((start.Y - end.Y) / 100 + 1); if (h1y < 15) { h1y = 15; } end.X += node2.GlobalBounds.Width / 2; end.Y += node2.GlobalBounds.Height / 2; } else { start.X += node1.GlobalBounds.Width; start.Y += node1.GlobalBounds.Height * 0.5f; end.Y += node2.GlobalBounds.Height * 0.5f; h1x = h2x = end.X > start.X ? 200 * (float)Math.Log10((end.X - start.X) / 200 + 1) : 200 * (float)Math.Log10((start.X - end.X) / 100 + 1); if (h1x < 15) { h1x = h2x = 15; } h1y = 0; } edge.Reset(); edge.AddBezier(start.X, start.Y, start.X + h1x, start.Y + h1y, end.X - h2x, end.Y, end.X, end.Y); }
/// <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); } } } } }
public bool DoesEdgeConnectSameNodes(PathfindingEditorEdge otherEdge) { return(EndPoints.All(otherEdge.EndPoints.Contains)); }
public void addEdgeBezier(PathfindingEditorEdge p) { edgeLayer.AddChild(p); UpdateEdgeBezier(p); }
public void addEdge(PathfindingEditorEdge p) { edgeLayer.AddChild(p); UpdateEdgeStraight(p); }