Для создания GUI (графический интерфейс пользователя) в Inner Core предусмотрены огромные возможности, которые позволяют не только создавать сложный интерфейс в стиле MCPE (и не только), но и эффективно интегрировать его с остальными игровыми элементами, которые добавляются модами с помощью контейнеров.
Все размеры и координаты в интерфейсе задаются в юнитах, где 1 юнит это 1/1000 от ширины окна, в котором создается интерфейс. Если юниты используются для задания позиции и размера окна, то 1 юнит составляет 1/1000 от ширины экрана (как и в случае, когда окно открыто на весь экран).
Текстуры интерфейса, которые находятся в папке gui вашего мода, будут загруженны и доступны под именем файла без расширения: "gui/slot.png" будет загружен как "slot". Также возможно использование объекта Bitmap вместо имени файла, если возникает такая необходимость.
Цвет задается с помощью метода класса android api android.graphics.Color.rgb(r, g, b) - где r, g и b - красная, зеленая и синяя составляющие цвета от 0 до 255 каждая.
Фонт текста задается как объект с 3 значениями: {size: ..., color: ..., shadow: ...}, где size - размер текста, color - цвет, shadow - тень со значением от 0 до 1.
Текстурой рамки является текстура размера 16x16, изображающая нужную рамку самого маленького размера, которая будет потом растянута до любых размеров.
Любой интерфейс имеет объект описания, позволяющий задать данный интерфейс и динамично изменять его, меняя этот объект, пока интерфейс открыт. Объект описания любого типа имеет значения drawing (массив) и elements (объект), которые задают отрисовку фона и элементы соответственно. Их изменение из любого места ведет к динамичному изменению интерфейса, если он открыт. Т.е если вы изменените параметры какого-то элемента или команды отрисовки, то интерфейс изменится в соответствии с вашими изменениями.
Команды рисования задаются в объекте описания в массиве drawing и отвечают за отрисовку фона интерфейса.
drawing: [ {/* команда 1 */}, {/* команда 2 */}, {/* команда 3 */}, .... ]
Элементы задаются в объекте описания в объекте elements, каждый элемент должен иметь уникальное имя. По этим именам с ними можно будет взаимодействовать из других частей кода.
elements: { "name1": {/* элемент 1 */}, "name2": {/* элемент 2 */}, "name3": {/* элемент 3 */}, .... }
Формат объекта:
{ onClick: function(position, container, tileEntity, window, canvas, scale){ // если определен, задает функцию короткого нажатия // container - контейнер, для которого открыт данный интерфейс // tileEntity - если интерфейс открыт для какого то tile entity, то передаст его, иначе null // остальные параметры будут рассмотрены в других уроках }, onLongClick: function(position, container, tileEntity, window, canvas, scale){ // если определен, задает функцию долгого нажатия // container - контейнер, для которого открыт данный интерфейс // tileEntity - если интерфейс открыт для какого то tile entity, то передаст его, иначе null // остальные параметры будут рассмотрены в других уроках } }
{ onClick: function(container, tileEntity, position, window, canvas, scale){/* ... */}, onLongClick: function(container, tileEntity, position, window, canvas, scale){/* ... */} }
Если invert определен и равен true, то позиция вырезки из текстуры будет инвертирована, что создаст видимость того, что шкала как бы выдвигается, а не заполняется.
overlay - если определен, накладывает на шкалу дополнительную текстуру, которая перекрывает шкалу.
overlayScale - параметр scale для перекрытия.
overlayOffset: {x: , y: } - если определен, задает позицию перекрытия, относительно позиции шкалы в юнитах.
Кроме drawing и elements в объекте описания можно определить объект стилизации интерфейса для изменения стандартных текстур элементов.
Если какое-то из нижеприведённых значений будет указано в объекте стилизации, оно заменит стандартый параметр.
params: { slot: "текстура слота", invSlot: "текстура слота инвентаря", frame: "текстура обычной рамки", selection: "текстура выделения слота", closeButton: "текстура кнопки закрытия", closeButton2: "текстура нажатой кнопки закрытия", }
Интерфейс бывает 3 типов: однооконный, многооконный и стандартный. В данной главе будет рассмотрен только последний, как самый простой в использовании и при этом эффективный и применимый в большинстве случаев. Объект интерфейса во всех этих случаев создается как объект класса одного из типов, после создания такой объект класса может быть настроен и открыт для любого контейнера.
Любой интерфейс может быть протестирован с помощью функции UI.testUI(объект интерфейса);
Создается как объект класса UI.StandartWindow, которому может быть передан объект описания.
Пример использования:
var testUiScreen = UI.StandartWindow({/* ... пустой объект описания ... */}); UI.testUI(testUiScreen); // откроет полностью пустой интерфейс
Формат объекта описания стандартного типа интерфейса:
{ standart: { // стандартные параметы, поддерживаемые данным типом интерфейса, позволяют быстро задавать базовые элементы, такие как заголовок, фон и инвентарь // если хотите определить какой то стандартный элемент, но оставить его без изменений, то пропишите там единственное значение - standart: true, например inventory: {standart: true} header: { // определите, если вам нужен заголовок, заголовок содержит кнопку закрытия text: { // обязательный параметр, если заголовок определен text: "текст заголовка", // содержание текста, обязательный параметр }, font: {...}, // фонт текста, определите, если хотите изменить стандартный color: цвет, // нужен только, если вы хотите изменить цвет заголовка frame: "текстура рамки", // нужно только, если вы хотите изменить текстуру рамки заголовка width: 80, // высота заголовка в юнитах, hideButton: true, // определите и установите значение на true, чтобы убрать кнопку закрытия }, inventory: { // для определения стандартного инвентаря используйте inventory: {standart: true} width: 300, // ширина окна инвентаря padding: 20, // паддинг окна инвентаря }, background: { // для определения стандартного фона используйте background: {standart: true} color: цвет, // определите, если хотите изменить цвет фона bitmap: "текстура фона", // определите, если хотите добавить текстуру фона frame: "текстура рамки" // определите, если хотите добавить рамку }, minHeight: 650, // если высота окна в юнитах меньше этого параметра, окно будет прокручиваться так, чтобы его внутренний размер составлял по высоте minHeight юнитов }, params: { // стилизация (изменение стандартных текстур) }, drawing: [/* команды отрисовки фона */], elements: {/* описание элементов */} }
Как пример использован реальный интерфейс из таумкрафта (реактор аспектов).
Для того, чтобы пример работал, установите таумкрафт или скопируйте оттуда нужные текстуры интерфейса (которые используются в объекте описания интерфейса).
var aspectReactorGui = new UI.StandartWindow({ standart: { header: { text: { text: "Aspect reactor" }, color: android.graphics.Color.rgb(0x47, 0x26, 0x0c), frame: "thaum_frame_header" }, inventory: { standart: true }, background: { bitmap: "thaum_background" }, minHeight: 600 }, params: { textures: { slot: "thaum_slot", invSlot: "thaum_inv_slot", selection: "thaum_selection", closeButton: "thaum_close_button_up", closeButton2: "thaum_close_button_down", frame: "thaum_frame_default" } }, drawing: [ {type: "bitmap", x: 842, y: 104, bitmap: "aspect_scale_background", scale: 4}, {type: "bitmap", x: 560, y: 100, bitmap: "aspect_reactor_background", scale: 360 / 128}, ], elements: { "slot1": {type: "slot", x: 400, y: 100, size: 160}, "slot2": {type: "slot", x: 400, y: 300, size: 160}, "aspectScale": {type: "scale", x: 850, y: 120, direction: 1, scale: 8, value: 1, bitmap: "aspectScale_nitor", overlay: "aspect_scale_overlay_1", overlayScale: 4}, "stateText": {type: "text", x: 625, y: 227, width: 90, height: 100, text: "", font: {color: android.graphics.Color.WHITE, shadow: .6, size: 25}} } }); UI.testUI(aspectReactorGui); // тестовое открытие после создания // добавляем созданный интерфейс нашему tile entity из прошлых глав IDRegistry.genBlockID("testBlock"); // ... // создаем блок TileEntity.registerPrototype(BlockID.testBlock, { defaultValues: { someValue: 0 // сохраняемое значение someValue, по умолчанию 0 }, tick: function(){ // что то сделать каждый тик, к примеру выводим someValue Debug.message(this.data.someValue); }, click: function(id, count, data, coords){ this.data.someValue = 1; // установить значение someValue на 1 }, getGuiScreen: function(){ return aspectReactorGui; // при попытке открыть интерфейс, возвращаем наш объект интерфейса } // остальные события не трогаем });