SystemParam lifetime more general. #20697
-
I have code like this (adapted from https://www.reddit.com/r/bevy/comments/18xgcm8/comment/kg5jmwp/): use std::{marker::PhantomData, ops::DerefMut};
use bevy::{
ecs::{
schedule::ScheduleConfigs,
system::{ScheduleSystem, StaticSystemParam, SystemParam, SystemParamItem},
},
prelude::*,
};
use crate::colors::{HOVERED_BUTTON, NORMAL_BUTTON, PRESSED_BUTTON};
// https://www.reddit.com/r/bevy/comments/18xgcm8/comment/kg5jmwp/
pub trait ButtonInteraction<C: Component>: SystemParam {
fn interact(&mut self, _: &C);
fn verify(&mut self, _: &C) -> bool {
true
}
}
pub trait SpinnerButtonInteraction<C: Component>: SystemParam {
fn increment(&mut self, _: &C);
fn can_increment(&mut self, _: &C) -> bool {
true
}
fn decrement(&mut self, _: &C);
fn can_decrement(&mut self, _: &C) -> bool {
true
}
}
#[derive(SystemParam)]
pub struct SpinnerParmeter<
'w,
's,
C: Component,
T: SystemParam + SpinnerButtonInteraction<C> + 'static,
>(Query<'w, 's, &'static C>, StaticSystemParam<'w, 's, T>);
#[derive(Debug, Component, Clone, Copy)]
pub struct Up<C>(Entity, PhantomData<C>);
impl<C, T> ButtonInteraction<Up<C>> for SpinnerParmeter<'_, '_, C, T>
where
C: Component,
T: SpinnerButtonInteraction<C>
+ for<'w, 's> SystemParam<Item<'w, 's> = T>
+ SpinnerButtonInteraction<C>,
{
fn interact(&mut self, c: &Up<C>) {
if let Ok(c) = self.0.get(c.0) {
self.1.increment(c)
}
}
fn verify(&mut self, c: &Up<C>) -> bool {
if let Ok(c) = self.0.get(c.0) {
self.1.deref_mut().can_increment(c)
} else {
false
}
}
}
#[derive(Debug, Component, Clone, Copy)]
pub struct Down<C>(Entity, PhantomData<C>);
impl<C, T> ButtonInteraction<Down<C>> for SpinnerParmeter<'_, '_, C, T>
where
C: Component,
T: SpinnerButtonInteraction<C>
+ for<'w, 's> SystemParam<Item<'w, 's> = T>
+ SpinnerButtonInteraction<C>,
{
fn interact(&mut self, c: &Down<C>) {
if let Ok(c) = self.0.get(c.0) {
self.1.deref_mut().increment(c)
}
}
fn verify(&mut self, c: &Down<C>) -> bool {
if let Ok(c) = self.0.get(c.0) {
self.1.deref_mut().can_increment(c)
} else {
false
}
}
}
#[derive(Debug, Component, Clone, Copy)]
pub struct Value<C>(pub Entity, PhantomData<C>);
pub fn button_system_with_generic<C: Component, T: SystemParam>(
button_query: Query<'_, '_, (&Interaction, &mut BackgroundColor, &C), (Changed<Interaction>,)>,
mut param: SystemParamItem<T>,
) where
for<'w, 's> T::Item<'w, 's>: ButtonInteraction<C>,
{
for (interaction, mut background_color, c) in button_query {
if param.verify(c) {
match *interaction {
Interaction::Pressed => {
param.interact(c);
*background_color = PRESSED_BUTTON.into()
}
Interaction::Hovered => *background_color = HOVERED_BUTTON.into(),
Interaction::None => *background_color = NORMAL_BUTTON.into(),
}
} else {
// TODO: have disable button color
*background_color = NORMAL_BUTTON.into()
}
}
} When the The An example implementation of #[derive(Debug, Component, Resource, Clone, Copy)]
pub enum GameResource {
// stuff
}
#[derive(Resource)]
pub struct TradingResources {
// stuff
}
impl TradingResources {
pub const fn get_mut(&mut self, selector: GameResource) -> &mut i8 {
todo!(),
}
}
#[derive(Debug, Component, Clone, Copy)]
pub struct TradingResourcesSpinner(GameResource);
impl SliderButtonInteraction<TradingResourcesSpinner> for ResMut<'_, TradingResources> {
fn increment(&mut self, resource: &TradingResourcesSpinner) {
*self.get_mut(resource.0) += 1;
}
fn decrement(&mut self, resource: &TradingResourcesSpinner) {
*self.get_mut(resource.0) -= 1;
}
} The problem is when I try to use the fn main() {
let mut app = App::new();
app.add_systems(
Update,
(common_ui::button_system_with_generic::<
Down<TradingResourcesSpinner>,
SpinnerParmeter<'_, '_, TradingResourcesSpinner, ResMut<TradingResources>>,
>,),
);
} I get an error:
It works fine when I do it with something that implements Sorry this was pretty long. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I got it to work by changing generics impls of : #[derive(Debug, Component, Clone, Copy)]
pub struct Up<C>(Entity, PhantomData<C>);
impl<'w, 's, C, T> ButtonInteraction<Up<C>> for SpinnerParmeter<'w, 's, C, T>
where
C: Component,
T: SystemParam,
for<'w1, 's1> T::Item<'w1, 's1>: SpinnerButtonInteraction<C>,
{
fn interact(&mut self, c: &Up<C>) {
if let Ok(c) = self.0.get(c.0) {
self.1.increment(c)
}
}
fn verify(&mut self, c: &Up<C>) -> bool {
if let Ok(c) = self.0.get(c.0) {
self.1.deref_mut().can_increment(c)
} else {
false
}
}
}
#[derive(Debug, Component, Clone, Copy)]
pub struct Down<C>(Entity, PhantomData<C>);
impl<'w, 's, C, T> ButtonInteraction<Down<C>> for SpinnerParmeter<'w, 's, C, T>
where
C: Component,
T: SystemParam,
for<'w1, 's1> T::Item<'w1, 's1>: SpinnerButtonInteraction<C>,
{
fn interact(&mut self, c: &Down<C>) {
if let Ok(c) = self.0.get(c.0) {
self.1.deref_mut().decrement(c)
}
}
fn verify(&mut self, c: &Down<C>) -> bool {
if let Ok(c) = self.0.get(c.0) {
self.1.deref_mut().can_decrement(c)
} else {
false
}
}
} |
Beta Was this translation helpful? Give feedback.
I got it to work by changing generics impls of
ButtonInteraction<Up/Down>
to mirror the trait boundsbutton_system_with_generic
.So putting the SpinnerInteraction constraint on T::Item and then dealing with the lifetimes with a
for<'w1, s1>
.: