diff --git a/docs/en/api/player.md b/docs/en/api/player.md index 0eeab6d..bca4790 100644 --- a/docs/en/api/player.md +++ b/docs/en/api/player.md @@ -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 | diff --git a/docs/en/workflow/usage_scripting.md b/docs/en/workflow/usage_scripting.md index fab68a7..8a3c223 100644 --- a/docs/en/workflow/usage_scripting.md +++ b/docs/en/workflow/usage_scripting.md @@ -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. diff --git a/docs/ja/api/player.md b/docs/ja/api/player.md index 7c171d2..2f1d6c8 100644 --- a/docs/ja/api/player.md +++ b/docs/ja/api/player.md @@ -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` はありません。常にキーフレームに勝ち、アニメーションを設定し直すと必ずクリアされます。 + ## シグナル | シグナル | 引数 | 発行タイミング | diff --git a/docs/ja/workflow/usage_scripting.md b/docs/ja/workflow/usage_scripting.md index d575db3..33a2a84 100644 --- a/docs/ja/workflow/usage_scripting.md +++ b/docs/ja/workflow/usage_scripting.md @@ -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())` を呼んで再描画させてください。