Skip to content
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

Merged
merged 1 commit into from
Jun 7, 2023
Merged

Conversation

Brocktho
Copy link

@Brocktho Brocktho commented Jun 5, 2023

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.

@Bromeon Bromeon added c: engine Godot classes (nodes, resources, ...) feature Adds functionality to the library labels Jun 5, 2023
Copy link
Member

@Bromeon Bromeon left a 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 🙂

@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-299

@Brocktho
Copy link
Author

Brocktho commented Jun 6, 2023

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.

@Bromeon
Copy link
Member

Bromeon commented Jun 6, 2023

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 🙂

@Brocktho
Copy link
Author

Brocktho commented Jun 6, 2023

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?

@Bromeon
Copy link
Member

Bromeon commented Jun 6, 2023

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.

@Brocktho
Copy link
Author

Brocktho commented Jun 6, 2023

what a mess...
working on it lol

@Brocktho
Copy link
Author

Brocktho commented Jun 6, 2023

My lord, that was painful. Rebasing is unpleasant.

Copy link
Member

@Bromeon Bromeon left a 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();
Copy link
Member

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":

Suggested change
let mut mob_scene: Gd<RigidBody2D> = self.mob_scene.instantiate_as();
let mut mob_scene = self.mob_scene.instantiate_as::<RigidBody2D>();


/// Extension trait for convenience functions on `PackedScene`
pub trait PackedSceneExt {
/// Instantiates the scene as type `T`, panicking if not found or bad type.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// 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.

/// If the scene is not type `T` or inherited.
fn instantiate_as<T>(&self) -> Gd<T>
where
T: GodotClass + Inherits<Node>,
Copy link
Member

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.

where
T: GodotClass + Inherits<Node>,
{
self.try_instantiate_as::<T>().unwrap()
Copy link
Member

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

/// ⚠️ **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,
)
})
}

Comment on lines 48 to 49
self.instantiate(GenEditState::GEN_EDIT_STATE_DISABLED)
.map(|gd| gd.cast::<T>())
Copy link
Member

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.

@Bromeon
Copy link
Member

Bromeon commented Jun 6, 2023

Worth noting, now the extension trait is implemented on PackedScene (and not Gd<PackedScene>), but as mentioned on Discord, I think it's fine for now.

We may want to revisit this topic later down the line, with load, get_node_as, and possibly more extension functions like that.

Comment on lines 48 to 53
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,)
})
})
Copy link
Member

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).

T: Inherits<Node>,
{
self.try_instantiate_as::<T>()
.unwrap_or_else(|| panic!("Failed to instantiate {to}", to = T::CLASS_NAME,))
Copy link
Member

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
@Brocktho
Copy link
Author

Brocktho commented Jun 7, 2023

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.

Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

bors r+

@bors
Copy link
Contributor

bors bot commented Jun 7, 2023

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.
For more help, visit the forum.

If you want to switch to GitHub's built-in merge queue, visit their help page.

@bors bors bot merged commit 21cf712 into godot-rust:master Jun 7, 2023
@Bromeon Bromeon mentioned this pull request Jun 13, 2023
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: engine Godot classes (nodes, resources, ...) feature Adds functionality to the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants