Godot version:
3.0
Issue description:
CallDeferred doesn't accept the pascal case method name in C#.
While using C# scripting you must pass in the 'snake case' function name same as GDScript.
I think that this causes confusion when all other names are changed to pascal case in C#.
It caused me quite a bit of confusion. Perhaps if it is not an issue changing the function could throw an error if the function name passed in is not recognized?
Steps to reproduce:
call CallDeferred and pass in a function name in pascal case e.g. "AddChild" and watch it not work.
CC @neikeq
@akien-mga @neikeq you can close this thread, because this definitely works currently in my project. Snippet https://gist.github.com/exts/73e82b7f77c89ccd0802283d686b5266
I'm finding that as of 3.0.3rc2 we are unable to access methods from the godot API with camel case:
````csharp
using Godot;
public class Node : Godot.Node
{
public override void _Ready()
{
CallDeferred("SetName", "NewName"); // This has no effect
//SetName("NewName"); // This would work if uncommented
}
}
````
@KellyThomas that sounds like a different issue than the title suggests.
So I was testing some code because this didn't make sense. Why would CallDeferred work on my autoload methods and execute my switch scene code, but not be able to execute godot api method names.
When I was testing I wanted to just make sure code was executing and I tested this snippet in one of my object nodes that I instance in.
public void DeferredNewName(string name)
{
Print("hello2");
SetName($"{name}_name");
}
public void ChangeName(string name)
{
Print("Called");
CallDeferred("DeferredNewName", name);
}
So I call ChangeName and "Called" gets printed 4 times and so does hello2. The methods are getting through, but the api methods aren't being executed. As you can see here https://i.imgur.com/YK165dq.png (in output window)
I switch CallDeferred to Call and everything works as expected. Why is CallDeferred not executing api methods? Seems like a weird edge case.
Last note: Despite being able to call user executed methods with both call and call deferred, with call being able to let api methods execute. Neither Call or CallDeferred allows you to execute node methods directly. What a weird issue
Also having the problem in Godot Mono 3.1 beta 2. CallDeferred passing "AddChild" or nameof(AddChild) does not work, but passing "add_child" does.
The most frightening part is that the error seems to be completely silent. Knowing that it will at some point be fixed means that I need to worry that when that change happens that it will also silently break my code. Because of that, I am going to do everything possible to avoid using CallDeferred.
This applies both to Call and CallDeferred. The reason this happens is because we do not search the methods in the engine classes. I think I know how to fix this, but there is still the problem of objects which do not have a C# script attached. Here is an example:
C#
var myNode = new Node();
myNode.Call("AddChild", this);
Supposing I fix this issue, the above code still would not work because myNode does not have a C# script attached, therefore it will never go through our calling process.
I think it would be confusing to allow PascalCase names in Call and CallDeferred if it only worked when there is a C# script attached. I think we either support it everywhere (somehow) or nowhere.
If we want to support this everywhere, I think we would need a call hook here in Object::call:
So if the method is not found, it attempts with our call hook.
@reduz What do you think? Would you be ok about adding a fallback at the end of Object::call?
@neikeq I was just wondering... what about converting all CamelCase methods to snake_case on-the-fly, both for C#'s Call/Connect/CallDeferred/FuncRef bindings and for methods defined in C# scripts?
@bojidar-bg I don't like the idea performance-wise, but it wouldn't solve this issue either since the cause of this issue is that we have no control over this (unless there is a C# script attached, in which case we could fix it, but it would be confusing as I explained above).
@neikeq Well, it is fixable since you are calling into Godot from mono. So, if the bindings don't just blindly call the function, but fix the string to snake_case... it might sort-of work.
But that does not include calls being made from other places. Like signals connected from the editor. And I still don't like the runtime overhead it would have.
As seen in #37284, the same applies to properties, not only methods.