#bevy_enhanced_input
1 messages Β· Page 3 of 1
using action.state::<A>() shouldn't ActionState::Fired only be given once?
If your action is assigned to a button press, it will behave like pressed in Bevy.
If you're looking for just_pressed behavior, use action.events::<A>().contains(ActionEvents::STARTED).
But for things like this I'd suggest to use an observer for a better API.
when is Cancelled raised?
Depends on the condition.
For example, with Hold condition it's triggered when you started to hold the button, but didn't hold it for enough time.
cool
Am I right to assume that touchpad on sony gamepads is not supported yet?
Yeah, this isn't exposed via winit or gilrs
I literally just came here to ask questions about the library being more component-y and just saw this
am I blessed?
I'm using components as states and so being able to have these components represent the input contexts too would be so cool
am I crazy if I literally start using this PR straight away @sharp warren? π
please do! I'd love to hear user feedback
It's actually a good idea!
Will be less breaking changes for you later. Let us know what you think about it.
I'd recomment to read the new quick start guide first. Just read it locally using cargo doc --open.
I'll draft a new release right after the merge.
Man, I really like this design
Very clean
And trivially serializable and adjustable at runtime
Ugh lol, the Github website hangs for me trying to review this
I guess I'll check it out locally
Okay, just set it up
this is SO MUCH BETTER
I'll find caveats thats for sure
but the way contexts are basically good old bevy components without anything special is just
π§π»βπ³ π
Thanks! I'm glad you all like it π
I really do!
I have complaints about the docs though :p 
Thanks, already started addressing them!
I also pushed a couple of tiny typo / grammar fixes to your branch
Now this is tidy
the entity has it's own statemachine (where each state is a compoonent such as InLauncher) and now I can just insert actions and observers inline like this
no declaring contexts anywhere involved π
One tiny suggestion. If you just want to clear actions, you can do despawn_related π
Addressed the suggestions!
I need some advice. To remove a context from an entity, users currently need to do the following:
entity.remove_with_requires::<Player>().despawn_related::<Actions<Player>>();
This feels a bit verbose. I'm thinking about marking Actions<C> as a required component for C and similar for Action<C> and Bindings. That way, despawning would be much simpler. What do you think?
Wait, git push failed. Now pushed
what would despawn related do? clear every action attached to an entity?
Yep!
Actually, I just looked at the code - it also removes the component, which is not what you want?
If yes, then another suggestion: you can remove the remove call, insert will overwrite the value π
Ah, looks like if linked_spawn is enabled and you remove the relationship target components, entities aren't depsawned. So we can't do this.
But it's not very expected. I will open an issue on the Bevy repo.
This also applies to your code: if you want to cleanup actions, you need to call despawn_related instead of remove. And insert is optional, in case you just need this component π
The overwriting will in fact be much better here π
And yeah, I don't want to remove the component, as it represents the state the entity is in
Opened https://github.com/bevyengine/bevy/issues/20252 and documented this behavior.
Waiting for a final approval from @outer wyvern, then I address this PR and we are ready for a release π
@sharp warren we just had this talk in #1124043933886976171, #ecs-dev and #1278871953721262090, so let me throw something potentially annoying in the room:
does this rework work with disabled entities?
See the following two issue for footguns:
Thanks for letting me know!
No, I didn't take this into account. I will open a fix before the release in a separate PR.
Yeah I also surprisingly found out that most of my crates donβt actually support disabled entities π
Yeah, it's a very recent feature, need some time for the ecosystem to adapt.
I remember in early Bevy days people didn't even disable default features on Bevy, I had to patch a ton of third-party crates π
I'm happy with the changes now, but Github keeps crashing on me lol
So please merge without my formal approval
It really doesn't like the many files changed PRs
Excellent!
Going to sleep right now, will address the remaining things tomorrow π
GitLab also doesn't like big merge requests...
once I reviewed +20k -19k merge request
much wow π
btw, i'm looking forward to test this all out upon release
Actions dont have Reflect, which means that you cant use bevy-inspector-egui to verify its state
It wasn't possible to reflect it back then. But it's fully reflected with the component-based API rework.
The release is today. In the meanwhile, you can switch to the current master.
I think Allows<Disabled> won't work for custom disabled components.
You mean user-defined things outside the default query?
If so: yes, #ecs-dev tells us thereβs no better way atm
From what I remember, users can define their own disabled components
Yep.
Not really possible to support those atm π
I have only a single place when I need it π’
We need a way to disable default filters, needed to uphold invariants.
Yep, agreed
Pretty sure @edgy shuttle would like that as well
Opened a PR that will work with Disabled:
https://github.com/projectharmonia/bevy_enhanced_input/pull/143
Damn, it's so annoying that I have to pull log directly.
Once again, I wrote a code that passes tests locally. I push it and on CI lib compilation fails because trace was pulled from the bevy::prelude::*, but bevy_log is a dev-dependency, which is unavailable when you compile the library, but present in the prelude when you run tests.
@kind summit by any chance we could have bevy_log with no_std in 0.17? Looks like tracing was released with your changes.
Looked properly into the opened PR. Not sure if the suggested modifier is useful, but I'll wait for a response from the author.
I don't think we need to block the release because of it. If we decide to include the proposed modifier, we can do it in a patch.
@outer wyvern waiting for your approval for this one and I will draft the release π
Approved π
Yeah, this is good minor version stuff
is there any example out there for touch input in BEI?
I'd love to be able to implement custom inputs from a touchscreen like pinch swipe press etc
or is it not even possible?
(without boilerplate I mean)
This needs to be tackled at the bevy_input level and higher for the most part π
Then exposed
hello, i asked in general chat but ill check here also, is adding data to the InputAction possible? i mean something like this
#[derive(InputAction)]
#[action_output(bool)]
pub struct TestAction{
pub value: f32
}
pub fn setup(mut cmd: Commands) {
cmd.spawn(actions!(
Context[
(
//HERE
bevy_enhanced_input::prelude::Action::<TestAction>::new(TestAction{
value: 0.
}),
bindings![KeyCode::Space, GamepadButton::South],
),]
No, you need to insert a separate component for this. Action stores only the output.
Looks like bevy_input has this module: https://docs.rs/bevy/latest/bevy/input/touch/index.html
But I never used it π€
The touch input functionality.
@quasi epoch published a patch release with your modifier π
great
Thanks for the contribution!
re: touch input
does bevy_enhanced_input support manually activating actions? is ActionMock good enough for that?
Yes, you need either to use mocking or intercept the value manually before the EnhancedInputSet::Apply system.
If its for touch, we better add a built-in option for it.
@sharp warren have you put any more thought into an input buffer feature? i would open a pr but i think this is beyond my skill level
Can't think of any compromise-free solution π’ I think this requires changes on the Bevy side.
My up-to-date thoughts are in this message. If you have other ideas - feel free to suggest!
Is this a deal-breaker for you? It's triggered only if you activate and deactivate actions quicker then your fixed tickrate. If you press buttons that quick, you can just increase the tickrate temporarely as a workaround while waiting for a soluiton.
I agree that the best way to fix this is to have timestamps upstream. @motgenror looked into implementing them by moving Bevy into its own thread and reserving the main thread for handling input events. IIRC that was a silly requirement that Windows has.
huh looks like their Discord profile is having issues
Anyways, there is a concrete solution suggestion now. Someone just needs to implement it π
Cool! Yeah, that would be great.
Yeah that would make quite a few people waiting for this feature happy haha
Ah, dug up the message
I won't be working on this, just posting it here in case a BEI user want to get nerdsniped into it 
Same, my current focus is on bevy_replicon, I need to implement a few important features π
After the refactor; how can i get the type of an InputAction if I know the Action entity?
Conversily, if I know the ActionType, how can i get the entity that holds the action value?
Thank you for this. It helped me see what was going on in the background. Been trying to figure out how Fired are reported as Completed. I was trying to figure out how to read a field or something. Turns out I just needed to create another function with Completed. Awesome, thanks again.
I don't have a component that holds the TypeId π€
I can add this, but maybe you could use Entity?
I would expect both client and server to spawn the hierarchy, then notify the server about entity IDs and just send the action changes.
It would work similar to replication, but with buffering that needed for the input. Does it make sense?
Actually, you register actions, right?
In that case inside your registration function you could do app.add_require_component<Action<C>, YourTypeIndicator>().
But I still highly suggest to consider the suggested approach above.
I was thinking of trying to do the replication with entities, it might be doable with my current approach, not entirely sure yet. The main issue I have right now is that I expect a single ActionState component; which in your case is split between 4 components. For now i will just create my own component which will be a copy of your 4 components
This would also work, sure. You can also include the type into it (if needed) and make it dynamically-required for Action<C>, like I suggested above.
The one component vs 4 components is independent from the previous question. It's because my API expects a single component https://github.com/cBournhonesque/lightyear/blob/main/lightyear_inputs/src/input_message.rs#L66 to query/update the state of the action.
It's used at various places like so: https://github.com/cBournhonesque/lightyear/blob/main/lightyear_inputs/src/client.rs#L307
Maybe you can replace the component requirement with QueryData? Inside the Query you can nest QueryData, so something like this Query<(Entity, (&B, &C))> is also a valid query.
So for a single component you would be able to define &A, for 2 it would be (&mut A, &mut B)
But yeah, a single component that copies the data is not a bad workaround for now π€
Yeah i thought about that, but it's not super straightforward actually, because for a component the query data is &A or &mut A, so i would need to have an ActionStateRef and and ActionStateMut for the equivalent (&A, &B) and (&mut A, &mut B) + there's other complications
QueryData stores it's read-only variant as QueryData::ReadOnly. So you only need a mutable variant.
Drafted a minor patch with a fix for Chord and more derives for ActionTime.
Um Hey : I've been struggling with getting enhanced_input to work in my game for some reason... similar code seems to be working in a separate demo but when i try to do it from inside my game something seems to be messing up:
input_manager
spawning characters here
plugging everything together here
Not sure what should I be looking for in the logs : I had added an info log for the observer that gets Trigger<Fired<Move>> for movement : but those logs don't get printed at all.
Have added the general TRACE level logs for when I run the game - think my states maybe messing up the bindings to the players maybe...
These logs are not related to BEI.
I meant to follow these instructions.
Input manager for Bevy, inspired by Unreal Engine Enhanced Input.
oh sorry I'll try that!
hmm : i see the players being registered here (they get unregistered when the game ends, and registered again when we restart and players spawn again)
but still the on_move observer doesn't seem to be working
So the context is working, but the action is not. You need to enable tracing to see more info
But enable it only for BEI, otherwise it will be too noisy.
DefaultPlugins.set(LogPlugin {
filter: "bevy_enhanced_input=debug".into(),
..Default::default()
}
this is what i used for logs
alright
Yeah, just repalce debug with trace
This line:
updating `demon_goat_salon::engine::input_manager::Move`
indicates that Move is setup correctly. On the next line you can see it reads input for it, passes through modifiers and such.
But there are no input, so the triggers don't fire.
Wait a minute. Why it's Axis1D?
oh the gamepad setup is messing it up?
It's not the gamepad, it's the action output
#[derive(InputAction)]
#[action_output(f32)]
pub struct Move;
ohh
I think i got it
maybe its using the Move from bevy
instead of the one i defined
leme try
If you need a 4-directional movement, you need Vec2 (which is Axis2D)
just bi directional
its 2d
Then it's fine. But you don't have any inputs from bevy_input.
At least from the logs
Bevy don't have such type and you wouldn't be able to accidentally use it as an action.
Maybe collect the logs again with any active input?
i was pressing buttons binded for both characters when i got the logs : if thats what you meant
i see i see
anyways thanks alot for this : its very helpful π
Yes. But there are no input π€
Could you try reading the raw input from Bevy?
I'll try
pub fn keyboard_input(
keyboard_input: Res<ButtonInput<KeyCode>>,
) {
if keyboard_input.just_pressed(KeyCode::KeyD) {
info!("Key D Input Pressesd");
}
if keyboard_input.just_released(KeyCode::KeyD) {
info!("Key D Input Released");
}
}
Added this system in FixedUpdate Schedule and can see the "Input Pressed" and "Input Released" in the logs
Alright! So for now here the inputs work!
They started working when I removed DeltaScale : also worked when I removed DeadZone::default() - but dont work when i used them together
was just trying it out so i dont think i need deadZone anyways
thanks for your help @sharp warren !
If you run your logic inside FixedUpdate, you probably want to register your input context inside FixedPreUpdate.
that makes sense, thanks for pointing it out!
Ah, looks like you had inputs even in the first log. But DeadZone dropped the value:
2025-07-29T09:19:26.727484Z TRACE bevy_enhanced_input::context::trigger_tracker: `Negate { x: true, y: true, z: true }` changes `Bool(true)` to `Axis1D(-1.0)`
2025-07-29T09:19:26.727597Z TRACE bevy_enhanced_input::context: reading value `Axis1D(0.0)`
2025-07-29T09:19:26.727689Z TRACE bevy_enhanced_input::context::trigger_tracker: `DeltaScale` changes `Axis1D(-1.0)` to `Axis1D(-0.0168728)`
2025-07-29T09:19:26.727780Z TRACE bevy_enhanced_input::context::trigger_tracker: `DeadZone { kind: Radial, lower_threshold: 0.2, upper_threshold: 1.0 }` changes `Axis1D(-0.0168728)` to `Axis1D(-0.0)`
For biderectional movement you don't need a DeadZone, yeah.
yeah! I saw them interacting together got Axis1D to 0
bet bet thanks!
Is it possible to use enums like in lwim?
I'm thinking the ability to have a clump of enums for each game mechanic as required would be suitable.
No, you need to use separate types because enums doesn't play with observers.
Just put them close to each other if they are related.
I see. Can't be helped then.
Separate types are way better, you will like them when you try it π
Maybe action bundles should work how bevy bundles work (if they don't already), where required defaults of components are already added if not edited.
Also, there seems to be no fmt implementations.
Also, can observers have all the operators as functions like run_if?
They are Bevy bundles, so I'm not sure what you meant.
What do you mean?
Like how if you don't specify a Camera next to a Camera2d, or OrthographicProjection, it'll just give a default one behind the scenes.
implementations for cargo fmt, you can do that so that it formats however you like.
Should be Display::fmt
(I think)
Actions already utilize the required components. If you mean configure user-defined actions via required components, then it's not possible because you need to create a hierarchy.
Sorry, but I don't unrestand what you are talking about.
I see.
Can't find any other explanation to why cargo fmt does nothing to bevy_enhanced_input's stuff, so I figured it's that.
Since Actions are their own Component structs, wouldn't you have to derive Display or Debug on them yourself?
You mean it doesn't format the macro?
Display and Debug are completely unrelated to the formatting.
I don't seem to be able to apply run_ifs in observers
Nor Schedules
Do I have to use a resource or something and separate the function?
@graceful tapir mentioned Display::fmt, so that's why I thought that.
I wasn't sure that it was related to cargo fmt.
No, it's not related to it
And you unlikely need to derive Display or Debug on actions. It's just unit structs.
Correct, observers doesn't support run conditions.
You mean getting value from a regular system? You can just query for Action<C>.
It's all in the quick start guide.
I see. But are observers more optimal?
Alice has mentioned that this is observer-first.
Yeah, it's a preferred way to run small logic.
But sometimes you need a system, so we support both ways.
Would you use a system for player movement?
Depends. If you need to execute a heavy logic inside it - yes. Otherwise observers are more convenient.
So no performance difference?
As I said, depends. If you have a heavy logic, a system is faster. For a small logic observers are beter because scheduling a system has its own cost, which might not outweight the logic inside it.
But realistically for an input handling you want to use an observer almost all the time.
And then use a resource to use them in systems?
What resource?
bevy::prelude::Resource
I know what resource is, I asking which resource are you talking about
Make your own so that a system can access it
Is what I meant
I don't understand you π
@graceful tapir Just Query for the Action component you created.
Please, read the quick start guide first
Ah.
I thought it was one or the other is all
Ah, Apologies. What I meant by resource is if you want to use the result of input handling in systems.
since an observer doesn't have run_if or schedules
There is no resource. Actions are components, you can query their values in a system.
This is why I suggesting to read the quick start guide.
I'm aware, i'm talking about the result of input handling, like if you want to set the y velocity to jumpheight or a gravity function depending on if the player jumps.
Would you need to make a resource
Since observers are best for inputhandling
This could be a resource or a component, depending on what is more convenient for your use case.
If you already have a component on the player entity keeping track of that information, then just pull that into the observer as well and modify it based on the input. There are examples as well as the quick start guide that could give you ideas.
I really need to update my project with the new component based model so that I have more experience with it.
Or if you already have a system that moves the character based on whether itβs jumping or its movement vector, just query for action values instead.
We need an example with a character controller π€
I were thinking about re-creating Mario controls from SMW.
But currently busy with other things
I can add a simple example based on my code. You want 2d or 3d?
Doesn't matter π
But without physics to avoid pulling 3rd party deps.
Am I doing something wrong? are Cardinal\Axial bindings not suitable for bindings! macro?..
actions!(PlayerContext[(
DeadZone::default(),
Scale::splat(0.3),
Action::<Move>::new(),
bindings![ Cardinal::wasd_keys(), Axial::left_stick() ]
)]
Ok, I yield - I need to figure out new component approach before I do an example.
IMO it's not really intuitive. For example if I had lots of bindings I have no idea where to put Cardinal, Axial and others
Correct. Same like you can't use SpawnWith inside children!. That's just how spawning in Bevy works, it's not BEI specific.
It will be more convenient when BSN lands.
See https://docs.rs/bevy_enhanced_input/latest/bevy_enhanced_input/#presets for more details
Input manager for Bevy, inspired by Unreal Engine Enhanced Input.
oh, ok, I'll take another shot at this
Made a small post about my project, which mentions this crate too π
#1264625779296174110 message
I have a bit of an issue, in bevy_asset_loader, you can have loading screen via loading states that are attached to bevy states, in which you have to make sure a function runs only when it's in the after load state, meaning that currently input handling observers are seemingly impossible.
You may have to explain what you are trying to do. Why don't you hold off on creating the Input Context until the after load state is valid?
How?
I haven't played with bevy_asset_loader yet. How does it inform you that an asset is loaded? Does an observer get triggered?
I know how, nvm, and you just use run_if(in_state(state))
Ok, just to verify, you figured out what you need to do?
I haven't coded it yet, but I should be just about done with it.
Do you have to spawn the input context with the player?
@heady mauve
For player input
No you don't have to, but it might be easier to do what you want to do if it is.
That way the input contexts are only valid while the player exists. But you might also have input contexts that are only valid for menus so those wouldn't be associated with the player but when the menu exists.
Technically big_space root_grid is only for normal objects anyway
Spawning the player in it would be meaningless if it's the floating origin
I just realized that my setup function only runs after everything is loaded
so issue solved
Basically anything spawned in the same funciton as the input creation doesn't need run_if(in_state())
But just one issue
run_if(not(egui_wants_any_keyboard_input)) is required for anythign keyboard
Input manager for Bevy, inspired by Unreal Engine Enhanced Input.
Observers ignore states, right? So if I have a Paused state but don't want player input to activate during an observer is the easiest way to accomplish that to remove and then readd the bindings when transitioning into and out of the Paused state?
I'd just check the state inside the observer and early-return. I hope we will have run conditions for them in the future π
Seems like a lot of code duplication if I have a lot of observers though.
But what you suggest is also a good option.
Hm, agree
You can also remove observers, for example when you leave a state. If you abstract the details away (removing them is a little weird), then you can avoid a lot of boilerplate.
Hmmmm. Trying to use Cardinal::wasd_keys() and ran into an issue:
Cardinal::wasd_keys().with(Negate::x())
will crash with the following error:
Bundle (bevy_enhanced_input::binding::relationship::BindingOf, (bevy_enhanced_input::binding::Binding, bevy_enhanced_input::modifier::negate::Negate), bevy_enhanced_input::modifier::negate::Negate) has duplicate components: bevy_enhanced_input::modifier::negate::Negate
Moving the Negate::x() to the Action level doesn't crash.
Ah, I guess you can't attach Negate to Caridnal because it utilizes it internally.
technically you don't even have to do that if you can use a Single in your observer.
fn spawn(mut commands: Commands) {
commands.spawn((
Player,
OnFoot,
actions!(OnFoot[(Action::<Jump>::new(),
ActionSettings {consume_input: false, ..Default::default()},
bindings![KeyCode::Space])]),
actions!(MidAir[(Action::<Jump>::new(),
ActionSettings {consume_input: false, ..Default::default()},
bindings![KeyCode::Space])])
));
}
fn foot_jump(trigger: Trigger<Started<Jump>>, mut commands: Commands, player: Single<Player, With<OnFoot>>) {
println!("Foot Jump triggered on {:?}", trigger.target());
commands.entity(trigger.target()).remove::<OnFoot>();
}
fn air_jump(trigger: Trigger<Started<Jump>>, player: Single<Player, With<MidAir>>) {
println!("Air Jump triggered on {:?}", trigger.target());
}
The above will only print the Foot Jump line (and more importantly it will only do it once, despite leaving the binds and actions active), even though theres no logic to make it not trigger the air jump, and i have ActionStates non consuming so its not just OnFoot consuming the jump action, just the fact that the Single is empty.
I don't know why it works instead of panic'ing, but it does.
well it might start panicking in 0.17 π
Change the behavior of Single and Populated to fail validation instead of skipping systems. Users who want the skipping behavior can recover it by wrapping them in When<T>.
Honestly not even mad, bug becomes feature 
so wed just be adding When<Context> on everything
that issue just made me aware of Populated too, which i guess is more appropriate for the examples i used instead of Single 
@sharp warren i've been thinking about an input buffer feature, i'm not sure how technically difficult it would be to implement, but a high level overview of how it would work in a basic form would be this. action bindings can optionally contain a run condition system (like the run_if() function) and maximum holding ms (or frames), and when the input is triggered that condition it checked for, and if it's not met the action is added to a vec of queued inputs. each frame all the timers are ticked, and then if completed the input is deleted, otherwise the run condition is checked again, and if true then the action event is sent like normal
idk how run conditions work under the hood, nor sending input actions, but apart from that it seems doable
i might even open a pr if i can figure out those two things
I think this will break the action timings π€
And right now it's possible to evaluate input context in a fixed schedule, but are you suggesting to always use PreUpdate?
Wait, you are not talking about https://github.com/projectharmonia/bevy_enhanced_input/issues/106 ?
You just want to delay the input?
basically yeah
Ah, then disregard this π
i dont really understand what this is talking about, but yeah i think it's different
I think you can just create a modifier
It's about missing inputs when you run your actions as a part of a fixed update. I probably should change the issue title π€
ah
how can modifiers change timing? i thought they could only change the output value
Modifiers accept an input and output a value. I think you should be able to buffer the input and remember its timing (this info is available), but output the some old value.
What is your use case with the input delay? Just curious π
in platformers it's a pretty common feature to be able to input a jump a few frames before touching the ground, and for it to register when you actually touch it
Not just platformers. Lots of action RPGs let you queue up the next attack in a similar way!
Makes sense, but I didnβt expect it to be handled on the BEI side π€
Feel free to experiment with it, though.
what type would you suggest using to store the actions?
and then triggering them
You need to store ActionTime, ActionValue and ActionEvents components.
added simple character controller PR, let me know if you want to add anything
So far I have to say - there are quite a few rough edges with new component approach that can lead to a confusion. At least these two:
- with Cardinal/Axial only spawnable like this, not in macro
- if you add keys/buttons to
bindings!in a way other than [btn, btn] it will error out with a non-clear message. f.e.[(KeyCode::Space, GamepadButton::South)]which is what I though should intuitively work from children macro
Input manager for Bevy, inspired by Unreal Engine Enhanced Input.
Thanks! I submitted the review.
This first one is a Bevy limitation. That's just how Bevy macro also works, you can't use things like SpawnWith with the macro.
As for the second one, [(KeyCode::Space, GamepadButton::South)] won't work because you trying to spawn a single entity with 2 bindings, while it should be separate entities.
The reason the error is not super clear it's because unlike with children! I expect the first element to be Into<Binding>. Otherwise it would be inconvenient to write π
It will be much nicer when bsn comes.
Right now we are a little limited by the Bevy spawning ergonomics.
Do you think archetype invariants could help, too? I'm working on some APIs that work similarly. I'm a little worried that an inability to enforce constraints in a robust way with this approach will lead to lots of confusion.
Right? Like we lose the ability to provide people with compiler errors when we move towards a BSN-first approach.
bsn is a macro and a scene format. So you get compile errors when you use it as a macro and scene format is checked syntactically.
What I mean is that you can't guarantee people use the correct components in the correct places, just like oleks did with the bindings.
Oh but is your bindings! macro not a simple relationship like children!?
Ah, yeah, that's true. But it's unrelated to BSN then.
I think with the editor it will be less prone. Like in Unreal you have a special blueprint to define mappings.
It is, but with a small change:
It accepts Into<Bindings> for the first element for each entity. Just to avoid typing things like Binding::from(KeyCode::KeyW).
mmh i must say the BEI as components has not clicked yet for me.
In the process of converting from the old way. I have optional (e.g. no binding for an empty slot) and bindings with dynamic modifiers (e.g. depends on an ability/item/... equipped), all in a particular order. Having to cramp them into impl bundles runs me into some ergonomic issues. E.g. i can use ActionSpawner to dynamically (if) spawn (sub)bundles but than it triggers closure lifetime issues which requires clones for things that should not need it etc. Nothing unsolvable just a bit un-ergonomic. Are these the kind of issue you expect to improve once BSN lands?
Or maybe my design needs to be revisited.
Have you checked the updated bindings menu example? I updated it too and it shows how I'd handle this. It's just needs to be done a bit different than before.
If not, please, let me know what you think about this approach π
And I think you can replicate the old behavior by just spawning separate entities with ActionOf π€
I have to say I also stumbled upon the bindings![] error and I had to reread the docs (as I should have done before that ππ) but I like the new components system!
Is it a problem to have two input contexts at the same time on an entity?
@proud coral You can stack input contexts, set the ContextPriority to determine which ones consume inputs first.
oooh, it looks like I wanted to disable "consume_input"
for the way I'm using the lib
Because I have keys that trigger an Event depending on the State an entity is, and when it's on multiple layered states I want all actions to trigger, and then decide what I want to do with them based on the state/s I'm in
is there a way to make it a global default? Instead of having to disable it per action with
ActionSettings {
consume_input: false,
..Default::default()
},
I don't think so with Actions holding their own state. I suppose to make it easier you could save it as a Resource and then use that to set all the actions using it.
i've found out that bevy_tnua has a built-in input buffer, as well as a bunch of other cool features so i'm migrating to that
is there a way of running a function every frame but still connecting to bei? i assume it wouldn't work but like an Option<Trigger<>>
Yeah, we even have an example that showcases context overlay.
There are several options:
- Write a custom input condition that considers your state when deciding whether to trigger the action.
- Add or remove contexts based on the state.
- Create a constant for
ActionSettingsand pass it everywhere.
You can query ActionEvents in systems to check if the action was triggered this frame. The action value is stored in Action<C> and ActionValue in typed and dynamically typed forms, respectively.
Changed the org name. @outer wyvern
Could you update the link in the first message to https://github.com/simgine/bevy_enhanced_input ?
I know GitHub redirects, but only for a few months.
And the same for #1090432346907492443
That one points to crates.io so I think you're good already
Ah, right π
Thank you!
project harmonya got a final name?
I hope so! But this time I used links to crates.io just in case π
I made a small post about it: https://lemmy.ml/post/34012299
Background For those who donβt know, Iβm trying to create a FOSS life
simulation game β something similar to The Sims. I havenβt posted updates in
[email protected] [/c/[email protected]] about the project for a
while, only updates to the related crates I maintain. Itβs just me and my wife
didnβt have enough motivat...
I have pretty much looked at every example of BEI at this point :p I indeed ended up manually spawing each action (+ ActionOf) . How my code is currently structured is the item/ability/... decides the settings/components of its action/binding (maybe item A needs a key be hold down x seconds, while B is only needs to trigger on key up, ... or maybe some items require no action/binding) hence it is dynamic and proves hard in practice to compose a single "final impl Bundle"; closures of ActionSpawner also have implications.
Once i let go of trying to create a single impl Bundle the problems also disappeared. It is a bit more verbose but not that bad.
Thanks!
I should probably give manual creation of the entities a try.
I found the actions macro workflow "forcing" me to delete all the actions and bindings and remake them even if they are shared between contexts, when changing inputcontext to be... unsavory to put it bluntly.
it felt bad with the old way too, but atleast there since actions and contexts were coupled it was kind of ignorable.
But looking at the way the new api works, i guess theres no reason I couldn't just manually spawn an action, and then insert the ActionOf component for each context that uses it.
If you want dynamic actions, you need to compose contexts instead of rebuild or modify a single one. That's the point of the crate.
But we probably could add a way to disable contexts in order to avoid re-creating them π€
what do you mean by compose contexts?
Ive been thinking of contexts as states in an FSM, so the behaviours are whats tied to the context not the actions. Then to change the resultant behaviour of an action, I change the "state" of the "fsm" by inserting the relevant context, and removing the now invalid context.
Genuinely might just be thinking about it wrong and having a stupid moment ngl 
That said, having a way to disable contexts would be pretty neat.
inb4 contexts are entities
with a "ContextOf" component
You can have as many contexts as you want. Just split actions into multiple contexts and add or remove necessary actions by just attaching / removing contexts.
Of course, you can also manage actions dynamically, but depending on your use case, managing only the contexts might be more convenient.
Ah k yeah if thats the intended design I can see how that conflicts with the way I was trying to use it.
I was doing things like having a single Move action thats reused by any context that has some kind of movement behaviour, then writing systems/observers for each context
ContextPriorities I guess would be how I would get the behaviour im looking for, + making sure the binds are consuming
The advantage of managing actions is the ability to attach StateScoped to them to automatically delete the action when you leave the state.
Yes, that's the setup I would expect.
Is there anything for doing single axis input with a and d?
given that there's an f32 type for action_output.
Do you mean with WASD you just want the X, or side to side, axis instead of the 2D result?
But it's not merged yet.
Speaking of which, @outer wyvern, just a gentle reminder to take a look at https://github.com/simgine/bevy_enhanced_input/pull/150 π
yes
yep
out of curiosity why not just pull the Vec2 and just grab the X value from it?
Saving a single f32 value isnt going to make a terribly large difference performance wise.
Unless you want to bind W and S to something else that is.
It just looks cleaner in the code as to me.
valid tbh
I guess you could kind of jerry rig a franken action 
like make two f32 binds, for a Left and Right action.
then have an unbound "1d move" action, and just combine the values of the left and right binds in a mock to get the final value.
its more janky but you end up with the same "I just want an f32" api at the edge
Atleast until bidirectional is merged i mean.
Oh wait bidirectional is already in 15.2.
so he can just copy paste that preset into his codebase 
ignore me im overthinking stuff
Yeah, the PR just added a few convenient helpers.
Merged!
Thank you!
@weary maple @graceful tapir drafted a patch release with the mentioned methods.
on crates.io?
How do you capture mouse wheel input using the new api?
Have you looked at Binding::mouse_wheel:
https://docs.rs/bevy_enhanced_input/latest/bevy_enhanced_input/binding/enum.Binding.html#method.mouse_wheel
A an input bound to an Action<C>.
Tried, but it panics saying output value should be axis 2D
Even without the action that is fired by the mousewheel
Yes, because some mice not only have scroll forward/back but side to side as well. If you look towards the top of the page it mentions MouseWheel and how to handle what is returned:
https://docs.rs/bevy_enhanced_input/latest/bevy_enhanced_input/binding/enum.Binding.html#variant.MouseWheel
A an input bound to an Action<C>.
That worked, thanks
Now I'm convinced this is a compleely unrelated issue
Yep
Wow, this should never happen. Could you provide a minimal repro?
In my crates I use panics for things I expect to never happen.
It's really weird, I don't know why but I can't reproduce it. Maybe it's something I did in my main repo. I'll keep trying to find the bug
In the meantime, I suggest that the panic message be like Output value should be axis 2D, got X
What I did find, is that using Swizzling doesn't seem to work, here
https://github.com/Joakker/bevy-input-repro
finally trying to move from older version and I have a question: any ideas how can I add actions to already spawned context?
for example before I was doing it with just a cfg(feature, but we cannot do that inside children! yet. Here is an example for older code:
#[cfg(feature = "top_down")]
{
actions.bind::<ScrollZoom>().to(Input::mouse_wheel());
actions.bind::<RotateToggle>().to(MouseButton::Right);
}
but I cannot wrap my head around how to do it with newer approach
Is there a reason you don't want to have them as additional contexts you can layer on?
Also updating to the new API, so far loving it π
One thing that I believe must have a better way is this:
(
Action::<Rotate>::new(),
Negate::all(),
Scale::splat(DEFAULT_SENSITIVITY),
Bindings::spawn((Spawn(Binding::mouse_motion()), Axial::right_stick()))
),
That last Bindings::spawn call looks very verbose for something that seems very usual to do. Is there a way to make this work with bindings!?
Hmm, good idea ! I had a pretty verbose way of changing context in one system and tracking the current context, I guess splitting them up a bit would be nicer with no need to track it manually.
Yes, I'd go with additional contexts.
But you can also:
- Spawn an entity manually with
ActionOf - Use
SpawnWith.
I wish, but that's just how spawning works in Bevy.
children! macro also doesn't work with SpawnWith
heck
SpawnWith and presets like Axial are SpawnableList.
Interesting, I don't see a single issue about it in Bevy π€
I guess people rarely spawn related entities?
*outside of children π
Even children, they have the same problem.
I use SpawnWith to spawn children with observers on them
yeah but there you rarely run into that issue
Outside of things like this ^
Oh, or the 16 children limit
I believe that one also requires SpawnWith?
I guess people rarely mix regular children and SpawnWidth π€
I do, but it's hidden behind a function:
spawn(
children![
Node { something something },
button_widget("Foo", some_observer),
]
)
Where button_widget internally calls SpawnWith
But yeah I see how there's little BEI can do about that
Feel free to suggest!
Suggest what? π
How to work around this? No clue :/
Ah, sorry - I read it wrong. I thought you had a little suggestion π
button_widget returns a bundle?
yep
Ah, important, SpawnWith is used in an subchild
so that doesn't help in this case
At least, not without post-hoc adjusting the hierarchy
Would also be better if https://github.com/bevyengine/bevy/issues/19715 wash not a thing
Then you would have some more freedom in applying children! multiple times
Ah, got it :(
I'll keep looking for a solution. BSN would probably help.
But I think we need to adjust the spawning API in general...
Not sure how exactly it would help, but the extra flexibility wouldn't hurt in finding a solution
Maybe mention it in the BSN PR
Seems like a requirement that would be best to catch early
Good idea!
Link for your convenience: https://github.com/bevyengine/bevy/pull/20158
Thanks, mentioned!
not that i'm aware of, just have to use the macro or drop down to RelationshipTarget::spawn((SpawnXyz(), ...)) for more flexibility
other than abusing BundleEffect
That's exactly the issue; ::spawn is super verbose in this fairly common case: #1297361733886677036 message
You forgot to use bindings!
(
Action::<Zoom>::new(),
- SwizzleAxis::YXZ,
- Binding::mouse_wheel()
+ bindings![(Binding::mouse_wheel(), SwizzleAxis::YXZ)]
)
I starting to think we need to swap X and Y axes for the wheel π€
Who even use horizontal scrolling? π
Or provide a bundle
Maybe separate the axes? Most people use vertical scroll but still have a separate horizontal scroll binding? Like maybe mouse_wheel for regular and mouse_sidescroll for horizontal?
I have never seen a mouse that scrolls sideways, so that might be a good idea
I own one! π
Burn the heretic! π₯ π₯ π₯
Also apple mice have omnidirectional scrolls
Also, do laptop touchpad scrolls count as horizontal scrolls?
I think itβs more common than you'd think
Good question, they likely are seen as the same thing.
Ah, yes, I were thinking about the same thing, but forgot to write it down π
You probably want to use Binding::mouse_wheel().with(SwizzleAxis::YXZ)
Ok now I'm starting to think the crate is just not on my side
That might be a my bad. I didn't go to the docs to double check it was right.
Is fine, I'll try going ahead without this crate for now until I can really grok it
Weird, why it tries to create a Binding from Binding and Swizzle?
Here is the exact patch:
Just git apply <path/to/file.patch>
That's from pre-component era π
Ah, it's because of a comma after Swizzle! This is so weird π€
I will look into it. That's because bindings! are a bit special comparing to children!. In bindings! I try to apply Bindings::from for the first element to writing it for every binding. But it's quite hard to do with macro_rules correctly. Maybe I should switch to proc macro for this specific one. We have a macro crate anyway.
I do )
Don't worry, with the approach we planning, you will be able to use horizontal mouse scrolling too.
Although, I think it's cursed.
cursed? why? how? π
Hello
What do i do if i have put too many actions in the actions! Macro? I try to nest some of them in () but that just causes a crash.
My guess is that you'll have to go with the manual SpawnWith API, same as when you have too many children! 
Is this a macro_rules limitation?
Because there are no tuple impls, I woudn't expect any limits
the problem was more the trait than the macro (fake variadics), but the macro could be adjusted to work better with the trait (oh sorry wrong context)
You said "many actions". But actions are not components. You can spawn as many actions as you want.
Didnβt look into it, but youβre right, seems fishy
Ah, it's because of the RelationshipTarget::spawn that accepts tuples. I think I can copy a fix from the main.
Fixed it:
https://github.com/simgine/bevy_enhanced_input/pull/152
This also removes the need of wrapping single elements into braces when mixed with tuples.
Great!
Switched to related! internally, so when 0.17 comes, it will work automatically for BEI too. Thanks for the report!
I considered copying the macro from the main, but since the release is around the corner, I think itβs not worth it π
We thinking about setting ActionSettings::require_reset to true by default. I would like to hear opinions from other users of the crate.
I am scratching my head on how to translate this way of getting value to a new approach
let handle = if actions.value::<Crouch>()?.as_bool() {
Do you know the action output type at compile time?
If yes, then the most convenient is crouch: Single<&Action<Crouch>> and then let handle = **crouch;.
Implemented context activation/deactivation:
https://github.com/simgine/bevy_enhanced_input/pull/158
Binding::VertWheel and Binding::SideWheel. Each captures input for a different axis as Axis1D.
Users were incredibly confused because the most common case is vertical scrolling, which corresponds t...
I'll draft a new release once Alice reviews them π
Hi, i haven't done extensive testing, but it seems like the Actions relationship target might be getting updated every frame?
(not necessarily modified, but changed detection is triggered on it).
I just noticed that a system that has Changed<Actions triggers every frame
Ah, right... That's because I need to sort actions π€
I'm coming back to networking the new version of BEI; I got my problem of switching from one ActionState component to multiple components working (although it's a bit brutal https://github.com/cBournhonesque/lightyear/pull/1151/files#diff-ff31fe36f056472edc4156635f518657425cbbd635046c91818104db4d1302a0R60).
I have a couple of flows in mind:
-
user spawns Context + Actions entities on server, and replicates them to the client. On the client, the user adds Bindings (or an InputMarker) to the action entities. I think I need to replicate
Action<A>so the user can identify which action entity corresponds to which action, so the user still has to register each action type to the registry.- one issue is that ideally the user wouldn't have to spawn Action entities on the server, since inputs are mostly a client side concern
-
user spawns Context + Actions entities on the client, and adds bindings to them. I send an InputMessage which holds something like
Vec<(Entity, (ActionState, ActionValue, ...))(the Entity is theActionEntity, and the values are the snapshot needed by the server to reconstruct the actions).
The issue is that with this design, the server doesn't know which Action entity corresponds to which InputAction, so I would also have to send some extra data likeAction<A>, and have custom logic on the server to add theActionOf+ theAction<A>entity on the client. I cannot do that directly via replication because I don't want to add the Replicate component on the client entity
I guess I can have a special BEIInputMessage that is distinct from my normal InputMessage.
The InputMessage contains Vec<(Entity, ActionState)> and is used to transmit the steady-state stream of inputs.
The BEIInputMessage would be used to transmit the hierarchy of Context<>Actions from client to server + add the Action<A> component on the server action entities
I think the first approach is fine! Server doesn't need to know anything about bindings, but it does need to know which actions to use since their logic should run on the server as well.
But I don't think you need to replicate Action<A>, I'd expect you to replicate entity mappings from the client one time to know which entity corresponds to which.
But I can try to fix it if needed.
@sharp warren there's a couple more complex PRs in the BEI queue
I've seen them, but I'm not going to be able to dedicate time to them today
And may not be able to for a bit due to the 0.17 Bevy release
Didn't even expect to get reviews on weekends π
Sure, take your time!
The activation/deactivation PR may look big diff-wise, but the first commit contains a few relevant internal renames. The implementation itself is very straightforward.
The second PR just splits MouseWheel field into 2. But we can't decide on naming.
After that I'll draft a new release, no more changes planned.
If you want, I can split out the renames and just rebase the PR after the merge (I few of these renames are needed).
Went ahead and split it: https://github.com/simgine/bevy_enhanced_input/pull/161
We decided to replace the second PR with simple documentation improvements.
it would be nice to avoid this as I have some systems that rely on Changed<Actions>
I think i need to replicate Action<A>, or at least spawn it on both client and server, because that seems to be what inserts ActionFns and ActionFns is needed to trigger events
Maybe that's niche, but should the update system use Option<InputReader> so that it would still run without InputPlugin? (and users would update inputs via mocking)
I'll take a look into it.
Answered in DM, but I'll duplicate it here just in case π I'd expect both the client and the server to spawn contexts, since they know which actions they use, and then map them to each other.
It's a good suggestion, I'll open an issue!
Ran into another input accumulation issue, caught by a user :/ https://github.com/janhohenheim/foxtrot/issues/418
Bit unfortunate to be forced to change another push-style to a pull-style
I realize there's nothing BEI can do about this until we have timestamps
Just a bit sad that the push-style is a bit of a footgun when working with character controllers right now :/
this works, but holy moly thats a lot of stars π
crouch: Single<&Action<Crouch>>,
...
let crouch = ***crouch;
let handle = if crouch {
let crouch = *crouch.into_inner();
In general, into_inner() is very useful when working with Single π
foo: Single<(&A, &B)>
then
let (a, b) = foo.into_inner();
Doubly sad since I believe that the push-style API design is extremely neat
Yeah, I also prefer the push-style π
One day I'll succumb to the temptation of writing a character controller that internally accumulates inputs so that users can just use BEI normally and don't need to know about this
But so far, I've successfully fended off that particular yak shave haha
Or we find a brave soul to implement timestamps for Bevy input π
There's a very specific proposal floating around, maintainers are broadly on board
We just need someone to actually implement it
I don't feel qualified at all for this though, otherwise I'd have done it
Yeah, not an easy task...
Is it still blocked by the non-send stuff?
#input-dev message
should be doable-ish
After some discussion in DM, we agreed on this solution:
https://github.com/simgine/bevy_enhanced_input/pull/166
I would also appreciate user opinions on this one:
https://github.com/simgine/bevy_enhanced_input/pull/158
Looks helpful to me. So for example you could build a Player entity with 2 contexts (InGame, InMenu) and swap between the two by selecting which one is active?
I would use it when merged as currently I have a context that I am cycling on/off quite fast based on inputs and this would probably be more effecient
I would love that for when my player dies
Yep!
Thank you all!
Will draft a release once Alice reviews π
While debugging I find that it would be helpful if I could instead ActionOf<C> in the egui inspector
Would you be ok with a PR that defines a trait Context: Component + Reflect? or (Component + TypePath)?
This will require Reflect derive for each action...
Maybe just manually call .register_type::<ActionOf<C>>?
It doesn't work; compiler asks for TypePath to be implemented on C
oh you mean in my code?
yep, this works
Yes
I wonder if with automatic reflection we can automatically get the registration if the action marker is reflected π€
I think automatic reflection doesn't work with generics; we'll see
I think you are right.
But I remember there was a suggestion to automatically register on use in a system, which would work for generics. But not sure if the team decided against.
Reviewed all open PRs π
Thank you!
Going to sleep, will draft a new release tomorrow after job.
any thoughts on a macro for defining a context + all of its actions more concisely?
something like:
input!(
#[input_context(priority = 5)]
context PlayerInput {
Move(Vec2),
Jump(bool),
MouseAim(Vec2),
Dig(bool),
Interact(bool),
}
);
// =>
#[derive(Component, InputContext)]
#[input_context(priority = 5)]
pub struct PlayerInput;
#[derive(Debug, InputAction)]
#[input_action(output = Vec2)]
pub struct Move;
#[derive(Debug, InputAction)]
#[input_action(output = bool)]
pub struct Jump;
#[derive(Debug, InputAction)]
#[input_action(output = Vec2)]
pub struct MouseAim;
#[derive(Debug, InputAction)]
#[input_action(output = bool)]
pub struct Dig;
#[derive(Debug, InputAction)]
#[input_action(output = bool)]
pub struct Interact;
the set up of the actions/context are prob the biggest friction point for me
Have you looked at the new system? That looks like the old stuff before the Component rework. Check out version 0.15 for the new stuff.
o no I probably haven't seen it, lemme check it out
ok ya this looks much nicer! ty @heady mauve π
To grab an action value, for example the amount of mouse motion i had in that frame. I need to query &Action<CursorMovement> as per
fn apply_input(
jump_events: Single<&ActionEvents, With<Action<Jump>>>,
move_action: Single<&Action<Move>>,
mut player_transform: Single<&mut Transform, With<Player>>,
) {
// Jumped this frame
if jump_events.contains(ActionEvents::STARTED) {
// User logic...
}
// We defined the output of `Move` as `Vec2`,
// but since translation expects `Vec3`, we extend it to 3 axes.
player_transform.translation = move_action.extend(0.0);
} ```
Correct?
that will return the given vector
@sharp warren I made a TPS game camera if you want I can make an example displaying how to do it using your api
I would like that!
Yep
We already have a fly camera example π€
I'm not sure if TPS adds something new. I think all sorts of camera examples related more to bevy_camera.
Definitely useful once we upstream the crate for bevy, just not sure about adding it to BEI
Is it a pull style using systems instead of push using observers? Having examples of both might be helpful in that case.
Ah, good point. Agree, an example for it would be awesome.
Do you think the return type of the macro actions! is a little chonky. I have multiple times where I build my InputContext and I used to do a simple helper impl like this.
On 0.16 now it keeps returning the SpawnableRelatedBundle which is rough π do you perhaps knwo any other way Mr Shatur
impl PlayerInputs {
pub fn default_input_map() -> Actions<Self> {
let mut actions = Actions::<Self>::default();
actions
.bind::<Move>()
.to(Cardinal::wasd_keys())
.with_modifiers((DeadZone::default(), SmoothNudge::default()));
actions.bind::<Jump>().to(KeyCode::Space);
actions.bind::<Dash>().to(KeyCode::ShiftLeft);
actions.bind::<Interact>().to(KeyCode::KeyT);
actions.bind::<Attack>().to(Input::MouseButton {
button: MouseButton::Left,
mod_keys: ModKeys::empty(),
});
actions.bind::<NextWeapon>().to(KeyCode::KeyE);
actions.bind::<PreviousWeapon>().to(KeyCode::KeyQ);
actions
}
} ```
Not sure if I get you.
It's identical to children!, which returns impl Bundle.
Are you creating different action sets within the same context? Or something else that requires you to separate out the action bindings from the Context bundle creation?
Oh my god, so I can just return impl Bundle?
and call it ah man i just learned something
I think the context switch example shows exactly that.
it does
And I just found out that now
Darn. I was kinda hoping you had a unique use case that would have been interesting.
no sir just good old avoid repetitive code
@sharp warren I finished the example just let me know if you want it in. This is a sample in one of my game sub-crates
Yeah, if you use pull-based approach, that's exactly what we need!
Okey dokey
I ran into a problem where I wanted to be able to press an action to interact with ui, an the ui element can't handle clicks on it's own, but I don't the player doing an ingame action while they're interacting with it, so I thought maybe something like action layers would be a good idea?
Because input handling libraries exist so that you don't have to do pressed() || pressed() && pressed() and then copy and paste it several times, however there doesn't seem to be a way to avoid it in this scenario.
You can layer contexts on top of each other and @sharp warren recently added the ability to deactivate contexts so that you don't have to remove them. Can you describe what you are trying to do a little more?
For example, are you doing something like a quick time event where something pops up on the UI and you want the user input to do something during that but the input would otherwise be used for different actions? If so, adding another context layer specific for those events with a higher priority should consume those inputs if received. Although you could also inactivate the current context and activate the QTE context instead.
Perhaps look at the context layer and context switch examples.
Can you only have one layer active at a time?
You can have multiple context layers, and the highest priority layer with a valid action binding for an input will consume the input (unless you set it not to).
Awesome, thanks.
Sure, look into the context layer example and if you have any questions about it, let us know.
According to the docs, the bidirectional stuff (I searched for ad_keys specifically) is in 0.15.3 so if you are pulling at least that version you should have it.
everytime I do cargo add it justs adds 0.15.2
maybe I have to remove then add it
Have you tried cargo update after changing the version?
Everytime I do that it seems to update the dependencies of cargo.toml dependencies and breaks it in the process
Try specifying the package specifically you want to update:
cargo update --package bevy_enhanced_input
I forgot to add tpscontext
spent 30 minutes trying to do layering
today is not my day
You mean registering the context?
Yes, it's available since 0.16:
https://crates.io/crates/bevy_enhanced_input
Is there any way to set a global bind without the need of an inputcontext?
I guess not, the context_switch example has the same binding for opposite actions.
Also in this case I just want to overlap one action of the player context on switch
A way you can have "global" binds is by layering contexts on each other and any input not consumed by contexts on higher priority layers will be available for lower layers. So you could have a Global context that uses the Escape key to show a pause menu and still have a player context with a priority above that which doesn't use the Escape key in any actions. Pressing Escape will still let you see the pause menu then.
See the context layers example for something like that.
I'm spawning Bidirectional according to bidirectional.rs and it's not working
(Key_.into())
Try doing this instead and let me know if it works:
Bidirectional {
positive: Binding::from(KeyCode::KeyD),
negative: Binding::from(KeyCode::KeyA),
};
Replace the KeyCode::Key with whatever key you are trying to use.
@graceful tapir Did you have any luck or still working on it?
Apparently 2 contexts can be active at the same time.
The other option is to do it like this:
let bidi: Bidirectional<Binding, Binding> = Bidirectional {
positive: KeyCode::KeyD.into(),
negative: KeyCode::KeyA.into(),
};
By explicitly saying what you want to turn it into it knows what to do.
Therefore I can just divide the needed inputs into one.
unreadable tbh
Yeah, you better use Binding::from.
Apparently the compiler doesn't like this
Combat,
actions!(
Combat[
(Action::<Attack>::new(),bindings![MouseButton::Left, GamepadButton::West],),
]
),
We can't help you without you providing us with the compiler error.
Unfortunately the only meaningful error is that component isn't derived for combat, which it is.
Compiles just fine for me:
let mut world = World::new();
world.spawn((
Combat,
actions!(
Combat[
(Action::<Attack>::new(),bindings![MouseButton::Left, GamepadButton::West],),
]
),
));
#[derive(Component)]
struct Combat;
#[derive(InputAction)]
#[action_output(bool)]
struct Attack;
Apparently I had to wrap every inputcontext into a tuple for it to work.
If you spawn multiple components (like the context and its actions), you need to wrap the spawn into a tuple.
@sharp warren Here is the sample of the plugin I wrote, I think I will need to adjust from avian to meshcast but besides that is pretty much it. It does use the so called pull style
We might need to remove the raycasting from the example completely. You don't have character movement anyway, right?
I can make it shorter for sure could also make a simple character that is followed around your choice
It's more like a suggestion π
I think if we had movement, checking for collisions would make sense.
I had to do a double tuple
One more thing: I think it would be nicer to apply smoothness using BEI instead of lerping manually.
@vague temple Also looks like your lerping is not quite right in general π€
You need to use half decay
That's what BEI uses
A type with a natural interpolation that provides strong subdivision guarantees.
I think I was doing this weird way because when collision happenz i want it to snap to it. Dont know wrote that code one year ago
Guess I could just do the shapecast chonkier hoho
How do I get the entity target from bei without a trigger?
With pull-based API? When you query the action, there is ActionOf<C> component.
Example?
Because I want to make certain contexts inactive based on conditions.
You mean how to query multiple components?
wdym by pull based api
When you Query to get the state of an action.
But if I wanted to set a context inactive without needing a trigger how would I do that?
ActionOf<Context>?
I'm not understanding how it's supposed to be used.
Just Query<Entity, With<Context>>
And insert ContextActivity<Context>::INACTIVE.
Also, forgot to answer: you don't need to do a double tuple.
@sharp warren Smooth nudge feels a little unresponsive
although it is smooth indeed
Pr on the way with finished sample
You can configure it to your liking.
It's basically just calls smooth_nudge, no magic.
yup
Works when both contexts are set respectively, but when set to reversed values (inactive, active to active,inactive) the second context remains active which shouldn't happen.
I'm going according to context_switch.rs btw
to be exact:
if scrollvalues.hovered {
commands.entity(*combat).insert(ContextActivity::<Combat>::INACTIVE);
commands.entity(*scroll).insert(ContextActivity::<Scroll>::ACTIVE);
} else {
commands.entity(*combat).insert(ContextActivity::<Combat>::ACTIVE);
commands.entity(*scroll).insert(ContextActivity::<Scroll>::INACTIVE);
}
context_switch works just fine, so I assume something is wrong with your code
Thank you, will take a look soon
Yeah contextactivity is a little bugged, when inserted only Started<> will make the boolean true
I don't understand what you're saying.
We have tests for context toggling and the switching example works as expected.
But feel free to submit a minimal example to reproduce the issue.
As in it will only register me clicking once if contextactivity is involved
But i'll debug a little more
I also didn't find what was wrong with my code in regards to the previous issue
It seems the inputs are overlapping somehow
When I switch between fired and started for Attack, the other input for another thing is effected
keep in mind the trigger is just for a function that prints something
nvm
It still just has to do with switching activity
I'm aware that you said that the context_switch works, but in this case i'm using 2 entities grabbed from both input contexts
pub fn should_stop_attacking(
scrollvalues: Single<&ScrollValues>,
combat: Single<Entity, With<Combat>>,
scroll: Single<Entity, With<Scroll>>,
mut commands: Commands,
) {
if scrollvalues.hovered {
commands
.entity(*combat)
.insert(ContextActivity::<Combat>::INACTIVE);
commands
.entity(*scroll)
.insert(ContextActivity::<Scroll>::ACTIVE);
} else {
commands
.entity(*combat)
.insert(ContextActivity::<Combat>::ACTIVE);
commands
.entity(*scroll)
.insert(ContextActivity::<Scroll>::INACTIVE);
}
}
I will need a full example with clear steps what to do in order to reproduce.
The best way would be to submit a failing test.
Unfortunately everything else is by the examples, when I remove this, i'm able to have the other input with the same binds fire continuously, otherwise, it's for every time you begin a click.
I can give you a few functions just incase though
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
I will need a complete example, otherwise I won't be able to help.
Those 3 functions are the only 3 I could possible figure to be the perpetrators.
So i'm thinking it's a bug with ContextActivity.
Maybe it just doesn't like being inserted into inputcontexts.
I mean that I need a stripped-down version of what you currently have that I can compile and run in order to reproduce the problem.
wdym by stripped down?
I.e. without extra things.
Just copy the project and cut things as much as possible, leaving only things relevant to BEI usage.
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Can you just upload in a form of archive here (including Cargo.toml), so I can just cargo run it?
Looks like you're using plenty of 3rd party libraries here.
And I will need steps to reproduce. Like "press here", "click there", etc.
How can I do that?
temp github page?
Just select the folder, archive into .zip (or whatever) and drag'n'drop here.
Ah, that's what you meant.
This doesn't look like a stripped-down version of the game. It even contains assets. I need you to remove everything unrealted to BEI, so I can try to debug the problem on my side.
And I need steps to reproduce.
Ah, sorry.
And I mean to not just remove assets. Try to remove extra code. Ideally it's just a single with simplified logic that still triggers the issue.
Going to sleep right now, will take a look tomorrow. Or maybe other folks will take a look earlier.
Thanks! Now I need steps. I.e. instructions what do I need to do π
Q to open the "Scroll". click to place "symbols" down. If all works correctly, "oof" should only be printed when your mouse is not hovered or clicking the area that the scroll takes up, and holding click should paint a stream of symbols. This is currently not happening as when switching scroll and combat input contexts' activity, you can do neither.
This includes when the scroll is not present as well, "oof" should be printed.
Honestly, I still have absolutely no clue what is happening on the screen.
Also, you run your should_stop_attacking every frame.
Which means it will reset the context
While I still not sure what is happening, I think it's the source of your problem.
the "scroll" is in the middle of the screen when you press Q. when you click in that area, black squares will appear. if the square hitbox isn't touching the symbol, you either have to have it touching it or have the circle hitbox not touching another circle hitbox.
That could be btw.
That's probably why only a trigger is used in context_switch to insert the contextacitivity.
@graceful tapir You may want to look into the bevy::picking module. It would allow you to get the hover state with an observer so you aren't running a system every frame but using that observer to change the ContextActivity
You can insert in a regular system too, just check the value before the insertion.
bevy::picking it is.
None the less that phenomenon needs to be looked into.
As to why it does that when contextactivities are inserted multiple times or inserted into contexts.
Just to verify what you are saying here if you use a system then altering the ContextActivity triggers a rebuild of the Context so it's state is reset? So to avoid that you must check if the Context entity already contains a ContextActivity with the value you want to set it to.
Maybe a panic would do for that.
Yes. More specifically, when you insert INACTIVE every frame, it markes all inputs that require reset as consumed even if it wasn't previosly active already.
Interesting.
I wonder if we can handle this π€
But I can't get the previous and current value to properly check it.
It is using hooks for OnInsert or OnReplace, right?
I'm getting the hover state using egui from an egui image.
Triggers, just because we don't handle invariants, just regular crate logic.
Ok, it might be a little more complex but you could insert or remove a marker component from the entity when it is hovered.
Now that I think about it, systems don't run if they can't find anything in any of their queries.
So that might be better than boolean spaghetti code.
Can we use a Query with an Option in the deactivate function to see if there is an existing ContextActivity and get the value if there is one?
Or does that happen after the ContextActivity is replaced?
OnReplace is before, OnInsert is after.
and check in bevy::picking whether the component exists?
And in both cases I can't have both.
But I think I have an idea...
The bevy rabbit hole is quite deep... I didn't even know those 2 schedules/queries existed.
I'm starting to think bevy is designed against any indirection.
Don't need bevy::picking if you are using your own marker component. I didn't realize that the hover was from egui, so if you had rolled your own solution then bevy::picking might have been an option.
If the entity the context is on already exists you could just insert it on that entity. Although, if you are doing it based on the hover state of something you might want to put it on the entity that is hovered over in case you want to check for other things associated with that.
So just to clarify, I need a marker component because of how the OnReplace and OnInsert schedules work for contextactivities?
No, you can use a marker component to trigger two functions that you create, one for it being added and the other for it being removed, to change the ContextActivities instead of a system that runs every frame. Look into Component Hooks in the bevy documentation and the component_hook example they have.
Although Shatur might have a solution in process for the inputs being reset whenever an INACTIVE ContextActivity is inserted.
Still would recommend to avoid running such system every frame
You can also check if scrollvalues changes and then run the system via run condition.
Just for calrity and performance reasons
Is everything in this example what you would need for this task?
https://docs.rs/bevy/latest/bevy/ecs/component/struct.ComponentHooks.html
World-mutating functions that run as part of lifecycle events of a Component.
I'm guessing TrackedEntities isn't needed
You can also use triggers, which is more high-level
How do I do that in this case?
Not that i'm against using componenthooks.
Look at these:
https://docs.rs/bevy/latest/bevy/ecs/prelude/struct.OnAdd.html
https://docs.rs/bevy/latest/bevy/ecs/prelude/struct.OnRemove.html
Trigger emitted when a component is inserted onto an entity that does not already have that component. Runs before OnInsert. See crate::component::ComponentHooks::on_add for more information.
Trigger emitted when a component is removed from an entity, and runs before the component is removed, so you can still access the component data. See crate::component::ComponentHooks::on_remove for more information.
You're saying I could use a component hook to cause a trigger?
Those are the events that can be triggered in observers as an alternative to doing the lower level component hooks.
@sharp warren Might I ask why does the macro actions, require the filepath bevy?
[{
"resource": "/home/sirmadeira/Projects/psycho_duel/crates/psycho_core/src/player.rs",
"owner": "rustc",
"code": {
"value": "Click for full compiler diagnostic",
"target": {
"$mid": 1,
"path": "/diagnostic message [0]",
"scheme": "rust-analyzer-diagnostics-view",
"query": "0",
"fragment": "file:///home/sirmadeira/Projects/psycho_duel/crates/psycho_core/src/player.rs"
}
},
"severity": 8,
"message": "failed to resolve: could not find `bevy` in the list of imported crates\ncould not find `bevy` in the list of imported crates",
"source": "rustc",
"startLineNumber": 43,
"startColumn": 16,
"endLineNumber": 43,
"endColumn": 55,
"relatedInformation": [
{
"startLineNumber": 169,
"startColumn": 11,
"endLineNumber": 169,
"endColumn": 15,
"message": "Actual error occurred here",
"resource": "/home/sirmadeira/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bevy_enhanced_input-0.16.0/src/action/relationship.rs"
}
],
"origin": "extHost1"
}]```
I have a modular style of imports
only grabing specific crates of bevy
does "lower level" imply faster?
Because depending on bevy is less evil π
For more details, see: #engine-dev message
I don't know enough about the engine to be able to say for sure. But lower level isn't always associated with faster. Sometimes it is something that is more complex to do but often in more powerful ways. If a Trigger<OnAdd> or Trigger<OnRemove> works in observers for your case so you don't have to learn how to use component hooks, then I'd say go with that. If you find you are having difficulty with accomplishing what you are trying to do, then you might need to look at other options like using a component hook directly.
Agreed. Afterall observers are best for inputs, and hovering is technically an input.
Or at least inline with one.
Good argument, gonna refactor my code now
hahahaha
Wait, but what if I wanted to check which inputcontext the component is added to and trigger then?
You can include another query in your observer that pulls the input context entity you are looking for and see if the entities on the query and trigger match.
I lost 400 lines of code due to that slight change
I was doing 400 lines of code more because of compile time?
Yeah not worth it
Yes, but also less convenient. I usually use them to uphold invariants.
I think it'd be more efficient to use marker components for each individual context combo.
I assume since triggers are slow, component hooks aren't?
Per on_?
Yep
If that makes more sense to you then that should work as well.
Another question: What is the advantage of using the conditions instead of doing the modification myself? Is there any perfomatic gain?
Can you do queries in component hooks? I'm guessing not.
No gains, just convenience.
You can use World::query
What's the best way I would prevent a component from being added more than once since that's the issue with contextactivity?
Just check the previous value of the component and don't insert it
Use an option style query:
context: Option<Single<Entity, With<Scroll>>>,
If the query comes back as None, then there shouldn't be a component with it.
Then does that solve the multiple contextactivity issue?
I think he wants to have them both
There is no issue with multiple contextactivity. You just insert multiple times the activity component which causes the input to reset.
Right, that wouldn't work if there is an ACTIVE ContextActivity on the entity.
Not sure if I get you
Then I don't understand why i'm using componenthooks.
It would still find ContextActivity whether it is set to ACTIVE or INACTIVE, right?
Correct
To avoid inserting the same component every frame
But if @graceful tapir is using a different marker component, then that would take care of the issue.
would it be necessary to enable require_reset?
Or rather, how would using component hooks fix that?
So instead of looking for the context, look for the marker:
marker: Option<Single<MarkerComponent>>,
I don't understand the question
from ActionSettings
No, it's entirely unrelated
Then how would component hooks fix the issue?
What do you want to hook??
I don't want contextactivity to be added every frame
The problem: you disable/enable the context every frame.
The solution: don't do this.
There are a ton of options how would you do that.
Pick whatever works for you
I'm aware, but i'm not entirely sure how to go about this since there are many options.
Pick the easiest
Probably the simplest would be to check the current value. If the context is already active/inactive, don't insert active/inactive again.
@graceful tapir Have you tried doing something like this:
fn scroll_hovered(
trigger: Trigger<OnAdd<ScrollHovered>>,
scroll: Single<Entity, With<Scroll>>,
mut commands: Commands,
) {
if trigger.target() == scroll.entity() {
commands.entity(trigger.target())
.insert((
ContextActivity::<Scroll>::ACTIVE,
ContextActivity::<Combat>::INACTIVE,
));
}
}
fn scroll_lost_hovered(
trigger: Trigger<OnRemove<ScrollHovered>>,
scroll: Single<Entity, With<Scroll>>,
mut commands: Commands,
) {
if trigger.target() == scroll.entity() {
commands.entity(trigger.target())
.insert((
ContextActivity::<Scroll>::INACTIVE,
ContextActivity::<Combat>::ACTIVE,
));
}
}
Wait...I think I need the marker component in there. (Now added)
This is probably the best case scenario. No point in going any lower level if the logic is this light.
Wherever you check egui for whether a scroll is hovered you will then add or remove the ScrollHovered component to the context entity you put the Scroll context on.
Perfect. Just to clarify, triggers aren't duplicated in logic when 2 or more observers share the same trigger right?
What do you mean by duplicated in logic? As far as I know if multiple observers are looking for the same trigger event, they will all run. But you mentioned having different marker components for different contexts, so only the observers for the correct marker component would be triggered.
OnAdd doesn't take generic arguments apparently
I may have the order reversed. I typed it quick.
Ok, should be more like: trigger: Trigger<OnAdd, ScrollHovered>
Is this good btw or could I be more elegant with it?
if image.hovered() {
commands.entity(*scrollcamera).insert(ScrollHovered);
} else {
commands.entity(*scrollcamera).try_remove::<ScrollHovered>();
}
in regards to "try_remove"
@sharp warren In your review you told me to make player look at where camera is pointing, a funny issue I ran intoo while doing this in multtiplayer is that in thesis server doesnt have a camera. So I need to buffer the input before hand. Any ideas on how to do that?
You can create an entity first from commands.entity(*scrollcamera) and then use it in both blocks.
I think you can just do the regular remove
But honestly, I'd just check the status of activity in your case π€
I.e. without the trigger.
I think you can have a component that stores the look direction on the server.
thing is it is a predicted entity, perhaps I can use mock in this scenario
Server doesn't predict anything.
Hmm but if my predicted entity is rotating, perhaps server should instead be validating where the rotation would go no? Is there a way to "fill" an empty action?
wait perhaps I can insert an action? an this is confusing
Wouldn't I need a system for that?
fn buffer_rotation(
q_camera: Query<(&Transform, &CameraMode)>,
mut players: Query<Entity, (With<PlayerMarker>, With<Predicted>)>,
mut commands: Commands,
) {
let (transform, camera_mode) = q_camera.single().expect("Camera to have a transform");
// Only do this if in tps mode
if camera_mode.ne(&CameraMode::Tps) {
return;
}
let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
for player in players.iter_mut() {
commands.entity(player).insert(ActionMock::new(
ActionState::Fired,
Vec2::new(yaw, pitch),
MockSpan::Manual,
));
}
}```>
I think this works
I'm referring to back when you said checking if it's hovered every frame is bad so don't use s system
Why do you need to validate the rotation? In your game you can't rotate freely?
Yep
I meant to avoid inserting every frame.
What is ScrollHovered in your case?
Is this a custom component you insert from a system you run every frame? In that case, I'd just directly work with context activity.
In what way?
I mean I could just use componenthooks if that's what you mean, if it's truly a concern.
my game is competitive, also to guarantee server player is looking at where client player is looking
The solution I came up is not ideal, but I guess it will work. I made it so we have a empty Action, with an ActionMock. I later query that entity Action, and keep adding mock with the rotation value given by camera
Never mind, do whatever works for you π
If you need to take a break on this that's fine, I just want to get to the bottom of this.
As my game will be quite performance sensitive.
I'd recommend creating a working prototype first, then try to optimize.
I can of course advice what is faster, but most of the time I don't understand your questions π€
For now, if it's not specifically intended to use a trigger, but requires one or can use one, component hooks it is.
I will follow your advice.
@sharp warren Gonna leave it here just for your design opinion, I convert my inputs to states and i utilize those states for physics and animation what do you say Master Shatur?
Ai says that is a good idea
I'm wondering what the best way for equipping items from a hotbar or something similar would be. Making an action for each slots sounds like a lot of code duplication
right now I just map each key to a different 1d scalar value, but it feels pretty hacky
Feel free to experiment and let us know π
I think using separate actions could also work, just make their logic generic.
Yes, this sounds a bit hacky π But it's a clever workaround, actually.
Wait! Can't you spawn multiple entities with the same action, but different bindings? π€
I.e. create a single action and attach it multiple times to the same context.
This way you shouldn't have any duplicaton. And in order to detect which slot triggered, attach your own component on each of this action with slot index or something.
Yep, just added a test to ensure it's possible:
https://github.com/simgine/bevy_enhanced_input/pull/174
Realized we don't provide information about the action entity that triggered an action.
But that's nothing a quick PR can't fix: https://github.com/simgine/bevy_enhanced_input/pull/174
@glad hawk you can try this branch - this should unlock the use case I mentioned.
This is my replacement for the trigger system tsudico thought of.
pub fn should_attack_setup(world: &mut World) {
world
.register_component_hooks::<ScrollHovered>()
.on_add(|mut dw, context| {
let combat = dw
.query(&mut dw.try_query_filtered::<Entity, With<Combat>>().unwrap())
.single_mut()
.unwrap();
let mut commands = dw.commands();
commands.entity(combat).insert((
ContextActivity::<Scroll>::ACTIVE,
ContextActivity::<Combat>::INACTIVE,
));
})
.on_remove(|mut dw, context| {
let combat = dw
.query(&mut dw.try_query_filtered::<Entity, With<Combat>>().unwrap())
.single_mut()
.unwrap();
let mut commands = dw.commands();
commands.entity(combat).insert((
ContextActivity::<Scroll>::INACTIVE,
ContextActivity::<Combat>::ACTIVE,
));
});
}
It apparently does nothing to solve the issue. I'll try his trigger system as well.
If you insert the component every frame, it would still have the same effect. Are you checking to see if the egui hover state has changed since the last frame?
No.
Nonetheless it's on_remove and on_add
So I guess technically.
Could you add some logging to that? Either before or after you change the ContextActivity for both you might want to temporarily add an info!("ScrollHovered Added") and info!("ScrollHovered Removed") to check whether it occurs every frame or not.
Yep, it works.
What works? Does the log show it changing every frame or does the log show that it only changes when the hovered state changes?
Actually there's a bit of an issue.
It doesn't do anything until you first hover over it
Then it adds ScrollHovered every frame when it is, and removes it when it isn't.
So I would definitely alter the place where you check egui hovered state to see if it is already hovered and only insert or remove the component when the hovered state actually changes instead of checking the state every frame and doing something depending on that state without keeping track of whether it changed or not.
Although if you don't want to do that, you could go with what @sharp warren suggested previously and just check to see:
- if the ContextActivity exists on the entity and if so
- what value it is set to so that you aren't changing it every frame but only when an actual change occurs
Whichever is better for you.
How would I only check if it's been changed?
The egui hover state or the ContextActivity?
hover state
technically contexactivity would be better
I think it would be easier to check ContextActivity. The hover state you'd probably either need a Local State, Resource, or Component to hold the value. ContextActivity already exists so you can check it directly.
Are you already using a query with the Context to get the entity? If so you could just grab the ContextActivity as well:
scroll: Single<(Entity, Option<&ContextActivity<Scroll>>), With<Scroll>>,
then you can check whether ContextActivity exists and if so, what value it has in case you need to change it.
I had to make some changes to my query to make it valid.
Don't I have to add "ACTIVE" and "INACTIVE" for both contexts in one of the contexts like in context_switch? Wouldn't that mean ContextActivity always exists with whatever it's added to? Or does it work differently?
It probably doesn't have to be an option since I think it is a required component of Context so will always exist.
Do local variables have a way to only trigger when they change?
/check when they changed
vs just being set over and over again
That would most likely fix the entire issue
I think there should be a better implementation for dealing with contextactivity in the future in my opinion.
oh neat, that's pretty cool!
I don't think a local system variable would improve things. It just adds another thing to track. I looked at your should_stop_attacking function and here is an implementation that appears to do what you want. Let me know if it makes sense:
pub fn should_stop_attacking(
scrollvalues: Single<&ScrollValues>,
combat: Single<Entity, With<Combat>>,
scroll: Single<(Entity, &ContextActivity<Scroll>), With<Scroll>>,
mut commands: Commands,
) {
// First we check if the scroll hovered matches the context activity
if scrollvalues.hovered == **scroll.1 {
// We return if they are the same
return;
}
if scrollvalues.hovered && !(**scroll.1) {
commands
.entity(*combat)
.insert(ContextActivity::<Combat>::INACTIVE);
commands
.entity(scroll.0)
.insert(ContextActivity::<Scroll>::ACTIVE);
info!("Scroll Hovered");
} else if **scroll.1 {
commands
.entity(*combat)
.insert(ContextActivity::<Combat>::ACTIVE);
commands
.entity(scroll.0)
.insert(ContextActivity::<Scroll>::INACTIVE);
info!("Combat Active");
}
}
Don't get it. Isn't hovered a boolean and scroll.1 just ContextActivity?
One moment, I spotted a bug in the PR π€
Will fix soon.
Internally, ContextActivity represents ACTIVE and INACTIVE as a boolean, but since the field is private you have to dereference it to access.
Well the function fixed the timing issue, however the action Attack still triggers when it's hovered despite it's input context being inactive.
Maybe it should follow the context_switch example and give both contextactivities to one input context?
I think the issue is that when pressing the mouse button egui takes that as pressing the entity and so removes the hover state from the entity. This switches the context. If you try with a gamepad, the same situation doesn't happen.
I'm not well versed in egui so don't know of a possible solution to that.
Not quite, as that was one of the issues to begin with, and it still only plots one symbol at a time instead of a stream, so inputcontexts might be still out of touch somehow. As well as you have to use bevy_egui's "egui_wants_any_pointer" function which can be used for run_if and whatnot.
Maybe a redesigning of this is in need.
aaaah
I know why it's plotting one at a time
hovered and clicked states can be true at the same time
so i'll have to add a ||
Still no, odd.
Because I noticed ScrollHovered would be printed as active every time I click.
alright it required image.contains_pointer
now everything works fine
Thanks for all this
With that being said, if that was the issue, would my first solution be ok?
When it comes to issues that might be related to egui, that probably is better for bevy_egui. I have no knowledge of how bevy and egui interact.
I meant the one that just check hovered and inserted based on that
I'll see if it works
It works, but something tells me that inserting every frame is laggy, as well as Attack for some reason doesn't trigger when the scroll is turned off. I think a little maintenance should fix that.
@sharp warren Perhaps it would be nice to make it so we can prioritize one action above another, I know there is a way to prioritize contexts. But i can see some scenarios where an action should have a higher consumption prio (should occur first) than another. I can make the PR just wondering if that is okay by you. For example: I want to jump but to jump I need to disable my push to floor forces. Oddly specific but that is what I ran into.
I do believe actions are prioritized according to the order in which they appear (as long as they don't use any modifiers). So if you have an action you want to be able to consume an input prior to another action then you just need to list it before the action you want to have a lower priority with.
What do you mean by list it?
Write it first in the code, or if you procedurally generate the actions somehow, you'll need to make sure that whatever you do that action is generated first before the other action.
Correct. Actions evaluated by their spawn order.
Ah I see so for example: Move action is logged in first -> than jump action, move occur first to jump
Unless some of the actions has a binding with bigger amount of modifiers. Then BEI automatically re-prioritizes it.
Another question: Is it still possible to read the actions that are inflicting the target entity (player)? Like hey this was the actions that occurred on player recently component.
No, but I working on exactly this feature right now π
Also @glad hawk ^
I'll draft a new release right after merge.
O next update that is gonna avoid some 20 lines of code ( i habe quite a complicated char controller)
This was accidentally merged due to GitHub configuration. Once Alice answers, I'll draft a release.
So perhap prio actions should be a thing right? As that is quite counter intuitive
Also I think this little accident was cause by me hehe
sorry
Automatic prioritization is useful because you may not know the right ordering at compile time (when bindings assigned in settings, for example).
I'm open adding an additional explicit priority which overrides the automatic prioritization and ignores the action ordering, but I would like to hear a use case first π
Could be π
Looks like it accepts any approaval, not just from collaborators
I ran into one right now, in summary, I would like to guarantee input consumption ordering by still utilizing observers. So I can avoid the constant usage of the "pull style" (which is what I am currently doing).
Here is my case:
A player in my game can dash, but while dashing I do not want to apply walking force. WIthout constrained ordering. I lack determinism causing a rollback (server does dash walking), client(walking dash). Is worth noting my dash is a constant force due to gameplay reasons. (i like floaty dashes)
There are other scenarios, for example: I have a float char, while jump I need to ensure jump occurs first to apply grounded force. Or the same occurs
Oddly specific but hey you know my game is cool hohoh
But the ordering is deterministic. You just need to place your actions in the order you want.
Grounded is not something given by input, is a consequential scenario. Given by collisions
Do you want to reorder your actions based whether the character is grounded or not?
I think you won this argument, now that I think about it if my actions are guaranteed to be ordered in boot up I just need to do a simple comment.
ah
pain i will have to refactor again
gosh darnit
Also if you want to completely disable some actions, you can split into multiple input contexts.
wait no, that doesnt ensure my grounded state scenario. It does fix my walk dash for sure
I'm still open adding the mentioned feature if it simplifies things. It's just not something I tried myself, so I need feedback of users who run into such use cases.
I think the multiplayer deterministic scenarios like stun and so on would still require it, althought they are extremely specific and pull style got it handled.
Could you elaborate?
Here is how I see the feature: we can add ActionPriority and if it's present, use this value during sorting. If not, use the amount of modifiers as the value.
It's a very simple change. But! I think explicitly putting indices is less nicer then ordering your actions correctly.
The way I see when it's useful for dynamic ordering. But I need to hear a use case for it.
I predict my entity will be moving at timeline x+3, but then I get stunned by an ability. That should immediately disable my walking action. The problem is that move is applied through an observer, so I canβt guarantee when it runs. As a result, I might still process a walk input for one frame while Iβm actually supposed to be stunned, which creates a clientβserver mismatch.
The same issue shows up with dashing: the dash needs the walking input from the current frame to determine direction. If I read the wrong value because of update order, the dash goes in the wrong direction. Worth noting I can order them in boot up (but it feels ifei you mentioned the conditions change ordering)
Again technically this exists, but I dont think that is the approach you want with your API (you groove the observers)
I don't see how adding ActionPriority solves the issue at all.
Your issues looks completely unrelated to the priority.
All events triggered in the action evaluation order. So action observers are ordered.
so I canβt guarantee when it runs
Observers triggered inEnhancedInputSet::Apply. So just schedule your system after it and it will run after observers.
yeah I saw that in the docs about now
HAHAHA oh well refactor again
@sharp warren One last question: ( Action::<MoveInput>::new(), DeadZone::default(), Bindings::spawn(( Cardinal::wasd_keys(), Axial::left_stick(), )), ), (Action::<RotateInput>::new(),ActionMock::new(ActionState::Fired, Vec2::ZERO, MockSpan::Manual)), (Action::<JumpInput>::new(),bindings![KeyCode::Space]), (Action::<DashInput>::new(),bindings![KeyCode::ShiftLeft]),
I have the Deadzone condition, will that make move run first or dash?
No, no, only keyboard modifiers (ModKeys) affect the ordering.
Like Shift, Ctrl, etc.
how do you bind ui? my other input is OnAdd for the player, but in the main menu that doesn't exist
I bind a context to the root entity in the UI.
i'm gonna temporarily use the built in input to have a universal command
but the universal command probably won't exist later
then later i'll bind separately to teh player and to the ui
Not sure if I get you.
But you can have separate contexts for your UI and player
Just spawn your UI together with its context.
yeah i know, i'm just putting this in to set up the main menu
@outer wyvern I'll need you response on this one:
https://github.com/simgine/bevy_enhanced_input/pull/175#issuecomment-3193891265
All good, drafting a new release?
Yep, I'm fine with that
Great, sorry for the confusion π
@glad hawk @vague temple the release with action entity inside events is up.
It's not a patch-release since I added a field. But no annoucement this time, the release is too small.
@thick kiln should be just a version bump in Cargo.toml for you ^
sweeet thanks!
I'll try it out once I am done with all the other stuff I still have to do
AH
How would one do an axis like chord? E.g. holding a button and moving a stick, but outputting the stick's value to the action?
Create 2 actions: for the stick and for the button.
Then attach chord modifier to the stick which references the button.
So the following should work?
let zoom_lb = context.spawn((
Action::<Chord1Action>::new(),
bindings![GamepadButton::LeftTrigger]
)).id();
context.spawn((
Action::<ZoomCameraAction>::new(),
Chord::single(zoom_lb),
bindings![GamepadAxis::LeftStickY]
));
Yep
Nice, ty
works perfectly!!
much cleaner than my previous solution
thanks a bunch
Great!
It would be nice to have a runnable example for newcomers...
If you have some free time and can extract your code into a small example, I would appreciate a PR π
Hmm. One thing I noticed that if you want to check multiple actions inside the system - you have to derive Component. but for observers you don't, I do not understand why yet.
Hope it is reflected in docs, because it's somewhat confusing
I also got caught by the Actions<T>(old way) vs Action<T> in systems. nasty
any idea why my Navigate action always [0,0] using wasd? for example Crouch queried the same way works.
UPD: Interestingly enough, if I add arrow_keys they work
#[derive(InputAction, Component)]
#[action_output(Vec2)]
pub struct Navigate;
#[derive(InputAction, Component)]
#[action_output(bool)]
pub struct Crouch;
(
Action::<Navigate>::new(),
DeadZone::default(),
Scale::splat(0.3),
Bindings::spawn(( Cardinal::wasd_keys(), Cardinal::arrow_keys(), Axial::left_stick() )),
),
(
Action::<Crouch>::new(),
bindings![KeyCode::ControlLeft, GamepadButton::East],
),
// query in system
navigate: Single<&Action<Navigate>>,
crouch: Single<&Action<Crouch>>,
...
let (navigate, crouch) = (*navigate.into_inner(), *crouch.into_inner());
Shouldn't be necessary to derive Component π€ Can you provide a minimal repro?
Maybe WASD consumed by other actions?
done (:
heya @sharp warren I created a Cooldown input condition for my game and pushed a PR with it if it might be wanted by others, really appreciate the library so wanted to contribute back β€οΈ
Thank you, glad you like the crate!
Left a review π
To set manually the Axis2D value, I would have to use mocking?
Also the triggers seem to be triggered on the Context entity, but in the pull-mode (looking at the components directly; I would have to pull from components on the Action entity)? I think i need to use pull-mode because i'm handling 2 Actions in the same system
@sharp warren I've got a Binding for AnyKey/Button/Whatever we decide to call it working with an example of assigning gamepads. But it currently has to be the last action because I haven't figured out a good way to do consumption. Do you want me to put a Draft PR together so you and possibly Alice can look it over and provide feedback?
To set manually the Axis2D value, I would have to use mocking?
If you want to manually set any value, you need to use mocking, yes.
the triggers seem to be triggered on the Context entity, but in the pull-mode (looking at the components directly; I would have to pull from components on the Action entity)?
Yes. If you need the context entity, it's available viaActionOf<C>.
Sure, feel free to open.
But it's necessary to figure out the consumption logic. My expectation: it should go first and consume all buttons.
Like "Press any key to continue" should trigger first and then user should remove the context/action.
Would it be a good idea to insert automatically the Context component on the parent, if we spawn ActionOf<Context>? Or is that something that's already done?
Not done currently. But as for my taste it's too implicit.
but would there be a situation where that's incorrect? or should the context component always be present?
To switch contexts we don't remove/re-add the component, right?
The context component should be inserted because the BEI associates several required components with it during registration.
To switch contexts, you can either deactivate it with ContextActivity<C> or remove the context component (but donβt forget to despawn actions).
See context_switch and context_layering for each approach, respectively.
Ok thanks; i'll add the Context component on the ActionOf parent automatically then; it would be easier for me to have that when ActionOf is replicated
ah actually I might not be able to, since Context doesn't necessarily implement default
But why do something like this? π€
When replicate the context entity, I'd expect the context to be a required component for some other gameplay component (i.e. it will be inserted automatically on replication) or replicated with the entity. And actions just deterministically spawned for it, like a scene, you just need to map them properly. Or are you trying a different strategy?
Hm maybe; it's ok I found another solution
@outer wyvern I saw you approved #182, could you also check #180 ? It's tiny, half of the lines are tests.
I've gone through several iterations of this and still can't get it to require the chord.
let right_mouse = context.spawn((
Action::<Chord1Action>::new(),
bindings![MouseButton::Right]
)).id();
context.spawn((
Action::<CameraMoveAction>::new(),
Chord::single(right_mouse),
bindings![Binding::mouse_motion()]
));
This ends up firing with the mouse motion alone, without requiring the right click to be pressed. Am I misunderstanding how the chord is supposed to work?
The only version I've seen in the docs is one with 2 ids in the chord without any bindings.
This version also does not work, but results in no mouse motion at all
let right_mouse = context.spawn((
Action::<Chord2Action>::new(),
bindings![MouseButton::Right]
)).id();
context.spawn((
Action::<CameraMoveAction>::new(),
Bindings::spawn((
Spawn((
Binding::mouse_motion(),
Chord::single(right_mouse),
)),
)),
));
Wait, this may be because I had an additional different action bound to right click.
Yeah, that was it. I assumed that I could freely bind multple actions to the same input, but I assume they're getting consumed?
Yes, but you can disable the consumption
You could put the chord dependent action prior to the other ones. It would only be able to activate if the chord was active then.
You can also use logging to debug this kind of issues, see the troubleshooting section in the quick start guide
@sharp warren Thanks for the help getting that PR over the finish line.
Thank you too for the submission π
Will wait for reviews from Alice for 2 last PRs and I'll draft a new release.
If I remove input context from an entity, its triggers still get called.
Looks like a bug, v0.17.0
How are you removing the context?
commands
.entity(entity)
.remove::<Flying>();
I think it needs to be done a different way to fully remove the associated required components and related actions.
I dont want to remove actions, I only want to temporarily disable context
If you just want to disable the context, look at ContextActivity
I think the context_switch example was updated to use it.
Thanks, it works
Also in the docs
Inserting [`Self::INACTIVE`] is similar to removing the context.
Not similar, though
If you want, you could open a PR if you have a better, more understandable, way of wording it. As more people use BEI it becomes clearer where in the docs need work.
You just removing it wrong, you need remove_with_requires.
Wait, what? Does it remove only required components of the specified components or recursively?
It remove the component and it's required components:
https://docs.rs/bevy/latest/bevy/prelude/struct.EntityCommands.html#method.remove_with_requires
A list of commands that will be run to modify an Entity.
So if A requires B, which requires C. Then it wont remove C, right?
It works with context though, thanks
I don't know actually π€
I think it would be better if Bevy used the same approach as with despawn
Yeah
We no longer need to remember to call despawn_recursive.
What problem does this solve or what need does it fill? In https://github.com/simgine/bevy_enhanced_input we need to tell our users to remove input contexts using remove_with_requires instead of ju...

