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
38 changes: 38 additions & 0 deletions docs/en/api/player.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,44 @@ func _ready() -> void:
| `style` | `0` | Normal / One-way |
| `style` | `1` | PingPong (Round-trip) |

## Part queries

* `get_part_names() -> PackedStringArray`: Every part name in the current animation.
* `get_part_index(part_name: String) -> int`: Resolves a part name to its part index, or `-1` if it does not exist.
* `get_part_transform(part_name: String) -> Transform2D`: The part's local `Transform2D` on the current frame. Returns the identity when the part is unknown.
* `is_part_hidden(part_name: String) -> bool`: Whether the part is hidden on the current frame.

## Part overrides

Override a single part's color / cell / visibility so that it wins over the keyframes. Every method returns `true` on success, or `false` when the part is unknown or the runtime rejects the call. See [Scripting and Event-Driven Control → Part Overrides](../workflow/usage_scripting.md) for the details and caveats.

* `set_part_color_override(part_name: String, color: Color, blend_op: int = 0, priority: int = 1) -> bool`
* `set_part_cell_override(part_name: String, cellmap_name: String, cell_name: String, priority: int = 1) -> bool`
* `set_part_visibility_override(part_name: String, force_hidden: bool, cascade: bool = false) -> bool`
* `clear_part_color_override(part_name: String) -> bool` / `clear_part_cell_override(part_name: String) -> bool` / `clear_part_visibility_override(part_name: String) -> bool`
* `clear_all_part_overrides() -> bool`
* Each method has an index-based variant `*_by_index(part_index: int, ...)` that skips the name lookup (get the index from `get_part_index()`).

### Values for `blend_op`

| Value | Blend operation |
| --- | --- |
| `0` | Mix (default) |
| `1` | Mul (multiply) |
| `2` | Add |
| `3` | Sub (subtract) |

### Values for `priority`

| Value | Priority mode | Meaning |
| --- | --- | --- |
| `0` | OverwriteOnNextKeyframe | Applies until the animation updates that attribute |
| `1` | HoldUntilNextAnimation (default) | Applies for the current animation; cleared when a new animation is set up |
| `2` | Permanent | Applies for as long as the same `.ssab` is playing, surviving animation changes |

> [!NOTE]
> `set_part_visibility_override` has no `priority`. It always wins over the keyframes and is always cleared when a new animation is set up.

## Signals

| Signal | Arguments | Emitted When |
Expand Down
82 changes: 82 additions & 0 deletions docs/en/workflow/usage_scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,85 @@ This feature allows you to build an efficient avatar system without needing to p
> [!TIP]
> ![Before outfit change](../../assets/7-cellmap_override_before.png)
> ![After outfit change](../../assets/7-cellmap_override_after.png)

---

## Part Overrides (Color / Cell / Visibility)

Per-part runtime overrides let a script say "make this part this color / this cell / hidden **now**". An override wins over both the keyframe and any animation blending, so it does not have to fight the animation.

```gdscript
@onready var ss_player = $SpriteStudioPlayer2D

func _ready():
# Tint a part red (multiply). Applies to normal (image) parts.
ss_player.set_part_color_override("body", Color.RED, 1) # 1 = Mul

# Make a part draw a different cell (cell map name is written without ".ssce").
ss_player.set_part_cell_override("body", "Ringo", "effect3")

# Force-hide a part, cascading to its descendants.
ss_player.set_part_visibility_override("body", true, true)

# Revert
ss_player.clear_part_color_override("body")
ss_player.clear_all_part_overrides()
```

| Method | Description |
|---|---|
| `get_part_index(part_name)` | Part index, or `-1` if the part is not in the asset |
| `set_part_color_override(part_name, color, blend_op = 0, priority = 1)` | Color override (single color) |
| `set_part_cell_override(part_name, cellmap_name, cell_name, priority = 1)` | Draw a different cell |
| `set_part_visibility_override(part_name, force_hidden, cascade = false)` | Force-hide (`force_hidden = false` reverts to the animation) |
| `clear_part_color_override` / `clear_part_cell_override` / `clear_part_visibility_override` | Clear one override on one part |
| `clear_all_part_overrides()` | Clear every override on the player |
| `*_by_index(part_index, ...)` | Part-index variant of each method above (skips the name lookup) |

Every method returns `false` when the part is unknown or the runtime rejects the call.

The cell map / cell names you can pass to a cell override are enumerated from the resource:

```gdscript
var ssab := ss_player.get_ssab_resource()
print(ssab.get_cellmap_names()) # -> ["Ringo", ...]
print(ssab.get_cell_names("Ringo")) # -> ["effect3", ...]
```

> **On choosing between a texture swap and a cell override**: `set_cellmap_texture()` in the previous section replaces a **whole cell map (texture)** at once, affecting every part that uses it. This feature instead replaces the cell that a **single part** draws. Pick whichever matches your intent.

> **On using part indices**: Part indices are stable within one asset (the same `.ssab`), so if you set overrides frequently, resolve the name once with `get_part_index()` and reuse that index with the `*_by_index()` variants.

