Пользовательский интерфейс

Библиотека Helianthus позволяет вам легко создавать элементы пользовательского интерфейса, такие как кнопки, поля для ввода текста, выпадающие списки и многое другое.

Для этого в проект включена библиотека Nuklear UI. Данная библиотека предоставляет большой набор функции и нам здесь будет затруднительно описать их все. Поэтому отправляем вас на сайт Nukear чтобы ознакомиться со всей документацией из первых рук:

https://immediate-mode-ui.github.io/Nuklear/doc/index.html

Здесь мы лишь дадим небольшой пример и опишем функции связывающие Nuklear с Helianthus. И вот пример простой программы:

#include <helianthus-nk.h> // обратите внимание на -nk.h

nk_heli hnk;           // контекст Helianthus-Nuklear
struct nk_context *nk; // контекст непосредственно Nuklear

void init() {
    nk_heli_init(&hnk, 12); // инициальзоровать Nuklear
    nk = &hnk.context;      // получить контекст
}

void draw() {
    // Создаём окно Nuklear и заполняем его кнопками
    if (nk_begin(nk, "My Window", nk_rect(10, 10, 200, 300),
        NK_WINDOW_BORDER|NK_WINDOW_TITLE|NK_WINDOW_MOVABLE))
    {
        // если окно создано и его видно, то продолжаем:
        
        // создаём новую строку в интерфейсе
        nk_layout_row_dynamic(nk, 30, 1);
        
        // Добавляем кнопку в строку и, одновременно с этим,
        // проверяем нажата ли она.
        // Если нажата то печатаем текст в консоль
        if (nk_button_label(nk, "hello"))
            printf("hello\n");
        
        // следующая строка
        nk_layout_row_dynamic(nk, 30, 1);

        // и следующая кнопка
        if (nk_button_label(nk, "world"))
            printf("world\n");
    }

    // независимо от того было ли видно окно, нужно сообщить
    // Nuklear, что c этим окном мы работу закончили:
    nk_end(nk);

    // После того как все окна созданы и заполнены
    // нужно, чтобы Nuklear проанализировал нажатые
    // клавиши и движения мыши и в итоге нарисовал
    // сформированный нами интерфейс на экране.
    // Это делается одной командой:
    nk_heli_process(&hnk);
}

void deinit() {
    nk_heli_deinit(&hnk); // завершить работу с Nuklear
}

int main() {
    windowSetVariableFrameRate(); // для более плавной анимации
    windowSetInit(&init);
    windowSetDraw(&draw);
    windowSetDeinit(&deinit);
    windowRun();
    return 0;
}

Обратите внимание, что для работы с Nuklear вам нужно подключить файл <helianthus-hk.h> вместо обычного <helianthus.h>. Это сделано для того, чтобы у вас была возможность не загромождать пространство имён Си обширным набором функций Nuklear, тогда когда они вам не нужны.

Для работы с Nuklear вам нужно создать переменную типа nk_heli и инициализировать её с помощью функции nk_heli_init. И, соответственно, после завершения работы с Nuklear нужно ей деинициализировать, вызвав функцию nk_heli_deinit. Если одновременно с этим вы заканчиваете и работу всей программы, то деинициализировать переменную не обязательно. Вот в нашем примере как раз деинициальзацию можно было и не делать — она там только для примера...

Структура nk_heli содержит в себе поле context — это указатель на контекст Nuklear, он нужен при обращении к любой фукнции Nuklear. Для удобства в нашем примере мы скопировали его в отдельную переменную.

Функция nk_begin открывает работу с новым окном Nuklear. После заполнения окна нужно обязательно вызвать nk_end. Нельзя оставлять nk_begin без пары (nk_end) — это может привести к ошибкам в работе программы (и обязательно приведёт). Подробнее об этих функциях вы можете почитать в документации на сайте Nuklear.

Функции семейства nk_layout_xxxxx управляют размещением элементов в окне. Мы использовали один из самых простых методов разметки — nk_layout_row_dynamic. Он создаёт новую строку элементов в окне качестве аргументов принимает высоту строки и количество элементов в ней. Точнее количество элементов которое будет в строке — изначально строка создаётся незаполненной. Подробнее о разметке смотрите в оригинальной документации Nuklear.

Функция nk_button_label создаёт кнопку и сразу же проверяет была ли она нажата. Это кажется странным, так как на этом этапе Nuklear толком не знает где должна находиться кнопка и к тому же ещё и не проанализированы движения мыши и нажатия клавиш. Дело в том, что Nuklear запоминает какие элементы интерфейса были созданы на предыдущем кадре, и, если порядок создания элементов не изменился, можно легко связать старые и новые элементы и вычислить, была ли кнопка нажата на предыдущем кадре. Так в общем Nuklear и работает. Если вам это не очень понятно — не волнуйтесь, Nuklear всё равно делает всю работу за вас, а для вас оставляет простой в использовании функционал. Подробнее про nk_button_xxxxx и другие элементы читайте в оригинальной документации Nuklear.

После того как интерфейс сформирован и работа с окном завершена (nk_end) необходимо вызвать функцию nk_heli_process. Она проанализирует пользовательский ввод (мышь и клавиатуру) и затем нарисует интерфейс на экране. Как вы можете видеть функция делает сразу две операции: анализ ввода и рисование. Если вы хотите вы можете запустить их по отдельности используя функции nk_heli_input и nk_heli_draw, соответсвенно.

Некоторые элементы Nuklear работают с изображениями. Чтобы создать изображение для Nuklear используйте функцию nk_heli_image.

Также Helianthus включает в себя ещё две полезные функции: nk_color_from_heli и nk_color_to_heli. Они преобразуют цвет из формата Helianthus в формат Nuklear и наоборот.

Функции:

nk_bool nk_heli_init(nk_heli *n, double fontSize);

Инициализирует контекст Helianthus-Nuklear. Функция возвращает TRUE если инициализация прошла успешно. После успешной инициализации указатель на чистый контекст Nuklear можно получить из поля context структуры nk_heli (n->context). См. также nk_heli_deinit, nk_heli_process.

Параметры:

n — указатель на переменную типа nk_heli;
fontSize — размер шрифта, который будет использоваться во всех элементах Nuklear.

void nk_heli_deinit(nk_heli *n);

Деинициализирует ранее инициализированный контекст Helianthus-Nuklear. После этой операции все внутренние структуры Nuklear будут очищены и их память освобождена. Контекст больше нельзя использовать (но можно повторно инициализировать, см. nk_heli_init).

void nk_heli_input(nk_heli *n);

Данная функция анализирует нажатия клавиш и движения мыши и выполняет соответствующие действия в интерфейсе. См. также nk_heli_init, nk_heli_draw и nk_heli_process.

void nk_heli_draw(nk_heli *n);

Рисует элементы интерфейса на экране. См. также nk_heli_init, nk_heli_input и nk_heli_process.

void nk_heli_process(nk_heli *n);

Анализирует нажатия клавиш и движения мыши и рисует элементы интерфейса на экране. Данная функция вызывает последовательно nk_heli_input и nk_heli_draw, ничего от себя не добавляя. То есть вместо nk_heli_process вы можете вызвать указанные функции по отдельности самостоятельно, если вам это будет удобнее. См. также nk_heli_init, nk_heli_input и nk_heli_draw.

struct nk_image nk_heli_image(Animation anim, int width, int height);

Функция преобразует указатель на анимацию в формат понятные Nuklear. Полученную в результате структуру можно свободно копировать в другие переменные (того же типа. естественно) и передавать в Nuklear там где требуется изображение.

Как либо удалять или деинициализировать структуру после завершения работы с ней не требуется. Однако нельзя удалять изначальную анимацию до тех пор пока она привязана к элементам Nuklear.

Функция принимает в качестве аргументов размеры изображения. Эти параметры указывают в каком размере следует рисовать картинку Nuklear. Они могут не совпадать с оригинальными размерами картинки, в этом случае картинка будет просто смасштабирована при рисовании до указанных здесь размеров.

См. также nk_heli_init и createAnimation.

Параметры:

anim — указатель на анимацию;
width — ширина изображения в пикселях;
height — высота изображения в пикселях.

unsigned int nk_color_to_heli(struct nk_color c);

Преобразует цвет из формата Nuklear в формат Helianthus. См. также nk_heli_init и nk_color_from_heli.

struct nk_color nk_color_from_heli(unsigned int c);

Преобразует цвет из формата Helianthus в формат Nuklear. См. также nk_heli_init и nk_color_to_heli.