#leafwing-input-manager
5297 messages Β· Page 6 of 6 (latest)
here's the "patch" if anyone wants this behaviour early π (and the gist)
is there no way to use same button for 2 different actions depending on press duration without hardcoding it?
hmm, why does leafwing bring in the default bevy setup? I added it to my server (which uses a minimal set of bevy features only) and for some reason it now includes all the graphics stuff as well
Double check its features
That shouldn't be happening but maybe there's a bug?
oh, I guess I need to diable ui
Ah yeah that would do it
what is the action type to detect mouse movement? @karmic monolith
i want make the character rotates
A DualAxis action iirc
okie, but like for move i use VirtualDPad::wasd()
what would be the mouse one?
i cant find on docs
like with .with_dual_axis(CharacterAction::Rotate,idk wich one is here)
Probably something with Mouse in the name π€
i didnt find anything lol
have a lot of options but neither of them seens right
Hmmm, docs.rs seems to have failed building so I can't see the latest docs ... At least I remember the right thing being it's own type, tho I haven't migrated my game to to 0.15 and thus haven't used the latest LWIM release yet, so it might've changed
your game looking fire brother
hope you can do it
did the docs for lwim 0.16 not build?
Yeah I think they failed π¦
Im considering making a plugin to create input prompts for bevy using xelu's free prompts, possibly with a feature to work with leafwing. Would this be something worth doing or is there already a crate out there to achieve this?
I don't think I've seen this before!
Kenney has some good assets to use too
i was thinking about doing the same thing but then i realized i'd want to account for rebinding and availability/cooldowns and decided to procrastinate instead π¬
#crates and Bevy Assets when you're ready π
just xelu and keycodes for now and i didn;t want to embedded_asset! every file individually so there's a concerning workaround
there is an example for scroll to zoom but can i do that in a way that respects mod_picking? so when i scroll with my cursor on the map its different from scrolling with my cursor on a scollable ui
I'm looking into whether this would be a good fit for my game. The readme mentions being able to "control the state this plugin is active in". That sounds appealing for not triggering a bunch of behaviour when a level isn't loaded, but I haven't been able to identify that in any of the examples. Am I missing something or is it just referring to the disable/enable methods on ActionState, and I should manage those manually?
Also, should the egui feature flag automatically enable consuming actions when an egui context is hovered? That is what I understood the feature to do, but it seems like the action (bound to left mouse) is still triggering.
Could be a egui versions mismatch.
I'll check that!
Yep, that fixed the egui issue, thanks!
Hi @karmic monolith ! I've just released an rc version of bevy_egui. Just wanted to give a heads-up on the change that will affect this crate.
bevy_egui has (finally) got its own implementation for absorbing inputs: #369, #373. It's not enabled by default, and there are two different options for users two opt in: either add run conditions (that bevy_egui exposes) for their systems or set a global flag which will enable a system that clears Bevy input buffers.
The latter is basically what leafwing-input-manager has been doing when a user enables the egui feature.
But now we don't want to have a situation when there are two crates that possibly reset Bevy input buffers (either bevy_egui or leafwing-input-manager will likely just break, depending on the system ordering). I see there are two possible ways to go about this issue:
- just remove the
eguifeature altogether and expect the users to use the global flag I mentioned - instead of mutating the Bevy input resources, adopt the run conditions approach, and add the run conditions when the
eguifeature is enabled (or give users some other API to customise and provide their own run conditions, not sure how feasible this is though)
I think the latter should be a better option, since it leaves users both options to chose from. Not every user may want 3rd party crates meddle with the global Bevy input state, which is why I was hesitant to enable this behavior in bevy_egui by default in the first place. For them, the run conditions approach might work better. I hope this makes sense.
Let me know what you think or if you have any questions, I'll try to support with any info you might need for the migration
Does LWIM modify Bevy's input resources?
I thought it just skipped reading them if egui claimed the input.
I think Bevy itself needs a proper focus system π€
Having input crates depend on UI crates creates many issues.
Yeah, it does:
https://github.com/Leafwing-Studios/leafwing-input-manager/blob/90e80af0d38d045f406b1bca034ced93f09c3d70/src/systems.rs#L126-L137
I just stumbled upon this yesterday, when I wanted to make some custom hotkeys for my interface in Egui, and leafwing-input-manager was consuming them because one of the text fields was focused π
I remember there is a longstanding issue about that.. not sure if there were any recent updates though
Interesting, I didnβt know!
In bevy_enhanced_input (the input manager crate Alice and I are working on), we donβt modify resources - we only skip reading inputs when egui or bevy_ui claims them.
btw, now you can use the EguiWantsInput resource to read wants_keyboard_input and friends without the need to borrow the EguiContext mutably
Yeah, we havenβt made any progress on this yet π’
I hope weβll have something by 0.17 - at least a resource to report whether the keyboard or mouse is being used, as a temporary workaround. Itβs not a proper solution, of course, but it would still be better than depending on UI crates.
Cool, thanks! I will wait for bevy_inspector_egui update before updating the version.
@karmic monolith can you please remind me how to use InputMap::new() with an heterogenous collection of inputs? The compiler doesn't manage to infer the impl ButtonLike of the iterator, so I think I need to cast the first item of the slice to a trait object but I can't remember how π
Actually it's impossible, because new() takes impl Trait and not something like &dyn Trait and we can't mix different types in a slice.
Unrelated; what's #[actionlike(DualAxis)] doing? I see it in examples but can't find anything in docs?
This is declaring which flavor of actionlike each variant is
Correct
Oh right because not all of them are buttons
I ended up chaining one with_multiple() per type, since there's only 2-3 of them that's 2-3 lists instead of one
So I assume there's somewhere some #[actionlike(tripleaxis)] too for example?
Yep that's correct
And yeah π
Ok thanks!
Small update: In bevy_enhanced_input, we've added a special resource to disable specific input sources (keyboard, mouse, etc.). We've left the integration with UI library of choice to users. This should pair nicely with the EguiWantsInput system you introduced π
We should probably upstream that resource in 0.17 (cc @crimson stream)
Then bevy_egui can write to it directly
the resource is definitely welcome! but I'm not entirely sure how to deal with the "priority" problem, because I don't think that we can always make an assumption that bevy_egui should take priority in absorbing inputs
btw, do you guys see implementing the same approach in LWIM as you have in bevy_enhanced_input?
I think we should, but I'm not prioritizing work on this crate right now
So if someone wants to PR that I'd be really happy to merge it
Right now we delegating it to users. But yeah, we definitely need a proper focus system.
Which we have the start of for 0.16 π
But yeah, this needs to be better integrated and fleshed out
I have thought about this, but not as much as some folks here. And I'm not as well versed in the specific needs of egui, LWM, enhanced, etc. I wrote up a doc a while ago, proposing something like an "input graph" - sort of like an animation graph, but for input events - but I realized later that this idea wasn't well thought out. Graphs are good for unidirectional flow, pushing events but not pulling. But for input you often need to pull / poll as well as push.
If you recall, I started a long thread a while back talking about the keyboard behavior of Kerbal Space Program, whereby holding down a key (for thrusting or turning) maps to different effects depending on which panel the mouse is hovering over (Blender has similar behavior). KSP is a useful example because it really pushes the envelope of what an input mapper's feature set should be.
Is the input_processing example meant to print anything when I press WASD on my keyboard?
Nothing's happening for me for some reason (I'm currently on the main branch)
same on the 0.15.1 tag
is bevy_enhanced_input the progression from leafwing input manager?
Yes, Alice and I are working on it.
awesome π
how can I manually override an action's value ? right now I am calling action_state.press(&action) at every frame, and it does almost work, however .just_pressed() returns true on every frame when keeping the input pressed. how can I avoid that ?
You should be able to access the underlying value: https://docs.rs/leafwing-input-manager/0.15.1/leafwing_input_manager/action_state/struct.ActionState.html#method.action_data_mut
Stores the canonical input-method-agnostic representation of the inputs received
Looking at the history of the crate it looks like at some point it was possible to use resources to collect global input from any gamepad:
https://github.com/Leafwing-Studios/leafwing-input-manager/pull/379
But not any more, from the changelog:
when no associated_gamepad is provided to an input map, find_gamepad will be called to attempt to search for a gamepad. Input from any gamepad will no longer work
Is this due to some limitation in new versions of Bevy or a design decision? Any suggestion on how to handle this input now (e.g. pausing the game)? The resources seem more ergonomic than iterating over entities for certain use cases.
thanks this helped
Is this due to some limitation in new versions of Bevy or a design decision
This was a design decision: the "any gamepad" behavior didn't line up with behavior in existing games I tested
and IIRC it was easier internally
i am trying to disable an action state with ActionState::disable() for a chat function, but its not fully consistent, about 10% of the time it doesnt disable or enable.
is there some system ordering messing it up? i dont know how to find out which systems the could be, im running disable() and enable() in the OnEnter(State) schedule.
will leafwing-input-manager release a version to support bevy 0.16 soon?
0.16 is supported on the latest main - you can pin the git version for now.
[Alice is currently sick](#engine-dev message), so we can't draft a new release yet.
Alternatively, you might try bevy_enhanced_input, which Alice and I are developing. The latest release supports 0.16.
thanks - i'll pin to get off the ground - and bevy_enhanced_input looks pretty good. It will be a lift to port to it but I like the ergonomics so it's probably worth the time
I think it's an opinionated question, but I'd prefer enum-centered approach to all actions instead of separate structs for each action, its the main reason I will always prefer leafwing input manager β€οΈ
Give separate structs a try.
Enums won't work nicely with triggers. Plus, this approach lets you split action logic across the codebase rather than centralizing everything in one place.
maybe someday, I do love your serialized toml settings exampleβ€οΈ
I think I might be confused one some things but if .set_axis_pair is for changing a DualAxis input how do you set a singular axis?
oh I can use axis_data_mut ok
what would be the proper way to insert my own Box<dyn Buttonlike> into an InputMap? the insert function creates a Box internally, so i must be missing something.
Is there a way to require a leafwing input map like auto add it for me?
ActionState should include into as a required component now
But I'm not sure if that's what you're asking?
I was just wondering how would I make CamerMode require the camera inputs component
#[derive(Component, Clone, Copy, PartialEq, Reflect)]
pub enum CameraMode {
/// A stationary camera, does nothing fancy just stand still
Simple,
/// Tps camera, a camera that follows around an anchor entity with the [`AnchorMarker`] component
Tps,
/// Pant orbit camera, a debug mode camera, usually used when wanna check your scene out
PanOrbit,
}
/// Inputs actions for camera
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Reflect)]
pub enum CameraInputs {
GrabCursor,
SimpleMode,
TpsMode,
PanOrbitMode,
}
impl Actionlike for CameraInputs {
fn input_control_kind(&self) -> InputControlKind {
match self {
Self::GrabCursor => InputControlKind::DualAxis,
Self::SimpleMode => InputControlKind::Button,
Self::TpsMode => InputControlKind::Button,
Self::PanOrbitMode => InputControlKind::Button,
}
}
}
impl CameraInputs {
/// Returns the default input map!
pub fn default_input_map() -> InputMap<Self> {
InputMap::default()
.with_dual_axis(Self::GrabCursor, MouseMove::default())
.with(Self::SimpleMode, KeyCode::Digit1)
.with(Self::TpsMode, KeyCode::Digit2)
.with(Self::PanOrbitMode, KeyCode::Digit3)
}
}```
So it auto adds him with the given inputmap
You should be able to use the #require macro here and pass in the default_input_map constructor π
I will give you a meme if you teach me how :>
I am quite plebeian when it comes to find required components examples
A data type that can be used to store data for an entity.
@karmic monolith I am a wizar now
π§ π₯
where's the meme? >:C
@karmic monolith
Your payment has been processed
is this an appropriate place to ask about a problem I'm having with the crate?
Yep π
okay, well I'm trying to use my input map as a resource an I'm following along with the example it's giving the error
error[E0277]: `fn() -> leafwing_input_manager::input_map::InputMap<core::input::Action> {core::input::Action::mkb_input_map}` is not a `Resource
#[derive(Actionlike, PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
pub enum Action {
#[actionlike(DualAxis)]
Move,
Jump,
Run,
AttackUp,
AttackLeft,
AttackRight,
Cancel,
#[actionlike(Axis)]
Camera
}
impl Action {
pub fn mkb_input_map() -> InputMap<Self>{
//create binding
InputMap::new([(Self::Jump, KeyCode::Space)])
.with_dual_axis(Self::Move, VirtualDPad::wasd())
.with_dual_axis(Self::Move, GamepadStick::LEFT)
.with(Self::Jump, GamepadButton::South)
.with(Self::Run, KeyCode::ControlLeft)
.with(Self::Run, GamepadButton::RightTrigger)
.with_axis(Self::Camera, GamepadAxis::RightStickX)
.with_axis(Self::Camera, VirtualAxis::new(KeyCode::KeyQ, KeyCode::KeyE))
}
}
.add_plugins(InputManagerPlugin::<input::Action>::default())
.init_resource::<ActionState<input::Action>>()
.insert_resource(input::Action::mkb_input_map)
and looking at the example I should be doing it right
https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/examples/action_state_resource.rs
.insert_resource(input::Action::mkb_input_map)
->
.insert_resource(input::Action::mkb_input_map())
You're inserting the function, but you need to actually evaluate it
okay thank you
is it not supported (system-ordering-wise) to call ActionState::press within a Pointer<Click> observer?
i'm seeing the code to call press gets reached but the code that runs on just_pressed does not
and it worked when the observer was an Update system instead
wait i think i remember seeing an issue about this..
nvm the issue contents are unrelated: https://github.com/Leafwing-Studios/leafwing-input-manager/issues/496
ah i needed to enable the picking feature on LWIM :)
how can I create an axis from the l/l1 and r/r1 buttons on my controller since VirtualAxis::new(GamepadButton::LeftTrigger, GamepadButton::RightTrigger), isn't working for me
(it doesn't even use the actual triggers)
action state that's just pressed don't have instant_started set; is this normal?
oh actually nevermind, i think it's because i improperly copied over the action datas
I'm a bit overwhelmed attempting a giant version migration
so forgive the dumb question but what's the current way to add a chord
let shift_left: InputKind = ShiftLeft.into();
let shift_right: InputKind = ShiftRight.into();
binds.insert(SaveWorld, [shift_left, KeyP.into()]);
binds.insert(SaveWorld, [shift_right, KeyP.into()]);
binds.insert(CameraToggleFollow, [shift_left, KeyC.into()]);
binds.insert(CameraToggleFollow, [shift_right, KeyC.into()]);
```hoping this is not it
Ok it's like ```rs
binds.insert(SaveWorld, ButtonlikeChord::new([ShiftLeft]).with(KeyP));
bad example because I didn't need .with here but w/e
I feel like I might stick to a builder pattern for consistency, though I wonder what this looks like when the user is configuring it rather than me hardcoding. it must all be different
@karmic monolith would you accept a PR to where i can create system Sets for the swap_to_fixed_update and swap_to_update systems so i can order against them?
Absolutely
ended up doing something slightly different: https://github.com/Leafwing-Studios/leafwing-input-manager/pull/703
Cannot map a DualAxislike input for action AvatarMove of kind Button
found prior discussion
Wondering if I should singleaxis my camera forward/backwards, or does that make it a triple axis π€ but there is also rotation
Fixed with the new actionlike attribute thing that I missed because I am drowning in migration guides
Is there any library that builds off LWIM to have some quick and dirty custom binds thing? I found a library on Google that reads from a pretty nice YAML format, but it doesn't appear to build off LWIM, instead just sort of doing similar things, so it's probably quite limited
and I'd probably prefer toml over yaml but w/e
teensy tiny documentation error π€
use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
/// Plugin for handling user input.
pub struct InputPlugin;
impl Plugin for InputPlugin {
fn build(&self, app: &mut App) {
app.add_plugins(InputManagerPlugin::<Action>::default());
}
}
#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
#[actionlike(DualAxis)]
enum Action {
Move,
}
fn spawn_input_map() {
let input_map = InputMap::default().with_dual_axis(
Action::Move,
VirtualDPad::new(KeyCode::KeyW, KeyCode::KeyS, KeyCode::KeyA, KeyCode::KeyD),
);
}
Diagnostics:
1. the trait bound `leafwing_input_manager::plugin::InputManagerPlugin<input::Action>: Plugins<_>` is not satisfied
the trait `bevy::bevy_app::plugin::sealed::Plugins<_>` is not implemented for `leafwing_input_manager::plugin::InputManagerPlugin<input::Action>`
you can use `cargo tree` to explore your dependency tree
required for `leafwing_input_manager::plugin::InputManagerPlugin<input::Action>` to implement `Plugins<_>` [E0277]
2. required by a bound introduced by this call [E0277]
And waaay more errors. What I am missing? This looks very minimal and close to the minimal.rs example.
I think you're supposed to put the actionlike attribute on the move variant, not as the enum as a whole
I'm guessing your Action being wrong cascaded to the thing using it being wrong
Whats a good way to do a input bindings controls Settings Menu with leafwing ?
I have tried to make a resource with a HashMap < PlayerAction, MyCustomButtonType >
where MyCustomButtonType impls -> To< dyn Buttonlike>
so then i try to do this
impl Into< InputMap<PlayerAction> > for PlayerActionBindings {
fn into(self) -> InputMap<PlayerAction> {
let mut map = InputMap::default();
// no vec so no sized ?
for (action, ui_control) in self.bindings_map.iter() {
let buttonlike = ui_control.to_buttonlike();
map.insert(action.clone(), * buttonlike);
}
map
}
}
but it throws an error saying the size of ButtonLike cant be known at compiletime so it wont compile
so what am i doing wrong? what am i missing? I m having real bad problems navigating around the fact that ButtonLike is a trait instead of a simple enum
how the heck do i dynamically build a InputMap ??? like from a resource..
ok i figured out a hack lol
#[derive(Debug,Clone,Hash,Eq,PartialEq, Reflect ,Serialize,Deserialize )]
pub enum UiControlNode {
Mouse (MouseButton),
Keyboard(KeyCode),
Gamepad(GamepadButton),
}
impl UiControlNode {
pub fn append_to_input_map<'a, T>(
&self,
action: T , //make this dyn ?
input_map: &'a mut InputMap<T>
) -> &'a mut InputMap<T> where T:Actionlike {
match self {
Self::Mouse(m) => { input_map.insert( action, *m ); },
Self::Keyboard(k) => { input_map.insert( action, *k ); } ,
Self::Gamepad(g) => { input_map.insert( action, *g ); }
};
input_map
}
using a match statement to avoid a Box
since box will never work since then it becomes unsized
I'm not sure what you're trying but a Box is sized
would it be possible to release this change? https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/RELEASES.md#unreleased
Sure; remind me tomorrow?
hi, its tomorrow
π«‘
Thanks alice-chan
hi, do we have any examples for ui?
i see it was deleted :(
actually i am seeing a lot of problems, i am assuming this is moving over to enhanced input?
Yes, we think BEI is the future.
It takes a completely different approach, which might seem a bit more complicated at first β but once it clicks, you'll love it.
That said, we donβt have a UI navigation example yet, if thatβs what you're asking π We'd definitely appreciate a contribution.
Or maybe keybindings?
Just FYI 90% of my game's CPU time is spent in possible_clashes()
Seems a bit excessive π That O(n^2) loop in there hurts...
Yeah, that doesn't particularly surprise me. How many actions do you have?
@bold lodge's simple priority based approach is probably more scalable
We could cache these
Actually never mind, that was a bug that resulted in way too many actions being added
Okay, I won't prioritize fixing this then. Thanks for updating me π
(I would welcome a PR to improve this if anyone tries, but I have other priorities on the engine itself currently)
What's the preferred way to conditionally disable certain mouse move input actions, but only the mouse? I have a dual axislike action that can be controlled by mouse and joystick, and when UI is on screen I want to suppress the mouse input for that action. But joystick should always work.
I have a very odd issue
When my game lags like running at 10fps, my walk input from leafwing arr βstickyβ and its insanely annoying
So that is to say, its like the walk commands ( holding w ) are being queued up so even when i let go of w my character keeps walking forward for 8 seconds
And whats really weird is all other things respond immediately like orbitting my camera w my mouse has no stickiness or delay or lag its perfect
Is this a known issue w leafwing ? Btw this is with a setup very similar to foxtrot
Are you using fixed update?
That will probably cause that behavior
Since you'll start getting extra fixed update cycles queued up
leafwing input manager is using almost 4ms per frame, how is that possible ?
what can update_action_state do during 2ms and why does it run twice per frame
I'm so confused
removing it effectively doubled my fps
the time is spent doing what looks like heavy allocations in possible_clash
ok sorry for the noise, it seems that was caused by memory allocation overhead due to trace_tracy_memory feature. after checking again there don't seem to be a problem
@old axle Good work with https://github.com/Leafwing-Studios/leafwing-input-manager/pull/714. I'm going to wait for the final 0.17 Bevy release and then ship it in a new breaking version if that's okay with you
does leafwing-input-manager make it easy to respond to 'Double Click' ?
or do i need to build my own low level solution for that ?
We don't have anything built-in for this right now
okay darn. Im trying t build it low level and it seems to be a gigantic pain
to make it hook in to this crate and play nice and stuff
I wish LWIM had the ability to dynamically preprocess the inputs in an application-specific way. I want to disable the "mouse move" input, but keep the joystick version intact, when a GUI window is open. Today I just gave up and split the action that the mouse controls into a "mouse version" and a "joystick version" and added app-specific checks that suppress the "mouse version" if the UI is open, but this felt inelegant.
I know there's some magic stuff specific to egui to do this in LWIM, but that's very ad hoc and inflexible.
You can dynamically control inputs with bevy_enhanced_input.
There are no built-in UI stuff yet, but it's easier to express stuff like you describing.
v0.19.0 is out π This is a technically breaking but very mild bug fix release, courtesy of community contributions. The big fix is for analog gamepad triggers, which were previously pretty badly broken.
https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/RELEASES.md
@jolly stream I've cleared the cache for CI and I'm rerunning it for https://github.com/Leafwing-Studios/leafwing-input-manager/pull/729
Bumping to the new RC and bumping the edition to 2024 to match Bevy which triggered some required changes and a bunch of clippy/fmt stuff.
@alice-i-cecile I looked at some old PRs but I'm n...
CI improvements are also welcome though
I saw there are several improvements for CI in the issues. It needs a good round of TLC. Maybe after the next release I'll poke at it
after clearing cache CI went swimmingly. After two weeks I think we can finally do a final review and bump to RC
Awesome; I'll ship it tomorrow
so I'm trying to store my input as a resource and I followed the example, but despite that I'm getting this error saying that the resource doesn't exist
thread 'Compute Task Pool (1)' panicked at /home/oreboat/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bevy_ecs-0.17.3/src/error/handler.rs:125:1:
Encountered an error in system `Pipe(project_yurimech::character::player::systems::player_velocity::set_player_h_velocity, bevy_pipe_affect::system_combinators::affect<core::option::Option<bevy_pipe_affect::effects::entity_components::EntityComponentsSet<(project_yurimech::character::components::Character,)>>, core::option::Option<bevy_pipe_affect::effects::entity_components::EntityComponentsSet<(project_yurimech::character::components::Character,)>>, ()>)`: Parameter `Res<ActionState<PlayerAction>>` failed validation: Resource does not exist
If this is an expected state, wrap the parameter in `Option<T>` and handle `None` when it happens, or wrap the parameter in `If<T>` to skip the system when it happens.
//----------------------------player/resources.rs-----------------------------
#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
pub enum PlayerAction {
#[actionlike(DualAxis)]
Move,
Jump,
Attack,
}
impl PlayerAction {
pub fn mkb_input_map() -> InputMap<Self>{
InputMap::new([
(Self::Jump, (KeyCode::Space))
])
.with_dual_axis(Self::Move, VirtualDPad::wasd())
.with_dual_axis(Self::Move, GamepadStick::LEFT)
}
}
//------------------------player/mod.rs-----------------------------
pub struct PlayerPlugin;
impl Plugin for PlayerPlugin{
fn build(&self, app: &mut bevy::app::App) {
app
.add_plugins(InputManagerPlugin::<resources::PlayerAction>::default())
.insert_resource(resources::PlayerAction::mkb_input_map())
.add_systems(FixedUpdate, (
systems::player_velocity::set_player_h_velocity.pipe(affect),
));
}
}
//--------------------------player_velocity.rs----------------------------------------
pub fn set_player_h_velocity(
character_asset: Res<Assets<CharacterAsset>>,
player: Single<(Entity, &Character), With<Player>>,
input: Res<ActionState<PlayerAction>>,
time: Res<Time>
) -> Option<EntityComponentsSet<(Character,)>> {
if let Some(character) = character_asset.get(&player.1.handle){
let input_vector = get_input_vector(&input);
let velocity = set_velocity(character.acceleration, character.speed, player.1.velocity, input_vector, time.delta_secs());
Some(entity_components_set(player.0, (Character{handle: player.1.handle.clone(), velocity},)))
}
else {
None
}
}
I'm taking a look at this
This example has PlayerAction in thecurrent scope but the insert_resource refers to a resources::PlayerAction. Was this like a copy/paste thing? Or do you have two versions of PlayerAction?
no just one, it's just a copy paste thing and I forgot to indicate where separate files are
edited to indicate separate files
Are you trying to use the resource anywhere outside this plugin?
Gotcha. I'm afk right now but I'll look at it when I get back to my desk in a bit
Ohhhhhh it do be like that. Sorry I got roped into watching the finale of Stranger Things π
lol
28 but who is counting? Certainly not me π
For clarification I'm just goofin. I know you are busy. No rush π«Ά
The problem is actually that I forgot about holidays and the weekend lol
My partner is a big jerk and makes me try to respect them
how dare
it's all good. it'll ship when it ships. just don't be surprised when I push a lot of draft PRs for after the bump
I appreciate you taking care of this crate; I've been quite busy with other things
I know it. Not like you are one of only a couple of people charged with overseeing an absolutely massive crate with a community of over 20k in discord alone or anything.
I have been a hobbyist game dev for a decade and a professional software engineer for about as long. Bevy has by far been my favorite game engine I've ever touched and I feel like I've touched them all. Input management is such a deceptively simple concept and fun challenge and I have been trying to get more into the open source community anyway. And I get someone who is going to force me to do a damn good job when they review my PRs. It's a perfect storm. It's something I truly enjoy contributing to and I feel like it makes me a better engineer especially in the context of Rust and Bevy which is still relatively new to me compared to the web stuff I've been reluctantly mainlining for the last 10 years.
So nah fam I appreciate you
question: this is how creating an input map as a resource is supposed to work correct?
#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
pub enum PlayerAction {
#[actionlike(DualAxis)]
Move,
Jump,
Attack,
}
impl PlayerAction {
pub fn mkb_input_map() -> InputMap<Self>{
InputMap::new([
(Self::Jump, (KeyCode::Space))
])
.with_dual_axis(Self::Move, VirtualDPad::wasd())
.with_dual_axis(Self::Move, GamepadStick::LEFT.with_deadzone_symmetric(0.2))
}
}
because I'm trying to get to the bottom of this and it seems to occur when I get an input
2026-01-05T17:59:54.802759Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 3, sub_id: 0 }
2026-01-05T17:59:57.252734Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 5, sub_id: 0 }
2026-01-05T17:59:58.835485Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 7, sub_id: 0 }
2026-01-05T18:00:00.402523Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 10, sub_id: 0 }
2026-01-05T18:00:02.135136Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 12, sub_id: 0 }
2026-01-05T18:00:03.502149Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 13, sub_id: 0 }
2026-01-05T18:00:04.652190Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 15, sub_id: 0 }
2026-01-05T18:00:06.068278Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 18, sub_id: 0 }
2026-01-05T18:00:07.235388Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 20, sub_id: 0 }
2026-01-05T18:00:07.918661Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 21, sub_id: 0 }
2026-01-05T18:00:08.718771Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 22, sub_id: 0 }
2026-01-05T18:00:11.801110Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 25, sub_id: 0 }
2026-01-05T18:00:16.117465Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 29, sub_id: 0 }
2026-01-05T18:00:16.701027Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 30, sub_id: 0 }
2026-01-05T18:00:18.933796Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 32, sub_id: 0 }
2026-01-05T18:00:20.716796Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 33, sub_id: 0 }
2026-01-05T18:00:22.233385Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 36, sub_id: 0 }
2026-01-05T18:00:23.900202Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 40, sub_id: 0 }
2026-01-05T18:00:25.417218Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 43, sub_id: 0 }
2026-01-05T18:00:26.000266Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 44, sub_id: 0 }
2026-01-05T18:00:27.432818Z WARN calloop::loop_logic: [calloop] Received an event for non-existence source: TokenInner { id: 3, version: 47, sub_id: 0 }
here's the full example but that seems good at a glance https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/examples/action_state_resource.rs
A straightforward stateful input manager for the Bevy game engine. - Leafwing-Studios/leafwing-input-manager
if you run the LWIM example do you still see that? I don't
well that crosses the input being the cause off the list
wait, do you know if cloning a handle might cause the afformentioned warning?
that may be the case. can you write up a quick minimal repro?
I can try but I'll have to figure out how to handle it with a custom asset
I've seen a couple people have this log show up so having a repro would be great for a Bevy issue if you get a chance
@karmic monolith there was a merge conflict I had to resolve and it kicked out auto-merge π
https://github.com/Leafwing-Studios/leafwing-input-manager/pull/729
@jolly stream I've sent you an invite for triage permissions for this crate π
I won't let you down! π«‘
Since I now have this ability can you do me a favor and create milestones for 0.20 and 0.21? I think I can do everything else from there. I didn't want to ask before and put more on your plate but now I have the power!
I don't think a 0.20.1 will make sense because it seems like all the bugs reported are going to require changes that may break current users.
Yeah, feel free!
Wait, do you not have the power to do this?
I can't create milestones. I can put things in the milestones though
Done π
Thankies! 
Alice has released 0.20.0 of LWIM featuring Bevy 0.18 RC support.
https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/RELEASES.md
For the next milestone I'm looking at a lot of bug fixes and TLC behind the curtains.
@karmic monolith I've already got half the issues I tagged for the next release done and I'll keep working on it fairly actively outside of my day job until the next jam starts. If you have time to take a look through the list and go shopping for anything you'd want to see included in the next release feel free.
Thanks for the release! Btw, will we get 0.21.0 for the final Bevy release? Maybe 0.20.0 should have been also marked as a pre-release, since there's still a possibility of breaking changes in Bevy itself?
That's a good question. Best practice maybe should have been to do that. Blame Alice π
but in all seriousness I don't expect any breaking changes in any of the things upstream of the surface area that LWIM touches specifically. If there is a breaking change as far as LWIM is concerned then we can adjust as needed. If not, then we could just do a 20.1 with the bump to full. Thoughts @karmic monolith ?
If we need to bump it further we can, but I expect this to continue to work just fine
We can do a 0.20.1 to increment the version number since it seems to bother people 
I think that would be the easiest to do if you were so inclined. I know previous versions have just sat on rc and it seems to not be an issue. I'm unaware of any in the weeds reasons there would be that the way we have done it would be inherently bad.
Yeah, it'll be semver compatible with the full release, but it is slightly confusing
That was my assumption. I could see it being an issue if it was relying on something that is currently still in the works for release that could possibly be a breaking change? Then someone could potentially have something that worked then didn't? I'd have to research the nuance to this.
What's the best way to distinguish a button press from a button hold?
I would generally recommend BEI for that sort of distinction π
But you could look at the press duration
LWIM is still on 0.17. Do you want a PR to update it?
Doesn't look like it π
It should work just fine as is, but if it bothers you I'd merge that and do a point release
the rc versions are semver compatible according to Cargo
It's quite surprising, but very convenient for lazy crate authors!
Has anyone written up a comparison with LWIM and bevy_enhanced_input?
I don't know of one. There's some discussions here and there about it. LWIM has been around longer, BEI is planned to maybe possibly eventually be upstreamed. Personally, look at each of them and see which one you prefer ergonomically. If you are considering networking then that may play into it though I'm not as knowledgeable on the options there.
LWIM has a simpler API, BEI supports more complex behaviors and has more sensible serialization strategy and uses observers
how can i make mouse movement become a unique action when the mouse wheel is pressed? like pressing the wheel while moving should register as some sorta dual-axis Pan action
I would probably make a little state machine to manage this π€
probably the best option
just wondering if lwim had support for these sort of input chords
I agree with Alice though I wonder if a run_condition could handle this. I'd have to tinker with it. I thought there was at least some example for it but it either doesn't exist or escapes me but essentially you can do something like
// excuse the nasty pseudo code. I have just risen from a sick nap which is a nap while sick and not a nap that is sick
.add_systems(Update, pan.run_if(action_pressed(Action::MouseWheelHold)))
nvm I found an actual example. there doesn't seem to be one specifically for common_conditions but it is included here in this example:
@trim wigeon ^
Mentally playing with this a little I think run conditions could work just fine but without knowing the full context of what other requirements you have it may become difficult to reason about spaghetti if you have a lot of these run conditions it may be simpler to just have a sort of state machine like Alice said.
This problem is essentially needing to turn a specific arbitrary Action into a modifier. I don't think I've ever needed to do this in a real project yet but that seems to be a fairly common control scheme in any genre with a camera like city builders / RTS etc. Editor even tbh.
Probably worth hooking some peepers into at some point especially since I also have a couple small gripes with the official unofficial Bevy FreeCamera that I have on my backburner to figure out. My backlog is so full and brain is so mush.
ok so i'm trying to figure out how to do a rebinding menu. InputMap::get_dual_axislike gives you a dyn DualAxislike which does indirectly impl Any. should <dyn Any>::downcast_ref::<GamepadStick> be able to do the downcast? i'm trying to figure out what the concrete type is, or if this is even an angle worth pursuing
these types also impl Reflect of course. but i'm not sure what the expectation is for how to handle this at all
yeah bleh it's been a while since i had to muck around with Any but i can't figure out what the concrete type to use here is
aha! right it's because of Box. <dyn Any>::downcast_ref::<GamepadStick>(&**x) did it
Noticed something in the docs https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/src/systems.rs#L147
Try doing a repo-wide search for "prmessage"
||I wonder what other crates this happened in||
lmao
PR?
Hi- Is there a (simple-ish) way to limit the input action to trigger only when hovering or not some area? The use case is that I have some binding for mouse wheel to zoom the main camera, but it currently triggers also while scrolling some UI. I'd like it to be disable while hovering the UI. Otherwise said, I'd like the UI scrolling to "swallow" the input so it never reaches the camera binding. Currently the UI doesn't use the input manager, so before switching to it I'd like to make sure this is doable.
I'm guessing maybe I need to dynamically turn ON/OFF the InputMap based on the cursor hover maybe?
I tried enabling/disabling ActionState<A> based on what the HoverMap from picking reports. This kind of works. But for example dragging actions (chord with LMB + mouse move for example) will stop working when the mouse moves over UI, which is weird for the user. That means the ON/OFF logic of ActionState<A> not only needs to account for what the mouse hovers, but also if any action currently "grabbed" the mouse. It feels like the two systems (input and UI picking) are not really working well together.
if i'm making my own UpdatableInput implementer, it seems like that's the thing that needs to be a serializable, persistent value. this is steaminput, and it kind of seems like you need to implement gamepads yourself (for non-steam releases) or completely ignore them (for steaminput releases). i'm exposing a Gamepad-like Component that the UpdatableInput reads..
the bit i'm puzzling over is whether it makes sense to persist the bindings or regenerate them always, when they're just as simple as input_map.insert_dual_axis(PlayerAction::Move, ConstSteamAction::analog("move"))
input_map.insert(PlayerAction::UseItem, ConstSteamAction::digital("use_item")) etc
well, i suppose InputMap is supposed to be idempotent about adding the same input more than once ..
but also hm i don't think with serde i can make a Serialize impl that says "skip me" at the struct level. just at the field level ..
the specific bad interaction i'm worried about with persistence is if someone changes a steam action name and now the binding for a player action contains two separate steam actions
i'm just trying to think of how to have the fewest possible bad states, heh
oh wait that's right there's an example for indirection https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/examples/arpg_indirection.rs
is it expected that just_pressed is firing every frame while I'm holding GamepadButton::RightTrigger2 or GamepadButton::LeftTrigger2? (while just GamepadButton::RightTrigger and GamepadButton::LeftTrigger behave normally)