Я не являюсь trueкастомкоделом, богом панорамы и т.п. я лишь хочу сообщить базовые знания которые помогут вам на начале и дадут стимул узнавать что-то новое.
Тут не будет абсолютно всей инфы, так как информации очень много и иногда её легче выразить словами и простым языком, или показать на паре примеров, чем помещать в гайд.
Тут не будет абсолютно всей инфы, так как информации очень много и иногда её легче выразить словами и простым языком, или показать на паре примеров, чем помещать в гайд.
- Создаем пустой проект или открываем существующий.
- Заходим в папку контента вашей кастомки, расположена она по адресу:
{папка стима}/steamapps/common/dota 2 beta/content/dota_addons/{название вашей кастомки}/ - Там у вас должна быть следующая структура (минимально, для того, чтобы небыло проблем с туториалом, т.е. могут быть ещё папки и файлы, но эти обязательны):
в нем:
*.vmap - это файл вашей карты (в моем случае это test.vmap)
custom_ui_manifest.xml - файл конфигурации UI для вашей кастомки
custom_loading_screen.xml - файл кастомного загрузочного экрана вашей кастомки
custom_loading_screen.css - файл стилей для загрузочного экрана вашей кастомки (можно назвать как угодно, но чтобы не путаться назовем его так)
Итак, теперь про директории по порядку:
1) maps - содержит все карты вашей кастомки
2) panorama - содержит все файлы, необходимые для вашего UI
2.1) images - папка с картинками
2.2) layout - папка с xml файлами (для тех кто знаком с web'ом - аналог html - файлы разметки)
2.3) scripts - папка с вашими скриптами js(javascript) или ts(typescript)
2.4) styles - папка с стилями
Для чего нужно содержание папок maps и images можете догадаться сами, это не сложно, мы же перейдем сразу к содержимому layout
XML - это язык разметки, он нужен для того чтобы размечать некую информацию на сегменты, является прародителем html.
Сам XML ничего особо из себя не представляет, это просто набор тегов и информация в них. Как же тогда отображаются элементы у вас на экране?
Все просто - интерпретатор. Интерпретатор считывает информацию из вашего файла, он знает что делать с информацией в ваших тегах и как её представить на экране.
Теперь к тематике доты.
Основным тегом в доте является тег <Panel>, да и вообще, в доте, по заявлению самих Valve - любой элемент это Panel, и опять же, по заявлению из
документации по панораме - Panel - аналог <div> в html.
Сам XML ничего особо из себя не представляет, это просто набор тегов и информация в них. Как же тогда отображаются элементы у вас на экране?
Все просто - интерпретатор. Интерпретатор считывает информацию из вашего файла, он знает что делать с информацией в ваших тегах и как её представить на экране.
Теперь к тематике доты.
Основным тегом в доте является тег <Panel>, да и вообще, в доте, по заявлению самих Valve - любой элемент это Panel, и опять же, по заявлению из
документации по панораме - Panel - аналог <div> в html.
Существует несколько готовых видов специализированных панелей, которые представлены тут:
1) Button - в переводе на русский - Кнопка, в плане функционала - та же Panel, только для вашего удобства вы можете использовать тег <Button>
2) Image - Картинка - имеет required(обязательный) атрибут "src"(не то чтобы вам будут сообщения в консоль, но без него этот тег бесполезен) в который вы помещаете ссылку на изображение.
Под ссылкой на изображение подразумевается путь до картинки и сам файл, например, file://{images}/custom_game/myImage.png.
Где file://{images} указывает на путь до папки ...content/panorama/images
так же имеет дополнительный атрибут "scaling" отвечающий за отображение изображения при несовпадении размеров Image панели с самим изображением.
узнать какие параметры принимает вы можете узнать из ссылки выше.
3) Label - поле с неизменяемым(без учета скриптов, но об этом потом) текстом, соответственно содержит обязательный(по аналогии с картинкой) атрибут "text"
в котором, как вы уже догадались можно писать этот самый текст, но это ещё не всё! Label поддерживает некоторые html теги,такие как <br> <a> <h1> <img> и другие, с полным списком вы можете ознакомится по ссылке выше.
4) TextEntry - поле с изменяемым текстом (т.е. можно редактировать ручками!). В общем ничего особого, html теги не поддерживает, имеет параметры:
"maxchars" - максимальное количество вводимых символов
"placeholder" - "подложка", это как когда вы на сайте пытаетесь ввести в поле где написано email свою почту, а когда вы начинаете печатать слово email
магическим способом исчезает.
"oninputsubmit" - при подтверждении ввода выполняет то что в теле параметра, является одним из listener'ов event'ов, но об этом чуть позже.
5) DropDown - Выпадающий список, аналог select в html, для полей используются не option, а другие панели, например Label, имеет параметр "oninputsubmit", который отрабатывает при выборе определенного поля из списка
6) ToggleButton - аналог checkbox в html, по простому - поле с галочкой, имеет 2 основных параметра:
"checked" - если true - голочка стоит, если false - не стоит
"text" - текст, тот что справа.
7) RadioButton - xor выбор, но для вас это ничего не скажет, в общем - "выбираем что-то одно из предложенного". Имеет 3 основных параметра, "checked" и "text" как у ToggleButton
, а так же "group", который указывает, с какими кнопками он использует общий выбор, т.е. если вы выбрали 1 кнопку из группы a, то остальные становятся не выбранными.
8) DOTAHeroImage - то же саоме что и Image, только выдает нам статичный портрет персонажа, есть 3 основных параметра:
"heroid" - указывает на то, что надо взять изображение героя с id указанном в значении
"heroname" - то же что и выше, но не по id, а по имени, пример, "npc_dota_hero_sven"
"heroimagestyle" - имеет 3 вида значений -
landscape - изображение 128х72(то что используется в игровой таблице),
portrait - 71x94(то что используется при выборе персонажа),
icon - 32х32 - изображение на миникарте
9)DOTAItemImage - то же самое что и с героями, но возвращает изображение предмета имеет 1 параметр "itemname" - название предмета
10)DOTAAbilityImage - то же самое что и с героями, но возвращает изображение умения имеет 1 параметр "abilityname" - название умения
11) DOTAAvatarImage - то же самое что и с героями, но возвращает аватарку игрока, имеет 1 параметр:
"steamid" - steamid игрока(число), есть одно доп значение 'local' - возвращает id игрока на том клиенте, на котором исполняется команда
12)DOTAUserName - то же самое что и пункт 11, но возвращает не аватарку игрока, а его имя.
2) Image - Картинка - имеет required(обязательный) атрибут "src"(не то чтобы вам будут сообщения в консоль, но без него этот тег бесполезен) в который вы помещаете ссылку на изображение.
Под ссылкой на изображение подразумевается путь до картинки и сам файл, например, file://{images}/custom_game/myImage.png.
Где file://{images} указывает на путь до папки ...content/panorama/images
так же имеет дополнительный атрибут "scaling" отвечающий за отображение изображения при несовпадении размеров Image панели с самим изображением.
узнать какие параметры принимает вы можете узнать из ссылки выше.
3) Label - поле с неизменяемым(без учета скриптов, но об этом потом) текстом, соответственно содержит обязательный(по аналогии с картинкой) атрибут "text"
в котором, как вы уже догадались можно писать этот самый текст, но это ещё не всё! Label поддерживает некоторые html теги,такие как <br> <a> <h1> <img> и другие, с полным списком вы можете ознакомится по ссылке выше.
4) TextEntry - поле с изменяемым текстом (т.е. можно редактировать ручками!). В общем ничего особого, html теги не поддерживает, имеет параметры:
"maxchars" - максимальное количество вводимых символов
"placeholder" - "подложка", это как когда вы на сайте пытаетесь ввести в поле где написано email свою почту, а когда вы начинаете печатать слово email
магическим способом исчезает.
"oninputsubmit" - при подтверждении ввода выполняет то что в теле параметра, является одним из listener'ов event'ов, но об этом чуть позже.
5) DropDown - Выпадающий список, аналог select в html, для полей используются не option, а другие панели, например Label, имеет параметр "oninputsubmit", который отрабатывает при выборе определенного поля из списка
6) ToggleButton - аналог checkbox в html, по простому - поле с галочкой, имеет 2 основных параметра:
"checked" - если true - голочка стоит, если false - не стоит
"text" - текст, тот что справа.
7) RadioButton - xor выбор, но для вас это ничего не скажет, в общем - "выбираем что-то одно из предложенного". Имеет 3 основных параметра, "checked" и "text" как у ToggleButton
, а так же "group", который указывает, с какими кнопками он использует общий выбор, т.е. если вы выбрали 1 кнопку из группы a, то остальные становятся не выбранными.
8) DOTAHeroImage - то же саоме что и Image, только выдает нам статичный портрет персонажа, есть 3 основных параметра:
"heroid" - указывает на то, что надо взять изображение героя с id указанном в значении
"heroname" - то же что и выше, но не по id, а по имени, пример, "npc_dota_hero_sven"
"heroimagestyle" - имеет 3 вида значений -
landscape - изображение 128х72(то что используется в игровой таблице),
portrait - 71x94(то что используется при выборе персонажа),
icon - 32х32 - изображение на миникарте
9)DOTAItemImage - то же самое что и с героями, но возвращает изображение предмета имеет 1 параметр "itemname" - название предмета
10)DOTAAbilityImage - то же самое что и с героями, но возвращает изображение умения имеет 1 параметр "abilityname" - название умения
11) DOTAAvatarImage - то же самое что и с героями, но возвращает аватарку игрока, имеет 1 параметр:
"steamid" - steamid игрока(число), есть одно доп значение 'local' - возвращает id игрока на том клиенте, на котором исполняется команда
12)DOTAUserName - то же самое что и пункт 11, но возвращает не аватарку игрока, а его имя.
Но так же вы можете найти панели, которые не перечислены в основной документации, например, можете порыскать здесь.
Там есть панели, которые не описаны в документации, но тем не менее есть в клиенте и, возможно, доступны в кастомках, например,<DOTAChat> или <DOTATopBar>.
Ну что же, самую сложную(нет) часть мы разобрали. Обратимся немного к CSS и JS, и продолжим с панорамой.
Так как CSS почти ничем не отличается от обычного, то смело идите смотреть русскоязычные гайды о каскадных таблицах стилей, но
так же они претерпели небольшие изменения, о которых вы можете узнать отсюда
Теперь по JS - та же ситуация что и с CSS, но тут валвы не совсем обленились и подвезли нам такую классную штуку как выбор элементов по классам и id без лишних заморочек
как в JQuery, пример, $("#MyLabel") возвратит вам xml элемент помеченный idшником "MyLabel", чтобы выбрать элементы по классу используем вместо "#" ".", вот и все, вы превосходны,
Так же в местный JS были добавлены глобальные функции, такие как $.Msg или $.CreatePanel, о них вы можете почитать тут
Ещё можно использовать TS, но это уже совсем другая история...
Ну что же, прдолжаем в XML, на очереди параметры - это такие штуки, которые дают интерпретатору понять, что делать с этим элементом, помимо того, что разместить его в рабочей области
Начнем с самого простого это id и class
они нужны для того, чтобы выбрать нужные элементы, основное различие - id можно помечать только 1 объект(ну вообще в реалиях интерпретатора доты нет, но о контекстах как-нибудь в другой раз)
и вы всегда будете обращаться к именно одному этому элементу; классы же позволяют вам объеденить несколько элементов в одну группу, чтобы придать им некоторые общие свойства.
href - ссылка, например href="vk.com/razrabkastomki", используется в реалиях доты мало в каких элементах, но все равно полезна.
src - ссылка на ресурс - описана выше в Image.
style - (никогда не пользуйтесь!) позволяет указать стили прямо в элементе, например <Panel style="margin-top: 10px;"></Panel>
disabled - говорит о том, что эта кнопка недоступна\выключена\т.п. , т.е. что с ней нельзя производить некоторые действия, например не будет работать нажатие
Третий вид параметров - listener'ы event'ов, в их значение можно вставить скрипт, который будет выполнятся при определенном действии с элементом,
например, <Panel onactivate="somefunc();"></Panel> или <Panel onactivate="$.Msg('Hello, DONT FUCKIN DO THIS!')"></Panel>
в первом варианте будет вызываться метод somefunc(), если его найдет интерпретатор в xml или в прикрепленны js файлах, а во 2м случае - вывод сообщения в консоль
Я упустил один очень важный момент - связывание панормы и Lua и не случайно, дело в том, что это информация для полых новечков,
и если они захотят развиваться дальше, они без проблем найдут как это сделать в документации от Valve. На всякий случай, искать тут
они нужны для того, чтобы выбрать нужные элементы, основное различие - id можно помечать только 1 объект(ну вообще в реалиях интерпретатора доты нет, но о контекстах как-нибудь в другой раз)
и вы всегда будете обращаться к именно одному этому элементу; классы же позволяют вам объеденить несколько элементов в одну группу, чтобы придать им некоторые общие свойства.
href - ссылка, например href="vk.com/razrabkastomki", используется в реалиях доты мало в каких элементах, но все равно полезна.
src - ссылка на ресурс - описана выше в Image.
style - (никогда не пользуйтесь!) позволяет указать стили прямо в элементе, например <Panel style="margin-top: 10px;"></Panel>
disabled - говорит о том, что эта кнопка недоступна\выключена\т.п. , т.е. что с ней нельзя производить некоторые действия, например не будет работать нажатие
Третий вид параметров - listener'ы event'ов, в их значение можно вставить скрипт, который будет выполнятся при определенном действии с элементом,
например, <Panel onactivate="somefunc();"></Panel> или <Panel onactivate="$.Msg('Hello, DONT FUCKIN DO THIS!')"></Panel>
в первом варианте будет вызываться метод somefunc(), если его найдет интерпретатор в xml или в прикрепленны js файлах, а во 2м случае - вывод сообщения в консоль
Я упустил один очень важный момент - связывание панормы и Lua и не случайно, дело в том, что это информация для полых новечков,
и если они захотят развиваться дальше, они без проблем найдут как это сделать в документации от Valve. На всякий случай, искать тут
На этом предположу, что теории вполне достаточно (переписал в доступном, надеюсь, виде чуть ли не всю документацию от Valve),
преидем к практике.
Ну, а на практике, я продемонстрирую вам (может быть костыльно) следующее:
1) Мы сделаем окошечко полностью с нуля. (тут закрепим основы по XML)
2) Сделаем все красиво. (тут работаем с CSS)
3) Динамически добавим туда кнопочку. (тут поучимся работать с JS)
4) По нажатию на кнопочку вылетит сообщение в консоль. (смотрим на то, что можно сделать потом).
Итак, поехали!
напоминаю мы находимся в папке panorama и вот относительно неё все пути будут прописаны дальше
Первым делом создаем основные файлы, с которыми мы будем работать
generalPanel.xml в папке layout/custom_game
XML:
<root>
<styles>
<include src="file://{resources}/styles/custom_game/generalPanel.css" />
</styles>
<scripts>
<include src="file://{resources}/scripts/custom_game/generalPanel.js" />
</scripts>
<Panel>
<Panel id="general" class="general">
</Panel>
</Panel>
</root>
generalPanel.js в папке scripts/custom_game и оставляем пока пустым
generalPanel.css в папке styles/custom_game тоже пока пустое
если у вас ещё нет custom_ui_manifest, то создаем его, если есть просто добавляем строчку
<CustomUIElement type="Hud" layoutfile="file://{resources}/layout/custom_game/generalPanel.xml" />
в итоге, содержимое должно выглядеть примерно так:
XML:
<root>
<Panel>
<CustomUIElement type="Hud" layoutfile="file://{resources}/layout/custom_game/generalPanel.xml" />
</Panel>
</root>
я хочу сделать окошечко, чтобы:
1)оно было красного цвета
2)с закругленными краями
3)появлялось сверху и постепенно
4)при наведении на него оно меняло цвет на синий
первым делом идем в generalPanel.css
изначально элемент привязан к левому верхнему краю родителя и имеет размер 0 по ширине и высоте, начнем с того, что назначим ему размер и цвет и скругляем края, для этого пишем
CSS:
.general{ /* обращаемся к элементам с классом general, для них мы*/
height: 500px; /* ставим высоту 500 пикселей*/
width: 500px; /* ставим ширину 500 пикселей*/
background-color: red; /* устанавливаем цвет фона красный*/
border-radius: 20px;/* устанавливаем радиус углов границы 20 пикселей*/
position: 40%/*расстрояние по оси x*/ 25%/* по y*/ 0px/* по z*/; /* устанавливаем позицию примерно по центру, учитываем что
отсчет идет от левого верхнего угла, а не от центра нашей панели*/
}
теперь сделаем так, чтобы при наведении цвет менялся на синий, а при нажатии на желтый, для этого служит псевдокласс
"hover" - при наведении
добавляем код все в тот же файл
CSS:
.general:hover{
background-color: blue;/* при наведении ставим цвет заливки синий*/
}
а теперь сделаем так, чтобы наше окошко появлялось постепенно сверху
для этого в класс general дописываем:
CSS:
animation-name: myanim; /* название нашей анимации*/
animation-duration: 1s; /* сколько по времени будет воспроизводится*/
animation-timing-function: linear; /*временная функция, о них почитайте в интернете, в основном можно юзать линейную*/
animation-iteration-count: 1;/* сколько раз повторять*/
а в сам документ дописывает это
CSS:
@keyframes 'myanim' {/*говорим что это анимация с названием myanim*/
0% {/*когда она только началась, наш анимируемый объект будет иметь такие свойства*/
opacity: 0; /*объект полностью прозрачный*/
position: 40% 0 0px; /*объект примерно по центру вверху */
}
/*сюда можно вставить дополнительные контрольные точки, например 50% или 75% по аналогии с выше и ниже описанными примерами*/
100% {/* когда закончится, должен иметь такие */
opacity: 1;/* объект полностью не прозрачный*/
position: 40% 25% 0px; /* объект примерно по центру экрана*/
}
}
Осталось сделать кнопочку, которую мы будем добавлять и переидем к JS
так как мы хотим сделать красивую кнопку, нам надо на неё смотреть, поэтому сначала захардкодим её, чтобы поставить нужные нам стили
добавляем в нашу general панель кнопку, должно выглядеть так
XML:
<Panel>
<Panel id="general" class="general">
<Button id="button" class="button" onactivate="">
</Button>
</Panel>
</Panel>
далее я просто сделаю красивую кнопочку, css с комментариями приложу ниже
CSS:
.button {
height: 50px;
/* высота*/
width: 50px;
/* ширина*/
background-color: aqua;
/* фон цвета aqua*/
position: 225px 225px 0;
/* делаем кнопку по середине*/
border-radius: 5px;
/*скругляем края*/
}
.button:hover {
box-shadow: 0 0 5px aqua;
/* делаем свечение по краям при наведении*/
}
.button:active {
box-shadow: 0 0 5px green;
/* делаем свечение по краям при нажатии*/
background-color: green;
/*меняем цвет при нажатии*/
}
У нас получается нечто вроде такого
теперь самое интересное - убираем кнопку из xml и переходим к файлу generalPanel.js, где будем творить магию
ниже представлен код с комментариями
JavaScript:
button = $.CreatePanel("Button", $("#general"), "button"); /* создаем нашу кнопку с id = button в нашей general панели */
button.AddClass("button"); /* добавляем класс button нашей кнопке */
/*создаем функцию которая будет выводить сообщение в консоль */
function clickfunc() {
$.Msg("my custom button was clicked");
}
button.SetPanelEvent("onactivate", function() { /*почему-то консоль у меня ругается, если я сюда вставляю наш скрипт, но можно закостылять, как я и сделал */
clickfunc();
}); /* подписываемся, что при нажатии на эту кнопку должен выполнится clickfunc() */
и на всякий случай, полный код css файла и xml
CSS:
.general {
height: 500px;
width: 500px;
background-color: red;
border-radius: 20px;
position: 40% 25% 0px;
animation-name: myanim;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: 1;
}
.general:hover {
background-color: blue;
/* при наведении ставим цвет заливки синий*/
}
@keyframes 'myanim' {
0% {
opacity: 0;
position: 40% 0 0px;
}
100% {
opacity: 1;
position: 40% 25% 0px;
}
}
.button {
height: 50px;
/* высота*/
width: 50px;
/* ширина*/
background-color: aqua;
/* фон цвета aqua*/
position: 225px 225px 0;
/* делаем кнопку по середине*/
border-radius: 5px;
/*скругляем края*/
}
.button:hover {
box-shadow: 0 0 5px aqua;
/* делаем свечение по краям при наведении*/
}
.button:active {
box-shadow: 0 0 5px green;
/* делаем свечение по краям при нажатии*/
background-color: green;
/*меняем цвет при нажатии*/
}
XML:
<root>
<styles>
<include src="file://{resources}/styles/custom_game/generalPanel.css" />
</styles>
<scripts>
<include src="file://{resources}/scripts/custom_game/generalPanel.js" />
</scripts>
<Panel>
<Panel id="general" class="general">
<Button id="button" class="button" onactivate="buttonPressed()">
</Button>
</Panel>
</Panel>
</root>
Последнее редактирование модератором: