Ru/Dota 2 Workshop Tools/Panorama/Javascript: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (Using L template for links)
 
(16 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{otherlang2
{{Orphan|date=January 2024}}
|title=Panorama:ru/Javascript:ru
 
|en=Dota_2_Workshop_Tools/Panorama/Javascript
{{lang|title=Panorama/Javascript|Dota 2 Workshop Tools/Panorama/Javascript}}
}}
Panorama использует Javascript в качестве скриптового языка, позволяя пользовательскому интерфейсу динамически реагировать на действия пользователя и события игры. Код Javascript выполняемый в клиенте может взаимодействовать с кодом сервера пользовательской игры (реализованном в Lua.)
Panorama использует Javascript в качестве скриптового языка, позволяя пользовательскому интерфейсу динамически реагировать на действия пользователя и события игры. Код Javascript выполняемый в клиенте может взаимодействовать с кодом сервера пользовательской игры (реализованном в Lua.)


== Javascript API ==
== Javascript API ==
[[Dota 2 Workshop Tools:ru/Panorama:ru|Panorama]] JS API в основном расширенный вариант Scaleform ActionScript API.
{{L|Dota 2 Workshop Tools/Panorama|Panorama}} JS API в основном расширенный вариант Scaleform ActionScript API.


Задокументировано: [[Dota 2 Workshop_Tools/Panorama/Javascript/API]]
Задокументировано: {{L|Dota 2 Workshop_Tools/Panorama/Javascript/API}}


== Workflow ==
== Рабочий процесс ==
=== Hooking Up Scripts ===
=== Подключаем Scripts ===
Your Panorama XML can refer to JS files in a <code>'scripts'</code> block, or include inline Javascript in a <code>'script'</code> block (only suitable for very small amounts of code.)
Ваш Panorama XML может ссылаться на JS файлы в блоке <code>'scripts'</code>, или включать в себя Javascript в блоке <code>'script'</code> (подходит только для не очень большого кода.)
<source lang="XML">
<source lang="XML">
<root>
<root>
<scripts>
<scripts>
<!--
<!--
This is a reference to a script file located here:
Это ссылка на script файл расположенного в:
content/dota_addons/ADDON_NAME/scripts/custom_game/my_script_name.js
content/dota_addons/ADDON_NAME/scripts/custom_game/my_script_name.js
-->
-->
Line 23: Line 22:
</scripts>
</scripts>
<script>
<script>
// This is an inline Javascript (XML experts: Panorama automatically wraps your script block inside a CDATA section.)
// Это встроенный Javascript в код (XML experts: Panorama automatically wraps your script block inside a CDATA section.)
$.Msg( "Hello, world!" );
$.Msg( "Hello, world!" );
</script>
</script>
<Panel>
<Panel>
<!-- (Panel hierarchy goes here.) -->
<!-- (Иерархия Panel находится здесь.) -->
</Panel>
</Panel>
</root>
</root>
</source>
</source>


(The script above will be auto-compiled by the tools to this location: <code>game/dota_addons/ADDON_NAME/scripts/custom_game/my_script_name.vjs_c</code> or can be manually compiled using resourcecompiler.)
(Данный script автоматически скомпилирован по адресу: <code>game/dota_addons/ADDON_NAME/scripts/custom_game/my_script_name.vjs_c</code> или может быть скомпилирован вручную с помощью resourcecompiler.)


=== Reload Behavior ===
=== Процесс перезагрузки ===
When a panel is reloaded, the associated javascript will usually also re-execute. This normally results in the desired behavior, but sometimes leads to confusion. When iterating on a complicated UI, it's usually worth the trouble to ensure that your script is robust to being reloaded. Callbacks registered with the system for things like game events will automatically be ignored when they go stale - it's safe to re-register. However, if you're dynamically creating panels, consider checking to see if they're already there for a previous reload. A bit of careful checking can go a long way to improving your iteration speed.
Когда panel перезагружается, связанный с ним javascript выполнится повторно. Это обычно приводит к заданному поведению, но иногда приводит к путанице. When iterating on a complicated UI, it's usually worth the trouble to ensure that your script is robust to being reloaded. Callbacks registered with the system for things like game events will automatically be ignored when they go stale - it's safe to re-register. However, if you're dynamically creating panels, consider checking to see if they're already there for a previous reload. A bit of careful checking can go a long way to improving your iteration speed.


== Panels ==
== Panels ==


