/// <summary>
        /// Returns a color from this gradient at the specified lerp value.
        /// </summary>
        /// <param name="amount">The lerp amount.</param>
        /// <returns>A color.</returns>
        public Color Lerp(float amount)
        {
            if (Stops.Length == 0)
            {
                throw new global::System.IndexOutOfRangeException("The ColorGradient object does not have any gradient stops defined.");
            }

            else if (Stops.Length == 1)
            {
                return(Stops[0].Color);
            }

            int counter;

            for (counter = 0; counter < Stops.Length && Stops[counter].Stop < amount; counter++)
            {
                ;
            }

            counter--;
            counter = (int)MyMathHelper.Clamp(counter, 0, Stops.Length - 2);

            float newLerp = (Stops[counter].Stop - (float)amount) / (Stops[counter].Stop - Stops[counter + 1].Stop);

            return(ColorHelper.Lerp(Stops[counter].Color, Stops[counter + 1].Color, newLerp));
        }
Beispiel #2
0
        /// <summary>
        /// Processes an area and applies a gradient calculation to each part of the area.
        /// </summary>
        /// <param name="position">The center of the gradient.</param>
        /// <param name="strength">The width of the gradient spread.</param>
        /// <param name="angle">The angle to apply the gradient.</param>
        /// <param name="area">The area to calculate.</param>
        /// <param name="applyAction">The callback called for each part of the area.</param>
        public static void GradientFill(Point cellSize, Point position, int strength, int angle, Rectangle area, ColorGradient gradient, Action <int, int, Color> applyAction)
        {
            double radians = angle * Math.PI / 180; // = Math.Atan2(x1 - x2, y1 - y2);

            Vector2 angleVector = new Vector2((float)(Math.Sin(radians) * strength), (float)(Math.Cos(radians) * strength)) / 2;
            Vector2 location    = new Vector2(position.X, position.Y);

            if (cellSize.X > cellSize.Y)
            {
                angleVector.Y *= cellSize.X / cellSize.Y;
            }

            else if (cellSize.X < cellSize.Y)
            {
                angleVector.X *= cellSize.Y / cellSize.X;
            }

            Vector2 endingPoint   = location + angleVector;
            Vector2 startingPoint = location - angleVector;

            double x1 = (startingPoint.X / (double)area.Width) * 2.0f - 1.0f;
            double y1 = (startingPoint.Y / (double)area.Height) * 2.0f - 1.0f;
            double x2 = (endingPoint.X / (double)area.Width) * 2.0f - 1.0f;
            double y2 = (endingPoint.Y / (double)area.Height) * 2.0f - 1.0f;

            double start = x1 * angleVector.X + y1 * angleVector.Y;
            double end   = x2 * angleVector.X + y2 * angleVector.Y;

            for (int x = area.Left; x < area.Width; x++)
            {
                for (int y = area.Top; y < area.Height; y++)
                {
                    // but we need vectors from (-1, -1) to (1, 1)
                    // instead of pixels from (0, 0) to (width, height)
                    double u = (x / (double)area.Width) * 2.0f - 1.0f;
                    double v = (y / (double)area.Height) * 2.0f - 1.0f;

                    double here = u * angleVector.X + v * angleVector.Y;

                    double lerp = (start - here) / (start - end);

                    //lerp = Math.Abs((lerp - (int)lerp));

                    lerp = MyMathHelper.Clamp((float)lerp, 0f, 1.0f);

                    int counter;
                    for (counter = 0; counter < gradient.Stops.Length && gradient.Stops[counter].Stop < (float)lerp; counter++)
                    {
                        ;
                    }

                    counter--;
                    counter = (int)MyMathHelper.Clamp(counter, 0, gradient.Stops.Length - 2);

                    float newLerp = (gradient.Stops[counter].Stop - (float)lerp) / (gradient.Stops[counter].Stop - gradient.Stops[counter + 1].Stop);

                    applyAction(x, y, ColorHelper.Lerp(gradient.Stops[counter].Color, gradient.Stops[counter + 1].Color, newLerp));
                }
            }
        }
        /// <summary>
        /// Creates a <see cref="SadConsole.ColoredString"/> object using the current gradient.
        /// </summary>
        /// <param name="text">The text to use for the colored string.</param>
        /// <returns>A new colored string object.</returns>
        public SadConsole.ColoredString ToColoredString(string text)
        {
            SadConsole.ColoredString stringObject = new SadConsole.ColoredString(text);

            if (Stops.Length == 0)
            {
                throw new global::System.IndexOutOfRangeException("The ColorGradient object does not have any gradient stops defined.");
            }

            else if (Stops.Length == 1)
            {
                stringObject.SetForeground(Stops[0].Color);
                return(stringObject);
            }

            float lerp      = 1f / (text.Length - 1);
            float lerpTotal = 0f;

            stringObject[0].Foreground = Stops[0].Color;
            stringObject[text.Length - 1].Foreground = Stops[Stops.Length - 1].Color;

            for (int i = 1; i < text.Length - 1; i++)
            {
                lerpTotal += lerp;
                int counter;
                for (counter = 0; counter < Stops.Length && Stops[counter].Stop < lerpTotal; counter++)
                {
                    ;
                }

                counter--;
                counter = (int)MyMathHelper.Clamp(counter, 0, Stops.Length - 2);

                float newLerp = (Stops[counter].Stop - (float)lerpTotal) / (Stops[counter].Stop - Stops[counter + 1].Stop);

                stringObject[i].Foreground = ColorHelper.Lerp(Stops[counter].Color, Stops[counter + 1].Color, newLerp);
            }

            return(stringObject);
        }