Ru/Understanding VGUI2 Animation: Difference between revisions

From Valve Developer Community
< Ru
Jump to navigation Jump to search
No edit summary
No edit summary
Line 48: Line 48:
****Любые значения типов KeyValues ​​::TYPE_FLOAT и KeyValues ​​::TYPE_COLOR, которые доступны при вызове '''RequestInfo''' на панели, также можно изменять. <Sup id = "fnote1"> '''[[#Footnotes|1]]'''</sup>
****Любые значения типов KeyValues ​​::TYPE_FLOAT и KeyValues ​​::TYPE_COLOR, которые доступны при вызове '''RequestInfo''' на панели, также можно изменять. <Sup id = "fnote1"> '''[[#Footnotes|1]]'''</sup>
**** [[#Defining animation variables in code|Variables defined in code]]
**** [[#Defining animation variables in code|Variables defined in code]]
*** Valid target values: Any floating-point value. '''Up to four values are possible.''' Put multiple values between quotes (e.g. "255 0 0 255" or "512 512")
*** Допустимые целевые значения: любое значение с плавающей запятой. '''Возможно до четырех значений.''' Поместите несколько значений в кавычки (например, "255 0 0 255" или "512 512")
*** Valid interpolators:
*** Действующие интерполяторы:
**** Linear
**** Линейный
**** Accel - starts moving slow, ends fast
**** Accel - начинает двигаться медленно, быстро заканчивается
**** Deaccel - starts moving fast, ends slow
**** Deaccel - начинает двигаться быстро, заканчивается медленно
**** Spline - very smooth interpolation
**** Spline - очень плавная интерполяция
**** Pulse - uses a sine pulse to interpolate. Expects a frequency value.
**** Pulse - использует синусоидальный импульс для интерполяции. Ожидает значение частоты.
**** Flicker - uses the [http://en.wikipedia.org/wiki/Pseudorandom_number_generator PRNG] to determine whether to be at original value or at the final value, which causes a flicker effect. Expects a noise amount value. {{Tip| Both Pulse and Flicker take an extra value, so be sure to put one in the scripts.}}
**** Flicker - использует [http://en.wikipedia.org/wiki/Pseudorandom_number_generator PRNG], чтобы определить, следует ли использовать исходное значение или конечное значение, что вызывает эффект мерцания. Ожидает значение количества шума. {{Tip:ru| И Pulse, и Flicker имеют дополнительное значение, поэтому обязательно укажите его в скриптах.}}
*** Valid start times: Any floating-point value. Essentially a delay factor.
*** Допустимое время начала: любое значение с плавающей запятой. Фактически фактор задержки.
*** Valid durations: Any floating-point value.
*** Допустимая продолжительность: любое значение с плавающей запятой.


* '''RunEvent''': starts another event running at the specified time.
* '''RunEvent''': запускает другое событие, запущенное в указанное время.
** Arguments: <event name> <start time>
** Значения: <event name> <start time>
*** Valid event names: Any event defined in the animation files.
*** Допустимые имена событий: любое событие, определенное в файлах анимации.


* '''StopEvent''': stops another event that is currently running at the specified time.
* '''StopEvent''': останавливает другое событие, которое в данный момент выполняется в указанное время.
** Arguments: <event name> <start time>
** Значения: <event name> <start time>


* '''StopAnimation''': stops all animations referring to the specified variable in the specified panel.
* '''StopAnimation''': останавливает все анимации, ссылающиеся на указанную переменную на указанной панели.
** Arguments: <panel name> <variable> <start time>
** Значения: <panel name> <variable> <start time>


* '''StopPanelAnimations''': stops all active animations operating on the specified panel.
* '''StopPanelAnimations''': останавливает все активные анимации, работающие на указанной панели.
** Arguments: <panel name> <start time>
** Значения: <panel name> <start time>


* '''SetFont''': {{Todo|Look up what this does.}}
* '''SetFont''': {{Todo:ru|Посмотрим, что это делает.}}
** Arguments: <panel name> <<nowiki>font parameter</nowiki>> <<nowiki>font name from scheme</nowiki>> <set time>
** Значения: <panel name> <<nowiki>font parameter</nowiki>> <<nowiki>font name from scheme</nowiki>> <set time>


* '''SetTexture''': {{Todo|Look up what this does.}}
* '''SetTexture''': {{Todo:ru|Посмотрим, что это делает.}}
** Arguments: <panel name> <texture ID> <material name> <set time>
** Значения: <panel name> <texture ID> <material name> <set time>


* '''SetString''': {{Todo|Look up what this does.}}
* '''SetString''': {{Todo:ru|Посмотрим, что это делает.}}
** Arguments: <panel name> <string variable name> <value to set> <set time>
** Значения: <panel name> <string variable name> <value to set> <set time>


= Executing Animations =
= Выполнение анимации =


== Accessing the controller ==
== Доступ к контроллеру ==
First off, you'll need some includes. If you're working in a class that uses the vgui namespace, you can call the animation controller by including '''vgui_controls/AnimationController.h''' and calling it like so:
Во-первых, вам понадобятся некоторые включения. Если вы работаете в классе, который использует пространство имен vgui, вы можете вызвать контроллер анимации, включив '''vgui_controls / AnimationController.h''' и назвав его так:
<source lang="cpp">
<source lang = "cpp">
  vgui::GetAnimationController()
  vgui ::GetAnimationController ()
</source>
</source>
If you're not using the vgui namespace, you'll need to include both '''clientmode.h''' and '''vgui_controls/AnimationController.h''', and call the animation controller like so:
Если вы не используете пространство имен vgui, вам необходимо включить как '''clientmode.h''', так и '''vgui_controls/AnimationController.h''', и вызвать контроллер анимации следующим образом:
<source lang="cpp">
<source lang = "cpp">
  g_pClientMode->GetViewportAnimationController()
  g_pClientMode-> GetViewportAnimationController ()
</source>
</source>


== Executing Events ==
== Выполнение событий ==
An event can be executed using the '''StartAnimationSequence''' method, which has two overloads. One simply takes the event name and looks up panels by itself, starting from the root panel, and the other takes the event name and a pointer to a panel that houses the controls that will be animated.
Событие может быть выполнено с помощью метода StartAnimationSequence, который имеет две перегрузки. Один просто берет имя события и ищет панели отдельно, начиная с корневой панели, а другой берет имя события и указатель на панель, в которой находятся элементы управления, которые будут анимированы.


<source lang="cpp">
<source lang="cpp">
Line 101: Line 101:
</source>
</source>


=== Defining animation variables in code ===
=== Определение переменных анимации в коде ===
Defining a variable that can be used in the event files is easy, and uses the following macro:
Определить переменную, которая может использоваться в файлах событий, несложно, и для этого используется следующий макрос:
<source lang="cpp">
<source lang="cpp">
  #define CPanelAnimationVar( type, name, scriptname, defaultvalue )\
  #define CPanelAnimationVar( type, name, scriptname, defaultvalue )\
Line 108: Line 108:
</source>
</source>


Looking through code references, this appears to work fine for: <sup id="fnote2">'''[[#Footnotes|2]]'''</sup>
Просматривая ссылки на код, кажется, что это нормально работает для: <sup id="fnote2">'''[[#Footnotes|2]]'''</sup>
* '''Colors:''' CPanelAnimationVar( Color, m_cChangableColor, "Changable_Color", "0 0 0 0" );
* '''Colors:''' CPanelAnimationVar( Color, m_cChangableColor, "Changable_Color", "0 0 0 0" );
* '''Fonts:''' CPanelAnimationVar( vgui::HFont, m_hChangableFont, "FontOverride", "DefaultSmall" );
* '''Fonts:''' CPanelAnimationVar( vgui::HFont, m_hChangableFont, "FontOverride", "DefaultSmall" );
Line 115: Line 115:
* '''Booleans:''' CPanelAnimationVar( bool, m_bChangableBool, "BoolOverride", "0" );
* '''Booleans:''' CPanelAnimationVar( bool, m_bChangableBool, "BoolOverride", "0" );


== Executing dynamic animations ==
== Выполнение динамической анимации ==
Events are handy for static animations, but if you want to load any argument on the fly, you'll need dynamic animations. It's surprisingly simple!
События удобны для статической анимации, но если вы хотите загружать любой аргумент на лету, вам понадобится динамическая анимация. Это на удивление просто!


=== Preparing for running animations ===
=== Подготовка к запуску анимации ===
The method we are interested in is called '''RunAnimationCommand''', and takes arguments similarly to the events defined above.
Интересующий нас метод называется RunAnimationCommand и принимает аргументы аналогично событиям, определенным выше.


{{Note|If you're accessing the controller via g_pClientMode, you'll want to call the '''UpdateAnimations''' method manually in the '''OnThink()''' method of your panel.}}
{{Note:ru|Если вы обращаетесь к контроллеру через g_pClientMode, вам нужно вызвать метод '''UpdateAnimations''' вручную в методе '''OnThink()''' вашей панели.}}




The '''RunAnimationCommand''' has two overloads: one for a single value, and another for multiple values. Unfortunately, the multiple-valued one uses the Color class to load any values, which means the values will be truncated to integers AND wrap around very quickly! To mitigate this, let's create a new overload:
'''RunAnimationCommand''' имеет две перегрузки: одну для одного значения, а другую для нескольких значений. К сожалению, многозначный использует класс Color для загрузки любых значений, что означает, что значения будут усечены до целых чисел и очень быстро обернутся! Чтобы смягчить это, давайте создадим новую перегрузку:


Copy this under the other '''RunAnimationCommand''' overloads in '''AnimationController.cpp''':
Скопируйте это в другие перегрузки '''RunAnimationCommand''' в '''AnimationController.cpp''':


<source lang="cpp">
<source lang="cpp">
Line 165: Line 165:
  void RunAnimationCommand(vgui::Panel *panel, const char *variable, PublicValue_t targetValue, float startDelaySeconds, float durationSeconds, Interpolators_e interpolator, float animParameter = 0 );
  void RunAnimationCommand(vgui::Panel *panel, const char *variable, PublicValue_t targetValue, float startDelaySeconds, float durationSeconds, Interpolators_e interpolator, float animParameter = 0 );
</source>
</source>
{{Note|I know, there's a perfectly fine '''Value_t''' struct that we can also use, but when I made it public, the entire class went haywire. Feel free to find a correct implementation.}}
{{Note:ru|Я знаю, что есть прекрасная структура Value_t, которую мы также можем использовать, но когда я сделал ее общедоступной, весь класс пошел наперекосяк. Не стесняйтесь искать правильную реализацию.}}


=== Running animations ===
=== Анимация бега ===
Now we're in business! You can call animations though the controller very easily. Here's an example as to how you would programmatically change the size of an ImagePanel:
Теперь мы в деле! Вы можете легко вызывать анимацию через контроллер. Вот пример того, как программно изменить размер ImagePanel:


Let's say we have an ImagePanel called '''"overviewImage "''', which is defined in our panel's .res file. First, we get the panel:
Допустим, у нас есть ImagePanel с именем '''"overviewImage"''', который определен в .res файле нашей панели. Сначала получаем панель:
<source lang="cpp">
<source lang="cpp">
  m_pOverviewImage = dynamic_cast<ImagePanel*>( FindChildByName( "overviewImage ", false ) );
  m_pOverviewImage = dynamic_cast<ImagePanel*>( FindChildByName( "overviewImage ", false ) );
</source>
</source>
{{Note|Put this in the class constructor right after you've loaded the Resource file. If you're confused, read this: [[Understanding_VGUI2_Resource_Files#Loading_a_resource_file|Loading a Resource File]].}}
{{Note:ru|Поместите это в конструктор класса сразу после загрузки файла ресурсов. Если вы запутались, прочтите это:[[Understanding_VGUI2_Resource_Files#Loading_a_resource_file|Loading a Resource File]].}}


You can then resize the ImagePanel as follows:
Затем вы можете изменить размер ImagePanel следующим образом:
<source lang="cpp">
<source lang="cpp">
  AnimationController::PublicValue_t newSize;
  AnimationController::PublicValue_t newSize;
Line 189: Line 189:




= Footnotes =
= Сноски =
1. ''AnimationController::GetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var)'' houses the according code.
1. «AnimationController ::GetValue (ActiveAnimation_t & anim, Panel * panel, UtlSymId_t var)» содержит соответствующий код.


2. You may also have noticed that '''CPanelAnimationVarAliasType''' is also a define, and takes an extra parameter: a type alias.
2. Вы также могли заметить, что '''CPanelAnimationVarAliasType''' также является определением и принимает дополнительный параметр: тип алиаса.
<source lang="cpp">
<source lang="cpp">
  // Only the first line
  // Only the first line
Line 198: Line 198:
</source>
</source>


This type alias is a string, and is used when converting the string-based default values into proper ones, and can also be used for custom processing. This processing is done in '''Panel::InitPropertyConverters()'''. This might be a good place to start if you want to extend this functionality to other variable types.
Этот псевдоним типа является строкой и используется при преобразовании значений по умолчанию на основе строк в правильные, а также может использоваться для пользовательской обработки. Эта обработка выполняется в '''Panel ::InitPropertyConverters()'''. Это может быть хорошим началом, если вы хотите расширить эту функциональность на другие типы переменных.


[[Category:Programming]]
[[Category:Programming]]
[[Category:VGUI]]
[[Category:VGUI]]

Revision as of 17:42, 19 June 2021

Template:Otherlang2

Вступление

VGUI2 имеет довольно мощную систему анимации для анимации как элементов HUD, так и панелей VGUI. Вот относительно полный обзор того, что с ним можно делать.

Обзор архитектуры

Система анимации определена в AnimationController.cpp, который можно найти в vgui2/vgui_controls. Он очень обширный, но основная концепция такова:

  • Добавлять анимацию можно несколькими способами
  • Запускайте эти анимации каждый тик, используя функцию интерполятора для вычисления промежуточного значения.

Есть два основных способа добавления анимации, которые представляют собой определяемые сценарием события и динамические анимации, которые выполняются во время выполнения.

События

События анимации могут быть загружены из двух источников, оба из которых находятся в папке scripts:

  • Манифест сценария анимации: hudanimations_manifest.txt. Если он не найден, загружается последний:
  • Один файл сценария: HudAnimations.txt.

Template:Note:ru


Манифест это обычный файл KeyValue. Он будет загружать каждый файл в манифесте:

"HudAnimationManifest"
{
	"file" "scripts/HudAnimations.txt"
	// You can add more here
}

Template:Tip:ru

Макет файла

Открыв HudAnimations.txt, вы увидите множество событий, используемых в Half-Life 2. Вот синтаксис события:

event <EVENTNAME>
{
	<COMMAND>	<ARGUMENTS>
}

Обзор событий

Вверху файла вы увидите прекрасный обзор возможных команд и их аргументов. Вот обновленный обзор (в коде есть кое-что новое):

  • Animate
    • Аргументы: <panel name> <variable> <target value(s)> <interpolator> <start time> <duration>
      • Допустимые названия панелей: любая панель VGUI или HUD.
      • Допустимые значения: Template:Note:ru
        • Унарный (1 аргумент): Xpos, Ypos, Ширина, Высота, Блюр, Прозрачность(Альфа), Прозрачность при выборе элемента
        • Двоичный (2 аргумента): Позиция, Размер
        • Более двух: FgColor, BgColor, TextColor, Ammo2Color Template:Tip:ru
        • Неизвестный: TextScan
        • Любые значения типов KeyValues ​​::TYPE_FLOAT и KeyValues ​​::TYPE_COLOR, которые доступны при вызове RequestInfo на панели, также можно изменять. 1
        • Variables defined in code
      • Допустимые целевые значения: любое значение с плавающей запятой. Возможно до четырех значений. Поместите несколько значений в кавычки (например, "255 0 0 255" или "512 512")
      • Действующие интерполяторы:
        • Линейный
        • Accel - начинает двигаться медленно, быстро заканчивается
        • Deaccel - начинает двигаться быстро, заканчивается медленно
        • Spline - очень плавная интерполяция
        • Pulse - использует синусоидальный импульс для интерполяции. Ожидает значение частоты.
        • Flicker - использует PRNG, чтобы определить, следует ли использовать исходное значение или конечное значение, что вызывает эффект мерцания. Ожидает значение количества шума. Template:Tip:ru
      • Допустимое время начала: любое значение с плавающей запятой. Фактически фактор задержки.
      • Допустимая продолжительность: любое значение с плавающей запятой.
  • RunEvent: запускает другое событие, запущенное в указанное время.
    • Значения: <event name> <start time>
      • Допустимые имена событий: любое событие, определенное в файлах анимации.
  • StopEvent: останавливает другое событие, которое в данный момент выполняется в указанное время.
    • Значения: <event name> <start time>
  • StopAnimation: останавливает все анимации, ссылающиеся на указанную переменную на указанной панели.
    • Значения: <panel name> <variable> <start time>
  • StopPanelAnimations: останавливает все активные анимации, работающие на указанной панели.
    • Значения: <panel name> <start time>
  • SetFont: Template:Todo:ru
    • Значения: <panel name> <font parameter> <font name from scheme> <set time>
  • SetTexture: Template:Todo:ru
    • Значения: <panel name> <texture ID> <material name> <set time>
  • SetString: Template:Todo:ru
    • Значения: <panel name> <string variable name> <value to set> <set time>

Выполнение анимации

Доступ к контроллеру

Во-первых, вам понадобятся некоторые включения. Если вы работаете в классе, который использует пространство имен vgui, вы можете вызвать контроллер анимации, включив vgui_controls / AnimationController.h и назвав его так:

 vgui ::GetAnimationController ()

Если вы не используете пространство имен vgui, вам необходимо включить как clientmode.h, так и vgui_controls/AnimationController.h, и вызвать контроллер анимации следующим образом:

 g_pClientMode-> GetViewportAnimationController ()

Выполнение событий

Событие может быть выполнено с помощью метода StartAnimationSequence, который имеет две перегрузки. Один просто берет имя события и ищет панели отдельно, начиная с корневой панели, а другой берет имя события и указатель на панель, в которой находятся элементы управления, которые будут анимированы.

 vgui::GetAnimationController()->StartAnimationSequence( "ShowCommentary" ); // Just the event name
 vgui::GetAnimationController()->StartAnimationSequence( this, "MapZoomToLarge" ); // Event name + parent panel (example from CS:S)

Определение переменных анимации в коде

Определить переменную, которая может использоваться в файлах событий, несложно, и для этого используется следующий макрос:

 #define CPanelAnimationVar( type, name, scriptname, defaultvalue )\
 	CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, #type )

Просматривая ссылки на код, кажется, что это нормально работает для: 2

  • Colors: CPanelAnimationVar( Color, m_cChangableColor, "Changable_Color", "0 0 0 0" );
  • Fonts: CPanelAnimationVar( vgui::HFont, m_hChangableFont, "FontOverride", "DefaultSmall" );
  • Floats: CPanelAnimationVar( float, m_fChangableFloat, "FloatAnimation", "0" );
  • Integers: CPanelAnimationVar( int, m_iChangableInt, "IntOverride", "0" );
  • Booleans: CPanelAnimationVar( bool, m_bChangableBool, "BoolOverride", "0" );

Выполнение динамической анимации

События удобны для статической анимации, но если вы хотите загружать любой аргумент на лету, вам понадобится динамическая анимация. Это на удивление просто!

Подготовка к запуску анимации

Интересующий нас метод называется RunAnimationCommand и принимает аргументы аналогично событиям, определенным выше.

Template:Note:ru


RunAnimationCommand имеет две перегрузки: одну для одного значения, а другую для нескольких значений. К сожалению, многозначный использует класс Color для загрузки любых значений, что означает, что значения будут усечены до целых чисел и очень быстро обернутся! Чтобы смягчить это, давайте создадим новую перегрузку:

Скопируйте это в другие перегрузки RunAnimationCommand в AnimationController.cpp:

 //-----------------------------------------------------------------------------
 // Purpose: Runs a custom command from code, not from a script file
 //-----------------------------------------------------------------------------
 void AnimationController::RunAnimationCommand(vgui::Panel *panel, const char *variable, PublicValue_t targetValue, float startDelaySeconds, float duration, Interpolators_e interpolator, float animParameter /* = 0 */ )
 {
 	// clear any previous animations of this variable
 	UtlSymId_t var = g_ScriptSymbols.AddString(variable);
 	RemoveQueuedAnimationByType(panel, var, UTL_INVAL_SYMBOL);
 
 	// build a new animation
 	AnimCmdAnimate_t animateCmd;
 	memset(&animateCmd, 0, sizeof(animateCmd));
 	animateCmd.panel = 0;
 	animateCmd.variable = var;
 	animateCmd.target.a = targetValue.a;
 	animateCmd.target.b = targetValue.b;
 	animateCmd.target.c = targetValue.c;
 	animateCmd.target.d = targetValue.d;
 	animateCmd.interpolationFunction = interpolator;
 	animateCmd.interpolationParameter = animParameter;
 	animateCmd.startTime = startDelaySeconds;
 	animateCmd.duration = duration;
 
 	// start immediately
 	StartCmd_Animate(panel, 0, animateCmd);
 }

And copy this above the prototype of RunAnimationCommand in AnimationController.h:

 struct PublicValue_t
 {
 	float a, b, c, d;
 };
 void RunAnimationCommand(vgui::Panel *panel, const char *variable, PublicValue_t targetValue, float startDelaySeconds, float durationSeconds, Interpolators_e interpolator, float animParameter = 0 );

Template:Note:ru

Анимация бега

Теперь мы в деле! Вы можете легко вызывать анимацию через контроллер. Вот пример того, как программно изменить размер ImagePanel:

Допустим, у нас есть ImagePanel с именем "overviewImage", который определен в .res файле нашей панели. Сначала получаем панель:

 m_pOverviewImage = dynamic_cast<ImagePanel*>( FindChildByName( "overviewImage ", false ) );

Template:Note:ru

Затем вы можете изменить размер ImagePanel следующим образом:

 AnimationController::PublicValue_t newSize;
 newSize.a = 256;
 newSize.b = 256;
 newSize.c = 0; // Unused
 newSize.d = 0; // Unused

 float totalAnimationTime = 3.0f;
 vgui::GetAnimationController()->RunAnimationCommand( m_pOverviewImage , "size", newSize, 0.0f, totalAnimationTime , vgui::AnimationController::INTERPOLATOR_LINEAR );


Сноски

1. «AnimationController ::GetValue (ActiveAnimation_t & anim, Panel * panel, UtlSymId_t var)» содержит соответствующий код.

2. Вы также могли заметить, что CPanelAnimationVarAliasType также является определением и принимает дополнительный параметр: тип алиаса.

 // Only the first line
 #define CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, typealias ) \

Этот псевдоним типа является строкой и используется при преобразовании значений по умолчанию на основе строк в правильные, а также может использоваться для пользовательской обработки. Эта обработка выполняется в Panel ::InitPropertyConverters(). Это может быть хорошим началом, если вы хотите расширить эту функциональность на другие типы переменных.