Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/en/api/player.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func _ready() -> void:
* `set_animation_process_mode(mode: AnimationProcessMode)` / `get_animation_process_mode() -> AnimationProcessMode`: Sets whether to sync with `_physics_process` (`ANIMATION_PROCESS_PHYSICS` / `0`) or `_process` (`ANIMATION_PROCESS_IDLE` / `1`), or to stop ticking on its own (`ANIMATION_PROCESS_MANUAL` / `2`).
* `advance(delta: float)`: Steps playback by `delta` seconds and emits `frame_updated`, exactly as an automatic tick would. Meant for `ANIMATION_PROCESS_MANUAL` — under the other modes it advances the animation *on top of* the node's own tick.
* **In-editor preview**: Select the node and use the **SpriteStudio** bottom panel — play from start / play from current / stop, a frame scrubber, and loop and speed controls — to preview without running the game. Shortcuts mirror the AnimationPlayer editor (**D** play from current, **Shift+D** play from start, **S** stop). *(The former `editor_playing` inspector toggle has been replaced by this panel.)*
* `play(start_frame: float = -1.0)`: Starts playback. `-1.0` (the default) **rewinds to the start of the section** — its end when the direction is backward — rather than continuing from where the playhead is. Pass `get_frame()` to play on from the current position.
* `play(start_frame: float = -1.0)`: Starts playback. `-1.0` (the default) **rewinds to the start of the section** — its end when the direction is backward — rather than continuing from where the playhead is. Pass `get_frame_no()` to play on from the current position.
* `pause()`: Holds playback where it stands, keeping the current frame. **Idempotent** — pausing twice leaves it paused.
* `resume()`: Lifts the hold and carries on from the same frame. **Idempotent**, and a no-op on an animation that is stopped rather than held — `play()` is what starts a stopped animation, and it rewinds.
* `stop()`: Stops playback. The playhead **stays where it was**, so the node keeps drawing the frame it stopped on.
Expand All @@ -40,7 +40,7 @@ func _ready() -> void:
* `just_looped() -> bool`: Whether the last update crossed a loop boundary. A **pulse**, not a state — the runtime clears it at the top of every update, so it only reads `true` inside the tick that crossed (which is why it is not `is_looped`: reading it a tick late reads `false`). The `animation_looped` signal delivers the same edge if you would rather not poll.
* `get_animation_names() -> PackedStringArray`: Names of the animations in the assigned [SSABResource] — the same list the `animation` property is chosen from.
* `is_playing_forward() -> bool`: Which way the playhead is **actually** travelling. Not `get_playback_direction()`, which reports the configured heading: on a ping-pong return leg this reads `false` while that still reads `PLAYBACK_DIRECTION_FORWARD` (a speed of zero or below is a stop, not a reversal, and does not flip it either). **Gate audio on it** — SpriteStudio has no reverse audio, so a sound key crossed on a backward leg is not meant to sound, and this is the test the node itself applies when `play_audio` is on. `true` before anything has played: forward is the resting state.
* `set_frame(frame: float)` / `get_frame() -> float` / `get_total_frames() -> int`
* `set_frame_no(frame: float)` / `get_frame_no() -> float` / `get_total_frames() -> int`
* `get_start_frame() -> int` / `get_end_frame() -> int`: The first and last frame that actually plays — the current playback section. They return the same values as `get_animation_section_start()` / `get_animation_section_end()`, which is the whole animation until `set_animation_section()` narrows it.
* `set_speed_scale(speed_scale: float)` / `get_speed_scale() -> float`
* `set_frame_rate(fps: int)` / `get_frame_rate() -> int`
Expand Down
2 changes: 1 addition & 1 deletion docs/en/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Keep the output directory (`res://ssab_generated` by default) intact, or move th

### An override does not appear on screen

While playback is stopped or paused — or on any frame that does not advance — the drawing is not rebuilt, so setting or clearing an override changes nothing visible. Force a redraw with `set_frame(get_frame())`.
While playback is stopped or paused — or on any frame that does not advance — the drawing is not rebuilt, so setting or clearing an override changes nothing visible. Force a redraw with `set_frame_no(get_frame_no())`.

### `animation_finished` never fires

Expand Down
4 changes: 2 additions & 2 deletions docs/en/workflow/usage_scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func _process(delta):
> [!IMPORTANT]
> There are three states, not two. **`is_playing()` stays `true` while paused** — a pause is a hold, not a stop — so `is_pausing()` is what tells a held animation from a running one, and both are `false` before the first `play()` and after `stop()`.
>
> **`play()` is not a resume.** It rewinds to the start of the section and re-arms the loop counter. Lift a hold with `resume()`, and carry on from a stop with `play(get_frame())`.
> **`play()` is not a resume.** It rewinds to the start of the section and re-arms the loop counter. Lift a hold with `resume()`, and carry on from a stop with `play(get_frame_no())`.

