Это популярное сообщение. Graff46 598 Опубликовано 3 Февраля 2019 Это популярное сообщение. Поделиться Опубликовано 3 Февраля 2019 (изменено) Тема посвещена аспектам работы и построению GUI Интерфейсов (оконные классы) в играх серии "Сталкер" Описание методов создания GUI интерфейсов от @Malandrinus Скрытый текст Начнём с того, что все задачи по работе с интерфейсом сводятся к двум: вывод и ввод. Сразу разделим наши задачи на два принципиально разных режима, в которых может находиться игра. Первый режим назовём игровым. В этом режиме игрок управляет персонажем в трехмерном мире. При этом ввод от мыши и клавиатуры полностью работает на управление пресонажем. Соответственно, вопрос о задаче ввода в этом режиме не стоит вообще. К сожалению, разработчики не оставили возможности добавить в этом режиме скриптовую реакцию на свои кнопки. Как-то этот вопрос решается, но сейчас об этом не будем. Итак, в игровом режиме можно только создавать на экране поверх трёхмерного изображения свои элементы. Взаимодействовать с ними будет невозможно. Второй режим назовём диалоговым. Это режим для главного меню, встроенных диалогов вроде инвентаря и пользовательских диалогов. В этом режиме открывается окно, которое полностью перехватывает управление мышью и клавиатурой. Соответственно, в этом режиме можно организовать ввод своих данных и реагировать на действия с мышой. События в игровом мире при этом могут остановиться (в главном меню) или продолжаться своим чередом (во всех остальных случаях). Начнём с игрового режима и для начала определимся с терминологией. В этом режиме игрок видит перед собой трёхмерную картинку происходящего и так называемый худ (HUD = heads-up display, ведет происхождение от интерфейса военных самолетов, при котором информация отображается на стекле обзора, что позволяет не опускать голову на приборы, т.е. голова остается поднятой (англ. "head up")). Причём, элементами худа являются в том числе руки и предмет, который актор крутит в руках. Эти объекты по своей природе трёхмерны и в этом движке на них влиять нельзя (а было бы неплохо на самом-то деле управлять, скажем, изображением на экране детектора, который находится в руках у актора в ЧН и ЗП). Так что в дальнейшем мы будем говорить о худе, имея в виду только плоские элементы интерфейса: индикаторы здоровья, оружия, слотов, миникарта и прочее в этом роде. Если точнее, будем называть худом ту прозрачную плоскость на которой все эти элементы расположены. Если это движковые элементы, то управлять ими можно только в плане скрыть/показать, и только все разом. Однако, при этом можно добавить своих элементов и уже с ними делать что угодно. Так можно создавать всякие хитрые индикаторы, движущиеся прицельные метки и прочее в этом роде. Все такие (плоские) элементы создаются с помощью окон, описанных ранее. Создав окно как объект, его нужно разместить на худе. Для управления худом имеется класс CUIGameCustom. Подобно некоторым другим классам существует всего один глобальный объект такого класса и получить его можно с помощью глобальной функции get_hud() (см. описание пространтв имён). Описание класса CUIGameCustom : class CUIGameCustom { void AddCustomMessage(string id, float x, float y, float font_sz, CGameFont *font, unsigned short alignment, DWORD color); // только ТЧ void AddCustomMessage(string id, float x, float y, float font_sz, CGameFont *font, unsigned short alignment, DWORD color, float flicker); // только ТЧ void CustomMessageOut(string id, string msg, DWORD color); // только ТЧ void RemoveCustomMessage(string id); // только ТЧ SDrawStaticStruct* AddCustomStatic(string id, bool single_instance); SDrawStaticStruct* GetCustomStatic(string id); void RemoveCustomStatic(string id); void AddDialogToRender(CUIWindow* wnd); void RemoveDialogToRender(CUIWindow* wnd); void HidePdaMenu(); // только ЗП void HideActorMenu(); // только ЗП void show_messages(); // только ЗП void hide_messages(); // только ЗП }; Этот класс даёт два метода для размешения на худе своих элементов. Метод первый и исторически самый распространённый. Используются функции AddCustomStatic, RemoveCustomStatic и GetCustomStatic. Теперь по порядку: Имеется файл xml с описаниями создаваемых элементов. Это файл configs\ui\ui_custom_msgs.xml, имя которого прописано прямо в движке. Необходимо внести в этот файл описание своего элемента и дать ему имя. Смотрите там, как это делается. Вкратце, создаётся новый узел XML с атрибутами и подузлами, содержашими все необходимые описания. Имя тега и будет именем нашего элемента. Можно использовать включаемые файлы (с помощью #include <имя файла>), чтобы минимально менять оригинальный файл. теперь во время выполнения получаем объект худа так local hud = get_hud() и создаём наш элемент так local st = hud:AddCustomStatic(<имя элемента>, true) при этом создаётся окно типа CUIStatic по описанию из XML и автоматически размещается на худе. Возвращаемый объект имеет тип SDrawStaticStruct. Его описание: class SDrawStaticStruct { float m_endTime; CUIStatic* wnd(); }; Здесь нам в основном интересен метод wnd, который возвращает указатель на созданный CUIStatic. Внимательно изучите возможности этого контрола, они довольно немаленькие. Удалить элемент можно так hud:RemoveCustomStatic(<имя элемента>) получить в любой момент можно так local st = hud:GetCustomStatic(<имя элемента>) хотя можно и просто запомнить ссылку на элемент, полученную при создании. Собственно всё. С помощью описания в XML можно изобразить что-то простое, но если вам нужна динамика или сложные элементы, то ничто не мешает разместить на созданном окне дополнительные дочерние окна с помощью AttachChild. При этом можно сделать описание в XML минимальным, фактически определив только координаты окна и более ничего, а всё, что требуется, сделать позже с помощью дочерних окон. Данный способ почти всем неплох, но у него есть один маленький недостаток. Все созданные таким образом элементы будут расположены под стандартными элементами худа. А иногда нужно создать элемент, который перекрывает стандартные индикаторы и диалоги. Для этого есть второй метод с использованием функций AddDialogToRender и RemoveDialogToRender. Последовательность работы такая: создаём любым методом окно любого типа wnd = <любое окно> размещаем его на худе так get_hud():AddDialogToRender(wnd) когда захотим, убираем с худа так get_hud():RemoveDialogToRender(wnd) Важное замечание: После помещения окна на худ таким способом обязательно надо как-то сохранить ссылку на объект окна вплоть до его удаления с худа. Если потерять ссылку, то сборщик мусора удалит окно, и игра рухнет. Ещё замечание: и первым и вторым способом можно размещать на худе сколь угодно сложные окна, в том числе с кнопками, полями ввода и прочим в этом роде. Но естественно, они не будут реагировать на пользователя, т.е. работать будут только на вывод. Теперь о диалоговом режиме. Здесь всё вертится вокруг класса CUIScriptWnd. Основная идея заключается в создании на основе этого класса своего скриптового. Не буду в подробностях это описывать (может потом как-нибудь). Есть масса примеров, то же главное меню сделано именно так (файл ui_main_menu.script). В качестве наиболее простого и наглядного примера рекомендую ui_numpad.script. Это - диалоговое окно с панелью ввода кода двери. Оно простое и вместе с тем имеет все необходимые элементы: кнопки, поле ввода, обработку мышиных событий и нажатий клавиатуры. В общем, стоит его для начала внимательно изучить. Я сейчас только рассмотрю вывод созданного окна на экран. В случае с главным меню его запускает сам движок. Прописывание пользовательского класса в этом случае делается через регистрацию клиентского класса в class_registrator.script. Это там всегда уже сделано и это единственное окно, которое открывается таким образом. Все остальные пользовательские окна надо открывать самому. Это делается по-разному в разных версиях движка. В ТЧ Допустим у вас есть скриптовый класс CMyDialog, сделанный на основе CUIScriptWnd. Сначала вы создаёте объект такого класса local dlg = CMyDialog() -- конструктор может быть и с параметрами, поскольку вы его сами написали затем запускаем диалог level.start_stop_menu(dlg, true/false) или так dlg:GetHolder():start_stop_menu(dlg, true/false) разницы никакой, это фактически одна и та же функция. Второй аргумент определяет, будут ли убраны стандратные элементы худа: индикаторы и прочее. закрыть диалог можно вызвав ту же функцию второй раз, второй булевский аргумент при этом значения не имеет. ЧН я не рассматриваю, но там вроде похоже на ТЧ В ЗП всё ещё проще, у самого диалога есть нужные методы ShowDialog и HideDialog. Сначала как обычно создаём объект диалога local dlg = CMyDialog() затем запускаем его dlg:ShowDialog(true/false) -- аргумент как и раньше позволяет скрыть индикаторы закрываем диалог dlg:HideDialog() Вот и всё. Остальные подробности про диалоги смотри в примерах. В неохваченном осталась тема о создании окон на основе XML описания. Для этого есть класс CScriptXmlInit. Он сам по себе несложен, но к нему надо ещё и описывать форматы XML файлов для разных окон, а к этому я сейчас морально не готов =) Также есть ещё достаточно сложная тема о модификации стандартных окон: торговли, PDA и прочего. Здесь на помощь может прийти функция level.main_input_receiver(), которая возвращает текущее активное окно. Приемы работы в этом случае достаточно нетривиальны. Кроме того, в ЗП этой функции нет. В ТЧ и ЧН были глобальные функции GetTextureInfo, GetTextureName и GetTextureRect. Это значит по имени текстуры получить ее файл (вроде как это еще полотном называют) и координаты прямоугольника. Напоминаю, что в таком понимании текстура это то, что обычно указывается в XML описаниях разных окошек. Там как правило прописывается имя, которое ссылается на отдельное описание (в другом XML файле), где уже и задается имя файла и координаты прямоугольника. Эти функции как раз и позволяют получить эту информацию. Особой пользы от этих функций не было, поскольку не было ни одной функции, которая возвращала бы имя текстуры. И вот в ЧН такая функция появилась! Для онлайновых объектов сталкеров стало возможно получить иконку персонажа с помощью функции character_icon. Это очень нужная функция, поскольку дает информацию о реальном профиле сталкера. Так и что вы думаете! В ЗП разрабы взяли и убрали функции получения информации о текстурах. И какой теперь толк от той функции получения иконки? XML прочитать нельзя, а иначе логическое имя ни о чем не говорит. Нет слов, одни междометья. Описание GUI классов от @Malandrinus: Скрытый текст CUIWindow - базовый класс для всех остальных оконных классов, в связи с чем описан наиболее подробно. class CUIWindow { CUIWindow (); // конструктор, как всегда доступен в виде глобальной функции void SetPPMode(); // включение события двойного клика void ResetPPMode(); // выключение события двойного клика void AttachChild(CUIWindow*); // присоединение дочернего окна void DetachChild(CUIWindow*); // отсоединение дочернего окна void SetWindowName(string); // установка имени окна, тег "window_name" string WindowName(); // получение имени окна void SetFont(CGameFont*); // только ТЧ, атрибут "font" CGameFont* GetFont(); // только ТЧ void Enable(bool); // включить/выключить возможность взаимодействовать с пользователем bool IsEnabled(); // получить статус активности void SetAutoDelete(bool); bool IsAutoDelete(); void Show(bool); // показать/скрыть окно bool IsShown(); // получить статус видимости void Init(float x, float y, float width, float height); // только ТЧ void Init(Frect*); // только ТЧ // установить положение верхнего левого угла окна относительно родительского void SetWndPos(float x, float y); // вариант ТЧ void SetWndPos(vector2*); // вариант ЗП vector2* GetWndPos(CUIWindow*); // только ЗП, получить положение окна // установить размеры окна void SetWndSize(float w, float h); // вариант ТЧ void SetWndSize(vector2); // вариант ЗП // установить положение и размеры окна void SetWndRect(Frect); void SetWndRect(float x, float y, float width, float height); // только ТЧ void SetHeight(float h); // только ТЧ, установить высоту окна float GetHeight(); // получить высоту окна void SetWidth(float w); // только ТЧ, установить ширину окна float GetWidth(); // получить ширину окна }; Производные от CUIWindow : CServerList список игровых серверов. Очевидно, для синглового режима мало применим. class CServerList : CUIWindow { CServerList (); void SetPlayerName(string); void SetFilters(SServerFilters&); void RefreshList(bool); void SetSortFunc(string, bool); void NetRadioChanged(bool); void ShowServerInfo(); void RefreshQuick(); void ConnectToSelected(); }; К нему (CServerList) прилагается служебный класс SServerFilters class SServerFilters { SServerFilters (); bool empty; bool full; bool listen_servers; bool with_pass; bool without_ff; bool without_pass; bool without_pb; // только ТЧ }; CUIComboBox - выпадающий список. В ТЧ есть, но недоэкспортирован, в связи с чем применять его можно только в ЗП class CUIComboBox : CUIWindow { CUIComboBox (); void Init(float x, float y, float width); // только ТЧ void Init(float x, float y, float width, float height); // только ТЧ void ClearList(); // только ЗП void SetListLength(int length); void SetVertScroll(bool v); void SetText(string s); // только ЗП string GetText(); // только ЗП void enable_id(int id); // только ЗП void disable_id(int id); // только ЗП CUIListBoxItem* AddItem(string s, int value); // только ЗП void SetCurrentID(int id); int CurrentID(); string GetTextOf(int id); // только ЗП void SetCurrentValue(); // только ЗП }; CUICustomEdit - поле редактирования текста : class CUICustomEdit : CUIWindow { void SetNumbersOnly(bool v); // только ТЧ void SetTextPosX(float x); // только ТЧ void SetTextPosY(float y); // только ТЧ void SetTextAlignment(enum CGameFont::EAligment); // только ТЧ CGameFont::EAligment GetTextAlignment(); // только ТЧ void SetTextColor(DWORD color); // только ТЧ DWORD GetTextColor(); // только ТЧ void SetText(string); string GetText(); void SetNextFocusCapturer(CUICustomEdit*); // только ЗП void CaptureFocus(bool v); // только ЗП }; От него (CUICustomEdit) унаследованы: class CUIEditBox : CUICustomEdit { CUIEditBox (); void InitTexture(string texture); }; class CUIEditBoxEx : CUICustomEdit { CUIEditBoxEx (); void InitTexture(string texture); }; CUICustomSpin - поле прокрутки значений. Не совсем понятно, можно ли его полноценно использовать по причине крайне скудного набора собственных свойств: class CUICustomSpin : CUIWindow { string GetText(); }; От CUICustomSpin наследуются несколько классов, которые к нему вообще ничего не добавляют: class CUISpinFlt : CUICustomSpin class CUISpinNum : CUICustomSpin class CUISpinText : CUICustomSpin CUIDialogWnd - класс диалогового окна. Сам по себе редко используется, но является базовым для чрезвычайно важного класса CUIScriptWnd: lass CUIDialogWnd : CUIWindow { void SetHolder(CDialogHolder*); // только ТЧ CDialogHolder* GetHolder(); void HideDialog(); // только ЗП void ShowDialog(bool <скрывать индикаторы>); // только ЗП // вместо этих функций в ТЧ надо использовать глобальную функцию level.start_stop_menu }; Классы, наследуемые от CUIDialogWnd: **************************************************************** CUIMessageBoxEx **************************************************************** CUIMessageBoxEx - диалоговое окно по функциональности схожее с CUIMessageBox: class CUIMessageBoxEx : CUIDialogWnd { CUIMessageBoxEx (); void Init(string template); // только ТЧ void InitMessageBox(string template); // только ЗП void SetText(string text); // только ЗП string GetPassword(); string GetHost(); }; Описание применения: Окно создаётся наподобие обычного контрола в процессе инициализации главного окна (как правило в типовом методе InitControls) self.msg_box = CUIMessageBoxEx() и регистрируется для возможности обрабатывать события нажатия на кнопки self:Register(self.msg_box, "msg_box") затем в методе InitCallBacks на кнопки этого окна устанавливают колбеки self:AddCallback("msg_box", ui_events.MESSAGE_BOX_OK_CLICKED, self.OnMsgOk, self) Все возможные коллбеки для CUIMessageBoxEx: MESSAGE_BOX_CANCEL_CLICKED MESSAGE_BOX_COPY_CLICKED MESSAGE_BOX_NO_CLICKED MESSAGE_BOX_OK_CLICKED MESSAGE_BOX_QUIT_GAME_CLICKED MESSAGE_BOX_QUIT_WIN_CLICKED MESSAGE_BOX_YES_CLICKED в нужный момент окно можно вызывать так: для ТЧ self.msg_box:Init(<строка_инициализации_окна>) self:GetHolder():start_stop_menu(self.msg_box, true) для ЗП self.msg_box:InitMessageBox(<строка_инициализации_окна>) self.msg_box:SetText(<сообщение>) // необязательное действие self.msg_box:ShowDialog(true) <строка_инициализации_окна> ссылается на одно из описаний диалогов из файла config\ui\message_box.xml примеры и подробности смотри там. Только несколько комментариев. Там можно создать своё окно, но требуется придерживаться шаблонных имён частей этого окна. Можно менять текстуры собственно окна, добавлять типовые кнопки "да, нет, ок, отмена", можно менять иконку окна. Также можно добавлять строки ввода. После выхода из окна, что можно отследить колбеками, введённые значения можно получить с помощью методов GetPassword и GetHost. **************************************************************** CUIMessageBoxEx **************************************************************** CUIScriptWnd - скриптовый диалог. Необычайно важный класс, основа для построения всего пользовательского интерфейса. Это единственный из всех оконных классов, позволяющий скриптовое наследование от себя. Это даёт возможность создавать окна с реакцией на события мыши и клавиатуры. class CUIScriptWnd : CUIDialogWnd,DLL_Pure { CUIScriptWnd (); DLL_Pure* _construct(); // от DLL_Pure, назначение неизвестно bool Load(string xml); // непонятно зачем - нет ни одного примера использования. Возможно, колбек на загрузку void Register(CUIWindow*, string name); // регистрация контрола для возможности обработки событий void Register(CUIWindow*); // делает тоже самое, но не устанавливает имя, в ЗП убрана void AddCallback(string name, int event, const function<void>&, object); // установка колбека на действия пользователя // event - константа из класса-перечисления ui_events void AddCallback(string name, int event, const function<void>&); // в ЗП убрана bool OnKeyboard(int dic, enum EUIMessages); // обработка событий от клавиатуры bool Dispatch(int cmd, int param); // ещё какой-то обработчик function Update(); // похоже на обновление окна в смысле обновления полей ввода, надо разбираться // перечисленные далее функции на практике не нужны и в ЗП удалены совсем CUIFrameLineWnd* GetFrameLineWnd(string); CUICheckButton* GetCheckButton(string); //function GetListWndEx(string); // этой возможно и в ТЧ нет CUIPropertiesBox* GetPropertiesBox(string); CUIButton* GetButton(string); CUIListWnd* GetListWnd(string); CUIStatic* GetStatic(string); CUITabControl* GetTabControl(string); CUIRadioButton* GetRadioButton(string); CUIFrameWindow* GetFrameWindow(string); CUIDialogWnd* GetDialogWnd(string); CUIEditBox* GetEditBox(string); CUIProgressBar* GetProgressBar(string); CUIMessageBox* GetMessageBox(string); }; CUIFrameLineWnd - вроде как окно с рамкой. Сам по себе (вероятно) не интересен, но порождает несколько практически важных классов: class CUIFrameLineWnd : CUIWindow { CUIFrameLineWnd (); void Init(string base_name, float x, float y, float w, float h, bool horiz = true); // только ТЧ void SetOrientation(bool horiz); // только ТЧ CUIStatic* GetTitleStatic(); // только ТЧ // SetWidth и SetHeight имеются и в ТЧ и в ЗП, но в ТЧ они унаследованы от родительского // окна, а в ЗП введены дополнительно void SetWidth(float w); void SetHeight(float h); void SetColor(DWORD color); }; от него (CUIFrameLineWnd) наследуются: // только ТЧ class CUILabel : CUIFrameLineWnd { CUILabel (); string GetText(); void SetText(string); } // только ЗП class CUIListBoxItem : CUIFrameLineWnd { CUIListBoxItem(float heght); CUITextWnd* GetTextItem(); void SetTextColor(DWORD color); void AddIconField(float width); void AddTextField(string text, float width); }; // от него (CUIListBoxItem ? ) в свою очередь (тоже только ЗП): class CUIListBoxItemMsgChain : CUIListBoxItem { CUIListBoxItemMsgChain(float heght); }; CUIFrameWindow - тоже что-то с рамкой: CUIFrameWindow : CUIWindow { CUIFrameWindow (); void Init(string name, int x, int y, int w, int h); // только ТЧ CUIStatic* GetTitleStatic(); // только ТЧ // как и в CUIFrameLineWnd SetWidth и SetHeight имеются и в ТЧ и в ЗП, но в ТЧ // они унаследованы от родительского окна, а в ЗП введены дополнительно void SetWidth(float w); void SetHeight(float h); void SetColor(DWORD color); }; от него (CUIFrameWindow) унаследован: class CUIPropertiesBox : CUIFrameWindow { CUIPropertiesBox (); bool AddItem(string); void AutoUpdateSize(); void RemoveAll(); void RemoveItem(DWORD); void Hide(); void Show(int, int); //(Frect, vector2) ?????????? }; CUIListWnd - список. Класс имеется только в ТЧ и активно там используется. В ЗП вместо него используется CUIListBox, который унаследован от CUIScrollView, который в ТЧ есть, но выглядит неработоспособным.: class CUIListWnd : CUIWindow { CUIListWnd (); void SetTextColor(DWORD); void ActivateList(bool); bool IsListActive(); void EnableScrollBar(bool); bool IsScrollBarEnabled(); void ShowSelectedItem(bool); void ResetFocusCapture(); void ScrollToBegin(); void ScrollToEnd(); void ScrollToPos(int); void SetItemHeight(int); int GetLongestSignWidth(); int GetSize(); // количество элементов void SetVertFlip(bool); bool GetVertFlip(); int GetItemPos(CUIListItem*); CUIListItem* GetItem(int); bool AddItem(CUIListItem*); // всегда возвращает true int GetSelectedItem(); void SetFocusedItem(int); int GetFocusedItem(); void RemoveAll(); void RemoveItem(int); }; к этому классу (CUIListWnd) прилагаются два служебных CUIListItem и CUIListItemEx, которые будут описаны далее в разделе наследования от CUIStatic CUIMMShniaga - этот контрол представляет собой комплексную конструкцию со списком элементов и ползунком с увеличительным стеклом. Это часть главного меню, если не забыли ещё. Одним словом это как-то не назвать, вот и у разработчиков видимо фантазии не хватило. Отсюда и такое имечко =) class CUIMMShniaga : CUIWindow { // enum CUIMMShniaga::enum_page_id // только ЗП const epi_main = 0; const epi_new_game = 1; const epi_new_network_game = 2; void ShowPage(enum CUIMMShniaga::enum_page_id); // только ЗП void SetPage(enum CUIMMShniaga::enum_page_id, string xml_file, string xml_path); // только ЗП void SetVisibleMagnifier(bool); }; CUIMapList , CUIMapInfo - видимо, список мультиплеерных карт. Как и в случае со списком серверов для сингла интереса не представляет: lass CUIMapList : CUIWindow { CUIMapList (); void LoadMapList(); viud SaveMapList(); bool IsEmpty(); void ClearList(); // только ЗП string GetCommandLine(string player); EGameTypes GetCurGameType(); void SetServerParams(string); void SetWeatherSelector(CUIComboBox*); void SetModeSelector(CUISpinText*); void SetMapPic(CUIStatic*); void SetMapInfo(CUIMapInfo*); void StartDedicatedServer(); void OnModeChange(); }; //к нему прилагается дополнительный класс class CUIMapInfo : CUIWindow { CUIMapInfo(); void InitMap(string name); // вариант ТЧ void InitMap(string name, string version); // вариант ЗП void Init(vector2 pos, vector2 sz); // только ЗП }; CUIProgressBar - ползунок прогресса. В ТЧ недоэкспортирован, в связи с чем практический интерес представляет только под ЗП: class CUIProgressBar : CUIWindow { CUIProgressBar (); float GetRange_max(); float GetRange_min(); void SetRange(float min, float max); // только ТЧ void SetProgressPos(float); // только ЗП float GetProgressPos(); // только ЗП }; CUIScrollView - класс имеется во всех версиях движка, но под ТЧ нигде не задействован. В ЗП напротив - заменяет класс CUIListWnd (если точнее, заменяет не он сам, а унаследованный от него): class CUIScrollView : CUIWindow { CUIScrollView (); void AddWindow(CUIWindow*, bool auto_delete); void RemoveWindow(CUIWindow*); void Clear(); void ScrollToBegin(); void ScrollToEnd(); int GetMinScrollPos(); int GetMaxScrollPos(); void SetScrollPos(int); int GetCurrentScrollPos(); }; в ЗП от него (CUIScrollView) наследуется: class CUIListBox : CUIScrollView { CUIListBox(); void AddExistingItem(CUIListBoxItem*); CUIListBoxItem* AddTextItem(string text); void RemoveItem(CUIWindow*); CUIListBoxItem* GetItemByIndex(int); int GetSelectedIndex(); CUIListBoxItem* GetSelectedItem(); int GetSize(); void RemoveAll(); void ShowSelectedItem(bool); CUIWindow* GetItem(int); }; к этому (CUIScrollView) классу прилагаются служебные классы CUIListBoxItem и CUIListBoxItemMsgChain, описанные ранее. CUIStatic - очень важный класс. В ТЧ его возможности огромны. В ЗП - существенно меньше (это один из классов, пострадавших от изменений в наибольшей степени), однако по-прежнему остаётся очень важным. В связи с большой разницей версий описание приводится по отдельности для ТЧ и ЗП Для ТЧ: CUIStatic : CUIWindow { CUIStatic (); void Init(float x, float y, float w, float h); void Init(string texture, float x, float y, float w, float h); void InitTexture(string texture); void SetColor(DWORD color); // фон DWORD GetColor() const; void SetOriginalRect(float x, float y, float w, float h); void SetTextureOffset(float x, float y); void SetStretchTexture(bool); bool GetStretchTexture(); void ClipperOn(); void ClipperOff(); bool GetClipperState(); void SetHeading(float angle); float GetHeading(); void SetText(string text); void SetTextST(string text); // дополнительно транслирует строку string GetText(); void SetTextX(float x); float GetTextX(); void SetTextY(float y); float GetTextY(); void SetTextColor(int a, int r, int g, int b); void SetTextAlign(CGameFont::EAligment ); CGameFont::EAligment GetTextAlign(); }; Для ЗП: CUIStatic : CUIWindow { CUIStatic (); void InitTexture(string texture); void SetTextureRect(Frect*); Frect* GetTextureRect(); void SetStretchTexture(bool); CUILines* TextControl(); }; Частично потерянная функциональность класса для ТЧ вынесена в дополнительный класс (только ЗП): class CUILines { void SetText(string); void SetTextST(string); // с трансляцией string GetText(); void SetTextColor(DWORD color); void SetFont(CGameFont*); void SetElipsis(bool); }; CUIStatic важен не только сам по себе. От него ещё и наследуется много практически важных специализированных классов: Классы, унаследованные от CUIStatic : CUIButton кнопка: class CUIButton : CUIStatic { CUIButton (); void SetHighlightColor(DWORD color); // только ТЧ void EnableTextHighlighting(bool); // только ТЧ }; от него унаследованы: специальная кнопка для работы с контролом управления закладками: class CUITabButton : CUIButton // ничего не добавляет кнопка с тремя состояними (нет наведения курсора, наведение курсора, нажатие): class CUI3tButton : CUIButton // ничего не добавляет от неё в свою очередь унаследован переключатель: class CUICheckButton : CUI3tButton { CUICheckButton (); void SetCheck(boolean); bool GetCheck(); void SetDependControl(CUIWindow*); }; CUITabControl - класс для управления закладками: CUITabControl : CUIWindow { CUITabControl (); void AddItem(CUITabButton*); void AddItem(string item, string texture, float x, float y, float h, float w); // вариант ТЧ void AddItem(string item, string texture, vector2 pos, vector2 size); // вариант ЗП void RemoveAll(); int GetTabsCount() const; CUIButton* GetButtonByIndex(int i); // только ТЧ void SetNewActiveTab(int i); // только ТЧ int GetActiveIndex(); // только ТЧ void RemoveItem(int i); // только ТЧ string GetActiveId(); // только ЗП void SetActiveTab(string tab); // только ЗП CUITabButton* GetButtonById(string id); // только ЗП }; CUIMessageBox Окно сообщения. Представляет собой фактически не контрол, а почти полноценный диалог с полем ввода: class CUIMessageBox : CUIStatic { CUIMessageBox (); void Init(string template); // только ТЧ void InitMessageBox(string template); // только ЗП void SetText(string text); // только ЗП string GetPassword(); string GetHost(); }; окно управления сном (только ЗП): class CUISleepStatic : CUIStatic // нет новых методов элемент списка (только ТЧ) class CUIListItem : CUIButton // нет новых методов продвинутый элемент списка (только ТЧ) class CUIListItemEx : CUIListItem { CUIListItemEx (); void SetSelectionColor(DWORD color); }; класс CUIListItemPair, упоминутый в lua_help и унаследованный от CUIListItemEx похоже не существует. Может когда-то и был... CUITrackBar - ползунок. Как и некоторые другие классы в ТЧ недоэкспортирован до применябельного состояния: CUITrackBar : CUIWindow { CUITrackBar (); void SetCheck(bool); bool GetCheck(); float GetFValue(); // только ЗП int GetIValue(); // только ЗП void SetCurrentValue(); // только ЗП }; CUITextWnd - какое-то текстовое поле. Есть только под ЗП. Видимо, частично компенсирует потерю аналогичных методов из других классов. class CUITextWnd : CUIWindow { CUITextWnd (); void SetText(string); void SetTextST(string); string GetText(); void SetTextColor(DWORD color); DWORD GetTextColor(); void SetFont(CGameFont*); CGameFont* GetFont(); void SetTextComplexMode(bool); void SetTextOffset(float x, float y); void SetTextAlignment(enum CGameFont::EAligment); void SetVTextAlignment(enum EVTextAlignment); void AdjustHeightToText(); void AdjustWidthToText(); void SetEllipsis(bool); // установка обрезания текста (используя троеточие) }; * Не плохо было бы разделить классы элементов простого вывода статиков и диалогового режима.... Описание XML тегов для GUI от @Desertir отсюда Скрытый текст stretch - как раз таки растягивание текстуры по величине окна, для ш\ф это действует как сужение complex_mode - многострочный текст, если у нас длина строки больше ширины окна, слова перенесутся на следующую строку параметры с префиксом la_ не имеют смысла, без параметра light_anim light_anim - задает тип анимации (например при ui_btn_hint будет плавное появление, при ui_pda_contacts - мигание) la_cyclic - повторение анимации la_texture - задействовать текстуру в анимации la_alpha - использовать альфа канал (???) la_text - задействовать текст в анимации aligment и align - выравнивание текста, возможные параметры l - по левому краю, c - по центру, r - по правому краю, возможно align новый вариант, т.к. используется во много раз чаще первого heading - разрешает поворот (???) используется для текстур стрелок (синяя стрелка вокруг ГГ на глобальной карте и стрелка, указывающая на текущее задание) На счет значений light_anim, скорее всего они записаны в движок, и определять экспериментально, какой параметр какую анимацию задает, достаточно муторная работа. Примеры, что я привел, это количество контактов (на худе около мини карты) - число мигает при появлении новых контактов, и подсказка снизу экрана (типа "Подобрать предмет", "Говорить" и т.п.) - она плавно появляется. Больше информации по XML, тегам и тд, от @Comador тут Программа для создания скриптовых окон Stalker UI Creator от @Stalk15 Изменено 25 Июня 2020 пользователем Graff46 4 2 12 Ссылка на комментарий
Graff46 598 Опубликовано 5 Февраля 2019 Автор Поделиться Опубликовано 5 Февраля 2019 Кто опишет создание окон на основе XML и все атрибуты тегов? Ссылка на комментарий
VIKKOV_CHSOP 2 Опубликовано 3 Ноября 2019 Поделиться Опубликовано 3 Ноября 2019 У меня есть вопрос: а как вернуть некоторые разделы КПК в игру, например в билдах можно почитать описание персонажей и я хотел бы вернуть эту функцию. Ссылка на комментарий
naxac 2 447 Опубликовано 5 Ноября 2019 Поделиться Опубликовано 5 Ноября 2019 @VIKKOV_CHSOP, биография в КПК возвращена в X-Ray Extensions. Аддон для ОП-2.09.2: Яндекс/Google/GitHub Ссылка на комментарий
karavan 36 Опубликовано 5 Января 2020 Поделиться Опубликовано 5 Января 2020 Добрый день! Пытаюсь вывести дополнительную кнопку в меню инвентаря. function button_remove_ui_open() button_1_ui():ShowDialog(false) get_hud():HideActorMenu() end --===== Выводим кнопку в инвентарь =========== class "button_1_ui" (CUIScriptWnd) function button_1_ui:__init(owner) super() self.owner = owner self:InitControls() self:InitCallBacks() end function button_1_ui:__finalize() end function button_1_ui:InitControls() self:SetWndRect(Frect():set(0,0,1024,768)) local xml = CScriptXmlInit() xml:ParseFile("ui_button_re.xml") self:Register(xml:Init3tButton("re_bt", self),"re_bt") end function button_1_ui:InitCallBacks() self:AddCallback("re_bt", ui_events.BUTTON_CLICKED, self.re_bt, self) end function button_1_ui:re_bt() self:HideDialog() end Код не сложный. Но только вот одна проблема. Кнопка выводится как бы за инвентарем и становится активной только после закрытия инвентаря. Как сделать что бы кнопка была активной при открытом инвентаре? Помогите пожалуйста! Ссылка на комментарий
Graff46 598 Опубликовано 11 Января 2020 Автор Поделиться Опубликовано 11 Января 2020 @karavan, Я пока без пк, код нормально не посмотрел, но наверное кнопку надо приаттачить к окну инвенторя Ссылка на комментарий
UriZzz 1 004 Опубликовано 8 Апреля 2020 Поделиться Опубликовано 8 Апреля 2020 @naxac, только в разделе Рейтинг, а вот на вкладке Контакты придется ручками. 1 Моя нычка, Нычка в арендованном у Опричника холодильнике Мы хорошие ребята, жаль патронов маловато:) Ссылка на комментарий
Graff46 598 Опубликовано 22 Апреля 2020 Автор Поделиться Опубликовано 22 Апреля 2020 В шапку добавлено: Описание XML тегов для GUI от @Desertir отсюда 2 Ссылка на комментарий
Это популярное сообщение. Comador 203 Опубликовано 24 Апреля 2020 Это популярное сообщение. Поделиться Опубликовано 24 Апреля 2020 На днях чистил комп и нашел свои записи по XML-окнам. Для описания XML-документа используются три термина: теги, элементы и атрибуты. Небольшой пример Скрытый текст <?xml version='1.0' encoding="UTF-8"?> <window> <minimap> <level_frame x="20" y="20" width="163" height="161"/> <background x="9" y="6" width="177" height="185"> <texture>ui_hud_map</texture> <dist_text x="30" y="3" width="150" height="20"> <text align="l" font="letterica16" color="ui_clr_1"/> </dist_text> </background> <compass x="150" y="146" width="32" height="32" heading="1"> <texture>ui\ui_hud_map_arrow</texture> </compass> <center width="4" height="4" alignment="c" stretch="1"> <texture >ui_minimap_point</texture> </center> </minimap> </window> Первая строка <?xml version='1.0' encoding="UTF-8"?> - декларация XML, говорящая о том, что это файл XML. Здесь version='1.0' - версия XML, а encoding="UTF-8" - кодировка символов. Тег - это текст между левой угловой скобкой ( <) и правой угловой скобкой ( >). Есть начальные (например <minimap>) и конечные (например </minimap>) теги. Теги чувствительны к регистру, т.е. тег <minimap> и тег <Minimap> - два разных тега. Открывающие и закрывающие теги должны быть написаны в одном и том же регистре. Элементом является начальный тег, конечный тег и все, что находится между ними. <center width="4" height="4" alignment="c" stretch="1"> <texture >ui_minimap_point</texture> </center> Атрибут - это пара имя-значение внутри начального тега элемента. Значения атрибута всегда должны быть в кавычках. <compass x="150" y="146" width="32" height="32" heading="1"> XML-документы образуют древовидную структуру, которая начинается с корневого элемента - основы (в нашем примере корневой элемент - <window>) и "ветвится" до дочернего элемента (в нашем примере - <minimap>). Все элементы могут иметь подэлементы. Если посмотреть на наш пример, то <level_frame>, <background>, <compass>, <center> - подэлементы <minimap>. Важное замечание: все элементы должны быть правильно вложены друг в друга. Каждый дочерний элемент должен быть целиком расположен между открывающим и замыкающим тегами своего родительского элемента. Дочерние элементы должны заканчиваться до начала следующего дочернего элемента. Что касается атрибута — или нескольких атрибутов — указывается внутри начального тега элемента. При добавлении нескольких атрибутов они разделяются пробелами. <compass x="150" y="146" width="32" height="32" heading="1"> Описание атрибутов: Скрытый текст x="" y="" width="" height="" - координаты, а также ширина и высота элементаstretch – используется, если нужно чтобы текстура имела определенный (фиксированный) размер. Для этого данному параметру нужно присвоить значение "1".custom_placement - пользовательское размещение элементаcomplex_mode – многострочный текст. Данный параметр имеет два значения – "0" и "1". Если длина строки будет больше ширины окна, то чтобы слова перенеслись на следующую строку нужно данному параметру выставить значение в "1".alignment - выравнивание тектсуры. Имеет такие значения: c - по центру, r - по правому краю, b - понизу Шрифтfont – название шрифта. Берется с fonts.ltx.align – выравнивание текста. Имеет такие значения: l - по левому краю, c - по центру, r - по правому краю.vert_align – выравнивание текста по вертикали. RGB – цвет шрифта, где R – красный, G – зеленый, B – синий. Так же вместе с этими значениями используется и четвертое – А ("интенсивность" шрифта). color – цвет шрифта. Берется с color_defs.xml. Анимация элемента:light_anim – тип анимации (ui_pda_contacts, ui_btn_hint, ui_slow_blinking_alpha, credits_head и т.д.),la_cyclic – повторение анимации (имеет два значения – "0" и "1"),la_texture – использовать текстуру в анимации (имеет два значения – "0" и "1"),la_text – использовать текст в анимации (имеет два значения – "0" и "1"),la_alpha – задействовать альфа-канал (не уверен) в анимации (имеет два значения – "0" и "1"). Основной атрибут – light_anim, все остальные атрибуты, с префиксом la_, идут в одной связке с ним, и без него не работают.xform_anim - тип анимации (map_spot_rel_xform, tutor_rad_sign_xform и т.д.)xform_anim_cyclic - флаг-признак циклического проигрывания анимации Все типы анимации прописаны в файле lanims.xr. Ячейки сеткиcell_width, cell_height – ширина и высота ячейкиrows_num – количество строкcols_num – количество столбцовscale - масштабированиеunlimited – ограничениеgroup_similar – "группировка" одинаковых предметов Прогресс барhorz - положение. Имеет два значения – "0" (по вертикали) и "1" (по горизонтали)min - минимальное значениеmax - максимальное значениеpos - "нулевая" позиция Анимация статикаframes - количество кадров анимацииduration - время показа всей анимации в mscolumns - размеры текстуры с анимацией в кадрахframe_width, frame_height - размеры кадра на тектуреcyclic - флаг-признак циклического проигрывания анимацииautoplay - флаг-признак автоматического проигрывания анимации Кнопкаcheck_mode - флаг-признак режима проверкиhighlight_text - подсвечивания текстаtexture_e, texture_t, texture_d, texture_h Цвет текста на кнопкахenabled - включеноdisabled - отключеноtouched - касаниеhighlighted - подсвечивание <text_color> <e r="227" g="199" b="178"/> <t r="180" g="153" b="155"/> <d r="106" g="95" b="91"/> <h r="0" g="0" b="0"/> </text_color> Скролalways_show_scroll - флаг-признак отображения прокруткиscroll_profile - предопределенный профиль. Берется с scroll_bar.xml Списокitem_height - количество "записей" в спискеcan_select - возможность выбораlist_length - длина списка right_ident, left_ident, top_indent, bottom_indent - отступы P.S. записи выкладываю как есть. Знающие/желающие могут дополнить и поправить инфу с этого сообщения. 1 5 Неважно – сколько у тебя друзей. Важно - сколько из них помогут тебе в трудную минуту и сколько вспомнят о тебе когда им хорошо. "Худ" и "Умное выпадание частей монстров" для Народной солянки Ссылка на комментарий
Prophet2002 2 Опубликовано 21 Декабря 2020 Поделиться Опубликовано 21 Декабря 2020 Тут есть те, кто шарят в UI? Помогите убрать размытие в главном меню, которое "шакалит" весь бэкграунд. При этом картина в меню опций никак не изменяется по качеству. Ссылка на комментарий
naxac 2 447 Опубликовано 28 Декабря 2020 Поделиться Опубликовано 28 Декабря 2020 @Prophet2002, что за размытие? Как это выглядит? Ничего такого не замечал никогда... 1 Аддон для ОП-2.09.2: Яндекс/Google/GitHub Ссылка на комментарий
Changer77 3 Опубликовано 28 Декабря 2020 Поделиться Опубликовано 28 Декабря 2020 @Prophet2002 Замечал, я менял с dx10 на статику отключал размытие и перезаходил. Detail information was delete. Ссылка на комментарий
wraanger 0 Опубликовано 28 Декабря 2020 Поделиться Опубликовано 28 Декабря 2020 Вопрос к товарищам модо/UI делам: В Народной Солянке 2016 есть вариант настроек HUD - "Минимализм". Возможно ли ( и насколько сложно ) изменить его следующим образом: 1. Миникарту переместить в правый верхний угол 2. Радар разместить под миникартой 3. Точку, отображающую наше местопомоложение на миникарте сделать какого-либо яркого цвета (синий, оранжевый или еще что-либо яркое) Заранее спасибо за ответы) Ссылка на комментарий
nasar75 3 869 Опубликовано 29 Декабря 2020 Поделиться Опубликовано 29 Декабря 2020 (изменено) @wraanger изучаешь тему https://www.amk-team.ru/forum/topic/8013-hud/ и правишь файлы. Кстати, в НС 2016 при выборе худа нужные файлы появляются в геймдате. По замене цвета хорошо написано тут: https://ap-pro.ru/forums/topic/1653-kak-sdelat-perenos-i-cvetnoy-tekst-bez-skriptov/ Зы. Из НА7, синяя точка, файлы zone_map.xml, zone_map_16.xml <center width="4" height="4" alignment="c" stretch="1" heading="1"> <texture r="0" g="150" b="255">ui_minimap_point</texture> </center> Изменено 29 Декабря 2020 пользователем nasar75 1 AMD Athlon II X2 250, NVIDIA GTS 450, RAM 8.0 GB, WIN 7/64 правки Золотой Шар Ссылка на комментарий
wraanger 0 Опубликовано 29 Декабря 2020 Поделиться Опубликовано 29 Декабря 2020 @nasar75Спасибо, попробовал - цвет поменять получилось...но проблема как и у предыдущео оратора - она полупрозрачная...и не реагирует на изменение параметров от слова никак. Как кстати и сама минимапа - пробовала менять а=100 на а=0, а=50 и тд....и ничего в смысле прозрачности не менялось. Что печалит. Полупрозрачная минимапа мне плохо видна, к сожалению =/ Ссылка на комментарий
nasar75 3 869 Опубликовано 29 Декабря 2020 Поделиться Опубликовано 29 Декабря 2020 @wraanger кто полупрозрачная, точка? Смотри файл ui_hud.dds, вроде непрозрачная... А текстуру миникарты смотри в файле ui_hud.dds, и фотошоп в помощь.... http://f26.i-fotki.info/thumb/81f81399e11eca5d75a0ac531cd335e40589f3391909455.png Зы. текстуры биорадара находятся в папке textures\biomap... AMD Athlon II X2 250, NVIDIA GTS 450, RAM 8.0 GB, WIN 7/64 правки Золотой Шар Ссылка на комментарий
wraanger 0 Опубликовано 29 Декабря 2020 Поделиться Опубликовано 29 Декабря 2020 Фотошоп и я - это из разных галактик, к сожалению... К тому же, точки остальных юнитов на минимапе используют ту же текстуру, но при этом не полупрозрачные..так что дело не в альфа-канале, по ходу... Вопрос только, в чем тогда... Ссылка на комментарий
Prophet2002 2 Опубликовано 2 Января 2021 Поделиться Опубликовано 2 Января 2021 28.12.2020 в 23:14, naxac сказал(а): @Prophet2002, что за размытие? Как это выглядит? Ничего такого не замечал никогда... В главном меню говорят из-за увеличительного стекла может размывать изображение. Такое наблюдается только в главном меню, а я вот не понимаю как его убрать. Ссылка на комментарий
naxac 2 447 Опубликовано 2 Января 2021 Поделиться Опубликовано 2 Января 2021 @Prophet2002 , в конфиге меню, ui/ui_mm_main.xml, убери текстуру у элемента magnifire. 1 1 Аддон для ОП-2.09.2: Яндекс/Google/GitHub Ссылка на комментарий
kolem 3 Опубликовано 11 Января 2021 Поделиться Опубликовано 11 Января 2021 02.01.2021 в 18:03, naxac сказал(а): в конфиге меню, ui/ui_mm_main.xml, убери текстуру у элемента magnifire Спасибо я думаю многим будет полезно знать. Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти