Пользовательский интерфейс
Библиотека 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.