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

LAPKI

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


Рисунок 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 - Результат создания окна и кнопки.​

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

I_GRIN_I

Друзья CG
15 Мар 2016
1,166
95
48
20
Реакции
93 0 2
#2
Сложновато будет для новичков столько инфы, поделить бы на определенные части, и не рассказывать в одном гайде и практику и матчасть. Например, зачем мне знать что такое xml, если мне нужно знать, просто как он работает
proxy.php?image=https%3A%2F%2Fvk.com%2Femoji%2Fe%2Ff09fa494.png&hash=61223b1cea085d8652df5c248e07a555
 
Реклама: