From e485aedc8ee41184bf6dd229945601ccae83f4f4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 25 Sep 2026 23:56:32 +0300 Subject: [PATCH 1/3] add 'period' keyframes-based line parameter --- res/modules/animation.lua | 3 ++- res/modules/internal/animation_codegen.lua | 12 ++++++------ res/modules/internal/formats/vca.lua | 4 +++- res/scripts/components/animator.lua | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/res/modules/animation.lua b/res/modules/animation.lua index cbed8a941..35a77b78e 100644 --- a/res/modules/animation.lua +++ b/res/modules/animation.lua @@ -48,8 +48,9 @@ local this = { INT_LINEAR = 2, INT_BEZIER = 3, INT_CUSTOM = 4, + ALMOST_HUGE = 1e9, - TRACE_CODEGEN = false, + TRACE_CODEGEN = true, maths = { bezier_interpolation = bezier_interpolation diff --git a/res/modules/internal/animation_codegen.lua b/res/modules/internal/animation_codegen.lua index 66db0bed4..316dd22b3 100644 --- a/res/modules/internal/animation_codegen.lua +++ b/res/modules/internal/animation_codegen.lua @@ -150,16 +150,16 @@ local function codegen_track(raw_track, lineset, memoised, keysets, use_tsf) local valueat = string.format("curves[%s]", string.escape(line.curve_func)) code = code .. string.format( - "\n local l%d = value_at_custom(keysets['%s'][%d], t * %s, %s)", - i, lineset.target_name, i, raw_track.fps, valueat) + "\n local l%d = value_at_custom(keysets['%s'][%d], t * %s %% %s, %s)", + i, lineset.target_name, i, raw_track.fps, line.period, valueat) elseif line.channel == animation.CH_TEXTURE then code = code .. string.format( - "\n local l%d = string_at(keysets['%s'][%d], t * %s)", - i, lineset.target_name, i, raw_track.fps) + "\n local l%d = string_at(keysets['%s'][%d], t * %s %% %s)", + i, lineset.target_name, i, raw_track.fps, line.period) else code = code .. string.format( - "\n local l%d = value_at(keysets['%s'][%d], t * %s, %s)", - i, lineset.target_name, i, raw_track.fps, line.interp) + "\n local l%d = value_at(keysets['%s'][%d], t * %s %% %s, %s)", + i, lineset.target_name, i, raw_track.fps, line.period, line.interp) end end diff --git a/res/modules/internal/formats/vca.lua b/res/modules/internal/formats/vca.lua index e22e220eb..99f03f15b 100644 --- a/res/modules/internal/formats/vca.lua +++ b/res/modules/internal/formats/vca.lua @@ -106,8 +106,10 @@ local function parse_track(root) end local line = { axis = node.by and ("xyz"):find(node.by) or "", - channel = channel + channel = channel, + period = node.period or animation.ALMOST_HUGE } + debug.print(animation.ALMOST_HUGE) if node.func then line.expression = node.func elseif node.curve then diff --git a/res/scripts/components/animator.lua b/res/scripts/components/animator.lua index 5bd3ef4fa..9fc5735fe 100644 --- a/res/scripts/components/animator.lua +++ b/res/scripts/components/animator.lua @@ -1,4 +1,4 @@ -local ALMOST_HUGE = 1e9 +local ALMOST_HUGE = animation.ALMOST_HUGE local rig = entity.skeleton From 0dfc87700d5723e6958dd6021791d897996b2001 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 25 Sep 2026 23:58:42 +0300 Subject: [PATCH 2/3] cleanup --- res/modules/animation.lua | 5 +++-- res/modules/internal/formats/vca.lua | 3 +-- res/scripts/components/animator.lua | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/res/modules/animation.lua b/res/modules/animation.lua index 35a77b78e..411623364 100644 --- a/res/modules/animation.lua +++ b/res/modules/animation.lua @@ -48,9 +48,10 @@ local this = { INT_LINEAR = 2, INT_BEZIER = 3, INT_CUSTOM = 4, - ALMOST_HUGE = 1e9, + MAX_DURATION = 1e9, + MAX_FRAMES = 1e9, - TRACE_CODEGEN = true, + TRACE_CODEGEN = false, maths = { bezier_interpolation = bezier_interpolation diff --git a/res/modules/internal/formats/vca.lua b/res/modules/internal/formats/vca.lua index 99f03f15b..4ecf4c895 100644 --- a/res/modules/internal/formats/vca.lua +++ b/res/modules/internal/formats/vca.lua @@ -107,9 +107,8 @@ local function parse_track(root) local line = { axis = node.by and ("xyz"):find(node.by) or "", channel = channel, - period = node.period or animation.ALMOST_HUGE + period = node.period or animation.MAX_FRAMES } - debug.print(animation.ALMOST_HUGE) if node.func then line.expression = node.func elseif node.curve then diff --git a/res/scripts/components/animator.lua b/res/scripts/components/animator.lua index 9fc5735fe..611ffa6f8 100644 --- a/res/scripts/components/animator.lua +++ b/res/scripts/components/animator.lua @@ -1,4 +1,4 @@ -local ALMOST_HUGE = animation.ALMOST_HUGE +local MAX_DURATION = animation.MAX_DURATION local rig = entity.skeleton @@ -54,7 +54,7 @@ local function update(delta) if state.track and intensity > 0.0 then state.track.func( rig, - state.timer % math.min(ALMOST_HUGE, state.track.duration), + state.timer % math.min(MAX_DURATION, state.track.duration), intensity * state.max_intencity ) end From 926bfc545d479046949217f1e813e0ca7d223db4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 26 Sep 2026 00:03:03 +0300 Subject: [PATCH 3/3] update doc/*/vca.md --- doc/en/vca.md | 10 ++++++++++ doc/ru/vca.md | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/doc/en/vca.md b/doc/en/vca.md index d8c0c238f..7b2bda0b5 100644 --- a/doc/en/vca.md +++ b/doc/en/vca.md @@ -86,6 +86,16 @@ For the `texture` directive, it is simpler. Example: > Here, `entities/tireman` is the name of the texture atlas containing `face_*` textures. > The texture does not necessarily have to be in an atlas. +If you do not wish to limit the animation duration via `configure` but want to loop the keyframe animation for a specific line, you can use the `period` parameter to specify the animation's repetition period in frames. Example: + +```vcd +@move by y curve linear period 24 { + @key frame 0 value 0 + @key frame 12 value 1 + @key frame 24 value 0 +} +``` + ## Expression curves The attribute describes a function `f(t) = x`, where t is time in seconds. diff --git a/doc/ru/vca.md b/doc/ru/vca.md index c4d97c2ec..2cba3c3ab 100644 --- a/doc/ru/vca.md +++ b/doc/ru/vca.md @@ -86,6 +86,16 @@ VCA файл состоит из набора директив, порядок > entities/tireman здесь - имя текстурного атласа, в котором находятся face_\* текстуры. > Текстура не обязательно должна находиться в атласе. +Если вы не хотите ограничивать длительность анимации через `configure`, но хотите зациклить анимацию по ключевым кадрам для конкретной линии, то можно использовать параметр `period` для указания периода повторения анимации в кадрах. Пример: + +```vcd +@move by y curve linear period 24 { + @key frame 0 value 0 + @key frame 12 value 1 + @key frame 24 value 0 +} +``` + ## Кривые через выражения Через атрибут описывается функция `f(t) = x` где t - время в секундах.