Exemple #1
0
        public override void DrawOn2DControlTopDownView(MapObjectHoverData hoverData)
        {
            float marioHeight = Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.YOffset);
            float?height      = _relativeHeight.HasValue ? marioHeight - _relativeHeight.Value : _absoluteHeight;

            List <TriangleMapData> wallDataList = GetFilteredTriangles()
                                                  .ConvertAll(tri => MapUtilities.Get2DWallDataFromTri(tri, height))
                                                  .FindAll(wallDataNullable => wallDataNullable != null);

            foreach (TriangleMapData wallData in wallDataList)
            {
                float angle          = (float)MoreMath.AngleTo_Radians(wallData.X1, wallData.Z1, wallData.X2, wallData.Z2);
                float projectionDist = Size / (float)Math.Abs(wallData.Tri.XProjection ? Math.Cos(angle) : Math.Sin(angle));
                List <List <(float x, float z)> > quads = new List <List <(float x, float z)> >();
                void addQuad(float xAdd, float zAdd)
                {
                    quads.Add(new List <(float x, float z)>()
                    {
                        (wallData.X1, wallData.Z1),
                        (wallData.X1 + xAdd, wallData.Z1 + zAdd),
                        (wallData.X2 + xAdd, wallData.Z2 + zAdd),
                        (wallData.X2, wallData.Z2),
                    });
                };
                if (wallData.Tri.XProjection)
                {
                    addQuad(projectionDist, 0);
                    addQuad(-1 * projectionDist, 0);
                }
                else
                {
                    addQuad(0, projectionDist);
                    addQuad(0, -1 * projectionDist);
                }

                List <List <(float x, float z)> > quadsForControl =
                    quads.ConvertAll(quad => quad.ConvertAll(
                                         vertex => MapUtilities.ConvertCoordsForControlTopDownView(vertex.x, vertex.z, UseRelativeCoordinates)));

                GL.BindTexture(TextureTarget.Texture2D, -1);
                GL.MatrixMode(MatrixMode.Modelview);
                GL.LoadIdentity();

                // Draw quad
                byte opacityByte = OpacityByte;
                if (this == hoverData?.MapObject && hoverData?.Tri == wallData.Tri && !hoverData.Index.HasValue)
                {
                    opacityByte = MapUtilities.GetHoverOpacityByte();
                }
                GL.Color4(Color.R, Color.G, Color.B, opacityByte);
                GL.Begin(PrimitiveType.Quads);
                foreach (List <(float x, float z)> quad in quadsForControl)
                {
                    foreach ((float x, float z) in quad)
                    {
                        GL.Vertex2(x, z);
                    }
                }
                GL.End();

                if (_showArrows)
                {
                    double totalDistance = MoreMath.GetDistanceBetween(
                        wallData.X1, wallData.Z1, wallData.X2, wallData.Z2);
                    List <double> markDistances = new List <double>();
                    if (totalDistance < 100)
                    {
                        markDistances.Add(totalDistance / 2);
                    }
                    else
                    {
                        int    cardinalAngle        = wallData.Tri.XProjection ? 16384 : 0;
                        double angleDiffCoefficient = 1 / Math.Abs(Math.Cos(MoreMath.AngleUnitsToRadians(wallData.Tri.GetPushAngle() - cardinalAngle)));
                        double firstDistance        = 25 * angleDiffCoefficient;
                        double lastDistance         = totalDistance - 25 * angleDiffCoefficient;
                        double distanceDiff         = lastDistance - firstDistance;
                        int    numMarks             = (int)Math.Truncate(distanceDiff / 50 + 0.25) + 1;
                        int    numBetweens          = numMarks - 1;
                        double betweenDistance      = distanceDiff / numBetweens;
                        for (int i = 0; i < numMarks; i++)
                        {
                            markDistances.Add(firstDistance + i * betweenDistance);
                        }
                    }

                    List <(float x, float z)> markPoints = new List <(float x, float z)>();
                    foreach (double dist in markDistances)
                    {
                        double portion = dist / totalDistance;
                        (double x, double z)pointOnMidpoint =
                            (wallData.X1 + portion * (wallData.X2 - wallData.X1), wallData.Z1 + portion * (wallData.Z2 - wallData.Z1));
                        (double x, double z)pointOnSide1 = wallData.Tri.XProjection ?
                                                           (pointOnMidpoint.x - projectionDist / 2, pointOnMidpoint.z) :
                                                           (pointOnMidpoint.x, pointOnMidpoint.z - projectionDist / 2);
                        (double x, double z)pointOnSide2 = wallData.Tri.XProjection ?
                                                           (pointOnMidpoint.x + projectionDist / 2, pointOnMidpoint.z) :
                                                           (pointOnMidpoint.x, pointOnMidpoint.z + projectionDist / 2);
                        markPoints.Add(((float x, float z))pointOnSide1);
                        markPoints.Add(((float x, float z))pointOnSide2);
                    }

                    markPoints = markPoints.FindAll(p => MapUtilities.IsInVisibleSpace(p.x, p.z, 200));

                    double pushAngle      = wallData.Tri.GetPushAngle();
                    double angleUp        = pushAngle;
                    double angleDown      = pushAngle + 32768;
                    double angleLeft      = pushAngle + 16384;
                    double angleRight     = pushAngle - 16384;
                    double angleUpLeft    = pushAngle + 8192;
                    double angleUpRight   = pushAngle - 8192;
                    double angleDownLeft  = pushAngle + 24576;
                    double angleDownRight = pushAngle - 24576;

                    double arrowBaseLength = 0.4 * Math.Min(Size, 50);
                    double arrowSideLength = 0.2 * Math.Min(Size, 50);

                    List <List <(float x, float z)> > arrowPoints = markPoints.ConvertAll(midPoint =>
                    {
                        (float x, float z)frontPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength, angleUp, midPoint.x, midPoint.z);
                        (float x, float z)leftOuterPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength / 2 + arrowSideLength, angleLeft, midPoint.x, midPoint.z);
                        (float x, float z)leftInnerPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength / 2, angleLeft, midPoint.x, midPoint.z);
                        (float x, float z)rightOuterPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength / 2 + arrowSideLength, angleRight, midPoint.x, midPoint.z);
                        (float x, float z)rightInnerPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength / 2, angleRight, midPoint.x, midPoint.z);
                        (float x, float z)backLeftPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength, angleDown, leftInnerPoint.x, leftInnerPoint.z);
                        (float x, float z)backRightPoint = ((float, float))MoreMath.AddVectorToPoint(
                            arrowBaseLength, angleDown, rightInnerPoint.x, rightInnerPoint.z);

                        return(new List <(float x, float z)>()
                        {
                            frontPoint,
                            leftOuterPoint,
                            leftInnerPoint,
                            backLeftPoint,
                            backRightPoint,
                            rightInnerPoint,
                            rightOuterPoint,
                        });
                    });

                    List <List <(float x, float z)> > arrowsForControl =
                        arrowPoints.ConvertAll(arrow => arrow.ConvertAll(
                                                   vertex => MapUtilities.ConvertCoordsForControlTopDownView(vertex.x, vertex.z, UseRelativeCoordinates)));

                    // Draw arrow
                    Color arrowColor = Color.Darken(0.5);
                    GL.Color4(arrowColor.R, arrowColor.G, arrowColor.B, opacityByte);
                    foreach (List <(float x, float z)> arrow in arrowsForControl)
                    {
                        GL.Begin(PrimitiveType.Polygon);
                        foreach ((float x, float z) in arrow)
                        {
                            GL.Vertex2(x, z);
                        }
                        GL.End();
                    }
                }

                // Draw outline
                if (LineWidth != 0)
                {
                    GL.Color4(LineColor.R, LineColor.G, LineColor.B, (byte)255);
                    GL.LineWidth(LineWidth);
                    foreach (List <(float x, float z)> quad in quadsForControl)
                    {
                        GL.Begin(PrimitiveType.LineLoop);
                        foreach ((float x, float z) in quad)
                        {
                            GL.Vertex2(x, z);
                        }
                        GL.End();
                    }
                }

                if (_customImage != null)
                {
                    for (int i = 0; i < quadsForControl.Count; i++)
                    {
                        var quad = quadsForControl[i];
                        for (int j = 0; j < quad.Count; j++)
                        {
                            var    vertex  = quad[j];
                            PointF point   = new PointF(vertex.x, vertex.z);
                            SizeF  size    = MapUtilities.ScaleImageSizeForControl(_customImage.Size, _iconSize, Scales);
                            double opacity = 1;
                            if (this == hoverData?.MapObject && hoverData?.Tri == wallData.Tri && i == hoverData?.Index && j == hoverData?.Index2)
                            {
                                opacity = MapUtilities.GetHoverOpacity();
                            }
                            MapUtilities.DrawTexture(_customImageTex.Value, point, size, 0, opacity);
                        }
                    }
                }

                GL.Color4(1, 1, 1, 1.0f);
            }
        }