### Blend operation (`blend_op`)

The `blend_op` of `set_part_color_override()` offers the same four operations as the keyframed Part Color.

| Value | Blend operation |
|---|---|
| `0` | Mix (default) |
| `1` | Mul (multiply) |
| `2` | Add |
| `3` | Sub (subtract) |

An out-of-range value fails the call and returns `false`.

### Priority mode (`priority`)

Color and cell overrides conflict with the animation, so they take a `priority` (visibility does not — it is a plain force-hide flag, and any new animation clears it):

| Value | Priority mode | Behavior |
|---|---|---|
| `0` | OverwriteOnNextKeyframe | The override applies until the animation data updates that attribute |
| `1` | HoldUntilNextAnimation (default) | The override wins for the current animation and is cleared when a new animation is set up |
| `2` | Permanent | The override applies for as long as the same animation data (`.ssab`) is playing, surviving animation changes |

### Notes

- **Color** applies to normal parts, **cell** to normal and mask parts; other part types silently ignore the override (the call still returns `true`).
- Colors are interpreted in the same 8-bit sRGB space as the authored Part Color, and alpha is pre-multiplied by the runtime — pass the color as authored, without converting it yourself.
- A cell override is resolved when you set it, so an unknown cell map / cell name fails immediately (returns `false`).
- Overrides live on the runtime, which owns their lifecycle. Do not re-apply them after an animation change; choose the priority mode that expresses what you want instead.
- 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.
38 changes: 38 additions & 0 deletions docs/ja/api/player.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,44 @@ func _ready() -> void:
| `style` | `0` | 通常 / 片道 (Normal) |
| `style` | `1` | 往復再生 (PingPong) |

## パーツの参照

* `get_part_names() -> PackedStringArray`: 現在のアニメーションに含まれる全パーツ名。
* `get_part_index(part_name: String) -> int`: パーツ名をパーツインデックスへ解決します。存在しない場合は `-1`。
* `get_part_transform(part_name: String) -> Transform2D`: 現在のフレームでのパーツのローカル `Transform2D`。パーツが不明な場合は単位行列を返します。
* `is_part_hidden(part_name: String) -> bool`: 現在のフレームでそのパーツが非表示かどうか。

## パーツオーバーライド

パーツ単位で、カラー / セル / 表示指定をキーフレームより優先して上書きします。各メソッドは成功時に `true`、パーツが不明な場合やランタイムが受け付けなかった場合に `false` を返します。詳細と注意点は [スクリプト制御とイベント → パーツオーバーライド](../workflow/usage_scripting.md) を参照してください。

* `set_part_color_override(part_name: String, color: Color, blend_op: int = 0, priority: int = 1) -> bool`
* `set_part_cell_override(part_name: String, cellmap_name: String, cell_name: String, priority: int = 1) -> bool`
* `set_part_visibility_override(part_name: String, force_hidden: bool, cascade: bool = false) -> bool`
* `clear_part_color_override(part_name: String) -> bool` / `clear_part_cell_override(part_name: String) -> bool` / `clear_part_visibility_override(part_name: String) -> bool`
* `clear_all_part_overrides() -> bool`
* 各メソッドには、パーツ名の解決を省略できるインデックス指定版 `*_by_index(part_index: int, ...)` があります(インデックスは `get_part_index()` で取得)。

### `blend_op` の値

| 値 | 合成モード |
| --- | --- |
| `0` | Mix(既定) |
| `1` | Mul(乗算) |
| `2` | Add(加算) |
| `3` | Sub(減算) |

### `priority` の値

| 値 | 優先モード | 意味 |
| --- | --- | --- |
| `0` | OverwriteOnNextKeyframe | アニメーションが当該アトリビュートを更新するまで適用 |
| `1` | HoldUntilNextAnimation(既定) | 現在のアニメーション中は適用され、アニメーション変更で解除 |
| `2` | Permanent | 同じ `.ssab` を再生している間は適用(アニメーション変更をまたいで持続) |

> [!NOTE]
> 表示指定(`set_part_visibility_override`)に `priority` はありません。常にキーフレームに勝ち、アニメーションを設定し直すと必ずクリアされます。

## シグナル

| シグナル | 引数 | 発行タイミング |
Expand Down
82 changes: 82 additions & 0 deletions docs/ja/workflow/usage_scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,85 @@ func change_costume():
> [!TIP]
> ![着せ替え前](../../assets/7-cellmap_override_before.png)
> ![着せ替え後](../../assets/7-cellmap_override_after.png)

---

## パーツオーバーライド(パーツカラー / セル / 表示指定)

パーツ単位のランタイムオーバーライドは、「このパーツを**今**この色に / このセルに / 非表示に」とスクリプトから指示する機能です。オーバーライドはキーフレームやアニメーションのブレンドよりも優先されるので、アニメーションと取り合いになりません。

