#leafwing-input-manager

1 messages ยท Page 4 of 1

karmic monolith
#

Yeah this would be really weird

candid vigil
#

I've completed the UserInput part, but I'm now working on modifying the InputMap and input mocking API

#

I feel like these could be split out from #490 because they're not particularly related and involve too many aspects

candid vigil
#

#513 ready

karmic monolith
#

I'll take a look tonight

candid vigil
#

I'm a bit unclear about the current issue with Gamepad input mocking

#

Bevy #9446 broke the behavior where Axis<GamepadButton> was not modified by GamepadButtonChangedEvent

karmic monolith
#

@river cliff maybe you remember more?

candid vigil
#

And then I've reviewed Bevy's gamepad_axis_event_system and gamepad_button_event_system

#

and there haven't been any logical changes to these systems since #9008 (included in Bevy 0.12)

#

the modifications made by GamepadButtonChangedEvent to ButtonInput<GamepadButton> seem to still be effective

#

Since GamepadButton is primarily treated as a button in LWIM, it seems feasible to modify the VirtualDPad implementation to check for presses from this perspective?

river cliff
candid vigil
#

Oops, I see the problem lies elsewhere

river cliff
candid vigil
#

the main issue just is that GameButtonType should get its value from Axis<GameButtonType>, but the external GamepadButtonChangedEvent cannot modify the value in this resource

#

It's not a problem with the implementation of VirtualDpad.

#

Directly modifying Axis<GamepadButton> in send_input mocking works for game_pad_virtual_dpad testing, but it might be too hacky

#

This resource is only used by gilrs_event_system in bevy_gilrs and gamepad_connection_system in bevy_input

candid vigil
#

with_gamepad() is used for this case

#

using set_gamepad would return a &mut Self

#

perhaps we could rename with_gamepad

#

@karmic monolith

karmic monolith
#

Ah okay, I see now

#

Yeah that's fine, merging now

#

Then we can merge that one

#

And then we can have a clearer view of 515, which seems trickier

candid vigil
#

ohh, I'm working on completing #515

#

just update docs

karmic monolith
#

๐Ÿ‘

candid vigil
#

done

karmic monolith
#

And review left for 515

#

Really excellent progress!

candid vigil
#

but this approach is quite hacky, and I'm unsure of any potential side effects.

karmic monolith
#

Yeah, I think we should consider just not allowing gamepad buttons to be mocked for now

#

until it's fixed upstream

candid vigil
#

rebased

karmic monolith
#

Merging now @candid vigil ๐Ÿ™‚

#

That should give you a nice clean base to tackle some of the more fundamental splitting tasks

candid vigil
karmic monolith
#

Off to bed for the night now

candid vigil
#

yeah good night!

#

I should be able to finish #490 in a few hours

#

trait refactoring

candid vigil
#

I just had this idea that we could add another trait, like MockRawInputEvent for UserInput

#

where the input itself decides how to send fake input events

#

Instead of dealing with it in MockInput for MutableInputStreams

#

MockInput would just call methods from UserInput within MockRawInputEvent

#

After that we can get rid of RawInputs since it also limit how we can extend new input types

candid vigil
#

I'm unsure of appropriate names for the dual-axis versions of mouse motion and mouse wheel inputs

#

These names are currently used by Bevy for the corresponding input events

#

in the current implementation

  • DualAxis::mouse_motion and DualAxis::mouse_wheel are now MouseMove and MouseScroll.
  • MouseMotionAxisType and MouseWheelAxisType are now MouseMoveAxis and MouseScrollAxis.
  • MouseMotionDirection and MouseWheelDirection are now MouseMoveDirection and MouseScrollDirection.
karmic monolith
#

We can do another pass once they're upstreamed

midnight bramble
candid vigil
#

#490 is done

#

but I'm not sure what format to use for writing doc examples for these input structs

#

Should I directly describe the various constructors and constants, or use InputMap, or use input mocking?

karmic monolith
candid vigil
#

I think the latter can be used as an additional example

#

but the QueryInput could be improved

#

Currently, it can only check whether a button is pressed

#

we can add new methods to read the value of axes

candid vigil
#

I feel like using InputMap in the documentation for each UserInput is a bit redundant

#

each case requires an additional Action

#

using MockInput and QueryInput seems like a better way to describe the behavior of the input, and what data the input will respond to

karmic monolith
small drum
#

Are there any good examples showing context-based actions? I'm implementing an editor where there's different edit states, and the same key will trigger a different action based on the state. Would it make sense to just have an Actionlike enum per edit state and enable/disable based on the state? Or maybe attach them to components that are added/removed based on the state?

foggy osprey
#

This could be a use case for entity disabling if it gets into 0.14

restive knoll
karmic monolith
foggy osprey
restive knoll
foggy osprey
#

Hmmm, too bad. Seemed pretty straightforward. Anything need reviews?

restive knoll
#

My current plans for disabled entities (and components) #ecs-dev message
Definitely would be nice if LWIM could be toggled in a way that doesn't even require checking the docs tho. The current ToggleActions is also hard to discover, but iirc that PR for enabling/disabling individual actions would move it to the type itself which would be a lot easier to discover

foggy osprey
#

Doesn't that mean if we can get default filters in, we could basically get entity disabling for free?

restive knoll
# foggy osprey Right, this is the pr I've been referring to. If I'm not mistaken, you could imp...

Not entirely. LWIM could show some very strange behavior if disabled like this, because it will consider all actions to stay the same as before being disabled, which means actions could still be held. The current ToggleActions approach is also slightly broken in that regard (tho it does behave a bit better because iirc there's a system that releases the actions when disabled), I think that toggle per-action PR is also supposed to fix those issues

foggy osprey
#

๐Ÿค” but even if an action is held, the user wouldn't be able to query for it since it'd be disabled. I guess once your reenabled it it'd probably break...

restive knoll
#

Yea it would trigger just released and that's probably not what you'd expect (there are some exceptions to that ofc)

foggy osprey
#

And this is where observers would come in handy right? If Bevy had first-party disabling, lwim would want to add an observer that properly handle Disabled being inserted

restive knoll
#

Yep, LWIM would definitely need some special handling to respond to that

candid vigil
#

PR #490 (trait refactoring) is ready for review

#

But it contains the new processors added in the new PR #521

umbral linden
#

Hi, is there a path forward for https://github.com/bevyengine/bevy/issues/6183?
It's pretty important for me in lightyear because my networking is tick-based so my input-handling systems run in FixedUpdate.
Would making the Schedule where most systems run (tick_action_state, update_action_state) configurable work? So that those systems run in FixedPreUpdate instead of PreUpdate

GitHub

Bevy version 0.8.1 What you did Create a system that responds to input events inside of a fixed times step. What went wrong Sometimes, input events are missed: Input::just_pressed and just_released...

#

But I guess in that case you would miss some inputs in systems that run in the Update schedule

restive knoll
#

I think the main issue here is that we need timestamps on inputs to meaningfully assign them to FixedUpdate ticks, and iirc the issue with that is that the event loop for winit is blocked while the app is updating ... I think someone recently adopted a PR that is necessary to even start fixing that problem, tho I have also seen work on an alternative approach where input timesteps are retrieved from the OS but that seemed like it was full of edgecases ๐Ÿค”

umbral linden
#

I mostly just need to be able to use just_pressed and just_released in FixedUpdate. I think if the tick_action_state system ran in FixedPreUpdate it would accomplish that.
Or are you saying that update_action_state wouldn't work in FixedUpdate because of some winit stuff?

restive knoll
#

I think currently the best we can do is:

  • Create inputs during PreUpdate, combining them if one is already built (happens constantly when FPS >= tickrate)
  • Finalize them inside the fixed loop
  • If another fixed tick runs the same frame, assume the previous input is still valid
  • If a fixed tick has run this Update, clear the inputs after FixedMain as ran
umbral linden
#

I"m not sure I understand..

  • create-inputs = read them from the bevy ButtonInput and MouseWheel events?
  • finalize = go from 'just-pressed' to 'pressed'?
restive knoll
umbral linden
#

Hm; so what does it mean in terms of LWIM handling just_pressed and just_released in FixedUpdate?

restive knoll
#

If it's handled on the LWIM side, everything that becomes just_* would stay just_* until a FixedUpdate consumes the just_* ๐Ÿค”

umbral linden
#

So the change would be to make the tick_action_system run in FixedPreUpdate?

restive knoll
#

That could be one part of the changes maybe ... I'd imagine release_on_disable would also need to be in there (tho hat might become irrelevant with the PR replacing toggle actions with per-action toggles) ... And there would need to be some logic that decides where to run these things

honest briar
#

Is it possible to easily detect double click on a single keyboard button yet?

I would like to create a controller where KeyS click would be coupled to a MoveBackward action and KeyS double-click would be coupled to a 180 degree character's rotation.

EDIT: I guess my answer is here: https://github.com/Leafwing-Studios/leafwing-input-manager/issues/485

umbral linden
#

I think I have something that works well while being minimally invasive (doesn't require many code changes): https://github.com/Leafwing-Studios/leafwing-input-manager/pull/522

The idea is to swap the state of the ActionData between a update_state updated in PreUpdate , and a fixed_update_state updated before we run the FixedMainRunLoop schedule. (credit to @karmic monolith for the idea!)

(exactly like how Time<()> swaps between Time<Virtual> and Time<Fixed> in the FixedMainRunLoop schedule).

I added some unit tests to show that it fixed the problems described in https://github.com/bevyengine/bevy/issues/6183
I think it's a huge improvement because right now using leafwing in FixedUpdate systems effectively has massive footguns and requires great care.

GitHub

Context
Fixes #252
(see description of the issue in bevyengine/bevy#6183)
It would also fix cBournhonesque/lightyear#349
(I did a write-up here: https://hackmd.io/_TGuaUTnRBeuisvUMr0QoQ?both)
i.e. ...

GitHub

Bevy version 0.8.1 What you did Create a system that responds to input events inside of a fixed times step. What went wrong Sometimes, input events are missed: Input::just_pressed and just_released...

karmic monolith
foggy osprey
#

What are the odds the bevy_ui integration could be completely replaced by the mod_picking upstream?

foggy osprey
#

Awesome, that was my impression after trying it

umbral linden
#

@karmic monolith I wonder if you had the time to look at my input PR? (no rush)

half viper
#

Hey, is this a good place for support around crates too?
I'm having an issue where my switch pro controller is picked up and used about half the time, I also can't seem to get buttons to work. (DualAxis is what works half the time). I've searched github but couldn't find anyone with the same behaviour as me. I'm grateful for any breadcrumbs of hope. I've not tested other controllers yet.

#

Hmm, that was my issue last night, just tried first thing this morning and it worked. So looks like a classic PEBKAC issue.

open trout
#

whats the status on the upstreaming effort/are there any PRs to review/refactors in need of completing

karmic monolith
#

I want to land the trait refactor, let that bake for a bit and then start upstreaming

open trout
#

cool

#

i'll leave some reviews

karmic monolith
#

Thank you!

#

It's been harder to keep on top of it while I'm doing Bevy itself full time

#

I should just accept that I need to take work time on my crates sometimes

open trout
#

i think that is an entirely valid use of work time

#

especially given that it will imminently be upstreamed

karmic monolith
#

Yep

#

I also want to look into the input sequence alternative and see if there are things to learn there

open trout
#

positively colossal

swift summit
open trout
#

@swift summit i responded in the pr

#

im gonna approve, i just dont understand the reasoning

swift summit
#

the reasoning is to fix issue #446 specifically, and it happens to also fix #416 incidentally

open trout
#

i see thanks

candid vigil
open trout
candid vigil
#

Most of the new input impls involve breaking down the logic of the original, large InputStreams

#

The secondary focus might be on naming these implementations, which I'm not particularly good at

#

I'm also unsure whether we should keep the original cross-device VirtualAxis and VirtualDPad. This PR only includes separate versions for keyboards and gamepads

candid vigil
#

My primary concern is that these two input types are essentially simulating directions

#

and a cross-device layout might feel strange

#

and using Chord (multiple buttons pressed simultaneously) as one direction for these inputs might also make it less convenient for players

swift summit
#

#416 can be closed as well now that #456 is merged

umbral linden
candid vigil
umbral linden
#

thanks

karmic monolith
#

That's the last missing piece for removing LWIM's own competing direction machinery in the 0.14 patch

karmic monolith
#

Working on the LWIM upgrade today

#

Starting with the trivial bump

#

Then leafwing_abilities

#

Then updating main

karmic monolith
#

Then once Bevy 0.14 is released, we'll cut another little bump from this branch as LWIM 0.14

#

And then ship main as LWIM 0.15

karmic monolith
#

I'm going to work off that, then push and merge my own fixes to it ๐Ÿ™‚

karmic monolith
#

Merged ๐Ÿ™‚

#

I don't think it's the optimal design yet, but I'm inclined to merge it in approximately its current state and then iterate, but if you have strong feelings otherwise I'll defer to you

candid vigil
#

@karmic monolith Yeah, Iโ€™ve left some comments as well. Could I hear your thoughts if you have time?

#

Most of changes in my comments seemed too much for a single PR before, but now there are already many changes in this PR. I'm not sure how to split it up step by step

karmic monolith
#

I'd really like to have an input mocking trait

#

But that can definitely be another PR

#

IMO we should merge now

#

And then I can spend the next week refining further

candid vigil
#

Maybe we could change the implementation of BasicInputs first, or handle it in a later PR

#

returning a Vec and just check the lengths and basic inputs of each should be enough?

candid vigil
#

sure

umbral linden
karmic monolith
#

Reviewing in earnest now

umbral linden
#

Yes it's a fairly big change, but it stays in the spirit of the Time resource (swapping between Time<Fixed>, Time<Virtual> and Time<()>).
It might have some perf or ergonomics implication though?

karmic monolith
#

Yeah, but I'm currently at "correctness and API" in my mindset for this crate

karmic monolith
umbral linden
#

awesome! will do

karmic monolith
#

Once that's in I'm going to resolve conflicts and merge in @candid vigil's monster

#

Then take a crack at splitting the UserInput traits

restive knoll
umbral linden
#

I haven't done extensive testing; i've only tested the cases where fixed update runs multiple times in a frame, and fixed update runs 0 times in a frame. I'll fully test it in lightyear soon; previously I had to do weird workarounds for handling inputs in FixedUupdate

restive knoll
#

I'm using some ugly workarounds too, generating inputs outside of FixedUpdate, but somewhere something goes wrong causing half of inputs to get dropped anyway when FPS is not exactly 60

#

Ideally we would've had input timestamps by now, but it's been blocked by some winit specifics for a long time and every attempt to unblock it ends up in review limbo until it's so hard to rebase it needs to be redone ๐Ÿค”

karmic monolith
karmic monolith
#

https://github.com/Leafwing-Studios/leafwing-input-manager/issues/538 needs a fix before LWIM's next release. It should be straightforward enough (and you can gawk at my terrible code!) if you, the reader, would like to help out ๐Ÿ™‚

candid vigil
#

I don't really get it. What changed that caused these failures? Did something change with the Bevy input?

karmic monolith
candid vigil
#

I found the issue. It seems that EventReader has undergone some breaking changes

#

for example, with this code

#

in Bevy 0.13, the arrow position would only read a single MouseMotion { delta: [0.0, 5.0] }

#

but in Bevy 0.14, it reads both the old MouseMotion { delta: [0.0, -5.0] } and the new MouseMotion { delta: [0.0, 5.0] }

#

this causes the error, as the accumulated result ends up being 0.0 and doesn't being pressed ๐Ÿ˜‚

#

Is there a migration guide ready?

topaz stratus
karmic monolith
#

Taking a crack at this bug myself now

karmic monolith
umbral linden
#

What do you think about filling the ActionState hashmap with the default value for ActionData for all possible actions on spawn?
Currently they are initializd on the first press or release, which is a bit confusing

candid vigil
#

I had considered this point in my previous PR

#

but it seems impossible now that Actionlike can use tuples and even struct variants

#

On the other hand, although OnAdd and OnChange can be used to detect changes in InputMap and update the corresponding ActionState, I am not completely sure whether this will have the expected effect

karmic monolith
#

Since Actionlike is no longer restricted to simple enums

umbral linden
#

Oh i see

karmic monolith
#

I took the time to do it right, and now all the tests (except the gamepad input mocking one) are green

karmic monolith
#

Alright, I've started on the next phase of the trait refactor, splitting apart UserInput into more semantically meaningful traits

#

I spent all day on this today, and I'll be back on it Tuesday or Wednesday of next week (long weekend)

#

Generally pleased though: I think this is the right direction!

umbral linden
#

For networking, I have a usecase where users want to transmit stuff like Cursor position in world-space + maybe camera rotation.
I think the cursor position part is possible by first converting the cursor coordinates from window-space to world-space and then setting them as a DualAxis input.
But for camera rotation I would need a TripleAxis Input.

Will the refactor allow me to send arbitrary data inside ActionLike? Such as a vec3?
cc @woeful totem

#

Also will it be possible to send 2 inputs at the same time (i.e. WorldPosition AND CameraRotation)? Basically a struct vs an enum

karmic monolith
#

Hmm. So, ActionDiff itself is effectively unchanged

#

I would probably use a custom message for more exotic things

#

Although if there's demand for other forms of input beyond just bool/f32/Vec2 this makes it really easy to add more subtraits

umbral linden
karmic monolith
#

Yeah, I'm super down for that in the future ๐Ÿ™‚

#

Let's land the refactor first though, then build on it

foggy osprey
karmic monolith
#

VR? A space mouse?

umbral linden
#

For me it's the 3D world-space orientation of a character (I can't just use the 2d mouse input values, since they have to be converted to world space when sent to the server)

foggy osprey
#

The alternative is to split up my motion into enum Motion { Regular, Vertical } or else enum Motion { Vertical, Lateral, Longitudinal }

#

Both work, it's just that things get ever so slightly cleaner and nicer to work with when the input abstraction just hands me a 3d direction

earnest phoenix
#

How can you detect a down press + button on a controller?

Like for a dropdown movement, you would press on the left stick down + the South button.

I tried with:

    input_map.insert_chord(Action::DropDown, [SingleAxis::negative_only(GamepadAxisType::LeftStickY, 0.3), GamepadButtonType::South]);

But the single axis is not a button.

candid vigil
earnest phoenix
candid vigil
#

there probably won't be a way in LWIM 0.13

karmic monolith
#

Yeah, you may be able to synthesize it somehow, but I'm really not sure of the best way in 0.13

candid vigil
#

In theory, this Chord should achieve that effect

#

Or are you referring to an error during the Chord construction?

#

The insert_chord function takes an iterator as a parameter, and Rust requires all items in an iterable to be of the same type

#

However, in the current version, there's a huge InputKind enum that encompasses all input kinds supported by LWIM

earnest phoenix
spring robin
#

Hitting this again in a new system and it continues to be surprising / confusing.

karmic monolith
#

https://github.com/Leafwing-Studios/leafwing-input-manager/pull/548

The second half of the UserInput refactor is now done*; take a look and let me know how you feel about the API?

*: except actually testing that it works

GitHub

Fixes #535.
This is a major refactor that splits user inputs into three kinds: buttonlike, axislike and dualaxislike.
This change ends up rippling through the whole stack: from Actionlike to UserIn...

#

Sorry for the monstrous PR: this really did end up touching the whole stack ๐Ÿ˜…

#

Generally feeling very good about the split and traitification as a whole: this is a much less leaky abstraction. No more wondering about "what does it mean for a control stick to be pressed" or other nonsense

umbral linden
#

So pressed/released only make sense for ButtonLike now?

karmic monolith
#

I redid how action-diffs are generated @umbral linden; you might be interested in those changes

umbral linden
#

Thanks, i'll take a look.
In general I don't use the action-diffs system directly anymore, because it's too risky to only send diffs. (if they arrive too late or don't arrive then it's hard to recover)
Instead I have a buffer of past ActionStates, and I send a base ActionState + diffs since that action state. I will probably have to update my logic to match what you did

#

One thing I don't really get is that an action could have independently all 3 (button/axis/2d-axis)? Do you have an example for where this is useful/relevant?

candid vigil
#

I think maybe we can add a with_button method to AxislikeChord and DualAxislikeChord

#

Otherwise, creating a chord that binds to more than one button requires creating a ButtonlikeChord first

limpid ledge
#

I just added this crate (0.13.3) to my Bevy app, but bevy_mod_picking seems to have completely stopped working. Is this expected? Is there a way to make both work side-by-side?

earnest phoenix
#

In v0.13.3 as well as current main, is it expected that the mouse_position example isn't working?

(main does nothing, v0.13.3 panics at examples/mouse_position.rs:64:22:)

tardy verge
#

ngl i haven't actually tried to integrate LWIM with bevy_oxr yet, i didn't realize it was lacking a Vec3

#

whenever I do get around to it i'll make a fork of the repo with the changes I need and then see which ones you want to adopt ( if i ever do end up getting to it cat_sob )

#

( my brain is so adhd i can't help myself, i code as a coping mechanism to deal with the stress of school so it's not entirely within my control )

midnight bramble
#

whatever input you use, it should just work out of the box ๐Ÿคทโ€โ™‚๏ธ

midnight bramble
tardy verge
midnight bramble
#

and with VR it could be way more fun

tardy verge
#

Ah yeah I do beatsaber

#

Love me beatsaber

#

'ate school

karmic monolith
#

Anyone want to update the 0.14 branch? I think you need to clean up features mostly ๐Ÿ™‚

#

I'm pretty low on time this weekend (dad's in town), but I'd like to get the LWIM update out at least

merry kraken
#

Oh, I already did that. I guess I forgot to submit a PR. Let me see.

#

I didn't submit it because bevy_egui hasn't updated.

karmic monolith
merry kraken
#

Is it that you want to release the 0.14 branch and then release main as 0.15?

karmic monolith
#

There's a bit more to do on main before I want to ship it

rugged mica
#

is there a migration guide ? ๐Ÿฅบ

#

i think i just need to figure out how to keep my ActionLike enums

#

cause the compiler doesn't like them now, saying they can't possibly implement FromReflect or smth

rugged mica
#

oh i had 2 bevy version in the tree

karmic monolith
warm shard
#

In case it helps I use cargo tree -d 2>&1 | less all the time when upgrading to figure out which crate is still pulling the old bevy ๐Ÿ™‚

karmic monolith
umbral linden
#

Yay

karmic monolith
#

This is just the compatability bump

rugged mica
#

is it normal to have
name = "leafwing_input_manager_macros"
version = "0.13.0"
in my .lock after upgrading to leafwing 0.14 ?

karmic monolith
rugged mica
#

ok, ty ๐Ÿ‘

umbral linden
#

I don't get why, but some of my tests with leafwing don't seem to be deterministic

#

Tests of the form:

app.world_mut()
    .resource_mut::<ButtonInput<KeyCode>>()
    .press(KeyCode::KeyA);
app.update()

sometimes my input-press isn't registered for some reason

karmic monolith
#

Hmm that's very weird

umbral linden
#

this kind of bug is probably some system ordering error on my part, but I can't figure it out

simple loom
open trout
#

another day another forget to .add_plugins(InputManagerPlugin::<XyzAction>::default())

#

wish it printed errors when i tried to read actions that arent registered

karmic monolith
#

That's a great idea

open trout
#

i was brainstorming last night how exactly i'd go about implementing that and i think its possible, it would resolve my most common footgun with lwim

#

not really a footgun tbh but not sure what else to call it. its definitely user error just easy to froget

karmic monolith
#

Yeah, I've done this too lol

open trout
umbral linden
open trout
#

how much latency does lwim add on top of bevy's input latency and whats the lowest latency way to do input in bevy

#

im looking to fire a midi note as soon as possible when a key is pressed, i dont care about framerate

restive knoll
#

I don't think lwim adds any latency as long as things are ordered correctly, but bevy's entire input system is currently tied to FPS and you don't actually receive input timestamps so you can't do a nice workaround like playing the notes with a consistent delay so it doesn't mess with timing ๐Ÿค”

midnight bramble
#

how is input lag normally solved anyway? it can't be just fixedupdate because it's too slow, and i can't imagine mixing both being a good idea

restive knoll
#

FixedUpdate would just add more lag, since it's just a loop running inside the frame's logic (tho that could possibly be decoupled, but that still wouldn't help outside of making things more consistent than FPS)

#

The usual solution here is to just not care about the lag. If you press a button, the sound comes out 50ms later, your mind will convince you that it was instant, despite that clearly not being the case

#

Alternatively you can handle inputs async and play sounds immediately with minimal lag and most importantly a perfectly consistent way

#

The obvious downside here is that you can't really use any built-in systems, which can be very problematic if it's not an app trying to do one specific thing, but a game that potentially does multiple things based on an input

karmic monolith
#

There's some follow-up that must be done before shipping, namely investigating why action diffing is failing and refactoring how clashing inputs are handled

#

This is already a very very large PR though, so I've marked the failing tests as ignored and I'm going to merge

#

Generally very pleased with the results though: the API and general contract of the crate is much clearer

#

And there's less "well, the user asked us a malformed question, what do we do?" nonsense like asking if axes are pressed

midnight bramble
#

what happened to @candid vigil btw

umbral linden
#

Overall i think the refactor goes in the right direction, it was strange to have both button/1d-axis/2d-axis data in the same ActionData

#

I'm not fully convinced about having 3 separate hashmaps for each action though

karmic monolith
#

This is really strict now

#

So the 3 hashmaps are really just an implementation detail

ruby furnace
#

How can I check if I'm focusing on an egui node to turn off leafwing's input processing?

warm shard
# ruby furnace How can I check if I'm focusing on an egui node to turn off leafwing's input pro...

I used this https://github.com/mvlabat/bevy_egui/issues/47#issuecomment-1922695612 : basically get the egui context, then use .wants_pointer_input() or .is_pointer_over_area() (according to your needs). Then you could put this in a Resource or a run-condition e.g. egui_has_focus

GitHub

Hey I'm having issues (and generally a nice time!) with using bevy-egui, and mouse/keyboard input still being consumed by the main bevy system code. This would be something nice to suppress som...

#

Question regarding this feature in LWIM's readme:

Create an arbitrary number of strongly typed disjoint action sets by adding multiple copies of this plugin: decouple your camera and player state

#

Concretely, when two input maps exist that use the same keys, do both get actions when I press that key? Is there a way to set priorities / disambiguate which of the non-disjoint input maps gets the action?

karmic monolith
rancid cairn
#

Would there any way to record a set amount of inputs and replay them?

karmic monolith
#

You probably want a dedicated crate for that

obtuse zinc
#

doesn't seem to be updated for 0.14 though

karmic monolith
warm shard
#

What are the best LWIM practices for letting the user configure keybindings? Probably something like modifying input maps, but I'm not sure what's the "right" way to do that.

karmic monolith
#

It's sorely in need of an example though

warm shard
#

& probably serialize it & save to the user's profile somewhere

karmic monolith
#

Love to see it

swift summit
#

i'm noticing that if i press A and then press Shift, then release Shift, it's yielding "action just pressed" for A, then Shift+A, then A again

#

i would expect just A

#

(i have one action mapped from A and one action mapped from Shift+A using insert_modified)

#

the second A is definitely a bug, the Shift+A may be debatable

#

this is in the latest LWIM release + bevy 0.14. i can open an issue later if there isn't one already, just busy with jam rn

quartz wedge
umbral linden
#

I think you might need to add a value to the ActionState first because by default the hashmaps are empty

quartz wedge
grim hollow
#

Hi, how does the result action.axis_pair() is computed? Is it accumulated of EventReader<MouseMotion>?

grim hollow
#

Is it safe to use action.axis_pair in FixedUpdate for physic based rotation? I'm concerning that it will lost some frames because its seem action data is reset every Update

karmic monolith
grim hollow
swift summit
river cliff
#

I ran into an issue where using .pressed() and other variants respond to all gamepads regardless of the associated_gamepad. Did some looking an I think it is due to this line in input_streams:

InputKind::GamepadButton(button_type) => self
                .associated_gamepad
                .into_iter()
                .chain(self.gamepads.iter())
                .any(|gamepad| {
                    self.gamepad_buttons.pressed(GamepadButton {
                        gamepad,
                        button_type,
                    })
                }),

It iterates over the associated, but then also chains all the gamepads into the iterator to check for the press. .value() correctly only responds to the associated_gamepad when set though.

karmic monolith
river cliff
karmic monolith
#

Awesome

#

I'm going to devote my energy to getting a new release out IMO

karmic monolith
#

Alright, rubberducking a bit

#

The input mocking PR is now merged, which is great

#

There's a few refactors, and a few bug fixes

#

I should do the refactors first, because there's a good chance I'll discover better ways to solve the bugs

#

Better disabling should be done following share metadata

#

And trait-based clashes are probably a good follow-up to remove input streams

#

Both of these are pretty orthogonal

#

I think the metadata one is the easier one, so I'm going to start there rubberduck

swift summit
#

at a glance it seems that way, since all the ActionData get reset and update is skipped while disabled

#

if so, i think that's an issue. since "just pressed" is used to trigger in-game effects, it should correspond to the user physically pressing a key from unpressed, not from disabled

#

the way this was handled at the ActionData level was to continue updating the input state, but report it as "released" regardless of the actual state (while disabled)

#

tldr "input is pressed but the action is disabled" is an important state to keep track of

karmic monolith
karmic monolith
#

@swift summit can you make an issue for this so I fix it before release?

swift summit
flat coral
#

I just did a quick and dirty migration from Bevy 0.12 to 0.14 and 0.11 LWIM to 0.14, but I am noticing an issue where alt+key is not registering

#

unless I click at the same time

#

This is probably a simple mistake on my part

#

It's the despawn here that is failing```rs
fn spawn_or_despawn_gizmos<'a>(
mut commands: Commands,
window: Query<&Window, With<PrimaryWindow>>,
window_dimensions: Res<WindowDimensions>,
action_state: Query<&'a ActionState<Action>>,
gizmos: Query<(Entity, &'a Transform, &'a GizmoType, Option<&'a Positive>)>,
) {
let action_state = action_state.single();
let window = unwrap_or_return!(window.get_single().ok());
let cursor_pos = unwrap_or_return!(window.cursor_position());
let cursor_pos = Vec2::new(cursor_pos.x, window.height() - cursor_pos.y);

for gizmo in GIZMOS {
    for (variant, positive) in [
        (Some(&gizmo.neutral_or_negative_variant), false),
        (gizmo.positive_variant.as_ref(), true),
    ]
    .iter()
    .filter_map(|(x, p)| x.map(|x| (x, p)))
    {
        if action_state.just_pressed(&variant.action) {
            if action_state.pressed(&Action::DespawnAllModifier) {
                despawn_all_gizmos(&mut commands, &gizmo, &gizmos, *positive);
            } else if action_state.pressed(&Action::DespawnModifier) {
                despawn_gizmo(
                    &mut commands,
                    cursor_pos,
                    window_dimensions.0,
                    &gizmo,
                    &gizmos,
                    *positive,
                );
            } else {
                spawn_gizmo(&mut commands, cursor_pos, &gizmo, *positive);
            }
        }
    }
}

}

#

especially the despawn all. the spawn always seems to work

#

I only ask because I suspect it's a simple migration oversight, if it's not then just ignore this and I'll try to dig deeper

#

It could easily be a scheduling thing, actually

#

Most of my application runs in FixedUpdate but that specific system runs in Update

#

It doesn't even run the just_pressed when alt is down so it's not recognising alt+1 as a press of 1, unless I am also holding down LMB at the time. That can't be intended behaviour

karmic monolith
#

Can you check on main please?

#

I really don't want to try and push fixes to the 0.14 branch if possible

karmic monolith
flat coral
#

Unchanged

#

It's hard not to blame myself because I haven't even touched Bevy in months though, this was just me being bored and going for a quick migration to pass time

#

but it worked before

karmic monolith
flat coral
#

I suppose I am constructing a chord in an unusual way

flat coral
#

assuming alt was pressed down before 1 was

#

(implied by alt+1 but I figured I'd be explicit)

karmic monolith
#

Assuming standard clash handling

flat coral
#

Is the same true for shift+1?

#

I do vaguely recall something being changed in this area

karmic monolith
flat coral
#

My shift+1 action is coded the same way as my alt+1 action, with makeshift chords, but that one always works. I also confirmed that just holding RMB is enough to make alt+1 work, even though RMB is not bound to anything

flat coral
#

On a whim I tried ctrl+alt+1 and that works.

#

To be clear though I already confirmed that the 1 action never triggers on alt+1, rather than 1 triggering but the alt not being pressed anymore

#

shift+alt+1 does not work

#

Doing the minimal thingy now

flat coral
#

does not have minimal compile time

flat coral
#

Doesn't repro in minimal

flat coral
#

and to be clear what happens in miminal is every modifier is individually detected

#

In my actual project I have a very unusual way of handling the binds, actually, because I have a const array of 4 items like ```rs
Gizmo {
gizmo_type: GizmoType::Deleter,
neutral_or_negative_variant: GizmoVariant {
action: Action::Deleter,
draw_properties: draw_properties::DELETER,
},
positive_variant: None,
has_movement: false,
},

flat coral
#

I will try that in my minimal repro next

flat coral
#

Didn't change behaviour

flat coral
#

Is there anything to be mindful of when mixing FixedUpdate and Update reading of the action state?

karmic monolith
#

(soon! I'm working on it...)

flat coral
#

I was only reading it in fixed update in 1 random place, and I changed that now

#

doesn't change bug (nor could I reproduce bug by reading in fixed update on purpose)

#

It's one of those bugs ๐Ÿ˜ฉ

karmic monolith
flat coral
karmic monolith
#

Generally not no

#

Does it work if you change the key bind? Especially to a non modifier

flat coral
#

It already does work currently with another modifier, shift, but I'll try that

#

It detects alt press, but it no longer recognises the 1 press, during the alt press

#

(unless holding LMB or RMB)

#

It's like a different action is capturing alt+1, but I have no chords set through LWIM

#

In my minimal repro, holding down both shifts counts as holding down shift, holding both ctrls counts as holding down ctrl, but holding down both alts does not count as holding down alt (I bound both of each)

karmic monolith
#

(debug-print)

flat coral
#

and I can't do it in reaction to pressing the 1 since it's not being picked up

karmic monolith
#

Although TBH for the InputMap, you should just be able to info_once! it, since it should be static after startup

flat coral
#

I did log it btw, nothing suspicious to me

#

just a whole bunch of ```rs
SpawnParticle: ActionData { disabled: false, kind_data: Button(ButtonData { state: Released, update_state: Released, fixed_update_state: Released, consumed: false }) }

#

Maybe I should log the other one

#

I guess you said input map

#

Nothing suspicious there

#

Isn't the double alt thing already quirky behaviour? It's in my minimum repro, fwiw

karmic monolith
#

Also: what happens if you change the clash strategy to None?

flat coral
# karmic monolith How do you mean?

Pressing both shifts is recognized as the action they're both bound to being pressed, same for ctrl, but not for alt. either alt works, but not both

#

This has the exact same behaviour```rs
if keys.just_pressed(KeyCode::Digit1) {
if keys.pressed(KeyCode::AltLeft) {
println!("Seen");
}
}

flat coral
#

Windows 10, but it's extra weird that I can't reproduce it, same Bevy version

#

Maybe I should've gone the other way and deleted things from my project until the problem goes away

#

Both alts down it takes no input in repro, in the real project it's only left alt that works that way

#

Or right alt (either alt)

#

(this is my project, it's not far beyond the minimal project)

#
if keys.pressed(KeyCode::Digit1) {
    if keys.pressed(KeyCode::AltLeft) {
        println!("Seen");
    }
}
```this now actually does work, even as the 1 action fails to activate. I'm just giving up, ctrl works I'll change to that
#

GL

karmic monolith
#

@umbral linden action-diffing is fixed ๐Ÿ˜„

#

Note that the behavior will change a bit for 0.15

#

Rather than generating 3 events every time you press a button (setting the axis value, dual-axis value and button state), it only generates 1 (button was pressed)

#

And vice versa for axislike inputs

#

Much simpler, and less wasteful

umbral linden
#

That's way better, awesome!

karmic monolith
#

@swift summit thanks for the design / prompt on how to handle disabling actions

#

This is much simpler / less buggy

karmic monolith
#

#crates message and released ๐Ÿ˜„

topaz stratus
#

er, specifically .data::<ReflectComponent>()

karmic monolith
silent drum
#

In my troubleshooting I added #[reflect(Component)] to both InputMap and ActionState but it didn't solve the specific issue (which came when using blenvy to spawn a blueprint and registering the inputs in a hook). Maybe something more needs to be changed for that workflow to work.

karmic monolith
#

@valid stratus, any tips?

topaz stratus
#

tldr; it came down to InputMap/ActionState not having .data when trying to reflect the component information, but I wasn't sure if they should have data.

restive knoll
#

Did the stuff necessary to use LWIM in FixedUpdate get in yet? ๐Ÿค”

topaz stratus
umbral linden
#

actions are not initialized as ButtonData right?

#

The first time i try to call set_axis_pair on an Actionlike that never appeared before (and I can verify via logging that it's not in the ActionState) my app crashes

#

Ah i see that the trait must be manually implemented

#

if you are storing non-buttonlike actions (e.g. movement) inside of your Actionlike enum, you must manually implement the trait

#

That's a bit misleading, i propose 2 changes:

  • add a #[actionlike(Button)] , #[actionlike(Axis)] attribute on the Actionlike derive macro to make it easier to configure the action type
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy, Hash, Reflect, Actionlike)]
pub enum PlayerActions {
    Up,
    Down,
    Left,
    Right,
    Shoot,
    #[actionlike(AxisPair)]
    MoveCursor,
}
  • don't require the user to specify the action type at all; the first time the user calls set_axis_pair then you can just create an ActionData::AxisPair for this action. Do we need to statically know the action type of an action?
#

(also because I would like to use Button for some of my actions, like Up/Down/Left/Right, and AxisPair for other actions like MoveCursor; even though they are part of the same Actionlike

#

ah actually that seems supported

restive knoll
# karmic monolith Yes this is in

Nice, guess I can finally write something sensible if I refactor my input stuff again (to fix inputs getting dropped at non-60FPS)

karmic monolith
karmic monolith
#

As for the second... I'm a bit more nervous

#

I don't think that's an easy refactor, and it risks correctness elsewhere

umbral linden
#

the checks wouldn't check against InputControlKind, they would check by matching against the ActionDataKind, but fair enough it's a pretty big change

umbral linden
#

there's no consume anymore?

karmic monolith
umbral linden
#

ah i see, thanks

silent drum
#
assertion `left == right` failed
  left: DualAxis
 right: Button
silent drum
#

Btw, I was also wondering why LWIM depends on rc3 of Bevy 0.14. I saw now for the LWIM 0.14 release that the dependency on rc2 was removed, but was it reverted later to rc3? Or am I reading the Cargo file wrong?

restive knoll
#

It depends on 0.14.0-rc.3 or a later semver compatable version, 0.14.0 is considered compatible and so is 0.14.1, so it doesn't really matter ๐Ÿค”

silent drum
#

Oh ok. I asked ChatGPT about Rust semver versions and it claimed that a rc version works differently and only matches exactly and not ^ like normal. But it was at first saying that it always matches exactly on regular version numbers as well so I had to correct it, and it "promised" that it was saying the truth after the correction ๐Ÿคฃ Damn ChatGPT with all its lies.

restive knoll
#

It's honestly hard to find accurate info on how rcs work. Iirc the book is the only place that's accurate, but you'll probably find tons of issues with very old info or things that are very misleading

midnight bramble
silent drum
#

The example on the main page only shows the Jump and not the Run update ๐Ÿ˜…

midnight bramble
#

yeah, documentation/examples could be better

#

for now just don't check if axis is pressed and assume that it always is

silent drum
midnight bramble
#

@karmic monolith that assert could give a better explanation, and btw the doc implies that it can be "not a buttonlike action"

umbral linden
#

@karmic monolith I updated some examples where I use JustPressed in FixedUpdate, it seems to work fine ๐Ÿ™‚

karmic monolith
midnight bramble
karmic monolith
midnight bramble
# karmic monolith I'm really not sure what you mean here ๐Ÿ˜…

if pressed(axis input) used to work before, not sure if it actually did anything though since like perry's case it wasn't something i'd notice if it just was using 0
if e.g. stick is in dead zone, i expected if pressed(axis input) to return false, is it supposed to just be if input == Vec2::ZERO now?

karmic monolith
midnight bramble
karmic monolith
fickle aurora
#

Just updated this crate, what is the new way of doing:

input_map.insert(Self::Zoom, SingleAxis::mouse_wheel_y());?

karmic monolith
fickle aurora
#

In the middle of updating all my deps, so I might have messed up somewhere

karmic monolith
#

The various input modes are now feature-flagged

cyan ruin
#

I would like to pan the camera:

.with(Pan, ButtonlikeChord::with_multiple([KeyCode::Space, MouseButton::Left]))

but MouseButton is not a KeyCode. My rust-fu is not good enough for this. How do I combine Keyboard and Mouse input?

karmic monolith
cyan ruin
#

Thank you! Works like a charm (had to swap new with default but even my rust-fu is strong enough for that one ๐Ÿ˜† )

fluid steeple
#

am I missing something or is the previous_duration broken? (macOs 14.5, bevy 0.14, leafwing-input-manager 0.15)

karmic monolith
umbral linden
#

I'm getting this error in wasm but i'm not sure why:

   --> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/leafwing-input-manager-0.15.0/src/action_state/mod.rs:203:51
    |
203 |             .for_each(|action_datum| action_datum.tick(_current_instant, _previous_instant));
    |                                                   ^^^^ ----------------  ----------------- expected `std::time::Instant`, found `bevy::bevy_utils::Instant`
    |                                                        |
    |                                                        expected `std::time::Instant`, found `bevy::bevy_utils::Instant`

I'm using bevy::bevy_utils::Instant everywhere

karmic monolith
umbral linden
#

what is the problem, out of curiosity? couldn't figure it out

karmic monolith
#

Which breaks on web

warm shard
#

I'm trying to send ActionDiffEvents from client to server, and used to do this by wrapping it in a MappedActionDiffEvents that implements MapEntities (& making a copy of the generate_action_diffs system to support the wrapped type), so that client entity IDs can be translated to server entity IDs.
But maybe I should just impl MapEntities for ActionDiffEvents<A> directly in LWIM and get rid of all the wrappers & copies -- would this be a good idea? (can write a PR)

swift summit
#

i updated to LWIM 0.15 and had to replace Actionlike derives with manual impls + match on all my action variants, which feels bad. i assume there's a good reason this is necessary? also i wonder if the derive macro could support field attributes like #[dual_axis] to make this easier

umbral linden
karmic monolith
warm shard
umbral linden
#

LGTM ๐Ÿ™‚

pseudo ledge
#

hey, trying to use DualAxis for character movement.
looking at the virtual_dpad example, it seems like it's exactly what i want.

now, at line 53 action_state.pressed is used.
... but i struggle to make that work on my end, as it crashes because of the assert in the beginning:

assertion `left == right` failed
  left: DualAxis
 right: Button
karmic monolith
#

I really should have fixed up the examples... ๐Ÿ˜…

#

You need to change the Actionlike impl

#

And probably don't check if a dual-axis is pressed

#

I'll get a full set of fixes up for the examples early next week when I'm back from vacation

midnight bramble
candid vigil
#

It's been a while since I've been over here. I was in the hospital

#

I guess there could be two small improvements to LWIM

#

First, for the input_control_kind method of Actionlike, I feel we could add [axis] and [dual_axis] field macros to the Actionlike to reduce some redundant code

#

But I don't think the InputControlKind design is ideal

#

Second, the InputManagerBundle might be able to be removed

#

Could we add the corresponding ActionState in the InputMap's component hook?

candid vigil
#

And the once::Lazy used for trait serde could be replaced with the std ones

foggy osprey
foggy osprey
candid vigil
candid vigil
#

I'm trying to understand the purpose of the Triggerlike trait

#

Could you elaborate on the conditions that would lead to a ButtonInput<Trigger> being false while the corresponding Axis<Trigger> is non-zero?

midnight bramble
karmic monolith
karmic monolith
karmic monolith
karmic monolith
midnight bramble
#

isn't it -1 for one trigger and +1 for the other?

#

yep

karmic monolith
midnight bramble
#

i mean it doesn't really make sense to me why they're connected in the first place, they feel more like 2x single axis

#

and couldn't threshold be done with axis too, since it needs a deadzone anyway? or is that pointless and handled somewhere else already

karmic monolith
midnight bramble
#

wouldn't some kind of a processor be better for both? i'm pretty sure it'd be easy to find cases where setting to 0 would be needed from triggers, and i wouldn't be surprised if someone wanted to use press/release with axes

karmic monolith
#

I think I want to steal the axis processor tech for triggerlikes though

midnight bramble
#

did you already try making visual editor or rebinding for players? they'll probably affect the final design a lot

#

and i'm mostly thinking from that end... processor would allow splitting the triggers or any other weird thing players might throw at it

restive knoll
#

If a trgger is made up of two triggers ... Isn't trigger_pos - trigger_neg enough to get the -1 to 1 behavior with correct deadzones? ๐Ÿค”

candid vigil
#

So Triggers need a saturation processor

#

Will axes use that?

#

I'm leaning towards adding TripleAxis first

#

It seems useful for a RTS camera

#

Any ideas for what to call the virtual buttons? DPad3D?

foggy osprey
candid vigil
#

Then we'd have these really long names like KeyboardVirtualSpaceMouse and GamepadVirtualSpaceMouse...

#

I'm not sure if we should separate them

#

Previously I feel like virtual axes and dpads, which use multiple Boxes, are frequently used for common actions like moving and zooming

#

Given LWIM isn't event-based, input values are checked every frame, and those pointers might impede compiler optimizations

#

My original plan was for Input to take &World as a parameter, which means it would read the Resources multiple times without optimization

#

But now using CentralInputStore seems to address this concern

candid vigil
karmic monolith
karmic monolith
umbral linden
karmic monolith
#

Oh and FYI the space mouse is actually 6 axis ๐Ÿ˜จ

#

We'll probably add support for that later lol

foggy osprey
#

I typically would use one for rotation and the other for translation. As a counterpoint to that, VR controllers

#

That said, you could always bind something to controller rotatoin and something else to controller translation

karmic monolith
#

InputKind::Isometric would be the name IMO

candid vigil
#

I have a question

#

In Bevy's scene coordinate system, forward is -Z and backward is +Z

#

So, does the DPad for TripleAxis also need to follow this rule?

karmic monolith
candid vigil
#

yeah, TripleAxislike is ready, after #608 is reviewed and merged, I can rebase and push it

karmic monolith
#

Fantastic

#

Thanks for reviewing and cleaning up the mistakes I made during all the refactoring ๐Ÿ’š

#

That was too much all at once lol

candid vigil
#

I feel like if I had to copy-paste the same code three times, I'd probably mess up big time too haha

karmic monolith
candid vigil
#

I feel like making inputs trait-based and splitting them to Buttonlike, Axislike, etc. seems to complicate InputMap and ActionState

#

Their interfaces wouldn't be compatible with other inputlike traits unless we add support in LWIM manually

#

A simpler approach might be to split them up as well: ButtonBindings, ButtonActionState, AxisBindings, AxisActionState, etc.

#

I mean, if users follow good coding practices that an input handling system probably only handle a few kinds of input

#

Even if there's overlap, we could just change spawn(InputMap) to spawn(ButtonBindings, AxisBindings) and Query<ActionState<Action>> to Query<(ButtonActionState<Button>, AxisActionState<AxisAction>)>

#

But obviously, this would be a huge breaking change

midnight bramble
#

bevy's coordinate system is already cursed enough, you don't have to make it even worse by messing with input

candid vigil
midnight bramble
#

i changed to Z-up Y-forward and i doubt i'll be the last person to do it

candid vigil
#

+Z means closer to you, and -Z means farther away

midnight bramble
#

it might make sense for ui, but it's completely counter-intuitive for 3d

candid vigil
#

yeah

karmic monolith
#

Being able to clearly list "here are the things the player can do" is really nice for conceptual organization, input binding and handling more complex state machines

#

BTW @candid vigil I think I'm going to tackle triggerlike today

candid vigil
#

I got that idea mainly because of these two functions. We have to add a lot of suffixes.

karmic monolith
#

Yeah ๐Ÿ™‚

#

We could be less picky about what we accept, and then rely on a constant or method on UserInput to put it in the right map

candid vigil
#

And if a user wants to add their own Input-like trait, the current InputMap and ActionState don't support it

karmic monolith
#

Yeah

#

I'm not sure we're going to run into that many more ways to extend it though

#

Unlike novel input mechanisms

candid vigil
#

If stable rust supports dyn T where T is a type parameter, I think it would be much easier

#

Perhaps when bringing this up to bevy, we can benefit from the collective wisdom of a larger community ๐Ÿค”

#

Not many people are talking about it here

candid vigil
#

๐Ÿ˜‚ I believe deserialization for inputs must be broken

#

because their deserializers are only registered in UserInputRegistry, but the actually used ones like ButtonlikeInputRegistry are empty

candid vigil
#

I've got another idea

#

We could probably remove all Inputlike traits and only keep the UserInput trait, like in my previous version

#

That PR was designed to minimize API changes, so the trait had methods like pressed, value, axis_pair, and so on

#

But I had an idea to make it simpler with just a fn get_data<T: DataType>(&self) -> Option<T::ValueType>, where DataType is a trait with implementors like Pressed, Released, AxisValue, etc

#

Essentially, there's a Res similar to the current CentralInputStore, but each input store a HashMap<DataType, DataType::ValueType>

#

For instance, a Trigger could have Data like {Pressed: true, AxisValue: 0.6}.

#

So, action_state.get_data<Pressed>(Trigger) returns Some(true), and action_state.get_data<AxisValue>(Trigger) get Some(0.6)

#

Or Result?

candid vigil
#

๐Ÿค” Maybe returning Some((true, 0.6)) by calling action_state.get_data<(Pressed, AxisValue)>(Trigger) and action_state.get_data<Trigger>(Trigger)

#

like Query

karmic monolith
#

Well, they kind of are

#

But you can't mix them

full iris
#

just googled "bevy playground" to try and prove a point, thanks Alice

#

i don't remember if this counts as object safety, or if i need to slap it in a Box

#

but if you specify the GAT you can use a dyn trait

#

but yeah, having to specify the GAT destroys the whole point

candid vigil
#

๐Ÿค” Just unit structs, and their TypeId as the map's keys, then use TypeId to retrieve the value?

full iris
#

type erasure will work but you need to have a safe API for retrieving the type

#

I'm not familiar enough with LWIM to say anything about that

#

wouldn't an enum work just fine here? no one is gonna invent a new action type, will they?

candid vigil
#

LWIM now does have a type-erasued one, so I think that might not be a problem

karmic monolith
#

Yeah ๐Ÿค”

candid vigil
full iris
#

does LWIM require every action to be a new type?

#

like, if I define a "jump" i need a struct Jump marker type?

candid vigil
#

You can have different actions with different control types in one enum

full iris
#

okay, then it's not as easy

#

if every input was a different type you could derive the input type at compile time and have a very clean api

candid vigil
#

yeah it could be

full iris
#

eg

struct Jump;

impl ActionMarker for Jump {
  trait ActionType = Buttonlike;
}

// [...]

let jump = actions.get::<Jump>(); // knows the return type from <Jump as ActionMarker>::ActionType
#

if it's an enum and every variant returns something different then it has to happend at runtime and you need falliable API

#

like, try_get::<Buttonlike>(PlayerAction::Jump)

#

and probably a bunch of helper methods that provide the generic, try_get_button(PlayerAction::Jump)

#

honestly, that doesn't look too bad

#

just a little bit of sugar

#

but you need to deal with unwraps

candid vigil
#

I think the problem with this code lies in the type of actions

#

Since Rust doesn't have wildcard generic types in parameter types, we can't get something like Actions<_>

#

So if we have a new action type, we will need a new system that processes its state ๐Ÿค”

full iris
#

you can always have T, A: Action<T>

#

which is annoying but works

candid vigil
#

Currenty in LWIM, if you add a new action type, you'll need to add an InputManagerPlugin::<Action> to your plugin set

#

which is more annoying I think ๐Ÿ˜‚

#

each plugin adds 11 systems to your app

full iris
#

there isn't much of a difference between adding a generic plugin and using a generic add plugin method

candid vigil
#

I mean, if you have two different action types, for example, Move and Jump

#

LWIM requires you to write down app.add_plugins((InputManagerPlugin::<Move>::default(), InputManagerPlugin::<Jump>::default()))

#

If they're just different variants of enum PlayerAction, we only need app.add_plugins(InputManagerPlugin::<PlayerAction>::default())

karmic monolith
restive knoll
#

Wait there's no deadzone by default? ๐Ÿ‘€

candid vigil
#

I took it out. It used to be there

#

but I think the default deadzone of 0.1 for both X and Y isn't great for many cases

#

People might want to tweak it

#

Also, the new processing pipeline is a Vec, so you have to know the exact index to change anything

#

I think it would be better if all built-in inputs started with an empty pipeline

full iris
restive knoll
#

Yea that makes sense ... I'm just surprised I never had issues with no deadzone ... I'll have to add some deadzone tho, people already complained in my last game release (before those reworks) that they got drift from a random connected controller ๐Ÿ˜‚

candid vigil
restive knoll
#

Since that was on the version before these reworks I'm pretty sure deadzones were still there

full iris
#

changing default behaviour is evil because your application will still work in a lot of scenarios
breaking changes at least force you to address the issue

candid vigil
#

yeah

candid vigil
#

Before, things like sensitivity, inversion, and deadzone were just fields of an input, and the order they were applied was fixed

#

That means input.sensitivity(2.0).inverted().deadzone(0.15) was just modifying the corresponding fields, and the order couldn't be specified

#

if you wanted Sensitivity to be applied after Deadzone, you had to calculate the result manually

#

In the new version, there's a field that's a Vec<Processor>, so you can specify any order of processors and can also apply different Deadzones simultaneously (some games are quite complex)

restive knoll
#

Do we have a "multiply_by_delta" yet tho? ๐Ÿค”

candid vigil
#

Previously input.sensitivity(0.5).inverted().deadzone(0.15).sensitivity(2.0) means:

  1. Scale up the input value by 2.0 (sensitivity has been overriden)
  2. Flip its sign.
  3. Apply a deadzone of 0.15
#

After 0.14 it means:

  1. Scale down the input value by 0.5
  2. Flip its sign.
  3. Apply a deadzone of 0.15
  4. Scale up the result by 2.0
restive knoll
#

The fact that sensitivity comes before deadzone sounds especially unintuitive ๐Ÿ˜‚

candid vigil
#

The old code was like that. I hadn't used Bevy back then

midnight bramble
#

not having to guess the order of execution is nice

karmic monolith
#

I'm really pleased with how this design came together ๐Ÿ˜„

restive knoll
restive knoll
#

So do we have anything for that yet? ๐Ÿค”

karmic monolith
restive knoll
#

Sensitivity doesn't make my inputs FPS independant right? ๐Ÿค”

karmic monolith
#

I don't think it should?

restive knoll
#

Yea, sensitivity definitely shouldn't ... But inputs like "Hold input to move" should be scaled by time while inputs like "Move by X units to move" shouldn't

#

If they're both "Hold input" it's easy to handle at the system level, like WASD vs a gamepad stick. But with gamepad stick vs mouse movement you can't handle that unless you look what's in the input (which seems counter to what LWIM tries to achieve)

#

And the same applies with scroll wheel to zoom vs hold left stick to zoom in and right stick to zoom in or whatever zooming scheme you come up with for controller

#

(Are those even reasonable bindings for zooming on a controller? Idk, I literally still have "TODO: controller bindings for zooming" in my code)

cyan ruin
#

Sorry to interrupt with a tangent: What's the best way to dig out the mapped input for an action so it can be displayed in a menu? Let's say for gamepads only for now, as I don't want to open the keyboard input pandora's box in this discussion. ๐Ÿ˜‚

I'd basically like to match over the mapped input to translate it to another value (for example a string to display a character in a font). I could do it with 0.14 and earlier, but now that everything's a dyn Buttonlike I don't know how.

restive knoll
#

But you do get boxed traits that you'd have to turn back I think, which might not be the most painless thing ๐Ÿค”

karmic monolith
#

Hey @candid vigil did you run into a pile of RA warnings about "unexpected token"?

#

Something is funky with the macros locally, even though cargo build runs fine

#

Trying a cargo clean...

#

welp, that fixed most of them

#

???

#

Bah lol

#

Oh, nope, it didn't

#

Well, I can cope ๐Ÿฅฒ

quartz wedge
#

if i want to fake keypresses to appear like the user pressed them am i right in thinking i just do: action_state.press(&PlayerActions::Up); and .release(..)? where should i order my system that does that so it's detected correctly?

karmic monolith
#

The key thing there is "after InputManagerSystem::Update"

quartz wedge
#

fab, thanks!

quartz wedge
#

if i say action_state.press(..) does that stay pressed until i release(), or do i need to call press() each tick to synthetically hold the key down?

#

i'm getting some flickering of my fake inputs atm

#

i'm reading the action_state in FixedUpdate fwiw

karmic monolith
quartz wedge
#

think i have to set it every frame..

karmic monolith
#

Yeah, that sounds right

candid vigil
cyan ruin
pseudo ledge
merry kraken
#

Ah, i was getting these unexpected tokens this morning. Annoying.

grave gale
#

For 0.15, is there a built-in run condition for detecting dual-axis inputs? Used to use action_pressed / etc. but looks like they only support button inputs now.

karmic monolith
flat coral
#

Surely it should be 3d in all cases, rather than 3D

midnight bramble
#

1DPad ๐Ÿง 

#

could also go with Vec3/Dir3 convention and just make it DPad3

quartz wedge
#

my inputmap maps mouse left click to an action, and i enabled the "egui" feature, hoping that would stop the actions if i'm clicking on egui things, but they still register. is there somethine else i need to do, or am i misunderstanding the feature? i don't want my engines to fire when i left click egui buttons etc.

karmic monolith
quartz wedge
#

ah, ok. thanks

cyan ruin
foggy osprey
#

That's a start at least... not sure how to get the actual button represented

foggy osprey
#

Seems like a sizable hole in lwim's API, but also can't think of any way to fix it off the top given that we can map arbitrary inputs to actions, which is something nobody wants to give up

restive knoll
#

But yea having a better API for that would be great. LWIM has had varying levels of difficulty for this but afaik it has never been easy, which is one of ther reasons I haven't attempted to make any keybinding UI or accurate input prompts

restive knoll
#

Probably the biggest question is what the API would look like ... I guess you ultimately want an enum that's easy to translate to some icons, and you can probably group the enums by separate groups like button vs axis

karmic monolith
#

I think that starting with a Display impl would be nice

#

Which you can then map to icons using localization / asset path style tech

midnight bramble
#

along with a list of everything that can go wrong

#

can LWIM distinguish between PS/xbox/nintendo controllers btw?

#

i guess it's just north/east/south/west that change between them though, i'm still not sure how UI would handle that

cyan ruin
#

Iโ€™m a rust newb so Iโ€™m completely not sure about this, but isnโ€™t it so that I can only downcast to the concrete impls if dyn Buttonlike can first be cast to dyn Any?

cyan ruin
restive knoll
midnight bramble
#

actually showing alternative bindings could be interesting though

karmic monolith
#

If we can recognize differnent controllers and use that in the display too that would be great
IIRC this is viable with a bit of gilrs integration

midnight bramble
#

"press c or ctrl to crouch"

restive knoll
#

A decent baseline would probably be:
Has this input been used? If yes, show the last used input
Has any inputs of the types registered been used? If yes, prefer that
Is a controller connected? If yes, prefer that
Is one of the input options missing? If yes, deprioritize that
If all else fails pick the first option

midnight bramble
#

wait, is it possible to make a key toggle with LWIM?

#

like "press c or hold ctrl to crouch", where c is toggle and ctrl isn't?

restive knoll
#

There are also some other considerations, like the API needs to be friendly to chords

#

Because chances are Shift + 1 is just as valid of an input as Q

midnight bramble
#

on PC it should default to MKB until controller is actually used

restive knoll
#

Defaulting to controller generally makes the most sense so people can immediately recognize the game can be played with controller ... But it gets really annoying when it only shows controller just because you have one connected. If you use kb/mouse it should show kb/mouse bindings

#

If you have one of those annoying 7 layers splash screens that are skippable people will also already have picked their input of choice before they see any prompts ๐Ÿ˜‚

midnight bramble
#

i also found that both controller and KBM are active at all times, even if it's only 1 being shown in ui

#

like sometimes character is stuck walking in 1 direction and it takes a while to realize it's the controller deadzone failing, even though i never touched controller

restive knoll
midnight bramble
#

or you start playing and it starts violently convulsing on the table in the middle of the night waking up the entire house

restive knoll
#

Games should really have a well functioning deadzone (that's ideally configurable tho)

restive knoll
#

I don't think rumble is in scope for LWIM tho, right?
If it was it would be leafwing-input-output-manager thonk

midnight bramble
#

it's shocking that it's pretty big games that fuck it up too

restive knoll
#

Triple A games are just lazy console ports anyway

midnight bramble
cyan ruin
#

I'm not sure LWIM should be too opinionated for example on whether gamepad or keyboard input or which key binding in general is prioritized - it might depend on the game. It could very well be that a tutorial wants to show a certain keybinding as it's the easiest for most players, while a settings screen just wants to show everything.

In my case it would be nice to just get an analyzable dump of all the inputs bound to a certain action, so I can make my own choices as to how they are shown on screen.

restive knoll
#

Well yea, there should probably be both a plain dump of inputs and some logic to pick what to show. There's also plenty of cases where you can show all the bound inputs, rather than only fitting one

vast bridge
#

Is there a migration guide between 14 and 15? I'm getting the trait bound bevy::prelude::KeyCode: leafwing_input_manager::user_input::Buttonlike is not satisfied [E0277] but my code looks the same as in examples. Can't spot the difference.

karmic monolith
#

That should work just fine ๐Ÿค”

#

Do you have two different versions of Bevy in your tree?

vast bridge
#

No but i have two different versions of leafwing-input-manager. Thanks for pointing out to the problem.

karmic monolith
#

Ha, I'm encountering that too tonight: I need to actually work on leafwing_abilities again...

karmic monolith
#

How much will y'all hate me if I add a Display trait bound to UserInput in a minor version

#

Technically semver incompatible but I really don't think that there's many users manually implementing this yet

#

And it would give us a start on the "how do I actually display a key binding menu" problem

#

I'm not totally sure it's possible: Bevy's winit types may not implement it

#

So I may be stuck adding an optional method to the trait

buoyant fable
#

Inlineable dyn extension trait?

#

Mayhaps

restive knoll
karmic monolith
#

You end up needing to map them to file paths ultimately

full iris
#

I was considering a Debug equivalent for UI-stuff, but it'd have to be immediate and rely on gizmos

#

and you can have a Display equivalent for spawning a permament UI element that shows that button

#

once new UI is somewhat stable Bevy should probably introduce traits for visual debugging

ripe prism
#

is there a solution in leafwing input manager for letting you hold a button down to perform an action on a cooldown?

#

i.e. if I hold space, then every 500ms it triggers another jump action, maybe via just_pressed or something

#

note that you can still manually press space at an interval shorter than 500ms, but it's just that if you keep it held down, you will repeatedly "press" it every 500ms

swift summit
#

autorepeat delay / rate would be neat

karmic monolith
#

I think that this is probably best handled in game code

ripe prism
#

idk I think this would be a useful feature at the input layer

#

since game logic usually just uses pressed, just_pressed, and it's inconvenient to have to keep track of a bunch of timers as well

#

you could have the timer/autorepeat logic in LIM, then use just_pressed to listen for the autorepeats

midnight bramble
ripe prism
#

no, not at all

#

this is better described as an autorepeat key delay

#

not an actual game-level cooldown system

#

you should still handle e.g. ability cooldowns at your gameplay layer

midnight bramble
#

ah

#

๐Ÿค”

#

yeah that might actually be really useful

ripe prism
#

it's similar to what minecraft does with its left and right clicks

#

where you can click as fast as you want and it'll break a block each time you left click, but you can also hold it down and break the block in front of you every 200ms

midnight bramble
#

yeah, or consumables that you don't want to accidentally use twice in a row but can configure it to be any delay from user side

ripe prism
#

but it could let you e.g. consume 10 items quickly if you just hold down the use key, instead of the player having to spam press

midnight bramble
#

input already tracks duration
for other use cases you might want to make duration threshold to cancel the action or release automatically
-# unity input system can do that, not sure about LWIM
and re-use is just another step on top of that

midnight bramble
#

when you press and hold the + button, you usually want it to keep adding and ramp up over time

ripe prism
#

that's a good use case as well

midnight bramble
#

not sure if that should be in LWIM though, i think mod_picking had something like it? or was it in example

ripe prism
#

if you have two configurable properties, an initial resend delay, then a resend interval

#

like you have on a regular keyboard, where you can press a key, keep it held, then after like 500ms it'll start repeatedly entering the same key

#

and my thinking of auto-resend is just a special case of that where the initial delay is 0ms

midnight bramble
#

yeah. i'm not sure how often you'd actually need it though

ripe prism
#

I want to use this for interactions and consuming items in an inventory

#

so that players wouldn't have to spam click to use up a lot of items

#

i'm sure there are valid use cases for this

midnight bramble
#

i guess it could also be useful for feedback, limiting the amount of sounds or ui animations that play

ripe prism
#

ehh

#

I'd keep this strictly to input

midnight bramble
#

it's still just input, just that you don't have to worry about handling the case where spamming the key(s) causes a noise bomb and abruptly flashing ui if you have that

cyan ruin
#

Sounds useful, but I'd maybe differentiate it from just_pressed and keep just_pressed as only the very first press event and have some just_pressed_repeat (naming tbd) for when you want auto-repeating behavior

midnight bramble
#

but yeah in some cases it just wouldn't make sense, like for aim/movement

swift summit
#

i wouldn't expect autorepeat for an axislike, and i'd expect it to be something you have to opt in to anyways

ripe prism
#

for sure, I don't expect it to be automatically enabled, but this sounds like a useful input-level feature that is opt-in

foggy osprey
# ripe prism it's similar to what minecraft does with its left and right clicks

Not exactly. It delays how often the action is repeated when held, but if you, say, point into the sky, hold down left click, then point at a block, it'll immediately break the block and then start the timer. I know that feels like a nitpick, but to me it's very indicative of how tightly coupled the behavior is with game logic. I feel like that's far out of scope for lwim (which I see as an action abstraction with an input manager tacked on) but could be a crate

wise goblet
#

wth
is inputkind no longer a thing?

#

heeeeeeeeelp

#

i'm trying to move to bevy 0.14 for funny reasons

wise goblet
#

uouuurgghhhee!!! i'm trying to just get my stuff set up and ignore the weird const thing i have for the moment
but i cant even do that because .insert returns a &mut for some reason that i cant use? and dereffing wont work

#

sorry if this should be in a help thread or something

wise goblet
#

whyyy does this work in the examples but not hereeee

#

i just want my damn code to compile PLEASE
is the examples code old and outdated or something?? i think i remember seeing something about that

#

im going to tear out functionality for looking for the time being

rugged mica
#

check if you have 2 versions of lwim in your .lock

#

i had this at some point and it breaks everything

#

ah

karmic monolith
#

The fancy derive didn't make the initial release

karmic monolith
#

Exactly the same as the manual impl

wise goblet
#

i wasnt aware there was a migration guide for this crate, could you send it to me?

karmic monolith
#

Note that 0.15.1 is still unreleased

bold lodge
#

Hi! I trying to migrate to 0.15, but faced an issue.
Looks like InputMap::insert have impl Buttonlike in the signature, which means that I have to know the type I insert.
But in games you rarely have hardcoded logic like input_map.insert(MyAction::A, [KeyCode::ShiftLeft]);, you usually load settings from the configuration file.
Previosly I just ser/de InputKind enum. But how can I pass dynamically deserialized input now? ๐Ÿค”

woeful totem
#

Hi there, i would like to have my action to contain the mouse position in world coordinates so it can be sent over network instead of the clients relative mouse position since that is not really useful, is there a way to hook into the dualaxis data or make a custom one?

woeful totem
#

its not really abt converting them, more so abt how to hook into the data itself, im not sure if/how i could modify that in an optimal way

#

hm wdym?

#

its just two floats, whats the issue?

woeful totem
#

well yea a dualaxis action is just two floats

#

mouse x and y

#

even then it should be acceptable, it shouldnt be too much of an issue

#

havent looked too much into how lightyear sends inputs but its prob as efficiently as possible so two floats shouldnt be that costly

#

its not like there is an alternative to sending them over anyways soo

#

then i wouldnt have the benefit of things like redundancy

#

actually isnt actionstate just a regular component? So maybe i could just query for it mutably, modify the underlying data

#

so basically the goal is to just

  1. user puts mouse somewhere
  2. convert the mouse coords to game coords
  3. send over said coords through inputs
  4. let the server use said coords in some way, in this case to take aim
#

adding what?

#

Well because it is an input and lightyear has redundancy for inputs by default which is useful for packetloss and such

#

it would be pretty weird to have mouse position split from all other inputs including stuff like mouse wheel

midnight bramble
#

uhhh i was thinking from server side, but i guess for client/host it makes sense

woeful totem
#

ill just have no processor

#

it would just need to run before the input buffering

#

i guess ill try that

torpid hornet
#

What is the idiomatic way to get the current mouse position with leafwing? Do I still have to use window.cursor_position() ?

bold lodge
# bold lodge Hi! I trying to migrate to 0.15, but faced an issue. Looks like `InputMap::inser...

@karmic monolith thinking about this.
We have 2 separate concepts:

  1. Actions that can be checked for just_pressed, pressed etc.
  2. Inputs that update actions state.
    I think that old design with enum for inputs was okay.
    If user want to have some esoteric input, they can create its own enum and just update actions state on their own, just provide the ability to do so.

With enums we have no issues with serialization (very important!), no small allocations on heap and unified interface to assign inputs to an action.

bold lodge
karmic monolith
#

The enum was really bloated and took to a huge amount of space due to the need to model chords

#

But I do need to get a realistic working example up for input key bindings, including serialization

restive knoll
#

Wasn't there a crate to provide serialization/deserialization for such Box<dyn X> usecases?

karmic monolith
#

Yeah, @candid vigil has a nice solution in place already

#

Quite complex

#

But functional

restive knoll
#

Other than that I think the small allocs aren't a huge problem (tho maybe it would be more efficient if more of them were combined), and the unified interface for assigning inputs we had in the past was deceptive

#

Assigning an axis to a button action never should've been a thing ๐Ÿ˜‚

bold lodge
#

Maybe we could have an enum between 4 traits?

#

And accept this enum everywhere.

restive knoll
#

It does internally do self.insert_boxed(action, Box::new(button));, so I don't think it would be hard to make a function that takes a Box

bold lodge
#

But exposing insert_boxed, insert_axis_boxed and insert_dual_axis_boxed isn't nice ๐Ÿ˜…

bold lodge
#

I.e.

enum ActionInput {
    Buttonlike(Box<dyn ButtonLike>),
    Axislike(Box<dyn Axislike>),
    DualAxisLike(Box<dyn DualAxisLike>),
}
restive knoll
bold lodge
restive knoll
#

Because a gamepad stick doesn't have a binary "forward"

#

So mapping it as 4 buttons instead of 1 dual axis would be very weird

bold lodge
#

Agree!

bold lodge
karmic monolith
bold lodge
#

Sure!
I asked here first to make sure I wasn't missing anything.

karmic monolith
#

Yep, it just got overlooked in the refactoring ๐Ÿ™‚

swift summit
restive knoll
swift summit
#

i think you only end up with that type if you create it yourself

bold lodge
#

It will work, but you will box a box

swift summit
#

oh you mean in the implementation it will get boxed

bold lodge
#

Internals do Box::new

swift summit
#

Buttonlike could expose a method that creates the Box<dyn Buttonlike> to avoid that :p

#

not pretty though

restive knoll
swift summit
#

ig at that point.. it's just impl Into<Box<dyn Buttonlike>> with extra steps :)

bold lodge
#

Ser/de is bigger issue, I don't like any of the proposed solutions ๐Ÿ˜…

#

Maybe we could just have better enums. Like keep all insert, insert_axislike, etc., but use enums instead of boxes.

restive knoll
#

Like make it enum dispatch but still keep them in some form where chord buttonlikes don't explode the enum dispatch?

bold lodge
#

Yep

restive knoll
#

Wait but if serialization/deserialization doesn't already work, what does LWIM use serde_flexitos for? ๐Ÿค”

karmic monolith
#

Yeah, we should have a functional serde solution already

#

It does need to be fully tested and taught though

restive knoll
#

LWIM development be like

full iris
#

how do you even deserialize trait objects

restive knoll
#

serde_flexitos apparantly thonk

#

Afaict it uses some type registry and probably a lot of cursed unsafe stuff bavy

karmic monolith
bold lodge
restive knoll
bold lodge
#

Yeah, totally understand you both ๐Ÿ˜…

candid vigil
#

However, Alice split it into inputlike traits, which are not currently compatible with Serde I think, since the deserializer registry isn't updated ๐Ÿค”

karmic monolith
restive knoll
#

I'm surprised LWIM even works considering the state of the examples ferris_spooky

#

I actually haven't hit any bugs, only the bad UX of the macro being bad

candid vigil
restive knoll
#

wasm strikes again ferris_sob

candid vigil
#

The reason for this is that when serializing trait objects with Serde, you need a way to identify the exact type being serialized

#

Typetag solves this by using inventory to create a registry of all possible implementations and placing it before the main function

#

However, wasm_init can only be used once, preventing typetag's use in this environment

#

LWIM currently uses serde_flexitos, which manually creates a registry but requires pre-creation and subsequent calls during deserialization

restive knoll
#

So kind of like bevy_reflect, which requires you to register things before the app does stuff with it?

candid vigil
#

yeah

#

So in the docs for the UserInput trait, I added this

#

๐Ÿค” but now we need register_buttonlike_input and friends, because InputMap stores HashMap<Action, Vec<Box<dyn Buttonlike>>> rather than UserInput objects

candid vigil
#

and add fn insert(&mut self, action: A, input: impl Into<UserInputWrapper>) to InputMap

candid vigil
#

๐Ÿค” It's an uncovered type

candid vigil
#

Perhaps I can add a new UserInput derive

candid vigil
#

the first attribute could be inputlike(...) for example #[inputlike(Button)], which implements UserInput::kind() -> InputControlKind::Button

#

the second attr could beclash_with(...), for example, clash_with(Simple(self)) for generating BasicInputs::Simple(self), clash_with(Composite(self.negative, self.positive)) for VirtualAxis, and clash_with(Chord(self.buttons)) for ButtonlikeChord

#

๐Ÿค” but I think we could split to another trait, or even refactor how input clashing check works

candid vigil
#

Weird. Compiler cannot get information of trait impls from another module?

#

Buttonlike is already implemented for GamepadButtonType in user_input/gamepad module

bold lodge
#

@candid vigil have you considered using enum dispatch instead?
Like keep Buttonlike, Axislike, but make them enums as before.

candid vigil
#

Actually, I think it's fine too

#

InputProcessors were originally trait objects, but we changed them to enum with a Custom(Box<dyn CustomInputProcessor>) variant

#

Reflection and serde for trait objects can be quite troublesome

bold lodge
#

Yes, I think the direction with enum dispatch worth exploring as well