예제 #1
0
        public SplinePoint0Node(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor)
            : base(idx, p, grapheditor)
        {
            StructProperty splineInfo = export.GetProperty <StructProperty>("SplineInfo");

            if (splineInfo != null)
            {
                var            pointsProp = splineInfo.GetProp <ArrayProperty <StructProperty> >("Points");
                StructProperty point0     = pointsProp[0];
                StructProperty point1     = pointsProp[1];
                a    = SharedPathfinding.GetVector2(point0.GetProp <StructProperty>("OutVal"));
                tan1 = SharedPathfinding.GetVector2(point0.GetProp <StructProperty>("LeaveTangent"));
                tan2 = SharedPathfinding.GetVector2(point1.GetProp <StructProperty>("ArriveTangent"));
                d    = SharedPathfinding.GetVector2(point1.GetProp <StructProperty>("OutVal"));
                const float w = 25;
                const float h = 25;
                shape          = PPath.CreateEllipse(0, 0, w, h);
                outlinePen     = new Pen(color);
                shape.Pen      = outlinePen;
                shape.Brush    = pathfindingNodeBrush;
                shape.Pickable = false;
                this.AddChild(shape);
                this.Bounds = new RectangleF(0, 0, w, h);
                SText val = new SText($"{export.Index}\nSpline Start");
                val.Pickable      = false;
                val.TextAlignment = StringAlignment.Center;
                val.X             = w / 2 - val.Width / 2;
                val.Y             = h / 2 - val.Height / 2;
                this.AddChild(val);
                this.TranslateBy(x, y);
            }
        }
예제 #2
0
        public override void LoadTrack()
        {
            Keys.ClearEx();
            var lookupstruct = Export.GetProperty <StructProperty>("LookupTrack");

            if (lookupstruct != null)
            {
                var trackKeys = lookupstruct.GetProp <ArrayProperty <StructProperty> >("Points"); //on lookuptrack

                var posTrack = Export.GetProperty <StructProperty>("PosTrack");
                ArrayProperty <StructProperty> points = posTrack?.GetProp <ArrayProperty <StructProperty> >("Points");
                if (trackKeys != null)
                {
                    int keyindex = 0;
                    foreach (var trackKey in trackKeys)
                    {
                        string tooltip = null;
                        if (points != null && points.Count > keyindex)
                        {
                            StructProperty vector = points[keyindex].GetProp <StructProperty>("OutVal");
                            var            point  = SharedPathfinding.GetLocationFromVector(vector);
                            tooltip = $"X={point.X},Y={point.Y},Z={point.Z}";
                        }

                        var time = trackKey.GetProp <FloatProperty>("Time");
                        Debug.WriteLine(time.Value);
                        Keys.Add(new Key(time, tooltip));
                        keyindex++;
                    }
                }
            }
        }
예제 #3
0
        public override void LoadTrack()
        {
            Keys.ClearEx();
            var vectorTrackProp = Export.GetProperty <StructProperty>("VectorTrack");

            if (vectorTrackProp != null)
            {
                foreach (var curvePoint in vectorTrackProp.GetPropOrDefault <ArrayProperty <StructProperty> >("Points"))
                {
                    var outval = SharedPathfinding.GetLocationFromVector(curvePoint.GetProp <StructProperty>("OutVal")); //gets X Y Z
                    Keys.Add(new Key(curvePoint.GetProp <FloatProperty>("InVal"), $"X={outval.X},Y={outval.Y},Z={outval.Z}"));
                }
            }
        }
예제 #4
0
        /// <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);
                        }
                    }
                }
            }
        }
예제 #5
0
        public void UpdateSplines(UpdateMode mode, bool save = false)
        {
            if (mode == UpdateMode.ArriveTangent || mode == UpdateMode.LeaveTangent)
            {
                Vector3 worldCoords;
                if (mode == UpdateMode.ArriveTangent)
                {
                    worldCoords = new Vector3(ArriveTangentControlNode.OffsetX, ArriveTangentControlNode.OffsetY, ArriveTangentControlNode.Z);
                    LeaveTangentControlNode.SetOffset(-worldCoords.X, -worldCoords.Y);

                    worldCoords = -worldCoords;
                }
                else
                {
                    worldCoords = new Vector3(LeaveTangentControlNode.OffsetX, LeaveTangentControlNode.OffsetY, LeaveTangentControlNode.Z);
                    ArriveTangentControlNode.SetOffset(-worldCoords.X, -worldCoords.Y);
                }

                if (save)
                {
                    //will cause a refresh,so no need to update UI
                    export.WriteProperty(CommonStructs.Vector3Prop(ActorUtils.GetWorldToLocal(export).TransformNormal(worldCoords), "SplineActorTangent"));
                    return;
                }

                foreach (Spline spline in Splines)
                {
                    spline.SplineInfo.Points[0].ArriveTangent = -worldCoords;
                    spline.SplineInfo.Points[0].LeaveTangent  = worldCoords;
                    UpdateSpline(spline);
                }

                foreach (SplineActorNode prevSplineActor in LinksFrom)
                {
                    foreach (Spline spline in prevSplineActor.Splines)
                    {
                        if (spline.NextActor == export)
                        {
                            spline.SplineInfo.Points[1].ArriveTangent = worldCoords;
                            spline.SplineInfo.Points[1].LeaveTangent  = -worldCoords;
                            UpdateSpline(spline);
                        }
                    }
                }
            }
            else
            {
                float   z        = (float)SharedPathfinding.GetLocation(export).Z;
                Vector3 location = new Vector3(OffsetX, OffsetY, z);

                if (save)
                {
                    //will cause a refresh,so no need to update UI
                    SharedPathfinding.SetLocation(export, location.X, location.Y, location.Z);
                    return;
                }

                foreach (Spline spline in Splines)
                {
                    spline.SplineInfo.Points[0].OutVal = location;
                    UpdateSpline(spline);
                }

                foreach (SplineActorNode prevSplineActor in LinksFrom)
                {
                    foreach (Spline spline in prevSplineActor.Splines)
                    {
                        if (spline.NextActor == export)
                        {
                            spline.SplineInfo.Points[1].OutVal = location;
                            UpdateSpline(spline);
                        }
                    }
                }
            }

            PathingGraphEditor.UpdateEdgeStraight(ArriveTangentControlNode.Edge);
            PathingGraphEditor.UpdateEdgeStraight(LeaveTangentControlNode.Edge);

            void UpdateSpline(Spline spline)
            {
                spline.RegenerateReparamTable();
                for (int i = 0; i < spline.ReparamTable.Points.Count; i++)
                {
                    (float x, float y, _) = spline.SplineInfo.Eval(spline.ReparamTable.Points[i].OutVal, Vector3.Zero);
                    spline.nodes[i].SetOffset(x, y);
                }

                if (spline.nodes.Count > 7)
                {
                    var directionVector = new Vector2(spline.nodes[7].OffsetX, spline.nodes[7].OffsetY) - new Vector2(spline.nodes[5].OffsetX, spline.nodes[5].OffsetY);
                    directionVector.Normalize();
                    spline.nodes[6].Rotation = (float)(Math.Atan2(directionVector.X, -directionVector.Y) * 180 / Math.PI);
                }

                foreach (PathfindingEditorEdge edge in spline.edges)
                {
                    PathingGraphEditor.UpdateEdgeStraight(edge);
                }
            }
        }