Как вывести часть текста в monogame, которая помещается в указанной области

Всем доброго времени суток. Недавно я начал изучать Monogame. Мне понравился этот фреймворк, но там нету (либо я не нашёл) элементов GUI. Я решил сам написать библиотеку для GUI, и там создать все необходимые мне элементы. Но я столкнулся с проблемой при выводе текста. Там есть метод DrawString, который позволяет вывести одну строку, но нет возможности выводить текст в указанном прямоугольнике. Я попробовал сам сделать метод:

/// <summary>
/// Выводит текст в указанной области с выравниванием по указанному краю.
/// </summary>
/// <param name="sb"></param>
/// <param name="font">Шрифт для вывода текста.</param>
/// <param name="text">Текст.</param>
/// <param name="parent">Область для вывода.</param>
/// <param name="color">Цвет текста.</param>
/// <param name="align">Выравнивание текста.</param>
/// <param name="padding">Дополнительный отступ.</param>
/// <param name="finalizer">Символ завершения текста. Будет появляться в случае, если текст не помещается с указанный прямоугольник.</param>
public static void DrawString(this SpriteBatch sb, SpriteFont font, string text, Rectangle parent, Color color, TextAlign align = TextAlign.Left, int padding = 10, char finalizer = '…')
{
    padding += 10;
    int remaininglength = text.Length;//Оставшееся количество символов.
    int id = 0;//Индекс символа, с которого начинается конкретная строка.
    int yshift = 0;//Отступ по оси y для многострочного вывода.
    if (font.MeasureString("…").X >= parent.Width || font.MeasureString("…").Y >= parent.Height)//Проверяем, сможет ли вообще поместиться текст в прямоугольнике.
    {
        return;
    }
    while (remaininglength > 0)
    {
        bool exending = false;//Если true, значит строка не была напечатана полностью из-за правил переноса.
        int prt = 0;//Коичество символов, которое будет выведено в этой строке
        float length; //Длина выводимого текста.
        while ((length = font.MeasureString(text.Substring(id, prt)).X) < parent.Width - padding || (prt + id >= text.Length - 2 && prt + id < text.Length))//Определяем число символов, которое будет выведено в этой строке.
        {
            if (prt + id >= text.Length) break;
            if ((text[prt + id] == '-' || text[prt + id] == ' ' || text[(prt + id + 1) % text.Length] == ' ') && length >= parent.Width - 4 * padding)
            {
                exending = true;
                prt++;
                break;
            }
            if (text[prt+id] == '\n')
            {
                exending = true;
                text = text.Remove(prt + id, 1);
                prt--;
                remaininglength--;
                break;
            }
            prt++;
        }
        if (prt + id < text.Length - 1)
            if (text[prt + id] != ' ' && (text[prt + id + 1] == ' ' || text[prt + id + 1] == '-'))
            {
                exending = true;
                prt++;
            }
        char addition = (remaininglength - prt <= 0) || exending ? ' ' : '-';//Определяем, какой символ будет добавлен в конце строки. Если был перенос, то '-', если текст не поместился полностью, то '…'.
        addition = (yshift + font.LineSpacing >= parent.Height - padding && remaininglength - prt > 0) ? finalizer : addition;
        switch (align)//Выводим текст в зависимости от выравнивания.
        {
            case TextAlign.Left:
                {
                     sb.DrawString(font, (text.Substring(id, prt) + addition).Trim(), new Vector2(parent.X, parent.Y + yshift), color);
                     break;
                }
            case TextAlign.Right:
                {
                    int shift = parent.Width - (int)font.MeasureString((text.Substring(id, prt) + addition).Trim()).X;
                    sb.DrawString(font, (text.Substring(id, prt) + addition).Trim(), new Vector2(parent.X + shift - 5, parent.Y + yshift), color);
                    break;
                }
            case TextAlign.Center:
                {
                    int shift = parent.Width - (int)font.MeasureString((text.Substring(id, prt) + addition).Trim()).X;
                    sb.DrawString(font, (text.Substring(id, prt) + addition).Trim(), new Vector2(parent.X + (shift/2) - 5, parent.Y + yshift), color);
                    break;
                }
        }
                
        id += prt;
        yshift += font.LineSpacing;
        remaininglength -= prt;
        if (yshift >= parent.Height - padding) break;
   }
}

Он выполняет эту функцию, но возможно ли его доработать? Например, можно бы было избавиться от переменной padding, но я не знаю, как сделать это. Шрифт же разный может быть.

После того, как я реализовал прокрутку элементов, я понял, что этот метод работает не так, как хотелось бы. При прокрутке у меня изменяются координаты элементов и области, в которых выводится контент. Если текст выходит за рамки контейнера, он просто выводит только начало строки, уменьшая количество символов, пока это возможно. Возможно ли частично отрисовывать текстуры символов, чтобы, если он частично выходит за границы прямоугольника, было, как будто он частично выходит за границы экрана? То есть по строчкам переносится, но когда выходит за рамки, перестаёт отрисовываться. И ещё можно сделать, чтобы он переносился по правилам переноса?


Ответы (0 шт):