=== Creating Panels ===
=== Создание Panels ===
A powerful way to reuse parts of your UI is to dynamically create panels. For example, the multiteam scoreboard creates a new child panel for each team, and in turn each team panel creates a new child panel for each player. This way the UI can dynamically adapt to any number of teams and players, with a single copy of XML/CSS/JS for each concept.
Мощным способом повторного использование частей вашего интерфейса, является динамически создаваемая панель. Например мульти-командная таблица результатов создаёт новую дочернюю панель для каждой команды, и в каждая командная панель создаёт новую дочернюю панель для каждого игрока. Таким образом интерфейс может адаптироваться под любое количество команд и игроков, с одной копией XML/CSS/JS для каждой концепции.


<source lang="javascript">
<source lang="javascript">
var parentPanel = $.GetContextPanel(); // the root panel of the current XML context
var parentPanel = $.GetContextPanel(); // корневая панель в текучем контексте XML
var newChildPanel = $.CreatePanel( "Panel", parentPanel, "ChildPanelID" );
var newChildPanel = $.CreatePanel( "Panel", parentPanel, "ChildPanelID" );
newChildPanel.BLoadLayout( "file://{resources}/layout/custom_game/new_panel.xml", false, false );
newChildPanel.BLoadLayout( "file://{resources}/layout/custom_game/new_panel.xml", false, false );
</source>
</source>


=== Accessing CSS Properties From Javascript ===
=== Доступ к свойствам CSS из Javascript ===
Many CSS properties can be accessed from javascript via <code>MyPanel.style.<font color='red'>property</font></code>. Due to syntax differences between the two languages their names are not identical to their CSS equivalent (this is the same on the web) but are easily deducible: Hyphen-delimited words are converted to camelCase equivalent. For example <code>background-color</code> in CSS is <code>style.backgroundColor</code> in Javascript.
К многим свойствам CSS можно обращаться из javascript с помощью <code>MyPanel.style.<font color='red'>property</font></code>. Из-за синтаксического различия этих языков, их имена не являются идентичными в эквиваленте CSS (Так же в интернете), но легко выводимые: Слова разделенные дефисом преобразуются в равнозначный camelCase. Например <code>background-color</code> в CSS является <code>style.backgroundColor</code> в Javascript.


== $ (Dollar Sign) ==
== $ (Символ Доллар) ==
 
