-
-
Notifications
You must be signed in to change notification settings - Fork 223
IAudioStreamPlaybackResampled requires useless implementation of "mix" #1133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Not sure if I'm missing something -- but if GDExtension exposes APIs that have to be implemented but serve no purpose, that seems like a bug in Godot and should probably be reported there? |
You are probably right. I will try to find some time to dig into GDExtension and figure out what's going on. |
I am wondering if the problem is something like:
I'm wondering if the tool that generates bindings for godot-rust gets confused and treats abstract methods of the base class So far I haven't investigated enough to know any more than what the symptoms are and how to work around them, so it's quite possible the problem is in GDExtension/Godot itself. |
btw @Bromeon I am a bit worried that me reporting a flurry of bugs today might have come across as relentless negativity, which is not what I intended at all! What has happened here is that I've been using godot-rust for a game jam all week, and now that it is over I'm reporting the handful of issues I encountered. But I want to be clear that I am very happy and impressed with godot-rust! Thank you to you and the team for all your hard work! :-) |
That sounds plausible 🤔 first, it's somewhat a violation of LSP if further-derived classes aren't supposed to overwrite a virtual method. But theoreticals aside, the problem is that in {
"name": "AudioStreamPlaybackResampled",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "AudioStreamPlayback",
"api_type": "core",
"methods": [
{
"name": "_mix_resampled",
"is_const": false,
"is_static": false,
"is_required": true,
"is_vararg": false,
"is_virtual": true,
"hash": 50157827,
"return_value": {
"type": "int",
"meta": "int32"
},
"arguments": [
{
"name": "dst_buffer",
"type": "AudioFrame*"
},
{
"name": "frame_count",
"type": "int",
"meta": "int32"
}
]
},
{
"name": "_get_stream_sampling_rate",
"is_const": true,
"is_static": false,
"is_required": true,
"is_vararg": false,
"is_virtual": true,
"hash": 1740695150,
"return_value": {
"type": "float",
"meta": "float"
}
},
{
"name": "begin_resample",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 3218959716
}
]
}, Whereas its base class {
"name": "AudioStreamPlayback",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "RefCounted",
"api_type": "core",
"methods": [
...
{
"name": "_mix",
"is_const": false,
"is_static": false,
"is_required": true,
"is_vararg": false,
"is_virtual": true,
"hash": 925936155,
"return_value": {
"type": "int",
"meta": "int32"
},
"arguments": [
{
"name": "buffer",
"type": "AudioFrame*"
},
{
"name": "rate_scale",
"type": "float",
"meta": "float"
},
{
"name": "frames",
"type": "int",
"meta": "int32"
}
]
},
], So I wonder if Godot should re-declare the method in the derived class, marking it as non-required this time. I don't think GDExtension does this anywhere else, and there's probably some benefits of having every method appear only once. But it's just that again (like in the many other issues), godot-rust is constrained by what the API offers here 🙂 we can of course build manual edge cases, but I'd prefer to discuss this one with Godot maintainers first... |
No worries at all, I appreciate the feedback! Your reports have been very constructive and detailed, as well 👍 You may have noticed there's a pattern of blurred responsibility between the binding (godot-rust) and the engine (Godot) when it comes to the GDExtension interface 😉 in some cases we need to take action in Rust, because Godot simply doesn't have certain concepts (thread-safety / Btw, may I ask which game jam that was? 🙂 |
It was I, Rebel: A Jeff Minter Game Jam organised by Atari. Unfortunately I didn't finish my game. Not for lack of trying. I've been struggling to finish games for quite some time for various reasons, but this is the closest I've come for a long time and the smooth integration between Godot and godot-rust helped a great deal. I'll be continuing to work on the game and I'll let you know how it goes if you're interested. There were some cool entries from other developers. Not all of them have been made public yet but some of them are here: https://itch.io/c/5660983/i-rebel-2025-atari-game-jam |
@djcsdy I created PR #1136 that addresses this. While I still think this is Godot responsibility, this is quite a small QoL change that may not be worth extending the JSON spec, so we can handle derived virtual methods manually in godot-rust for now. If you have some time, could you look if you find other such cases in Godot APIs and let me know? Just that we don't have to add 20 individual PRs everytime this comes up 😅 |
Thanks! Now that I see how everything fits together I am pretty sure this applies to every class that extends AudioStreamPlayback. I'll verify this in the next few days. |
Hey @Bromeon, I've been a bit busy. I'm going to try to check this right now, but may not get it done until the weekend. |
I investigated and found that in practice Godot does not allow native code to extend most of the The
|
Consider the following minimal implementation of
AudioStream
andAudioStreamPlaybackResampled
:Include the above code in a godot-rust project, then open the corresponding Godot project.
Create a scene containing an
AudioStreamPlayer
.Attach a new instance of
Foo
as thestream
property of theAudioStreamPlayer
in the inspector.Tick
Autoplay
in the inspector.Run the scene.
Godot produces the following output:
No sound plays because the minimal implementation doesn't actually generate any sound, but if it did (in
mix_resampled
) then that would be working as expected.However, notice that
IAudioStreamPlaybackResampled
requires an implementation ofmix
but Godot never calls it. I assume Godot always calls its internal implementation ofAudioStreamPlaybackResampled::mix
, which callsmix_resampled
and then resamples the sound for us.The text was updated successfully, but these errors were encountered: