diff --git a/docs/en/api/player.md b/docs/en/api/player.md index 40472b3..18a9e40 100644 --- a/docs/en/api/player.md +++ b/docs/en/api/player.md @@ -23,7 +23,7 @@ func _ready() -> void: ## Main methods * `set_ssab_resource(res: SSABResource)` / `get_ssab_resource() -> SSABResource` -* `set_animation(name: String)` / `get_animation() -> String` +* `set_animation(name: String)` / `get_current_animation() -> String` * `set_autoplay(autoplay: bool)` / `is_autoplay() -> bool`: Whether to start playing automatically when the scene starts. **Default `true`** — a node placed in a scene has no code to call `play()` for it, so it plays. Set it off for a node you drive yourself, or one that should hold its first frame as a pose. * `set_offset(offset: Vector2)` / `get_offset() -> Vector2`: Shifts the drawing position without moving the Node2D's origin. * `set_flip_h(flip: bool)` / `is_flipped_h() -> bool`: Flips the animation horizontally. diff --git a/docs/en/workflow/animation_player.md b/docs/en/workflow/animation_player.md index c2ff96d..b8bd76c 100644 --- a/docs/en/workflow/animation_player.md +++ b/docs/en/workflow/animation_player.md @@ -15,7 +15,7 @@ To control SSPlayer with an `AnimationPlayer`, you must first convert all animat 3. Upon success, a file named `[original_filename]_anims.res` will be generated in the same directory. > [!NOTE] -> The generated `_anims.res` automatically contains "Value Tracks" with the exact same names as the original SpriteStudio animations. These tracks control the `animation` (animation name) and `frame` (current frame) properties of the target node. +> The generated `_anims.res` automatically contains "Value Tracks" with the exact same names as the original SpriteStudio animations. These tracks control the `current_animation` (animation name) and `frame_no` (playhead) properties of the target node. --- @@ -29,7 +29,7 @@ Here is how to apply the generated library to your scene. Add an `AnimationPlayer` node to the scene. 3. **Specify the Target (Important!)** Select the added `AnimationPlayer` node and set its **`Root Node`** property in the Inspector to the **`SpriteStudioPlayer2D` node** from step 1. - *Note: Since the generated animations are configured to control the `animation` and `frame` properties of the target node itself, the Root Node must point directly to the SSPlayer node.* + *Note: Since the generated animations are configured to control the `current_animation` and `frame_no` properties of the target node itself, the Root Node must point directly to the SSPlayer node.* 4. **Load the Library** Open the "Animation" panel at the bottom of the editor, click the "Animation" menu > **"Manage Animations..."**. Click the folder icon (Load Library) in the dialog that appears, and load the generated `_anims.res` file. diff --git a/docs/ja/api/player.md b/docs/ja/api/player.md index ad93d49..2b76b95 100644 --- a/docs/ja/api/player.md +++ b/docs/ja/api/player.md @@ -23,7 +23,7 @@ func _ready() -> void: ## 主なメソッド * `set_ssab_resource(res: SSABResource)` / `get_ssab_resource() -> SSABResource` -* `set_animation(name: String)` / `get_animation() -> String` +* `set_animation(name: String)` / `get_current_animation() -> String` * `set_autoplay(autoplay: bool)` / `is_autoplay() -> bool`: シーン開始時に自動再生するかどうか。**既定は `true`** です。シーンに配置したノードのために `play()` を呼ぶコードは存在しないため、そのまま再生されます。自分で再生を制御したい場合や、先頭フレームをポーズとして保持したい場合はオフにしてください。 * `set_offset(offset: Vector2)` / `get_offset() -> Vector2`: Node2D の原点を動かさずに描画位置だけをずらします。 * `set_flip_h(flip: bool)` / `is_flipped_h() -> bool`: 水平反転。 diff --git a/docs/ja/workflow/animation_player.md b/docs/ja/workflow/animation_player.md index 47b21cf..acf888f 100644 --- a/docs/ja/workflow/animation_player.md +++ b/docs/ja/workflow/animation_player.md @@ -15,7 +15,7 @@ SSPlayer を `AnimationPlayer` で制御するためには、まず対象の `.s 3. 成功すると、同じフォルダに `[元のファイル名]_anims.res` というファイルが生成されます。 > [!NOTE] -> 生成された `_anims.res` の中には、元の SpriteStudio アニメーションと同じ名前の「Value Track(値トラック)」が自動生成されています。このトラックは対象ノードの `animation`(アニメーション名)と `frame`(現在のフレーム)を制御します。 +> 生成された `_anims.res` の中には、元の SpriteStudio アニメーションと同じ名前の「Value Track(値トラック)」が自動生成されています。このトラックは対象ノードの `current_animation`(アニメーション名)と `frame_no`(再生ヘッド)を制御します。 --- @@ -29,7 +29,7 @@ SSPlayer を `AnimationPlayer` で制御するためには、まず対象の `.s シーン内に `AnimationPlayer` ノードを追加します。 3. **ターゲットの指定(重要!)** 追加した `AnimationPlayer` ノードを選択し、インスペクタ内の **`Root Node`** を、手順1の **`SpriteStudioPlayer2D` ノード** に設定します。 - *※自動生成されたアニメーションは「対象ノード自身の `animation` と `frame` を制御する」ようになっているため、Root Node を対象ノードに向ける必要があります。* + *※自動生成されたアニメーションは「対象ノード自身の `current_animation` と `frame_no` を制御する」ようになっているため、Root Node を対象ノードに向ける必要があります。* 4. **ライブラリの読み込み** エディタ下部の「アニメーション (Animation)」パネルを開き、「アニメーション」メニュー > **「アニメーションを管理... (Manage Animations)」** をクリックします。 出てきたウィンドウのフォルダアイコン(ライブラリをロード)を押し、生成された `_anims.res` を読み込みます。 diff --git a/ss_player/doc_classes/SpriteStudioPlayer2D.xml b/ss_player/doc_classes/SpriteStudioPlayer2D.xml index 76f08af..d7ca50f 100644 --- a/ss_player/doc_classes/SpriteStudioPlayer2D.xml +++ b/ss_player/doc_classes/SpriteStudioPlayer2D.xml @@ -5,7 +5,7 @@ Node that plays a SpriteStudio 7 animation imported as an [code].ssab[/code] resource ([SSABResource]). - Assign a resource to [member ssab], pick an animation with [member animation], then drive playback from code with [method play], [method pause], [method resume] and [method stop], or preview it in the editor from the [b]SpriteStudio[/b] bottom panel (shown while the node is selected). + Assign a resource to [member ssab], pick an animation with [member current_animation], then drive playback from code with [method play], [method pause], [method resume] and [method stop], or preview it in the editor from the [b]SpriteStudio[/b] bottom panel (shown while the node is selected). [b]Editor preview:[/b] with the node selected, the bottom panel provides transport controls (play from start / play from current / stop), a frame scrubber, loop and speed. Its keyboard shortcuts mirror the AnimationPlayer editor ([kbd]D[/kbd] play from current, [kbd]Shift+D[/kbd] play from start, [kbd]S[/kbd] stop). @@ -53,7 +53,7 @@ - Returns [code]true[/code] once every configured loop has played. A [b]state[/b], not a pulse: it latches on completion and holds until the next [method play] or [member animation] change, so a caller that was not listening when [signal animation_finished] fired can still ask whether the run is over. + Returns [code]true[/code] once every configured loop has played. A [b]state[/b], not a pulse: it latches on completion and holds until the next [method play] or [member current_animation] change, so a caller that was not listening when [signal animation_finished] fired can still ask whether the run is over. Never [code]true[/code] under an infinite [member loop_count], and [b]not raised by [method stop][/b] - a commanded stop is not a completion. That is what separates it from [code]not is_playing()[/code], which cannot tell the two apart. Connect to [signal animation_finished] if you want the one-shot edge instead. @@ -85,7 +85,7 @@ - Names of the animations in the assigned [SSABResource], empty when none is assigned. The same list [member animation] is chosen from. + Names of the animations in the assigned [SSABResource], empty when none is assigned. The same list [member current_animation] is chosen from. @@ -120,7 +120,7 @@ Sets the playback direction and style. - Both are kept across [member animation] changes - "play this backwards" describes the playback rather than the clip that happens to be loaded. What does not carry is the heading within a [constant PLAYBACK_STYLE_PING_PONG] cycle: a new animation always starts on the outward leg. + Both are kept across [member current_animation] changes - "play this backwards" describes the playback rather than the clip that happens to be loaded. What does not carry is the heading within a [constant PLAYBACK_STYLE_PING_PONG] cycle: a new animation always starts on the outward leg. @@ -326,7 +326,7 @@ The SpriteStudio animation resource ([code].ssab[/code]) to play. - + Name of the animation to play, chosen from the animations contained in [member ssab]. @@ -359,10 +359,10 @@ How many times to play the animation. [code]n[/code] plays [code]n[/code] cycles and stops, so [code]1[/code] plays it once; [code]-1[/code] loops forever, and [code]0[/code] is an alias for that rather than "no cycles" - the runtime normalizes everything at or below zero to [code]-1[/code]. - Kept across [member animation] changes, because it is the node's own configuration - as are [member speed_scale], [member frame_skip_enabled], [member frame_rate] and the playback direction and style. Only the playback section is per-transition: frame indices mean nothing against a different clip. + Kept across [member current_animation] changes, because it is the node's own configuration - as are [member speed_scale], [member frame_skip_enabled], [member frame_rate] and the playback direction and style. Only the playback section is per-transition: frame indices mean nothing against a different clip. - Playback frame rate (FPS). Setting one overrides whatever the animation was authored at, and the override is kept across [member animation] changes; set it to [code]0[/code] to clear it and hand playback back to each clip's authored rate. + Playback frame rate (FPS). Setting one overrides whatever the animation was authored at, and the override is kept across [member current_animation] changes; set it to [code]0[/code] to clear it and hand playback back to each clip's authored rate. This is an [i]absolute[/i] rate where [member speed_scale] is a multiplier, so its effect depends on the clip: 60 against a 30fps animation is double speed, and against a 60fps one is none. @@ -392,7 +392,7 @@ Emitted when the current animation changes, with the name of the new one. - A host that called [method set_animation] already knows what it selected, so this exists for the routes that do not go through it: [member animation] is an exported property, so the inspector, an [AnimationPlayer] track or a tool script can mount a different clip without any of the node's own callers touching it. + A host that called [method set_animation] already knows what it selected, so this exists for the routes that do not go through it: [member current_animation] is an exported property, so the inspector, an [AnimationPlayer] track or a tool script can mount a different clip without any of the node's own callers touching it. diff --git a/ss_player/ss_internal_player.h b/ss_player/ss_internal_player.h index 8a4d3c3..2f35e5b 100644 --- a/ss_player/ss_internal_player.h +++ b/ss_player/ss_internal_player.h @@ -112,7 +112,7 @@ class SsInternalPlayer { Ref getSSABResource() const { return _ssabRes; } void setAnimation(const String& p_name); void setAnimationByHash(uint32_t p_hash); - String getAnimation() const { return _strAnimationSelected; } + String getCurrentAnimation() const { return _strAnimationSelected; } // Cached AnimationData* for the currently selected animation. Null until // setAnimation+_fetchAnimation succeed; lets callers skip a redundant // name->AnimationData lookup in their own binary. diff --git a/ss_player/ss_player_node_2d.cpp b/ss_player/ss_player_node_2d.cpp index 0d9c537..fbc3c8c 100644 --- a/ss_player/ss_player_node_2d.cpp +++ b/ss_player/ss_player_node_2d.cpp @@ -286,8 +286,8 @@ void SpriteStudioPlayer2D::setAnimation(const String& strName) { update_configuration_warnings(); } -String SpriteStudioPlayer2D::getAnimation() const { - return _internal->getAnimation(); +String SpriteStudioPlayer2D::getCurrentAnimation() const { + return _internal->getCurrentAnimation(); } void SpriteStudioPlayer2D::setAutoplay(bool p_autoplay) { @@ -479,7 +479,7 @@ void SpriteStudioPlayer2D::_bind_methods() { ClassDB::bind_method( D_METHOD( "set_ssab_resource", "res_ssab" ), &SpriteStudioPlayer2D::setSSABResource ); ClassDB::bind_method( D_METHOD( "get_ssab_resource" ), &SpriteStudioPlayer2D::getSSABResource ); ClassDB::bind_method( D_METHOD( "set_animation", "name" ), &SpriteStudioPlayer2D::setAnimation ); - ClassDB::bind_method( D_METHOD( "get_animation" ), &SpriteStudioPlayer2D::getAnimation ); + ClassDB::bind_method( D_METHOD( "get_current_animation" ), &SpriteStudioPlayer2D::getCurrentAnimation ); ClassDB::bind_method( D_METHOD( "set_autoplay", "autoplay" ), &SpriteStudioPlayer2D::setAutoplay ); ClassDB::bind_method( D_METHOD( "is_autoplay" ), &SpriteStudioPlayer2D::isAutoplay ); @@ -627,7 +627,13 @@ void SpriteStudioPlayer2D::_bind_methods() { "set_ssab_resource", "get_ssab_resource" ); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation", PROPERTY_HINT_ENUM, ""), "set_animation", "get_animation"); + // The accessors are deliberately asymmetric. `set_animation` is the verb the + // whole family publishes and `get_current_animation` is its read + // (SDK: 20_design/40_api_conventions), and ADD_PROPERTY names the two + // independently -- so the property reads as Godot expects + // (`AnimationPlayer.current_animation` is this same thing) without inventing a + // `set_current_animation` that would be a second name for one operation. + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_animation", PROPERTY_HINT_ENUM, ""), "set_animation", "get_current_animation"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay"); // Editor-only (never stored): the playhead is runtime state, but it stays in // the property list so an AnimationPlayer can keyframe it. @@ -747,7 +753,7 @@ void SpriteStudioPlayer2D::_get_property_list(List* p_list) const } void SpriteStudioPlayer2D::_validate_property(PropertyInfo& p_property) const { - if (p_property.name == StringName("animation")) { + if (p_property.name == StringName("current_animation")) { // Turn the statically registered enum hint into the animation names of // the bound resource. Left empty when no resource is assigned. Ref res = _internal->getSSABResource(); @@ -783,7 +789,7 @@ PackedStringArray SpriteStudioPlayer2D::get_configuration_warnings() const { #endif if (getSSABResource().is_null()) { warnings.push_back(tr("Assign an SSABResource to the \"ssab\" property to play an animation.")); - } else if (getAnimation().is_empty()) { + } else if (getCurrentAnimation().is_empty()) { warnings.push_back(tr("Select an animation in the \"animation\" property.")); } return warnings; diff --git a/ss_player/ss_player_node_2d.h b/ss_player/ss_player_node_2d.h index 4405dfe..aed0cd4 100644 --- a/ss_player/ss_player_node_2d.h +++ b/ss_player/ss_player_node_2d.h @@ -81,7 +81,7 @@ class SpriteStudioPlayer2D : public Node2D { void setSSABResource( const Ref& ssabRes ); Ref getSSABResource() const; void setAnimation( const String& strName ); - String getAnimation() const; + String getCurrentAnimation() const; void setAutoplay( bool p_autoplay ); bool isAutoplay() const; diff --git a/ss_player/ss_resource_inspector.cpp b/ss_player/ss_resource_inspector.cpp index a5a6f33..aee3f31 100644 --- a/ss_player/ss_resource_inspector.cpp +++ b/ss_player/ss_resource_inspector.cpp @@ -177,15 +177,17 @@ void SSResourceInspectorPlugin::_on_generate_animation_library_pressed(const Str anim->set_length(length); anim->set_step(1.0f / fps); - // Track 0: animation + // Track 0: the selected animation. The path is a PROPERTY path, so it has + // to be the exported name -- a track pointing at a property that no longer + // exists is not an error, it just silently drives nothing. int track_anim = anim->add_track(Animation::TYPE_VALUE); - anim->track_set_path(track_anim, NodePath(".:animation")); + anim->track_set_path(track_anim, NodePath(".:current_animation")); anim->track_insert_key(track_anim, 0.0, anim_name); anim->value_track_set_update_mode(track_anim, Animation::UPDATE_DISCRETE); - // Track 1: frame + // Track 1: the playhead. Same story as above. int track_frame = anim->add_track(Animation::TYPE_VALUE); - anim->track_set_path(track_frame, NodePath(".:frame")); + anim->track_set_path(track_frame, NodePath(".:frame_no")); anim->track_insert_key(track_frame, 0.0, 0.0f); // The player exposes frames 0..total_frame-1, and the last frame occupies // the final 1/fps slice of `length`. Keying the last VALID frame at its own