-
-
Notifications
You must be signed in to change notification settings - Fork 193
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
Added instantiate_as for PackedScene #299
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Is GenEditState
being explicitly provided a common occurrence? I think the idea of instantiate_as
is to cover the common case in an easy way, and adding significant type overhead for the 2nd parameter seems to work against that.
I'd keep it simple and just support the call without GenEditState
. If this becomes required, we can always change things later.
Please also consider the contribution guidelines, especially 1 commit per logical change 🙂
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-299 |
Would you like me to just turn GenEditState into a no arg function and have it add the GenEditState::GEN_EDIT_STATE_DISABLED. Then if the user wants to have more control they manage the instantiate themselves with the base PackedScene? I'm definitely not opposed to it after using the current method more, just initially posted it trying out the tuple approach to see how it felt. |
Exactly; I think an API like fn try_instantiate_as<T>(&self) -> Option<Gd<T>>
where
T: Inherits<Node>;
fn instantiate_as<T>(&self) -> Gd<T>
where
T: Inherits<Node>; is enough. Please document the methods 🙂 |
So you made a note about multiple commits, what should I do to make said changes? Most of my extra commits on here were mistakes of not fully pushed code, also now I'm assuming is safe to push an extra commit? |
Check the link I posted, there is a short explanation in the guidelines. If you haven't used those git commands before, https://git-scm.com/docs is a good resource. |
what a mess... |
My lord, that was painful. Rebasing is unpleasant. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update! Left a few comments.
With one commit, it's quite easy to do changes: just use git commit --amend
.
@@ -78,7 +77,7 @@ impl Main { | |||
.base | |||
.get_node_as::<PathFollow2D>("MobPath/MobSpawnLocation"); | |||
|
|||
let mut mob_scene: Gd<RigidBody2D> = instantiate_scene(&self.mob_scene); | |||
let mut mob_scene: Gd<RigidBody2D> = self.mob_scene.instantiate_as(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use this notation, as it reads more idiomatically "instantiate as RigidBody2D":
let mut mob_scene: Gd<RigidBody2D> = self.mob_scene.instantiate_as(); | |
let mut mob_scene = self.mob_scene.instantiate_as::<RigidBody2D>(); |
godot-core/src/engine.rs
Outdated
|
||
/// Extension trait for convenience functions on `PackedScene` | ||
pub trait PackedSceneExt { | ||
/// Instantiates the scene as type `T`, panicking if not found or bad type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Instantiates the scene as type `T`, panicking if not found or bad type. | |
/// ⚠️ Instantiates the scene as type `T`, panicking if not found or bad type. |
The emoji is for IDE inline docs, a convention we use for Gd::cast()
, Gd::from_instance_id()
, etc.
godot-core/src/engine.rs
Outdated
/// If the scene is not type `T` or inherited. | ||
fn instantiate_as<T>(&self) -> Gd<T> | ||
where | ||
T: GodotClass + Inherits<Node>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in my previous suggestion, GodotClass
is not necessary, since it's a bound implied by Inherits
.
godot-core/src/engine.rs
Outdated
where | ||
T: GodotClass + Inherits<Node>, | ||
{ | ||
self.try_instantiate_as::<T>().unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of unwrap()
, could you add a descriptive error message taking into account the variables?
For prior art, see
gdext/godot-core/src/obj/gd.rs
Lines 316 to 331 in 7573721
/// ⚠️ **Downcast:** convert into a smart pointer to a derived class. Panics on error. | |
/// | |
/// # Panics | |
/// If the class' dynamic type is not `Derived` or one of its subclasses. Use [`Self::try_cast()`] if you want to check the result. | |
pub fn cast<Derived>(self) -> Gd<Derived> | |
where | |
Derived: GodotClass + Inherits<T>, | |
{ | |
self.owned_cast().unwrap_or_else(|from_obj| { | |
panic!( | |
"downcast from {from} to {to} failed; instance {from_obj:?}", | |
from = T::CLASS_NAME, | |
to = Derived::CLASS_NAME, | |
) | |
}) | |
} |
godot-core/src/engine.rs
Outdated
self.instantiate(GenEditState::GEN_EDIT_STATE_DISABLED) | ||
.map(|gd| gd.cast::<T>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This panics if cast()
fails, violating the method contract. Use try_cast()
instead.
Worth noting, now the extension trait is implemented on We may want to revisit this topic later down the line, with |
godot-core/src/engine.rs
Outdated
self.instantiate(GenEditState::GEN_EDIT_STATE_DISABLED) | ||
.map(|gd| { | ||
gd.try_cast::<T>().unwrap_or_else(|| { | ||
panic!("Failed to cast {self:?} into {to}", to = T::CLASS_NAME,) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still panic here. The idea of try_
functions is to not panic, but propagate the error (or in this case, None
).
godot-core/src/engine.rs
Outdated
T: Inherits<Node>, | ||
{ | ||
self.try_instantiate_as::<T>() | ||
.unwrap_or_else(|| panic!("Failed to instantiate {to}", to = T::CLASS_NAME,)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing comma
Updates based on provided comments. panic with messages of failed instantiation into T Understood that I needed to return an option, just lost the plot because the map statement was giving a nested Option, and_then is what I was looking for. Remove trailing comma
Yikes, should be properly addressed now. I understood I needed to pass back an option, just lost the plot because of the map statement giving a nested option, and_then is what I was looking for. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
bors r+
Build succeeded! The publicly hosted instance of bors-ng is deprecated and will go away soon. If you want to self-host your own instance, instructions are here. If you want to switch to GitHub's built-in merge queue, visit their help page. |
I added PackedSceneExt as a trait for the PackedScene to impl, made the impl and added usage of instantiate_as to the example dodge the creeps.
I commented out areas in the dodge-the-creeps file.