---

Expand Down Expand Up @@ -293,4 +293,4 @@ Color and cell overrides conflict with the animation, so they take a `priority`
- Assigning a different `.ssab` resource clears every override, because part identity is lost.
- Overrides do not reach parts **inside** an instance part (the child animation runs as a separate player). Force-hiding the instance part itself does stop its contents from being drawn.

> **On when an override is not reflected in the drawing**: While playback is stopped or paused — or on any frame that does not advance — the drawing is not rebuilt, so setting or clearing an override will not appear on screen. Call `set_frame(get_frame())` to force a redraw when you need it reflected immediately.
> **On when an override is not reflected in the drawing**: While playback is stopped or paused — or on any frame that does not advance — the drawing is not rebuilt, so setting or clearing an override will not appear on screen. Call `set_frame_no(get_frame_no())` to force a redraw when you need it reflected immediately.
4 changes: 2 additions & 2 deletions docs/ja/api/player.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func _ready() -> void:
* `set_animation_process_mode(mode: AnimationProcessMode)` / `get_animation_process_mode() -> AnimationProcessMode`: `ANIMATION_PROCESS_PHYSICS`(`0`)で Physics (`_physics_process`) 同期、`ANIMATION_PROCESS_IDLE`(`1`)で Idle (`_process`) 同期、`ANIMATION_PROCESS_MANUAL`(`2`)でノード自身による更新を停止します。
* `advance(delta: float)`: 再生を `delta` 秒ぶん進め、自動更新と同じように `frame_updated` を発行します。`ANIMATION_PROCESS_MANUAL` 向けの API です。他のモードで呼ぶと、ノード自身の更新に *加えて* アニメーションが進みます。
* **エディタ内プレビュー**: ノードを選択すると表示される **SpriteStudio** ボトムパネル(先頭から再生 / 現在位置から再生 / 停止、フレームスクラバ、ループと速度)で、ゲームを実行せずにプレビューできます。ショートカットは AnimationPlayer エディタと同じです(**D** 現在位置から再生 / **Shift+D** 先頭から再生 / **S** 停止)。*(旧 `editor_playing` インスペクタトグルはこのパネルに置き換えられました。)*
* `play(start_frame: float = -1.0)`: 再生を開始します。既定値の `-1.0` は、現在の再生ヘッド位置から続きを再生するのではなく、**区間の先頭に巻き戻します**(逆再生方向なら区間の末尾)。現在位置から再生したい場合は `get_frame()` を渡してください。
* `play(start_frame: float = -1.0)`: 再生を開始します。既定値の `-1.0` は、現在の再生ヘッド位置から続きを再生するのではなく、**区間の先頭に巻き戻します**(逆再生方向なら区間の末尾)。現在位置から再生したい場合は `get_frame_no()` を渡してください。
* `pause()`: 現在のフレームを保持したまま、その場で再生を止めます。**冪等**です(2 回呼んでも一時停止のままで、再開はしません)。
* `resume()`: 保持を解除し、同じフレームから再開します。**冪等**で、一時停止ではなく停止している場合は何もしません(停止からの開始は `play()` で、こちらは巻き戻ります)。
* `stop()`: 再生を停止します。再生ヘッドは **その場に留まる** ため、停止したフレームを表示し続けます。
Expand All @@ -40,7 +40,7 @@ func _ready() -> void:
* `just_looped() -> bool`: 直近の update でループ境界を跨いだかどうか。**パルス**であって状態ではありません — ランタイムが毎 update の冒頭でクリアするので、跨いだ tick の内側でのみ `true` です(だから `is_looped` ではありません。1 tick 遅れて読むと `false` になります)。ポーリングしたくなければ `animation_looped` シグナルが同じエッジを配ります。
* `get_animation_names() -> PackedStringArray`: 割り当てた [SSABResource] のアニメーション名一覧。`animation` プロパティが選ぶのと同じリストです。
* `is_playing_forward() -> bool`: 再生ヘッドが**実際に**進んでいる向きです。設定した向きを返す `get_playback_direction()` とは別物で、ピンポン再生の戻りの脚では `get_playback_direction()` が `PLAYBACK_DIRECTION_FORWARD` のままでもこちらは `false` になります(速度 0 以下は逆再生ではなく停止なので、これも反転しません)。**音声のゲートに使ってください** — SpriteStudio に逆再生音声は無いため、後ろ向きの脚で跨いだサウンドキーは鳴らすべきものではありません。`play_audio` が有効なときにプレイヤー自身が掛けている判定と同じものです。何も再生していないときは `true`(前進が既定の状態)。
* `set_frame(frame: float)` / `get_frame() -> float` / `get_total_frames() -> int`
* `set_frame_no(frame: float)` / `get_frame_no() -> float` / `get_total_frames() -> int`
* `get_start_frame() -> int` / `get_end_frame() -> int`: 実際に再生される先頭 / 末尾フレーム、すなわち現在の再生区間です。`get_animation_section_start()` / `get_animation_section_end()` と同じ値を返します(`set_animation_section()` で狭めるまではアニメーション全体)。
* `set_speed_scale(speed_scale: float)` / `get_speed_scale() -> float`
* `set_frame_rate(fps: int)` / `get_frame_rate() -> int`
Expand Down
2 changes: 1 addition & 1 deletion docs/ja/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

