Open lilizoey opened 1 year ago
This could also mitigate #302 to an extent
One way to do this would be to make all virtual methods take
Gd<Self>
instead as the first argument, and have the#[godot_api]
macro rewrite the function slightly to take the appropriate reference.
It can be argued that since bad runtime borrows are a common source of confusion, having an explicit
fn ready(this: Gd<Self>) {
let this = this.bind_mut();
...
}
would be clearer. But I don't fully like this, as it makes code less ergonomic and punishes all the common cases like ready()
and process()
, which are usually perfectly fine.
I was also considering that &self
or &mut self
receivers could still be valid, but would be desugared by the proc-macro to this.bind()
and this.bind_mut()
. Problem is that it's not possible to use the self
modifier, so even the function body would need to be rewritten, which would likely be very involved with weird edge cases... 🤔
I was also considering that
&self
or&mut self
receivers could still be valid, but would be desugared by the proc-macro tothis.bind()
andthis.bind_mut()
. Problem is that it's not possible to use theself
modifier, so even the function body would need to be rewritten, which would likely be very involved with weird edge cases... 🤔
We could just have it desugar to something like
impl NodeVirtual for MyClass {
fn ready(this: Gd<Self>) {
Self::ready(this.bind())
}
}
impl MyClass {
fn ready(&self) {
// code
}
}
Idk the exact syntax to make the name resolution work properly here but yeah.
Regarding #338, I'm not sure if this would allow you to workaround the situation described therein.
fn ready(this: Gd<Self>) {
this.bind_mut().add_child(...); // Mutable borrow of Gd<Self>
}
fn on_notification(this: Gd<Self>, n: ...) {
// do something with this, either bind / bind_mut -> panic due to aliasing
}
on_notification would still be required to not touch this, as far as I can see
Shouldn't it work if this
is upcast to Node
first? It's not pretty or obvious, though...
fn ready(this: Gd<Self>) {
this.upcast::<Node>().add_child(...); // Uses DerefMut, since Node is an engine class
}
fn on_notification(this: Gd<Self>, n: ...) {
// do something with this, either bind / bind_mut -> no panic?
}
Shouldn't it work if
this
is upcast toNode
first? It's not pretty or obvious, though...
Great observation! In fact, that's one of the main motivations for https://github.com/godot-rust/gdext/issues/131. I'll probably implement that soon.
Maybe the user can optionally choose to impl Gd<MyClass>
instead of impl MyClass
:
#[godot_api]
impl NodeVirtual for Gd<MyClass> {
fn ready(self) {
...
}
}
Maybe the user can optionally choose to impl
Gd<MyClass>
instead of implMyClass
:
Interesting idea, but that would mean:
#[godot_api]
blocks, but that comes with its own issues&self
/&mut self
(not the value self
), this would need to be done here too, which is a bit weird 🤔 It doesn't address the case of existing interfaces, but I was able to throw together https://github.com/godot-rust/gdext/pull/396 to allow user defined methods to take this: Gd<Self>
instead of &self
as the first argument to a non-static method.
Just ran into this issue when I tried to test #883
#[derive(GodotClass)]
#[class(editor_plugin, tool, init, base=EditorPlugin)]
pub struct MySuperEditorPlugin {}
#[godot_api]
impl IEditorPlugin for MySuperEditorPlugin {
fn enter_tree(&mut self) {
let mut editor_button = Button::new_alloc();
editor_button.connect(
"pressed".into(),
Callable::from_object_method(
self, // ???????
"editor_button_pressed_event",
),
);
}
}
So I have to make an (unnecessary?) "inner" object just to handle signals
Currently most virtual methods take
&mut self
as the receiver, this can be problematic if you want to call multiple virtual methods at once from godot. We could loosen this restriction.One way to do this would be to make all virtual methods take
Gd<Self>
instead as the first argument, and have the#[godot_api]
macro rewrite the function slightly to take the appropriate reference.This would also allow you to workaround #338. Especially if we allow the user to specify
Gd<Self>
as the receiver.