Skip to content

feat(animation): add sound playback mode selector#3210

Open
nighca wants to merge 14 commits into
goplus:devfrom
nighca:codex/issue-3208-onplay
Open

feat(animation): add sound playback mode selector#3210
nighca wants to merge 14 commits into
goplus:devfrom
nighca:codex/issue-3208-onplay

Conversation

@nighca
Copy link
Copy Markdown
Collaborator

@nighca nighca commented May 25, 2026

Summary

  • Add a playback selector for animation-bound sounds in the sound binding dropdown.
  • Replace the old soundLoop model flag with AnimationSoundPlayback.
  • Export complete one-shot sounds through onStart.
  • Export animation-following looping sounds through onPlay.
  • Stop exporting the deprecated loop option from animation sound bindings.

This PR covers the Builder-side UI/model work for #3208. The issue still also depends on a future SPX version with the updated onStart / onPlay engine semantics, so this PR references the issue instead of closing it.

Do not merge this PR yet. Keep it open until Builder upgrades to an SPX version that implements the behavior concluded in #3208 (comment); after that SPX upgrade lands, this PR can be merged.

Refs #3208

Tests

  • npm test -- src/models/spx/animation.test.ts --run
  • npm test -- src/models/spx/project.test.ts --run
  • npm test -- src/models/spx/sound.test.ts --run
  • npm run type-check
  • npm run lint
  • npm run format-check -- src/components/editor/sprite/animation/SoundEditor.vue src/components/ui/UIDropdownForm.vue src/models/spx/animation.ts src/models/spx/animation.test.ts
  • git diff --check

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the animation export logic to use onPlay instead of the legacy onStart for sound bindings, now including the loop property. Correspondingly, several tests in animation.test.ts that were previously skipped have been re-enabled, and a new test case was added to ensure non-loop sound bindings are correctly preserved during project export and load. I have no feedback to provide.

Copy link
Copy Markdown
Contributor

@fennoai fennoai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, focused revert of the temporary onStart workaround back to the intended onPlay format. The logic change is correct, the skipped tests are properly re-enabled, and the new round-trip test adds good coverage.

Note (out-of-diff): The ActionConfig.loop JSDoc at animation.ts:14 says "for onPlay defaults to true", but the load path uses onPlay?.loop ?? false — defaulting to false. Since exports now always write loop explicitly, this comment is inaccurate and should be updated to avoid misleading future readers (e.g. simply "Whether to loop the sound; defaults to false"). This line isn't in the diff but is worth a quick follow-up fix.

Comment thread spx-gui/src/models/spx/animation.test.ts Outdated
@nighca nighca changed the title feat(animation): migrate sound binding back to onPlay feat(animation): add sound playback mode selector May 28, 2026
@nighca

This comment was marked as outdated.

@fennoai

This comment was marked as resolved.

Copy link
Copy Markdown
Collaborator

@cn0809 cn0809 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nighca
Copy link
Copy Markdown
Collaborator Author

nighca commented May 28, 2026

@cn0809 加上了 AnimationPlayer 对 sound playback 的支持,再帮瞅下 feea63

for (const audio of audios) {
audio.muted = muted
}
if (props.sound != null) {
Copy link
Copy Markdown
Collaborator Author

@nighca nighca May 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是特意判断 props.sound 是否为空而不是判断 audios 是否为空;因为 audios 为空有可能是在两个 audio 播放的间隙(playback: Once 的情况下),并不代表没有声音

* Play the audio with `playback: AnimationSoundPlayback.Once`.
* The sound is triggered once per animation cycle (duration).
* If the previous sound is still playing when the next cycle starts, it will keep playing.
* In that case, multiple sound instances can overlap.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIP: 意思是如果 animation duration 比 sound 时长短,就会有同一个 sound 的不同时段叠加播放,极限情况可能叠加 10 遍?这样设计是合理的吗

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果 animation duration 比 sound 时长短,就会有同一个 sound 的不同时段叠加播放

是的

极限情况可能叠加 10 遍

在编辑器这边限制为 10,在 spx 运行的时候我不确定,可能没有限制

这样设计是合理的吗

它针对的是某个动作,其音效比视觉上的时间略久的情况;比如人物做一次攻击,1s 就做完动作了,但是对应的声音有可能是 1.2s,这后边的 0.2s 有可能是动作的尾音,这从效果上是合理的。如果人物很快又做一次攻击动作,那么两个声音发生重叠也是预期的。

因此一般来说选择 playback: once 的应该是

  1. 像攻击、跳跃这种(区别于待机、行走等)不会默认循环播放的动画
  2. 比较短的、跟动画本身时长在一个数量级的音效

所以实际上不会有问题

如果这里真的达到了到 10 的限制,那大概率是配错了,我没想到有什么合理的场景,是需要为一个 animation 绑一个时长是它 10 倍的 playback: once 的 sound 的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants