-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Abstraction dev tools #12427
base: main
Are you sure you want to change the base?
Abstraction dev tools #12427
Changes from 5 commits
9e18452
2b5cef5
dd62c29
77f7bfb
ef68643
8355a39
8a81cd1
e2f8f89
93e697f
1ad3469
d999850
8e6eab9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,9 @@ | |
#![cfg_attr(docsrs, feature(doc_auto_cfg))] | ||
|
||
use bevy_app::prelude::*; | ||
use bevy_ecs::system::Resource; | ||
use bevy_utils::HashMap; | ||
use uuid::Uuid; | ||
|
||
#[cfg(feature = "bevy_ci_testing")] | ||
pub mod ci_testing; | ||
|
@@ -45,3 +48,111 @@ impl Plugin for DevToolsPlugin { | |
} | ||
} | ||
} | ||
|
||
/// Unique identifier for [`DevTool`]. | ||
#[derive(Debug, Hash, Eq, PartialEq, Clone)] | ||
pub struct DevToolId(pub Uuid); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering: Why not use a TypeId map instead of Uuid? I think its much more simple. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to identify each dev tool with a different type? We could use plugin struct for it, but what if plugin adds more than one dev tool? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was expecting to identify every tool with a single config type registered to it, but I see that's a similar approach taken by the gizmos multiple configs, and we aren't storing configs in this map by now, so, with what we have now on this PR, the TypeId doesn't make sense. |
||
|
||
impl DevToolId { | ||
/// Creates a [`DevToolId`] from u128. | ||
pub const fn from_u128(value: u128) -> DevToolId { | ||
DevToolId(Uuid::from_u128(value)) | ||
} | ||
} | ||
|
||
/// Information about dev tool. | ||
#[derive(Debug)] | ||
pub struct DevTool { | ||
/// Identifier of a dev tool. | ||
pub id: DevToolId, | ||
is_enabled: bool, | ||
} | ||
|
||
impl DevTool { | ||
/// Returns true if [`DevTool`] is enabled. | ||
pub fn is_enabled(&self) -> bool { | ||
self.is_enabled | ||
} | ||
|
||
/// Enables [`DevTool`]. | ||
pub fn enable(&mut self) { | ||
self.is_enabled = true; | ||
} | ||
|
||
/// Disables | ||
pub fn disable(&mut self) { | ||
self.is_enabled = false; | ||
} | ||
|
||
/// Toggles [`DevTool`]. | ||
pub fn toggle(&mut self) { | ||
self.is_enabled = !self.is_enabled; | ||
} | ||
} | ||
|
||
impl DevTool { | ||
/// Creates a new [`DevTool`] from a specified [`DevToolId`]. | ||
/// New tool is enabled by default. | ||
pub fn new(id: DevToolId) -> DevTool { | ||
DevTool { | ||
id, | ||
is_enabled: true, | ||
} | ||
} | ||
} | ||
|
||
/// A collection of [`DevTool`]s. | ||
#[derive(Resource, Default)] | ||
pub struct DevToolsStore { | ||
dev_tools: HashMap<DevToolId, DevTool>, | ||
} | ||
|
||
impl DevToolsStore { | ||
/// Adds a new [`DevTool`]. | ||
/// | ||
/// If possible, prefer calling [`App::register_dev_tool`]. | ||
pub fn add(&mut self, dev_tool: DevTool) { | ||
self.dev_tools.insert(dev_tool.id.clone(), dev_tool); | ||
} | ||
|
||
/// Removes a [`DevTool`]. | ||
pub fn remove(&mut self, id: &DevToolId) { | ||
self.dev_tools.remove(id); | ||
} | ||
|
||
/// Returns a [`DevTool`]. | ||
matiqo15 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub fn get(&self, id: &DevToolId) -> Option<&DevTool> { | ||
self.dev_tools.get(id) | ||
} | ||
|
||
/// Returns a mutable [`DevTool`]. | ||
matiqo15 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub fn get_mut(&mut self, id: &DevToolId) -> Option<&mut DevTool> { | ||
self.dev_tools.get_mut(id) | ||
} | ||
|
||
/// Returns an iterator over all [`DevTool`]s. | ||
matiqo15 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub fn iter(&self) -> impl Iterator<Item = &DevTool> { | ||
self.dev_tools.values() | ||
} | ||
|
||
/// Returns an iterator over all [`DevTool`]s, by mutable reference. | ||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut DevTool> { | ||
self.dev_tools.values_mut() | ||
} | ||
} | ||
|
||
/// Extend [`App`] with new `register_dev_tool` function. | ||
pub trait RegisterDevTool { | ||
/// Registers a new [`DevTool`]. | ||
fn register_dev_tool(&mut self, dev_tool: DevTool) -> &mut Self; | ||
} | ||
|
||
impl RegisterDevTool for App { | ||
fn register_dev_tool(&mut self, dev_tool: DevTool) -> &mut Self { | ||
let mut dev_tools = self | ||
.world | ||
.get_resource_or_insert_with::<DevToolsStore>(Default::default); | ||
dev_tools.add(dev_tool); | ||
self | ||
} | ||
} |
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 don't like this. This will run every time any tool has been changed, but I can't think of a solution to only run if a specific tool has been changed
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 think we can relax on that somehow by just making a global system that manages this, based on one-shot systems, I'm not sure how effective this can be do though. At the same time, that would be useless without some kind o cache to store what was changed and what was not.
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.
If we had some kind of cache storing what was changed, I don't think there would be any reason for complicating it with the global system. I'd just let the user interact with the cache and use it in a
run_if
condition.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 think this is a fine level of granularity for now: I wouldn't expect
DevToolsStore
to change regularly at all.If it becomes a problem we can also cache a
Local
within the system to short-circuit.