-
-
Notifications
You must be signed in to change notification settings - Fork 198
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
Support using Base
for initialization in init
function
#557
Comments
Another potential option:
In other words, type-state without introducing yet another type (which is also an option, but really makes the API even more complex). |
Yes please. At least as a quick/temporary solution.
May I suggest to document the situation, and why and when someone shall or shall not use this API (instead of hiding it). |
I'll just copy it here from my duplicate issue so it would not be lost. My case was a little different, I want to have a fully constructed tree when fn init() -> Gd<Self> {
let mut node = Node3D::new_alloc();
// do something with node
let mut this = Gd::from_init_fn(|base|
Self {
node: node.clone(),
base,
}
);
this.base_mut().add_child(node.upcast());
this
} |
Hi @MatrixDev Why not implementing it this way without fn init(base: Base</*Super*/Node>) -> Self /* Extended */ {
let mut base_gd = base.to_gd();
let inner_node = Node3D::new_alloc();
// ... manipulate the inner node:
// e.g. inner_node.set("foo_property", bar_variant);
// ...
base_gd.add_child(inner_node.clone().upcast());
// ...
Self {
base,
inner_node
}
} Just a side note: Currently
|
There's no guarantee. |
Sure! I should have added "for the time being"! |
I'm currently doing exactly this. But my issue #585 was Also there is a concern that we basically have "semi-invalid" object from when |
In case anyone stumbles upon this issue, it's a bit different for RefCounted classes like Resources. #[derive(GodotClass)]
#[class(base=Translation)]
pub struct TranslationFluent {
base: Base<Translation>,
}
#[godot_api]
impl ITranslation for TranslationFluent {
fn init(base: Base<Translation>) -> Self {
std::mem::forget(base.to_gd()); // <-- this was needed to fix crashes
base.to_gd().set_locale("".into());
Self {
base,
}
}
} |
Does the gdextension team have a position on what should go in if manipulating |
That's simply not true. A primary use case is any class that does not inherit Node, does not have a ready function. Initializing it must be done within a custom constructor or init. See my code snippet, I'd like for all created Translations to start with an empty locale, overriding the default of "en". There is no other way to do this in a way that Godot knows that this is the new default value (and won't show a revert arrow in the inspector). |
I think the issue with |
So that does sorta fix the issue, but there are some memory leaks and i dont think there is a way to fix those. Since if the refcount is initialized by The fundamental problem with this is that our |
I guess one thing that could be doable is, initialize the refcount early. And then keep track in |
When initializing an object in Godot, it is a fairly common pattern in c++ to do most of the setup in the
init
function. But as of #497 and #501, it is now impossible to directly use theBase
object to do anything (at least without using#[doc(hidden)]
functions). That means that in order to call any methods on base to set up the class, you'd need to first create theSelf
object and then use a method likeWithBaseField::to_gd
, like this:However this means that every field in
Self
has some sensible default, that doesn't require any calls to the base object. It would be nice to provide an official solution for this pattern.This was initially discussed in this discord thread https://discord.com/channels/723850269347283004/1193536016968073236, i will summarize the solutions we discussed here.
Possible Solutions
Base
'sto_gd
method public. This method is currently#[doc(hidden)]
, but using it solves the issue. However the reason it is hidden is because it may cause confusion in most other functions, where it may be unclear if people should useself.base.to_gd()
orself.to_gd()
or evenself.base_mut()
. As well as what the difference is. So if we do this we should likely rename it to make it more clear.init
. Whereas the stored base is what we currently have and is what is stored in the struct. This would however require us adding a new type that is only used in this one situation.Gd
of base to the init function. This might however be confusing as both theBase
andGd
point to the same thing, and people might be tempted to store the wrong object in the struct.I am currently inclined to go with the first option, to make
to_gd
public. It seems the simplest to me and giving it a new name with good documentation would hopefully solve the confusion issue.The text was updated successfully, but these errors were encountered: