-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Multiple Configurations for Gizmos #10342
Multiple Configurations for Gizmos #10342
Conversation
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
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 is excellent! I'm excited by this change. I've a few comments.
/// | ||
/// If `line_perspective` is `true` then this is the size in pixels at the camera's near plane. | ||
/// A trait adding `init_gizmo_config<T>()` to the app | ||
pub trait AppGizmoBuilder { |
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.
Nit: Could this be moved to its own module?
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.
I'm quite new to rust and big projects and would love to understand why this should be moved to its own module. For me, it seems to be related to the plugin build code above. Thanks!
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.
The general pattern in rust is to have a tinny lib.rs
. In bevy, it usually only consists of re-exports (such as the prelude) and the root impl Plugin for CratePlugin
definition.
The whole bevy_gizmo
crate started small enough that it could fit in a single file. But as we add features, it is good to split up. I think it's time to split it, just generally.
In the case of AppGizmoBuilder
, some crate authors define extension traits in a separate module, so it would be fit to move to its own module.
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.
Thank you for the explanation! I moved the aabb code into a separate module as I changed how additional gizmo configs should be added. Opening another PR to split the rest of lib.rs
seems to be a better fit. Or should I do everything in this one?
In #9187, I make the point that the API chosen here is similar to the one used by the diagnostics (with a diagnostics store). This API uses reflection so that we can add additional non-homogeneous configuration options. To me, it seems an asset based solution would not solve any of the problems the reflection-based approach solves, while introducing new ones. The gizmo API is very different from any other bevy API, as it is immediate, which is completely different from interacting with the ECS, which by definition is retained. I suspect that any ECS-based approach would give up all the ergonomics of the gizmo API. But if you have an idea in mind, feel free to implement it. I'd be glad to be proven wrong. |
use GizmoMeshConfig instead of GizmoConfig as a component on extracted gizmos
- renamed CustomGizmoConfig to GizmoConfigGroup - added derive macro - fixed comments
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 is already good for me.
crates/bevy_gizmos/src/config.rs
Outdated
} | ||
|
||
/// Returns [`GizmoConfig`] and [`GizmoConfigGroup`] associated with [`GizmoConfigGroup`] `T` | ||
pub fn get<T: GizmoConfigGroup>(&self) -> (&GizmoConfig, &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.
I would have this return an Option<(&GizmoConfig, &T)>
. Can always let the end-user do the 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.
I thought about returning Option<(&GizmoConfig, &T)>
but decided to use a panicking API for the generic getter methods. Contrary to the get_dyn
methods, the generic ones will only fail if the config isn't correctly registered as the type is already checked to be a gizmo config. The possibility of a plugin author failing to register the config or the user forgetting to add the plugin doesn't feel like something we need to be aware of every time the get method is used.
Even if these return an option, the Gizmos<T>
SystemParam would still fail to be built when the config isn't registered. I believe both generic access patterns should react the same way.
But I'm open to changing it. I just wanted to share my thoughts :)
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.
I just don't like the panicking API on a get
method. In the std, get
is for non-panicking indexing. My beef is more with the name than the fact it panics. What about config
? In fact, it doesn't really make sense to return an Option
, panicking is the correct behavior here…
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 are right, get
is an unfortunate name. I'm changing it to config
for now, but maybe we will find a better name in future.
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.
Really liked those changes, With this, its possible to use gizmos in tools context without blocking the user from using it.
One question, though: Should the Aabb
tool go in #11341 when it get merged? (That can probably be a follow up PR, just to be sure that this is indeed a debug tool and not something that we use regularly)
@jeliag if you resolve the merge conflicts here I can merge this in :) Sorry about missing this; it didn't get the Ready-For-Final-Review label. |
I think moving AABB gizmos (or any other special debug gizmos) out of the gizmos crate is a good idea. This way the gizmos crate can focus on providing a useful API for drawing gizmos. |
Objective
This PR aims to implement multiple configs for gizmos as discussed in #9187.
Solution
Configs for the new
GizmoConfigGroup
s are stored in aGizmoConfigStore
resource and can be accesses using a type based key or iterated over. This type based key doubles as a standardized location where plugin authors can put their own configuration not covered by the standardGizmoConfig
struct. For example theAabbGizmoGroup
has a default color and toggle to show all AABBs. New configs can be registered usingapp.init_gizmo_group::<T>()
during startup.When requesting the
Gizmos<T>
system parameter the generic type determines which config is used. The config structs are available through theGizmos
system parameter allowing for easy access while drawing your gizmos.Internally, resources and systems used for rendering (up to an including the extract system) are generic over the type based key and inserted on registering a new config.
Alternatives
The configs could be stored as components on entities with markers which would make better use of the ECS. I also implemented this approach (here) and believe that the ergonomic benefits of a central config store outweigh the decreased use of the ECS.
Unsafe Code
Implementing system parameter by hand is unsafe but seems to be required to access the config store once and not on every gizmo draw function call. This is critical for performance.
Is there a better way to do this?Future Work
New gizmos (such as #10038, and ideas from #9400) will require custom configuration structs. Should there be a new custom config for every gizmo type, or should we group them together in a common configuration? (for example
EditorGizmoConfig
, or something more fine-grained)Changelog
GizmoConfigStore
resource andGizmoConfigGroup
traitinit_gizmo_group
toApp
GizmoConfig
and aabb gizmos to use newGizmoConfigStore
Gizmos
system parameter to use type based key to retrieve configMigration Guide
GizmoConfig
is no longer a resource and has to be accessed throughGizmoConfigStore
resource. The default config group isDefaultGizmoGroup
, but consider using your own custom config group if applicable.