Several important global routines are accessible through the [[Dota_2_Workshop_Tools/Panorama/Javascript/API#.24|<code>$</code> global object]]


Несколько важных, глобальных процедур доступны через [[Dota_2_Workshop_Tools/Panorama/Javascript/API#.24|<code>$</code> глобальный объект]]


=== JQuery-Like Selection ===
=== JQuery-Like Selection ===
As with JQuery, you can find a panel in the current context using <code>$( "#PanelID" )</code>. Note that this currently has significant limitations: it can only match a single panel by ID. If there is no matching panel it will return null instead of a empty selector, which can result in unexpected JS errors. (And failure of the rest of the script to execute.)
Как и с JQuery, вы можете найти в текущем контексте с помощью <code>$( "#PanelID" )</code>. Обратите внимание, что на данный момент имеются существенные ограничения: он может соответствовать только одной панели по ID. Если это не соответствует панели то возвращает null вместо пустого селектора, что может привести к неожиданным ошибкам в JS. (И отказ выполнения остальной части скрипта.)


<source lang="javascript">
<source lang="javascript">
$( "#MyLabel" ).text = "hello";
$( "#MyLabel" ).text = "hello";
</source>
</source>


=== Msg ===
=== Msg ===
For simple logging, use <code>$.Msg()</code> - it supports all Javascript types and any number of arguments. (It will print all the arguments consecutively on a single line.)
Для простой записи, используйте <code>$.Msg()</code> - поддерживает все типы Javascript и любое количество аргументов. (Будет печатать все аргументы последовательно на одной строке.)


<source lang="javascript">
<source lang="javascript">
// This will print: Hello {"who":"world"}!
// Напишет: Hello {"who":"world"}!
$.Msg( "Hello ", { "who": "world" }, "!" );
$.Msg( "Hello ", { "who": "world" }, "!" );
</source>
</source>


=== GetContextPanel ===
=== GetContextPanel ===
Line 90: Line 86:


=== Game Events ===
=== Game Events ===
Javascript can register functions to get called when game events are fired. This works for both engine events and new [[Dota 2 Workshop Tools/Custom Game Events|Custom Game Events]]:
Javascript может зарегистрировать функцию на вызов когда игровое событие вызывается. Это работает для событий движка и нового {{L|Dota 2 Workshop Tools/Custom Game Events|Custom Game Events}}:
<source lang='javascript'>
<source lang='javascript'>
     function OnFoo( data ) { $.Msg( "foo_event: ", data ); }
     function OnFoo( data ) { $.Msg( "foo_event: ", data ); }
Line 99: Line 95:
=== Custom Nettables ===
=== Custom Nettables ===
Custom nettables are a way to communicate persistent state from the server to clients.
Custom nettables are a way to communicate persistent state from the server to clients.
See: [[Dota 2 Workshop Tools/Custom Nettables]]
See: {{L|Dota 2 Workshop Tools/Custom Nettables}}


== Best Practices and Javascript Gotchas ==
== Best Practices and Javascript Gotchas ==
=== "use strict" ===
=== "use strict" ===
Our example Javascript code employs the [[http://www.w3schools.com/js/js_strict.asp "use strict"]] feature to increase safety, robustness, and sanity.
Our example Javascript code employs the {{L|http://www.w3schools.com/js/js_strict.asp "use strict"}} feature to increase safety, robustness, and sanity.


=== That Weird Anonymous Function Thing (IIFE) ===
=== That Weird Anonymous Function Thing (IIFE) ===
In our example Javascript, you may see use of the [[https://en.wikipedia.org/wiki/Immediately-invoked_function_expression Immediately-invoked Function Expression (IIFE)]] pattern.
In our example Javascript, you may see use of the {{L|http://getinstance.info/articles/javascript/immediately-invoked-function-expressions/ Immediately-invoked Function Expression (IIFE)}} pattern.


<source lang='javascript'>
<source lang='javascript'>
Line 117: Line 113:
If you're familiar with C-family languages, you may be surprised to learn that Javascript has two equality operators: '==' and '==='
If you're familiar with C-family languages, you may be surprised to learn that Javascript has two equality operators: '==' and '==='


You can learn more about this [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness here]] or elsewhere on the web.
You can learn more about this {{L|https://developer.mozilla.org/docs/Web/JavaScript/Equality_comparisons_and_sameness here}} or elsewhere on the web.


=== Variable Capture ===
=== Variable Capture ===
Line 161: Line 157:


{{shortpagetitle}}
{{shortpagetitle}}
[[Category:Dota 2 Workshop Tools]]
[[Category:Dota 2 Workshop Tools]]
[[Category:Panorama]]
[[Category:Panorama]]
[[Category:Javascript]]
[[Category:Javascript]]

Latest revision as of 07:23, 11 July 2024

English (en)Русский (ru)Translate (Translate)

Panorama использует Javascript в качестве скриптового языка, позволяя пользовательскому интерфейсу динамически реагировать на действия пользователя и события игры. Код Javascript выполняемый в клиенте может взаимодействовать с кодом сервера пользовательской игры (реализованном в Lua.)

Javascript API

Panorama(en) JS API в основном расширенный вариант Scaleform ActionScript API.

Задокументировано: Dota 2 Workshop_Tools/Panorama/Javascript/API(en)

Рабочий процесс

Подключаем Scripts

Ваш Panorama XML может ссылаться на JS файлы в блоке 'scripts', или включать в себя Javascript в блоке 'script' (подходит только для не очень большого кода.)

<root>
	<scripts>
		<!--
			Это ссылка на script файл расположенного в:
			content/dota_addons/ADDON_NAME/scripts/custom_game/my_script_name.js
		-->
		<include src="file://{resources}/scripts/custom_game/my_script_name.js" />
	</scripts>
	<script>
		// Это встроенный Javascript в код (XML experts: Panorama automatically wraps your script block inside a CDATA section.)
		$.Msg( "Hello, world!" );
	</script>
	<Panel>
		<!-- (Иерархия Panel находится здесь.) -->
	</Panel>
</root>

(Данный script автоматически скомпилирован по адресу: game/dota_addons/ADDON_NAME/scripts/custom_game/my_script_name.vjs_c или может быть скомпилирован вручную с помощью resourcecompiler.)

Процесс перезагрузки

Когда panel перезагружается, связанный с ним javascript выполнится повторно. Это обычно приводит к заданному поведению, но иногда приводит к путанице. When iterating on a complicated UI, it's usually worth the trouble to ensure that your script is robust to being reloaded. Callbacks registered with the system for things like game events will automatically be ignored when they go stale - it's safe to re-register. However, if you're dynamically creating panels, consider checking to see if they're already there for a previous reload. A bit of careful checking can go a long way to improving your iteration speed.

Panels

Создание Panels

Мощным способом повторного использование частей вашего интерфейса, является динамически создаваемая панель. Например мульти-командная таблица результатов создаёт новую дочернюю панель для каждой команды, и в каждая командная панель создаёт новую дочернюю панель для каждого игрока. Таким образом интерфейс может адаптироваться под любое количество команд и игроков, с одной копией XML/CSS/JS для каждой концепции.

var parentPanel = $.GetContextPanel(); // корневая панель в текучем контексте XML
var newChildPanel = $.CreatePanel( "Panel", parentPanel, "ChildPanelID" );
newChildPanel.BLoadLayout( "file://{resources}/layout/custom_game/new_panel.xml", false, false );

Доступ к свойствам CSS из Javascript

К многим свойствам CSS можно обращаться из javascript с помощью MyPanel.style.property. Из-за синтаксического различия этих языков, их имена не являются идентичными в эквиваленте CSS (Так же в интернете), но легко выводимые: Слова разделенные дефисом преобразуются в равнозначный camelCase. Например background-color в CSS является style.backgroundColor в Javascript.

$ (Символ Доллар)

Несколько важных, глобальных процедур доступны через $ глобальный объект

JQuery-Like Selection

Как и с JQuery, вы можете найти в текущем контексте с помощью $( "#PanelID" ). Обратите внимание, что на данный момент имеются существенные ограничения: он может соответствовать только одной панели по ID. Если это не соответствует панели то возвращает null вместо пустого селектора, что может привести к неожиданным ошибкам в JS. (И отказ выполнения остальной части скрипта.)

$( "#MyLabel" ).text = "hello";

Msg

Для простой записи, используйте $.Msg() - поддерживает все типы Javascript и любое количество аргументов. (Будет печатать все аргументы последовательно на одной строке.)

// Напишет: Hello {"who":"world"}!
$.Msg( "Hello ", { "who": "world" }, "!" );

GetContextPanel

$.GetContextPanel() returns the root "context panel" that the script is running for. (Very similar to 'this' or 'self' in other languages.) This is the root panel of the XML that loaded the script.

<root>
	<script>
		$.GetContextPanel().SetHasClass( "context_panel", true ); // after this it will have both "context_panel" and "root_panel" classes
	</script>
	<Panel class="root_panel">
		<Label text="Hi" />
	</Panel>
</root>

Game APIs

Game Events

Javascript может зарегистрировать функцию на вызов когда игровое событие вызывается. Это работает для событий движка и нового Custom Game Events(en):

    function OnFoo( data ) { $.Msg( "foo_event: ", data ); }
    var handle = GameEvents.Subscribe( "foo_event_name", OnFoo );
    GameEvents.Unsubscribe( handle );

Custom Nettables

Custom nettables are a way to communicate persistent state from the server to clients. See: Dota 2 Workshop Tools/Custom Nettables(en)

Best Practices and Javascript Gotchas

"use strict"

Our example Javascript code employs the http://www.w3schools.com/js/js_strict.asp "use strict"(en) feature to increase safety, robustness, and sanity.

That Weird Anonymous Function Thing (IIFE)

In our example Javascript, you may see use of the http://getinstance.info/articles/javascript/immediately-invoked-function-expressions/ Immediately-invoked Function Expression (IIFE)(en) pattern.

(function () {
	$.Msg( "The panel associated with this javascript just got loaded or reloaded!" );
})();

Triple Equals

If you're familiar with C-family languages, you may be surprised to learn that Javascript has two equality operators: '==' and '==='

You can learn more about this https://developer.mozilla.org/docs/Web/JavaScript/Equality_comparisons_and_sameness here(en) or elsewhere on the web.

Variable Capture

If you're coming to Javascript from another language, you should know that nested functions capture their enclosing scope by reference, which can lead to unexpected results:

var closures_bad = [];
var closures_good = [];
function create()
{
	for (var i = 0; i < 5; i++)
	{
		closures_bad[i] = function()
		{
			$.Msg( "i = ", i );
		};
		closures_good[i] = (function( j ){return function()
		{
			$.Msg( "i = ", j );
		}}(i));
	}
}

function run()
{
	// prints "5 5 5 5 5" because loop variable 'i' is captured by reference above
	for (var k = 0; k < 5; k++)
	{
		closures_bad[k]();
	}
	// prints "0 1 2 3 4" because each value of loop 'i' is captured by a different function parameter 'j'
	for (var k = 0; k < 5; k++)
	{
		closures_good[k]();
	}
}

create();
run();

Misc

Panorama Javascript execution is handled by the Google V8 javascript engine.

Warning: Display title "Javascript" overrides earlier display title "Panorama/Javascript".