### オーバーライドが画面に反映されない

再生が停止・一時停止している間、あるいはフレームが進まないフレームでは描画が再構築されないため、オーバーライドを設定・解除しても見た目は変わりません。`set_frame(get_frame())` で再描画を強制してください。
再生が停止・一時停止している間、あるいはフレームが進まないフレームでは描画が再構築されないため、オーバーライドを設定・解除しても見た目は変わりません。`set_frame_no(get_frame_no())` で再描画を強制してください。

### `animation_finished` が発火しない

Expand Down
4 changes: 2 additions & 2 deletions docs/ja/workflow/usage_scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func _process(delta):
> [!IMPORTANT]
> 状態は 2 つではなく 3 つです。**`is_playing()` は一時停止中も `true` のまま**であり(一時停止は「保持」であって「停止」ではありません)、保持中かどうかを区別するのが `is_pausing()` です。初回の `play()` の前と `stop()` の後は、どちらも `false` になります。
>
> **`play()` は「再開」ではありません。** 区間の先頭へ巻き戻し、ループ回数を再設定します。保持の解除は `resume()`、停止位置からの続きは `play(get_frame())` を使ってください。
> **`play()` は「再開」ではありません。** 区間の先頭へ巻き戻し、ループ回数を再設定します。保持の解除は `resume()`、停止位置からの続きは `play(get_frame_no())` を使ってください。

---

Expand Down Expand Up @@ -293,4 +293,4 @@ print(ss_player.get_cell_names("Ringo")) # → ["effect3", ...]
- 別の `.ssab` リソースを割り当てると、パーツの同一性が失われるため全オーバーライドが解除されます。
- インスタンスパーツ**配下**のパーツには届きません(子アニメーションは別のプレーヤとして動作するためです)。インスタンスパーツ自体を強制非表示にした場合は、その配下もまとめて描画されなくなります。

> **オーバーライドの設定が描画に反映されないタイミングについて**: アニメーション停止 / 一時停止中や、フレームが進まない状況では描画が更新されないため、オーバーライドの設定・解除が画面に反映されません。その場で反映させたい場合は `set_frame(get_frame())` を呼んで再描画させてください。
> **オーバーライドの設定が描画に反映されないタイミングについて**: アニメーション停止 / 一時停止中や、フレームが進まない状況では描画が更新されないため、オーバーライドの設定・解除が画面に反映されません。その場で反映させたい場合は `set_frame_no(get_frame_no())` を呼んで再描画させてください。
8 changes: 4 additions & 4 deletions ss_player/doc_classes/SpriteStudioPlayer2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<return type="void" />
<param index="0" name="start_frame" type="float" default="-1.0" />
<description>
Starts playback. [param start_frame] of [code]-1.0[/code] (the default) [b]rewinds to the start of the playback section[/b] - its end when [method set_playback_direction] is set to [constant PLAYBACK_DIRECTION_BACKWARD] - rather than continuing from where the playhead is. Pass [method get_frame] to play on from the current position.
Starts playback. [param start_frame] of [code]-1.0[/code] (the default) [b]rewinds to the start of the playback section[/b] - its end when [method set_playback_direction] is set to [constant PLAYBACK_DIRECTION_BACKWARD] - rather than continuing from where the playhead is. Pass [method get_frame_no] to play on from the current position.
This is a fresh start, not a resume: it re-arms the loop counter and clears the paused state. Resuming a pause is [method pause]'s own toggle.
</description>
</method>
Expand All @@ -47,7 +47,7 @@
<method name="stop">
<return type="void" />
<description>
Stops playback. The playhead [b]stays where it was[/b], so the node keeps drawing the frame it stopped on; seek with [member frame] or start over with [method play] if you want it elsewhere.
Stops playback. The playhead [b]stays where it was[/b], so the node keeps drawing the frame it stopped on; seek with [member frame_no] or start over with [method play] if you want it elsewhere.
</description>
</method>
<method name="is_finished" qualifiers="const">
Expand Down Expand Up @@ -351,8 +351,8 @@
<member name="animation_section_end" type="int">
Last frame of the played section, inclusive. Setting it keeps [member animation_section_start]; use [method set_animation_section] to move both endpoints at once.
</member>
<member name="frame" type="float">
Current playback frame (editor-only display). Can be keyframed from an [AnimationPlayer] to drive playback from a timeline.
<member name="frame_no" type="float">
Where the playhead is, in frames. Fractional: sub-frame interpolation puts it between two authored frames, which is why it is not called [code]frame[/code] - [member AnimatedSprite2D.frame] is an integer index into a [SpriteFrames] set and means something else. Editor-only display. Can be keyframed from an [AnimationPlayer] to drive playback from a timeline.
</member>
<member name="speed_scale" type="float" default="1.0">
Playback speed multiplier. [code]1.0[/code] is normal speed.
Expand Down
4 changes: 2 additions & 2 deletions ss_player/ss_internal_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,14 @@ float SsInternalPlayer::getSpeed() const {
return ss_runtime_get_animation_speed(runtime_ctx);
}

void SsInternalPlayer::setFrame(float p_frame) {
void SsInternalPlayer::setFrameNo(float p_frame) {
if (runtime_ctx) {
ss_runtime_set_frame_no(runtime_ctx, p_frame);
_seek_and_redraw(ss_runtime_get_frame_no(runtime_ctx), 0.0f, false);
}
}

float SsInternalPlayer::getFrame() const {
float SsInternalPlayer::getFrameNo() const {
return ss_runtime_get_frame_no(runtime_ctx);
}

Expand Down
8 changes: 4 additions & 4 deletions ss_player/ss_internal_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ class SsInternalPlayer {
void setSpeed(float p_speed);
float getSpeed() const;

void setFrame(float p_frame);
float getFrame() const;
void setFrameNo(float p_frame);
float getFrameNo() const;

int getTotalFrames() const;

Expand Down Expand Up @@ -770,7 +770,7 @@ class SsInternalPlayer {
// forwarded to children whose EventInstance has `independent = true`
// (those children run their own controller via `ss_runtime_update`
// rather than being seeked deterministically from `parent_frame_no`).
// Pass 0 from non-tick callers (`setFrame`, `setSubFrameEnabled`,
// Pass 0 from non-tick callers (`setFrameNo`, `setSubFrameEnabled`,
// `_fetchAnimation`) — synced children still update via parent-frame
// seek; independent children stay where they are.
//
Expand Down Expand Up @@ -800,7 +800,7 @@ class SsInternalPlayer {
// Apply the current `frame_no` to this player's draw state in one shot:
// resolve `draw_frame` per `_sub_frame_enabled`, store it as
// `previous_frame_no`, drive Instance children for that frame, and
// redraw. Used by `setFrame`, `setSubFrameEnabled`, `_fetchAnimation`
// redraw. Used by `setFrameNo`, `setSubFrameEnabled`, `_fetchAnimation`
// (delta=0, parent_looped=false — non-tick callers don't step
// independent children) and the per-tick `update` path.
void _seek_and_redraw(float frame_no, float delta_seconds, bool parent_looped);
Expand Down
8 changes: 4 additions & 4 deletions ss_player/ss_playback_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ void SSPlaybackPanel::_sync_playhead() {
return;
}
_updating = true;
float frame = _player->getFrame();
float frame = _player->getFrameNo();
_frame_slider->set_value(frame);
_frame_spin->set_value(frame);
_updating = false;
Expand Down Expand Up @@ -320,7 +320,7 @@ void SSPlaybackPanel::_on_play_pressed() {
// ss_runtime_play, which does not restart from a stopped state; passing the
// current frame routes through play_with_start_frame so it reliably plays
// from wherever the playhead is.
_player->play(_player->getFrame());
_player->play(_player->getFrameNo());
}

void SSPlaybackPanel::_on_stop_pressed() {
Expand Down Expand Up @@ -349,7 +349,7 @@ void SSPlaybackPanel::_on_slider_changed(double p_value) {
if (_updating || !_player) {
return;
}
_player->setFrame((float)p_value);
_player->setFrameNo((float)p_value);
_updating = true;
_frame_spin->set_value(p_value);
_updating = false;
Expand All @@ -359,7 +359,7 @@ void SSPlaybackPanel::_on_frame_spin_changed(double p_value) {
if (_updating || !_player) {
return;
}
_player->setFrame((float)p_value);
_player->setFrameNo((float)p_value);
_updating = true;
_frame_slider->set_value(p_value);
_updating = false;
Expand Down
Loading
Loading