Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upInput rebinding phase 2 #261
Conversation
Xaeroxe
added some commits
Jul 21, 2017
Xaeroxe
requested a review
from amethyst/engine-devs
Jul 21, 2017
Xaeroxe
added some commits
Jul 21, 2017
| - pub fn pressed_keys(&self) -> PressedKeys { | ||
| - self.current_frame.pressed_keys() | ||
| + /// Returns a vector containing pressed down keys. | ||
| + pub fn pressed_keys(&self) -> &SmallVec<[VirtualKeyCode; 16]> { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| } | ||
| /// Returns a vector containing mouse buttons released on this frame. | ||
| - pub fn released_mouse_buttons(&self) -> &SmallVec<[MouseButton; 8]> { | ||
| - &self.released_mouse_buttons | ||
| + pub fn released_mouse_buttons(&self) -> &[MouseButton] { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
torkleyy
Jul 21, 2017
Member
I would find it more consistent to return an iterator everywhere or a slice everywhere. Since the latter seems to be impossible, let's go for the former. You can just use slice::Iter here.
torkleyy
Jul 21, 2017
Member
I would find it more consistent to return an iterator everywhere or a slice everywhere. Since the latter seems to be impossible, let's go for the former. You can just use slice::Iter here.
| - Button::Mouse(*mb) | ||
| -} | ||
| + /// Returns an action's bindings. | ||
| + pub fn get_action_bindings(&self, id: i32) -> Option<SmallVec<[Button; 8]>> { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| @@ -11,6 +11,6 @@ mod broadcaster; | ||
| pub use self::broadcaster::Broadcaster; | ||
| pub use self::camera::{Camera, Projection}; | ||
| -pub use self::input::{Axis, Button, InputHandler, PressedButtons, PressedKeys, PressedMouseButtons}; | ||
| +pub use self::input::{Axis, Button, InputHandler, ButtonIterator}; |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| @@ -71,6 +71,7 @@ pub extern crate amethyst_renderer as renderer; | ||
| pub extern crate amethyst_config as config; | ||
| extern crate cgmath; | ||
| +extern crate smallvec; |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
added some commits
Jul 21, 2017
ebkalderon
requested changes
Jul 21, 2017
Apart from some minor nitpicks, the meat of this PR looks solid! Thank you, @Xaeroxe.
| @@ -333,9 +333,9 @@ impl InputHandler { | ||
| } | ||
| /// Returns the value of an axis by the i32 id, if the id doesn't exist this returns None. | ||
| - pub fn axis_value(&self, id: i32) -> Option<f32> { | ||
| + pub fn axis_value(&self, id: &str) -> Option<f32> { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
Since this is a user-facing API, could we use AsRef<str> instead of &str in all the axis_ methods so users can easily pass in different kinds of string types?
ebkalderon
Jul 21, 2017
Member
Since this is a user-facing API, could we use AsRef<str> instead of &str in all the axis_ methods so users can easily pass in different kinds of string types?
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
torkleyy
Jul 21, 2017
Member
I disagree. It's more difficult to read and you'll almost always pass a literal. If we argue with "it can save the user a method call sometimes", then Rust's choice being explicit about conversions doesn't make sense.
torkleyy
Jul 21, 2017
Member
I disagree. It's more difficult to read and you'll almost always pass a literal. If we argue with "it can save the user a method call sometimes", then Rust's choice being explicit about conversions doesn't make sense.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
The AsRef trait exists precisely for this reason, though. It's meant to eliminate boilerplate in case users decide to pass in a String, CStr(ing), OsStr(ing), or perhaps even a simple array of bytes, and more importantly, it can prevent extra heap allocations on the user's end.
ebkalderon
Jul 21, 2017
•
Member
The AsRef trait exists precisely for this reason, though. It's meant to eliminate boilerplate in case users decide to pass in a String, CStr(ing), OsStr(ing), or perhaps even a simple array of bytes, and more importantly, it can prevent extra heap allocations on the user's end.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
Good point, I looked into it and I must have indeed been thinking about Into<String>. But my first point still stands. Even the Rust standard library makes frequent use of AsRef in exactly this way to avoid such boilerplate, and I think that users might appreciate an API that assists them similarly with zero runtime cost.
ebkalderon
Jul 21, 2017
•
Member
Good point, I looked into it and I must have indeed been thinking about Into<String>. But my first point still stands. Even the Rust standard library makes frequent use of AsRef in exactly this way to avoid such boilerplate, and I think that users might appreciate an API that assists them similarly with zero runtime cost.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
Jul 21, 2017
Member
If we use Into<String> we'll likely be introducing an unnecessary allocation, as the hashmap prefers to take keys by reference rather than by value. Most usage of this is going to be string literals.
Xaeroxe
Jul 21, 2017
Member
If we use Into<String> we'll likely be introducing an unnecessary allocation, as the hashmap prefers to take keys by reference rather than by value. Most usage of this is going to be string literals.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
@Xaeroxe Sorry, perhaps I wasn't clear enough. I am suggesting we use AsRef<str>, not Into<String>. I had mistakenly pointed out that AsRef<str> would reduce unnecessary allocations, confusing it for Into<String>.
However, I still stand by my point that AsRef<str> will behave identically to &str except it will allow users to pass in other string slice types like OsStr and CStr with less boilerplate. I also cite the Rust standard library as a frequent user of this pattern.
ebkalderon
Jul 21, 2017
•
Member
@Xaeroxe Sorry, perhaps I wasn't clear enough. I am suggesting we use AsRef<str>, not Into<String>. I had mistakenly pointed out that AsRef<str> would reduce unnecessary allocations, confusing it for Into<String>.
However, I still stand by my point that AsRef<str> will behave identically to &str except it will allow users to pass in other string slice types like OsStr and CStr with less boilerplate. I also cite the Rust standard library as a frequent user of this pattern.
| @@ -40,6 +40,7 @@ specs = "0.9.1" | ||
| rayon = "0.7" | ||
| ticketed_lock = "0.1" | ||
| wavefront_obj = "5.0" | ||
| +smallvec = "0.4" |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| + } | ||
| + } | ||
| + None => { | ||
| + make_new = true; |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
Why have a make_new variable? Can't lines 469-471 be copied into this branch verbatim and be easier to read?
ebkalderon
Jul 21, 2017
Member
Why have a make_new variable? Can't lines 469-471 be copied into this branch verbatim and be easier to read?
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
Jul 21, 2017
Member
No, because it makes the borrow checker mad. self.actions is already borrowed thanks to the match statement.
Xaeroxe
Jul 21, 2017
Member
No, because it makes the borrow checker mad. self.actions is already borrowed thanks to the match statement.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
Ahh, I see. I forgot about the borrow checker. I wonder if the upcoming non-lexical lifetimes in Rust will help with these kinds of issues.
ebkalderon
Jul 21, 2017
•
Member
Ahh, I see. I forgot about the borrow checker. I wonder if the upcoming non-lexical lifetimes in Rust will help with these kinds of issues.
| + action_bindings.swap_remove(index); | ||
| + } | ||
| + if action_bindings.len() == 0 { | ||
| + kill_it = true; |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| - pub fn pressed_keys(&self) -> PressedKeys { | ||
| - self.current_frame.pressed_keys() | ||
| + /// Returns a vector containing pressed down keys. | ||
| + pub fn pressed_keys(&self) -> Iter<VirtualKeyCode> { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| - pub fn mouse_button_is_pressed(&self, button: MouseButton) -> bool { | ||
| - self.current_frame.mouse_button_is_pressed(button) | ||
| + /// Returns a vector containing pressed down mouse buttons. | ||
| + pub fn pressed_mouse_buttons(&self) -> Iter<MouseButton> { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| + } | ||
| + | ||
| + /// Returns a vector containing the buttons that were pressed this frame | ||
| + pub fn down_buttons(&self) -> ButtonIterator { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ebkalderon
Jul 21, 2017
Member
Could ButtonIterator be renamed to Buttons to remain consistent with other iterator names?
ebkalderon
Jul 21, 2017
Member
Could ButtonIterator be renamed to Buttons to remain consistent with other iterator names?
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
@ebkalderon Changes you requested have been made. |
torkleyy
requested changes
Jul 21, 2017
That's great! It still needs some polishing, though.
| - /// Returns an iterator for all the pressed down keys. | ||
| - pub fn pressed_keys(&self) -> PressedKeys { | ||
| - self.current_frame.pressed_keys() | ||
| + /// Returns a vector containing pressed down keys. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| - /// Checks if the given key is being pressed. | ||
| - pub fn key_is_pressed(&self, key: VirtualKeyCode) -> bool { | ||
| - self.current_frame.key_is_pressed(key) | ||
| + /// Returns a vector containing keys pressed on this frame. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| - /// Checks if all the given keys are being pressed. | ||
| - pub fn keys_are_pressed(&self, keys: &[VirtualKeyCode]) -> bool { | ||
| - self.current_frame.keys_are_pressed(keys) | ||
| + /// Returns a vector containing keys released on this frame. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| + self.down_mouse_buttons.iter() | ||
| + } | ||
| + | ||
| + /// Returns a vector containing mouse buttons released on this frame. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| } | ||
| /// Checks if all the given actions are pressed. | ||
| /// | ||
| /// If any action in this list is invalid this will return the id of it in Err. | ||
| - pub fn actions_are_pressed(&self, actions: &[i32]) -> Result<bool, Vec<i32>> { | ||
| + pub fn actions_are_pressed<T: AsRef<str>>(&self, actions: &[T]) -> Result<bool, Vec<String>> { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
torkleyy
Jul 21, 2017
Member
Can we remove the verb here like it is the case above with the mouse buttons?
torkleyy
Jul 21, 2017
Member
Can we remove the verb here like it is the case above with the mouse buttons?
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
Jul 21, 2017
Member
Verb is used to visually distinguish this function name, otherwise the function names get too similar and people get confused.
Xaeroxe
Jul 21, 2017
Member
Verb is used to visually distinguish this function name, otherwise the function names get too similar and people get confused.
| - /// If one does exist this will replace the action at that id and return it. | ||
| - pub fn insert_action(&mut self, id: i32, binding: Button) -> Option<Button> { | ||
| - self.actions.insert(id, binding) | ||
| + /// Get's a list of all axes |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
| - self.actions.insert(id, binding) | ||
| + /// Get's a list of all axes | ||
| + pub fn axes(&self) -> Vec<String> { | ||
| + self.axes.keys().map(|k| k.clone()).collect::<Vec<String>>() |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
Jul 21, 2017
Member
Cuz I don't want another opaque Iterator type for this function, and this function is called very infrequently.
Xaeroxe
Jul 21, 2017
Member
Cuz I don't want another opaque Iterator type for this function, and this function is called very infrequently.
| + /// This will insert a new binding between this action and the button. | ||
| + pub fn insert_action_binding<T: AsRef<str>>(&mut self, id: T, binding: Button) { | ||
| + let mut make_new = false; | ||
| + match self.actions.get_mut(id.as_ref()) { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
Jul 21, 2017
Member
We can, I used it, it mandated an extra allocation in situations where it wasn't necessary, so I took it out.
Xaeroxe
Jul 21, 2017
Member
We can, I used it, it mandated an extra allocation in situations where it wasn't necessary, so I took it out.
| + if let Some(index) = index { | ||
| + action_bindings.swap_remove(index); | ||
| + } | ||
| + if action_bindings.len() == 0 { |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
torkleyy
Jul 21, 2017
Member
Let's use late binding here: Change the line at the beginning of the method to let kill_it; and change this line to kill_it = action_bindings.is_empty().
torkleyy
Jul 21, 2017
Member
Let's use late binding here: Change the line at the beginning of the method to let kill_it; and change this line to kill_it = action_bindings.is_empty().
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Xaeroxe
Jul 21, 2017
Member
Not possible, if the given action isn't valid then we can't run kill_it = action_bindings.is_empty() which leaves kill_it uninitialized.
Xaeroxe
Jul 21, 2017
Member
Not possible, if the given action isn't valid then we can't run kill_it = action_bindings.is_empty() which leaves kill_it uninitialized.
| @@ -11,6 +11,6 @@ mod broadcaster; | ||
| pub use self::broadcaster::Broadcaster; | ||
| pub use self::camera::{Camera, Projection}; | ||
| -pub use self::input::{Axis, Button, InputHandler, PressedButtons, PressedKeys, PressedMouseButtons}; | ||
| +pub use self::input::{Axis, Button, Buttons, KeyCodes, MouseButtons, InputHandler}; |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
torkleyy
Jul 21, 2017
Member
Sorry, but this is not ordered alphabetically. Hope I don't annoy you with that.
torkleyy
Jul 21, 2017
Member
Sorry, but this is not ordered alphabetically. Hope I don't annoy you with that.
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
kvark
Jul 21, 2017
Member
Alphabetical ordering together with the maximum line width is super annoying. Gotta redo quite a few lines just to make a simple change :(
kvark
Jul 21, 2017
Member
Alphabetical ordering together with the maximum line width is super annoying. Gotta redo quite a few lines just to make a simple change :(
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
torkleyy
Jul 21, 2017
Member
So what do you suggest? I just think that alphabetical order helps when you read them (and it looks really clean and tidy).
torkleyy
Jul 21, 2017
Member
So what do you suggest? I just think that alphabetical order helps when you read them (and it looks really clean and tidy).
Xaeroxe
added some commits
Jul 21, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
@torkleyy Requesting either your approval or additional input |
torkleyy
approved these changes
Jul 21, 2017
It's great, thanks for addressing my comments!
Xaeroxe commentedJul 21, 2017
•
edited
Edited 1 time
-
Xaeroxe
edited Jul 21, 2017 (most recent)
Things done in this PR
These functions will be helpful with assigning bindings in the first place when we just need to generically query for "whatever the user pressed."
These functions will be helpful for figuring out what to display on input rebinding screens.
ButtonIteratortype.Eventually there is going to be a phase 3 to make this interact with the asset system, which I plan on doing as soon as Ron is ready for use.