GUI. Часть 2. Пишем простой интерфейс.

Читать первую часть: GUI. Часть 1. Общее представление.

Эта статья будет довольно сухая.
Только конкретная выжимка практической информации.

Я уже озвучивал, что делю GUI (далее диалог) на 3 составляющие.
Начнем с визуальной части.

Открываем редактор Арма 3. Ставим любого юнита, и нажимаем играть в одиночную игру.

Теперь нажимаем ESC, а затем кнопку «редактор«.
У нас открылся графический редактор, в котором мы можем нарисовать наш интерфейс.
Нажимаем правой кнопкой, и открывается список элементов.
Все эти элементы являются довольно примитивными.
Теперь выбираем IGUIBack. Это будет наш «бэкграунд». Нажимаем ОК.
У вас должен появиться маленький прямоугольник.

Нажимаем на него правой кнопкой, в открывшемся окошке, в самом низу в выпадающем меню выбираем absolute (абсолютный размер, не зависящий от соотношения сторон экрана).
Нажимаем ОК.

Теперь, зажав левую кнопку мыши на нашем новом объекте, перемещаем его в нужную область. Затем зажимаем alt и левой кнопкой мыши растягиваем его до нужных размеров.

Таким же образом создаем рамку (RscFrame), текст (RsctText) и кнопки (RscButton).

В итоге у меня получилось следующее:

 

На этом визуализация закончена, и мы можем переводить ее в код.
Начнем с файла defines.hpp
Создаем его в корне нашей миссии.

Далее в игре, там же, в редакторе, где мы создали наш первый интерфейс, нажимаем сочетание клавиш «ctrl+P«. Открываем файл defines.hpp и вставляем в него код (ctrl+V).
Этот файл отвечает за базовые классы элементов. Их цвет, рамку, фон, шрифт и тп.

Создаем файл с понятным нам названием и разрешением .hpp
Например dialog.hpp

Далее в игре, там же, в редакторе, где мы создали наш первый интерфейс, нажимаем сочетание клавиш «ctrl+shift+S«. (окошко закрыть)
Открываем файл dialog.hpp и вставляем в него код (ctrl+V).
Этот файл отвечает за то, какие элементы у нас будут в диалоге, их размер, расположение и тп.

Сейчас это просто список, который мы должны обернуть в класс диалога.
Вот пример моего диалога:

class dialog_1 
{
  idd = 5555;

  class controls {
//выше создал кдасс диалога "dialog_1", задал идентификатор 5555, создал класс controls, в который уже поместил все контролы, созданные в редакторе Армы.
    class IGUIBack_2200: IGUIBack
    {
      idc = 2200;
      x = 0;
      y = 0;
      w = 0;
      h = 0.8;
    };
    class IGUIBack_2201: IGUIBack
    {
      idc = 2201;
      x = -1.0875;
      y = 1.02;
      w = 1.05;
      h = 0.36;
      colorText[] = {0,0,0,0.8};
    };
    class RscFrame_1800: RscFrame
    {
      idc = 1800;
      x = -1.075;
      y = 1.04;
      w = 1.025;
      h = 0.1;
      colorText[] = {0,1,0,1};
    };
    class RscText_1000: RscText
    {
      idc = 1000;
      text = "Хочешь перевооружиться?"; //здесь задаем текст
      x = -1.0625;
      y = 1.06;
      w = 0.95;
      h = 0.06;
    };
    class RscButton_1600: RscButton
    {
      text = "Да"; //здесь задаем текст
      idc = 1600;
      x = -1.075;
      y = 1.18;
      w = 1.025;
      h = 0.06;
      action = "execVM 'yes.sqf'"; //здесь действие при нажатии кнопки
    };
    class RscButton_1601: RscButton
    {
      text = "Нет"; //здесь задаем текст
      idc = 1601;
      x = -1.075;
      y = 1.26;
      w = 1.025;
      h = 0.06;
      action = "execVM 'no.sqf'"; //здесь действие при нажатии кнопки
    };
//ниже добавил закрытие скобок
  };
};

Заодно отредактировал текст, добавил строку «action» для кнопок.
На этом файл dialog.hpp готов, его можно закрывать.

Перейдем теперь к файлу defines.hpp.

Находим в нем  class RscButton.

