Система координат пользовательского интерфейса (UI)

Автор: Vlad333000 участник нашего Discord.

Абсолютные координаты (Absolute)

Когда разрабатывались первые версии Arma и ее движка Real Virtuality на рынке преимущественно были мониторы с соотношением сторон 4:3. Тогда решили привязать координаты интерфейса к этому соотношению сторон, и поэтому координаты [0, 0] и [1, 1] обозначают левый-верхний и правый-нижний углы не экрана, а некого абстрактного «квадрата», который имеет стороны с соотношением 4:3, а координата [0.5, 0.5] — всегда середина экрана.

Масштабирование интерфейса (GUI Scale)

Начиная с Arma 2 был введен параметр масштабирования интерфейса (англ. GUI Scale), который изменял размеры интерфейса без необходимости изменять положение и размеры элементов. Имеется 5 значений этого параметр:

  • Очень большой (англ. Very Large)
  • Большой (англ. Large)
  • Нормальный (англ. Normal)
  • Маленький (англ. Small)
  • Очень маленький (англ. Very small)

Примеры:

Absolute: 16:9

Absolute: 4:3

Absolute: 16:9 (Портретный режим)

Использование в конфиге:

class Control {
    x = 0;
    y = 0;
    w = 1;
    h = 1;
};

Использование в скрипте:

// В скрипте
control ctrlSetPosition [0, 0, 1, 1];

SafeZone

Со временем появились мониторы с соотношением сторон отличным от 4:3 и сейчас большинство мониторов имеют соотношение сторон 16:9. Так как старая система ориентировалась только на соотношение стороно 4:3, то в Arma 2 были введены несколько команд, которые определяли бы границы экрана при любом разрешении и соотношении сторон:

  • safeZoneX — левый край экрана
  • safeZoneY — верхний край экрана
  • safeZoneW — ширина экрана
  • safeZoneH — высота экрана

Примеры:

safeZone 16:9

safeZone 16:9

safeZone 16:9 (Портретный режим)

Использование в конфиге:

class Control {
    x = safeZoneX;
    y = safeZoneY;
    w = safeZoneW;
    h = safeZoneH;
};

Использование в скрипте:

control ctrlSetPosition [safeZoneX, safeZoneY, safeZoneW, safeZoneH];

SafeZoneAbs

Для работы с системами, которые состоят из трех мониторов, так же были введены следующие команды:

  • safeZoneXAbs — левый край левого монитора
  • safeZoneWAbs — ширина всех трех мониторов

При использовании системы с тремя мониторами:

При использовании системы с одним монитором:

Проблема SafeZone

При использовании команд safeZone* может возникнуть ситуация, при которой позиции и размеры элементов не соответствуют пикселям на экране, из-за чего возникают нежелательные пробелы, наезд элементов друг на друга, пропадание очень тонких элементов, размытие текста или границ элементов.

Это происходит при попытке разделить ширину или высоту на нечетное или очень большое число (safeZoneH / 3safeZoneW / 10000 и т. п. приведет к этому эффекту). Поэтому внимательно следите за тем, что вы рассчитываете и проверяйте расчеты при разных разрешениях.

GUI_GRID

Так как форма и размер элементов при использовании SafeZone зависит от соотношения сторон, то при разных настройках элементы интерфейса имеют различную форму. Так же из-за того, что SafeZone считается относительно размеров монитора, то такой интерфейс нельзя масштабировать при помощи соответствующего параметра.

Для решения этих двух проблем был разработан набор макросов, которые разделяют экран как минимум на 40 по ширене и 25 по высоте клеток. Клетки имеют фиксированное соотношение сторон 1:1 и изменяют свой размер в зависимости от параметра масштаба интерфейса.