```gdscript
@onready var ss_player = $SpriteStudioPlayer2D

func _ready():
# パーツを赤く着色(乗算)。通常(画像)パーツに適用されます。
ss_player.set_part_color_override("body", Color.RED, 1) # 1 = Mul

# 別のセルを描画させる(セルマップ名は ".ssce" を付けずに指定)。
ss_player.set_part_cell_override("body", "Ringo", "effect3")

# パーツを強制非表示にする(子孫にもカスケード)。
ss_player.set_part_visibility_override("body", true, true)

# 解除
ss_player.clear_part_color_override("body")
ss_player.clear_all_part_overrides()
```

| メソッド | 説明 |
|---|---|
| `get_part_index(part_name)` | パーツインデックス。アセットに無ければ `-1` |
| `set_part_color_override(part_name, color, blend_op = 0, priority = 1)` | パーツカラーオーバーライド(単色) |
| `set_part_cell_override(part_name, cellmap_name, cell_name, priority = 1)` | 別のセルで描画する |
| `set_part_visibility_override(part_name, force_hidden, cascade = false)` | 強制非表示(`force_hidden = false` でアニメーションに戻す) |
| `clear_part_color_override` / `clear_part_cell_override` / `clear_part_visibility_override` | 1 パーツの 1 オーバーライドを解除 |
| `clear_all_part_overrides()` | そのプレーヤの全オーバーライドを解除 |
| `*_by_index(part_index, ...)` | 上記各メソッドのパーツインデックス指定版(パーツ名の解決を省略) |

各メソッドは、パーツが不明な場合やランタイムが受け付けなかった場合に `false` を返します。

セルオーバーライドに指定できるセルマップ名 / セル名は、リソース側から列挙できます。

```gdscript
var ssab := ss_player.get_ssab_resource()
print(ssab.get_cellmap_names()) # → ["Ringo", ...]
print(ssab.get_cell_names("Ringo")) # → ["effect3", ...]
```

> **テクスチャとセルの差し替えの使い分けについて**: 前節の `set_cellmap_texture()` は**セルマップ(テクスチャ)まるごと**の差し替えで、そのセルマップを使う全パーツにまとめて効きます。こちらは**パーツ 1 つ単位**で、描画するセルそのものを差し替える機能です。目的に応じて使い分けてください。

> **パーツインデックスの使い方について**: パーツインデックスは同一アセット(同じ `.ssab`)内では安定しているので、頻繁にオーバーライドするなら `get_part_index()` で一度パーツ名をパーツインデックスに解決して、`*_by_index()` にそのインデックスを使い回すことを推奨します。

### 合成モード(blend_op)

`set_part_color_override()` の `blend_op` は、キーフレームのパーツカラーと同じ 4 種です。

| 値 | 合成モード |
|---|---|
| `0` | Mix(既定) |
| `1` | Mul(乗算) |
| `2` | Add(加算) |
| `3` | Sub(減算) |

範囲外の値を渡した場合は設定に失敗し、`false` を返します。

### 優先モード(priority)

パーツカラーとセルのオーバーライドはアニメーションと競合するため、`priority` を取ります(表示指定にはありません。単なる強制非表示フラグで、アニメーションを設定し直すと必ずクリアされます)。

| 値 | 優先モード | 挙動 |
|---|---|---|
| `0` | OverwriteOnNextKeyframe | アニメーションデータが当該アトリビュートを更新するまで、オーバーライドが適用される |
| `1` | HoldUntilNextAnimation(既定) | 現在のアニメーション中は勝ち続け、新しいアニメーションを設定するとオーバーライドが解除される |
| `2` | Permanent | 同じアニメーションデータ(`.ssab`)である間、オーバーライドが適用される(アニメーション変更をまたいでも持続) |

### 注意点

- **カラー**は通常パーツ、**セル**は通常パーツとマスクパーツに適用されます。それ以外の種別のパーツでは黙って無視されます(呼び出し自体は `true` を返します)。
- 色はオーサリングされた Part Color と同じ 8bit sRGB 空間として解釈され、アルファはランタイム側で pre-multiply されます。自前で変換せず、オーサリングどおりの色を渡してください。
- セルオーバーライドは設定時に解決されるため、存在しないセルマップ名 / セル名はその場で失敗します(`false` を返します)。
- オーバーライドはランタイムが保持し、そのライフサイクルもランタイムが管理します。アニメーション変更後に再適用する必要はありません。意図に合った優先モードを選んでください。
- 別の `.ssab` リソースを割り当てると、パーツの同一性が失われるため全オーバーライドが解除されます。
- インスタンスパーツ**配下**のパーツには届きません(子アニメーションは別のプレーヤとして動作するためです)。インスタンスパーツ自体を強制非表示にした場合は、その配下もまとめて描画されなくなります。

> **オーバーライドの設定が描画に反映されないタイミングについて**: アニメーション停止 / 一時停止中や、フレームが進まない状況では描画が更新されないため、オーバーライドの設定・解除が画面に反映されません。その場で反映させたい場合は `set_frame(get_frame())` を呼んで再描画させてください。