Этот класс содержит параметры наших кнопок. Вот мой код, с комментариями:

class RscButton
{
  deletable = 0;
  fade = 0;
  access = 0;
  type = 1;
  text = "";
  default = false; //добавил эту строку, для того, чтобы изначально кнопки не были выделены. По умолчанию true и первая кнопка выделена (мигает)
  colorText[] = 
  {
    1,
    1,
    1,
    1
  };
  colorDisabled[] = //альфа канал в 0, чтобы текст отключенной кнопки не выделялся
  {
    0,
    1,
    0,
    0
  };
  colorBackground[] = //альфа канал фона в 0
  {
    0,
    1,
    0,
    0
  };
  colorBackgroundDisabled[] = 
  {
    0,
    0,
    0,
    0.5
  };
  colorBackgroundActive[] = //при наведение мышки на кнопку она выделяется цветом. В моем случае темно-зеленым
  {
    0,
    0.3,
    0,
    1
  };
  colorFocused[] = 
  {
    0,
    1,
    0,
    0
  };
  colorShadow[] = 
  {
    0,
    0,
    0,
    0
  };
  colorBorder[] = 
  {
    0,
    0,
    0,
    0
  };
  soundEnter[] = 
  {
    "\A3\ui_f\data\sound\RscButton\soundEnter",
    0.09,
    1
  };
  soundPush[] = 
  {
    "\A3\ui_f\data\sound\RscButton\soundPush",
    0.09,
    1
  };
  soundClick[] = 
  {
    "\A3\ui_f\data\sound\RscButton\soundClick",
    0.09,
    1
  };
  soundEscape[] = 
  {
    "\A3\ui_f\data\sound\RscButton\soundEscape",
    0.09,
    1
  };
  idc = -1;
  style = 0; //здесь 0, для выравнивания текста по левому краю
  x = 0;
  y = 0;
  w = 0.095589;
  h = 0.039216;
  shadow = 2;
  font = "RobotoCondensed";
  sizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)";
  url = "";
  offsetX = 0;
  offsetY = 0;
  offsetPressedX = 0;
  offsetPressedY = 0;
  borderSize = 0;
};

Изменений тут не много. Вы можете этого не делать, тут дело вкуса и необходимости в каждом конкретном случае.

Вот и все! Наш интерфейс готов. Теперь осталось написать скрипты.

Вот пример:

создаем бота добавляем ему action:

player addAction ["Открыть диалог",{
  disableSerialization;
  createDialog "dialog_1";
}];

Далее сам диалог.
В dialog.hpp я добавлял кнопкам action. Теперь, при нажатии кнопки «Да«, будет запускаться скрипт yes.sqf, а при нажатии «Нет» — no.sqf.

Теперь сами скрипты!
yes.sqf:

disableSerialization;
_display = findDisplay 5555; //присваиваем наш диалог переменной _display
_text = _display displayCtrl 1000; //присваиваем контрол с текстои переменной _text

ctrlShow [1600,false]; //скрываем кнопку "Да"
ctrlShow [1601,false]; //скрываем кнопку "Нет"

ctrlEnable [1600,false]; //отключаем кнопку "Да"
ctrlEnable [1601,false]; //отключаем кнопку "Нет"

_text ctrlSetText "Перевооружайся."; //меняем текст

uiSleep 2;
closeDialog 5555; //выключаем диалог
uiSleep 1;
["Open",true] spawn BIS_fnc_arsenal; //запускаем арсенал

no.sqf по аналогии с предыдущим скриптом:

disableSerialization;
_display = findDisplay 5555;
_text = _display displayCtrl 1000;

ctrlShow [1600,false];
ctrlShow [1601,false];

ctrlEnable [1600,false];
ctrlEnable [1601,false];

_text ctrlSetText "Тогда счастливо!";

uiSleep 3;
closeDialog 5555;

 

Теперь осталось подключить наш интерфейс. Для этого в description.ext пишем:

#include "defines.hpp"
#include "dialog.hpp"

По сути, тут можно хоть диалоги с выбором ответов создавать.
НО! для этого есть более рациональный способ, который будет описан в расширенном курсе по GUI.

Демо миссия (от BETEP3526) — скачать.

 

Что-то не поняли? Заходите в наш Discord, там вам всегда помогут.