Список макросов:

  • GUI_GRID_X — позиция по X квадрата 40×25 клеток
  • GUI_GRID_Y — позиция по Y квадрата 40×25 клеток
  • GUI_GRID_W — ширина клетки
  • GUI_GRID_H — высота клетки
  • GUI_GRID_WAbs — ширина 40 клеток
  • GUI_GRID_HAbs — высота 25 клеток

Примечание: макрсосы чувствительны к регистру символом, поэтому внимательно смотрите, что пишите.

Примеры:

GUI_GRID 16:9

GUI_GRID 4:3

GUI_GRID 16:9 (Портретный режим)

Использование в конфиге:

#include "\a3\ui_f\hpp\defineCommonGrids.inc"
...
class Control {
    x = GUI_GRID_X;
    y = GUI_GRID_Y;
    w = 40 * GUI_GRID_W;
    h = 25 * GUI_GRID_H;
};

Использование в скрипте:

#include "\a3\ui_f\hpp\defineCommonGrids.inc"
...
control ctrlSetPosition [GUI_GRID_X, GUI_GRID_Y, 40 * GUI_GRID_W, 25 * GUI_GRID_H];

Pixel Grid System

GUI_GRID решила проблему соотношения сторон, но она не решила проблему соответствия пикселям на экране. Поэтому ей на замену была разработана система «Pixel Grid», которая дает высокую точность, фиксированное соотношение сторон и возможность изменения размера в зависимости от параметра масштаба интерфейса.

Pixel size

Для нахождения точных размеров пикселя используются две команды, результат которых зависит только от текущего разрешения и не зависят от параметра масштаба интерфейса или соотношения сторон:

  • pixelW — ширина пикселя;
  • pixelH — высота пикселя;

Примеры использования:

class Control {
    x = safeZoneX;
    y = safeZoneY;
    w = 800 * pixelW;
    h = 600 * pixelH;
};
control ctrlSetPosition [safeZoneX, safeZoneY, 800 * pixelW, 600 * pixelH];

Pixel grid

Для определения того, сколько нужно пикселей на одну клетку используются следующие команды:

  • pixelGridBase — зависит только от разрешения;
  • pixelGridNoUIScale — зависит от разрешения и от настроек конфига;
  • pixelGrid — зависит от разрешения, от настроек конфига и от параметра масштаба интерфейса;

В конфиге игры определены два параметра:

  • configFile >> «uiScaleMaxGrids» — целое число, на которое делится текущая высота;
  • configFile >> «uiScaleFactor» — целое число, на которое должен делится без остатка результат вычисления, которое описано в параметре uiScaleMaxGrids. Выбирается ближайший такой результат;

Пример расчета кол-ва клеток (При использовании pixelGrid число клеток может увеличиваться или уменьшаться в зависимости от параметра масштаба интерфейса):

// Используемые значения параметров (Являются стандартными значениями)
uiScaleMaxGrids = 64;
uiScaleFactor = 4;
// 1920x1080
1080 / uiScaleMaxGrids; // 16.875 - будет округлено до 16 (Ближайшее число, которое делится на uiScaleFactor)
1080 / 16;              // 67.5 клеток по высоте
1920 / 16;              // 120 клеток по ширине
// 2560x1440
1440 / uiScaleMaxGrids; // 22.5 - будет округлено до 24 (Ближайшее число, которое делится на uiScaleFactor)
1440 / 24;              // 60 клеток по высоте
2560 / 24;              // 106.(6) клеток по ширине

Примеры использования:

class Control {
    x = safeZoneX;
    y = safeZoneY;
    w = 20 * pixelGrid * pixelW;
    h = 20 * pixelGrid * pixelH;
};
control ctrlSetPosition [safeZoneX, safeZoneY, 20 * pixelGrid * pixelW, 20 * pixelGrid * pixelH];

Вторая часть руководства:
GUI: Кординаты (Часть 2)

Оригинал руководства: Система координат пользовательского интерфейса (UI)

Так же по GUI:
GUI. Часть 1. Общее представление.
GUI. Часть 2. Пишем простой интерфейс.

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