hecrj / coffee

An opinionated 2D game engine for Rust
https://docs.rs/coffee
MIT License
1.09k stars 55 forks source link

Controller events #29

Closed JohnDoneth closed 5 years ago

JohnDoneth commented 5 years ago

I've made some changes to essentially inject GilRs gamepad events as input events and added GilRs as a dependency.

Currently, there's no way to poll the gamepad directly as everything is event-based. This was a blocker for me to add a nice example but the basics are there and should suffice for handling simple events and button presses.

A catch I encountered is that if an axis event occurs there won't be the following event to "zero" that same axis out, so caching the state of an axis won't work.

This PR, or future PR's could expose more of the GilRs API such as querying the power state and allowing the use of the force-feedback module.

Edit: Currently, these changes expose two GilRs types (GamepadId and EventType) which may not be preferable.

hecrj commented 5 years ago

This looks like a great start! Thank you @JohnDoneth!

I see that integrating with Gilrs is simpler than I thought. Great! However, before merging this, I think we should work on an example showcasing how to use this properly. Some usage code will give us some confidence that the API is not lacking some essential functionality.

Currently, there's no way to poll the gamepad directly as everything is event-based.

I see. Maybe we could add the cached GamepadState in the GamepadEvent for convenience?

A catch I encountered is that if an axis event occurs there won't be the following event to "zero" that same axis out, so caching the state of an axis won't work.

Is this a Gilrs bug? Or is it expected?

Thank you again for your work.

JohnDoneth commented 5 years ago

I think we should work on an example showcasing how to use this properly. Some usage code will give us some confidence that the API is not lacking some essential functionality.

I completely agree! I'll push what I have so far for, for the example, which is just a window displaying the latest event as a string. My idea was to add some sort of visualization like a gamepad with pushed buttons highlighted or something similar.

Currently, there's no way to poll the gamepad directly as everything is event-based.

I see. Maybe we could add the cached GamepadState in the GamepadEvent for convenience?

Oh right! I completely forgot about the GamepadState struct. Good catch. I was attempting to cache the state directly in the example, which is why I ran into issues. That should work and seems reasonable to me.

A catch I encountered is that if an axis event occurs there won't be the following event to "zero" that same axis out, so caching the state of an axis won't work.

Is this a Gilrs bug? Or is it expected?

I'm not sure, it's just what I experienced under Linux. I'm going to test on Windows and see if the implementations differ in emitted events.

JohnDoneth commented 5 years ago

I've hit a snag where the previously discussed GamepadState doesn't implement PartialEq or Copy as required for the Event enum and I'm not sure how to work around that. I've thought about a wrapper type but that seems quite unergonomic.

hecrj commented 5 years ago

I've hit a snag where the previously discussed GamepadState doesn't implement PartialEq or Copy

I see, maybe we could drop those for the input::Event type?

What is the libudev error on CI? I am guessing gilrs needs the library in order to work on Linux?

hecrj commented 5 years ago

@JohnDoneth I am working on this. I will create a PR in your fork once I have something working.

JohnDoneth commented 5 years ago

@hecrj Sounds good, I'll be looking out for it! :+1:

hecrj commented 5 years ago

I've ended up pushing the changes directly to this branch because making a PR showed a lot of changes from master. You shoud be able to see the changes more clearly this way.

Take a look and let me know what you think. All that's left is to implement Debug and write some docs. I will get to that later today.

We could also create a Gamepad struct implementing the new Input trait, so users can easily query gamepad state (similar to GamepadState in gilrs). The difficulty there is offering a nice API for multicontroller support. We should probably do that in another PR.

hecrj commented 5 years ago

All right, this should be ready!

I have changed the input module structure a bit. The Gamepad option with a nested event was inconsistent with the rest of input::Event. Therefore, I have split input::Event into four different input sources: Keyboard, Mouse, Gamepad, and Window.

Each one of these sources has a module inside input with its own Event type. This also has the advantage of namespacing some concepts in a better way (i.e. MouseButton is now mouse::Button, input::KeyCode is now keyboard::KeyCode, etc.). It also makes these event types reusable, simplifying ui::Event quite a bit and removing duplication.

Finally, I have changed the gamepad example so now it uses the brand new UI.

JohnDoneth commented 5 years ago

Thanks for finishing this up! I just took a look. I really like the splitting of input into input sources; I think that makes a lot of sense intuitively.

hecrj commented 5 years ago

@JohnDoneth You started it! Thank you again for all your work! :rocket: