Ультимативный гайд по panorama для начинающих.

LAPKI

Пользователь
26 Окт 2018
57
10
Я не являюсь trueкастомкоделом, богом панорамы и т.п. я лишь хочу сообщить базовые знания которые помогут вам на начале и дадут стимул узнавать что-то новое.
Тут не будет абсолютно всей инфы, так как информации очень много и иногда её легче выразить словами и простым языком, или показать на паре примеров, чем помещать в гайд.
  1. Создаем пустой проект или открываем существующий.
  2. Заходим в папку контента вашей кастомки, расположена она по адресу:
    {папка стима}/steamapps/common/dota 2 beta/content/dota_addons/{название вашей кастомки}/
  3. Там у вас должна быть следующая структура (минимально, для того, чтобы небыло проблем с туториалом, т.е. могут быть ещё папки и файлы, но эти обязательны):

Рисунок 1.PNG
Рисунок 1 - Структура проекта.​


в нем:
*.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.

Существует несколько готовых видов специализированных панелей, которые представлены тут:
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) DOTAAvatarImage - то же самое, что и выше, только не изображение героя, а аватарка игрока, имеет 1 параметр:
"steamid" - steamid игрока(число), есть одно доп значение 'local' - возвращает id игрока на том клиенте, на котором исполняется команда

10)DOTAItemImage - то же самое что и с героями, но возвращает изображение предмета имеет 1 параметр "itemname" - название предмета

11)DOTAAbilityImage - то же самое что и с героями, но возвращает изображение умения имеет 1 параметр "abilityname" - название умения

12)DOTAUserName - то же самое что и пункт 9, но возвращает не аватарку игрока, а его имя.

Но так же вы можете найти панели, которые не перечислены в основной документации, например, можете порыскать здесь.
Там есть панели, которые не описаны в документации, но тем не менее есть в клиенте и, возможно, доступны в кастомках, например,<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. На всякий случай, искать тут

На этом предположу, что теории вполне достаточно (переписал в доступном, надеюсь, виде чуть ли не всю документацию от 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;
    /*меняем цвет при нажатии*/
}
У нас получается нечто вроде такого
Рисунок 2.PNG
Рисунок 2 - Результат создания окна и кнопки.​

теперь самое интересное - убираем кнопку из 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>
Рисунок 3.PNG
Рисунок 3 - Результат.​
 

I_GRIN_I

Друзья CG
15 Мар 2016
1,270
92
Сложновато будет для новичков столько инфы, поделить бы на определенные части, и не рассказывать в одном гайде и практику и матчасть. Например, зачем мне знать что такое xml, если мне нужно знать, просто как он работает
 

LAPKI

Пользователь
26 Окт 2018
57
10
Сложновато будет для новичков столько инфы, поделить бы на определенные части, и не рассказывать в одном гайде и практику и матчасть. Например, зачем мне знать что такое xml, если мне нужно знать, просто как он работает
Инфа разбита по блокам, так что в любом случае можно читать частями.
Да и инфа очень простая, так что особой нагрузки нет, я же не 3D графику с матрицами поворота и т.п. объясняю.
Вся описательная инфа скрыта в спойлеры, поэтому ты не обязан читать описание, а можешь сразу переходить к объяснению работы.
 
Реклама: