Skip to content

Commit

Permalink
Release 0.3 (#67)
Browse files Browse the repository at this point in the history
* Start 0.3 process

* Swap back to a by-value API

* Primitives for working with Axislike inputs

* Split primitives into a dedicated file

* Improve conversion strategy for primitives

* Direction partitionings

* Algebraic operations for Rotation

* Fixed broken tests

* InputAxis -> AxisPair

* AxisPair::new()

* Swap to usize-based hashing to support value-ful actions

* Noted addition of geometric rotation primitives

* Simplify set_state logic

* Correctly initialize ActionState again

* Fix PartialOrd trait for Timing

* Store and set action values

* Use Vec storage internally

Fixes #69.

* Experimentation with action value API

* Revert "Experimentation with action value API"

This reverts commit 76b9d15.

* Don't store action values

* Run examples in CI

Borrowed from https://github.com/bevyengine/bevy/blob/main/.github/workflows/ci.yml

* Remove bevy-specific logic in examples CI

* Don't try to run examples; way too hard

* Use underscores for crate name

* mdlint rules

* Move geometric primitives into leafwing_2d

* Remove dead code in macro

* Underscores in crate name

* Local development

* Relative path for macros crate

* Fix outdated example

* Fix underscores in crate name

* Polish README

* Fix broken doc links

* Simplify CI: no reason to try to run on all platforms

* Refactor `which_pressed` to return a `Vec<VirtualButtonState>`

This is not only cleaner than returning a `HashSet` of indicies, but also opens up the way to add `UserInput` information

* Update `get_clashes` to use a slice instead of a full `Vec`

Clippy recommended this for _performance purposes_

* Run `cargo fmt`

Oops

* Add API method to return which `UserInput` triggered an action

* Move bevy_ui dependency under a feature

* Vendor leafwing_2d orientation code

Should not block a release

* replace_at and clear_at can be used in a device-agnostic way

* Use usize for container sizes

* Fix missing dependencies

* Remove per_mode_cap

* Simplify InputMap API

* Fix docs formatting

* Remove extra pub specifier

* Remove UserInput::Null

* Remove empty_chords test

Doesn't make sense after `UserInput::Null` removal.

* Update RELEASES.md

* Add missing change to RELEASES.md

* Add methods to conveniently iterate over mappings

* Use type alias

* Add InputMap::remove

* Store ClashStrategy in a resource

* Remove clashing input caching

* Enable default for serde

* Fix formatting

* Changed `ActionState.button_states` inserts into direct assignments

* Added helper function for setting `action` as "held"

* Iterate over actions with mapping by default

In previous PR I added a method to iterate over inputs. But I realized
that such iteration should be with action like in normal map.
So I renamed the submitted `iter()` method into `iter_inputs()` and
added `iter()` that iterates over actions with inputs.
I also have to delete `IntoIter` currently because we can't use opaque
type in traits without nightly compiler.
If you know how to implement it properly - I would appreciate your
advice. But for now I removed it.

* Add binding_menu example

* Fix tests (#99)

* Fix which_pressed test

* Remove references to leafwing_2d

* Fix failing doc tests

* Depend on bevy subcrates (#100)

* Fix doc strings

* Use bevy subcrates for faster compiles and easier feature creation

* Replace run_in_state with DisableInput resource (#106)

* Replace run_in_state with DisableInput resource

* Update release notes

* Fix formatting

* Improve system label description

* Apply suggestions

* Systems refactor (#107)

* Refactor plugin systems logic

Insert systems right away instead of putting them into
input_manager_systems system set.

* Rename `InputManagerSystem::Reset` into `InputManagerSystem::Tick`

* Chain add_system_to_stage calls

* Allow use of InputMap and ActionState as resources

* Adding InputResource and supporting system modifications

* Second Attempt

* Cleaning up formatting.

* Adding RELEASES.md notice.

* Update RELEASES.md

New working as provided by alice-i-cecile

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>

* Addressing Shatur's naming Concerns.

* Adding lint exception

* adding clippy:: to too_many_arguments

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>

* Naming nits for systems (#111)

* Tests and refactoring for reasons pressed (#110)

* Move VirtualButtonState and Timing into a more appropriate location

* Use named fields in VirtualButtonState

* Removed poorly motivated ButtonThresholds struct

* reasons_pressed methods

* press and release methods on VirtualButtonState

* VirtualButtonState::tick

* Doc tests for reasons_pressed

* Shorten module names

* Refactor UserInput into its own file

* Fix timing test

* Fix broken doc tests

* ActionState::reset API (#112)

* ActionState::make_held -> ActionState::reset

* Fix rename in doc test

* Fixed misleading merge conflict in RELEASES

* Clean up release notes

* Fix import in doc tests

* More release note polish...

* Fix doc test

* Added example demonstrating how to use reset in system

* Refactor VirtualButtonState (#113)

* Rename VirtualButtonState to ButtonState

* Radically simplify ButtonState

* Re-add reasons_pressed functionality

* Fetch ActionData, not ButtonState

* Re-add Timing functionality

* Consolidate tests

* Updated release notes

* Assorted cleanup

* Fix tests

* Provide functionality to release inputs during mocking (#114)

* Note that mocked inputs will not be automatically released

* Add input releasing to input mocking tools

* Add UserInput::raw_inputs

* Add ActionState::freeze (#115)

* ActionState::freeze and ActionState::unfreeze

* Yeet DisableInput resource

* Fix stray doc test (#116)

* Replace freeze API with improved DisableInput resource (#117)

* Replace freeze API with DisableInput improved resource

ActionState::freeze was introduced to consume actions. But it turns
out not very ergonomic. Also freeze require to spawn an entity or
init the resource should which is not always the case.
In this iteration I used run criteria to make the code nicer.
Also I extended disable_input test to check if global and entity input
is released on disable.

* Use field to control if actions are enabled

* Update RELEASES.md

* Add ActionState::consume (#118)

* Update to Bevy 0.7 (#119)

* Bump dependencies

* New ergonomics!

* Fix typo

* Bump bevy_egui dev-dependency

* Finalize release notes (#120)

Co-authored-by: Rose Peck <olaf223224@gmail.com>
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
Co-authored-by: Elfein Landers <patlymlatun@mgail.com>
Co-authored-by: Hans W. Uhlig <huhlig@gmail.com>
  • Loading branch information
5 people committed Apr 17, 2022
1 parent de284e5 commit 4427392
Show file tree
Hide file tree
Showing 33 changed files with 3,009 additions and 1,939 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
toolchain: [stable]
os: [windows-latest, ubuntu-latest, macos-latest]
os: [windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
Expand Down
7 changes: 7 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"default": true,
"line-length": {
"line_length": 400
},
"no-duplicate-header": false
}
32 changes: 22 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "leafwing-input-manager"
name = "leafwing_input_manager"
description = "A powerfully direct stateful input manager for the Bevy game engine."
version = "0.2.0"
version = "0.3.0"
authors = ["Leafwing Studios"]
homepage = "https://leafwing-studios.com/"
repository = "https://github.com/leafwing-studios/leafwing-input-manager"
repository = "https://github.com/leafwing-studios/leafwing_input_manager"
license = "MIT OR Apache-2.0"
edition = "2021"
categories = ["games", "game-development"]
Expand All @@ -17,22 +17,34 @@ opt-level = 3
[workspace]
members = ["./", "tools/ci", "macros"]

[features]
default = ['ui']
ui = ['bevy_ui']

[dependencies]
bevy = {version = "0.6", default-features = false, features = ["render", "serialize"]}
leafwing_input_manager_macros = { path = "macros", version = "0.2" }

bevy_app = {version = "0.7", default-features = false}
bevy_core = {version = "0.7", default-features = false}
bevy_transform = {version = "0.7", default-features = false}
bevy_ecs = {version = "0.7", default-features = false}
bevy_input = {version = "0.7", default-features = false, features = ["serialize"]}
bevy_math = {version = "0.7", default-features = false}
bevy_utils = {version = "0.7", default-features = false}
bevy_ui = {version = "0.7", default-features = false, optional = true}
bevy_window = {version = "0.7", default-features = false}

petitset = {version = "0.2.1", features = ["serde_compat"]}
leafwing_input_manager_macros = "0.2"
derive_more = "0.99"
thiserror = "1.0"
itertools = "0.10"
serde = {version = "1.0", features = ["derive"]}

[dev-dependencies]
bevy = {version = "0.6", default-features = true}
bevy = {version = "0.7", default-features = false, features = ["bevy_sprite", "bevy_text", "bevy_ui", "bevy_render", "bevy_core_pipeline", "x11"]}
bevy_egui = {version="0.13", default-features = false}
derive_more = "0.99"

[lib]
name = "leafwing_input_manager"
path = "src/lib.rs"

[patch.crates-io]
# Use for local development
#leafwing_input_manager_macros = {path = "./macros"}
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,17 @@ and a single input can result in multiple actions being triggered, which can be

- Full keyboard, mouse and joystick support for button-like inputs.
- Effortlessly wire UI buttons to game state with one simple component!
- When clicked, your button will send a virtual button press to the corresponding entity.
- When clicked, your button will press the appropriate action on the corresponding entity.
- Store all your input mappings in a single `InputMap` component
- No more bespoke `Keybindings<KeyCode>`, `Keybindings<Gamepad>` headaches
- Look up your current input state in a single `ActionState` component
- Easily check player statistics while reading input
- That pesky maximum of 16 system parameters got you down? Say goodbye to that input handling mega-system
- Ergonomic insertion API that seamlessly blends multiple input types for you
- `input_map.insert(Action::Jump, KeyCode::Space)` XOR `input_map.insert(Action::Jump, GamepadButtonType::South)`? Have both!
- Can't decide between `input_map.insert(Action::Jump, KeyCode::Space)` and `input_map.insert(Action::Jump, GamepadButtonType::South)`? Have both!
- Full support for arbitrary button combinations: chord your heart out.
- `input_map.insert_chord(Action::Console, [KeyCode::LCtrl, KeyCode::Shift, KeyCode::C])`
- Sophisticated input disambiguation with the `ClashStrategy` enum: stop triggering individual buttons when you meant to press a chord!
- Create an arbitrary number of strongly typed disjoint action sets: decouple your camera and player state.
- Create an arbitrary number of strongly typed disjoint action sets by adding multiple copies of this plugin: decouple your camera and player state.
- Local multiplayer support: freely bind keys to distinct entities, rather than worrying about singular global state
- Networked multiplayer support: serializable structs, and a space-conscious `ActionDiff` representation to send on the wire
- Powerful and easy-to-use input mocking API for integration testing your Bevy applications
Expand All @@ -39,7 +38,7 @@ and a single input can result in multiple actions being triggered, which can be
- Please file an issue if you would like something more exotic!
- No built-in support for non-button input types (e.g. gestures or analog sticks).
- All methods on `ActionState` are `pub`: it's designed to be hooked into and extended.
- Gamepads must be associated with each player by the app using this plugin: read from the `Gamepads` resource and use `InputMap::set_gamepad`.
- Gamepads must be manually assigned to each input map: read from the `Gamepads` resource and use `InputMap::set_gamepad`.

## Instructions

Expand All @@ -48,7 +47,7 @@ This ensures the examples are in-sync with the latest release.

### Getting started

1. Add `leafwing-input-manager` to your `Cargo.toml`.
1. Add `leafwing_input_manager` to your `Cargo.toml`.
2. Create an enum of the logical actions you want to represent, and derive the `Actionlike` trait for it.
3. Add the `InputManagerPlugin` to your `App`.
4. Add the `InputManagerBundle` to your player entity (or entities!).
Expand Down
40 changes: 40 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Release Notes

## Version 0.3

### Enhancements

- added `reasons_pressed` API on `ActionState`, which records the triggering inputs
- you can use this to extract exact input information from analog inputs (like triggers or joysticks)
- added the ability to release user inputs during input mocking
- added `ActionState::consume(action)`, which allows you to consume a pressed action, ensuring it is not pressed until after it is otherwise released
- added geometric primitives (`Direction` and `Rotation`) for working with rotations in 2 dimensions
- stay tuned for first-class directional input support!

### Usability

- if desired, users are now able to use the `ActionState` and `InputMap` structs as standalone resources
- the crate name now uses underscores (`leafwing_input_manager`) rather than hyphens (`leafwing-input-manager`) to play nicer with `cargo`
- reverted change from by-reference to by-value APIs for `Actionlike` types
- this is more ergonomic (derive `Copy` when you can!), and somewhat faster in the overwhelming majority of uses
- relaxed `Hash` and `Eq` bounds on `Actionlike`
- `InputManagerPlugin::run_in_state` was replaced with `ToggleActions<A: Actionlike>` resource which controls whether or not the [`ActionState`] / [`InputMap`] pairs of type `A` are active.
- `ActionState::state` and `set_state` methods renamed to `button_state` and `set_button_state` for clarity
- simplified `VirtualButtonState` into a trivial enum `ButtonState`
- other metadata (e.g. timing information and reasons pressed) is stored in the `ActionData` struct
- users can now access the `ActionData` struct directly for each action in a `ActionState` struct, allowing full manual control for unusual needs
- removed a layer of indirection for fetching timing information: simply call `action_state.current_duration(Action::Jump)`, rather than `action_state.button_state(Action::Jump).current_duration()`
- fleshed out `ButtonState` API for better parity with `ActionState`
- removed `UserInput::Null`: this was never helpful and bloated match statements
- insert this resource when you want to suppress input collection, and remove it when you're done
- renamed the `InputManagerSystem::Reset` system label to `InputManagerSystem::Tick`.
- refactored `InputMap`
- removed methods that works with specific input mode.
- removed `n_registered`, use `get(action).len()` instead.
- added `insert_at` / `remove_at` to insert / remove input at specific index.
- added `remove` remove input for specific mapping.
- use `usize` for sizes as in other Rust containers.
- added `UserInput::raw_inputs`, which breaks down a `UserInput` into the constituent Bevy types (e.g. `KeyCode` and `MouseButton`)

### Bug fixes

- the `PartialOrd` implementation of `Timing` now correctly compares values on the basis of the current duration that the button has been held / released for

## Version 0.2

### Enhancements
Expand Down
16 changes: 8 additions & 8 deletions examples/arpg_indirection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
//! The first layer corresponds to a "slot",
//! which can then be set to a second-layer "ability" of the player's choice
//!
//! This example demonstrates how to model that pattern by copying [`VirtualButtonState`]
//! This example demonstrates how to model that pattern by copying [`ActionData`]
//! between two distinct [`ActionState`] components.

use bevy::prelude::*;
use bevy::utils::HashMap;
use bevy_utils::HashMap;
use derive_more::{Deref, DerefMut};
use leafwing_input_manager::plugin::InputManagerSystem;
use leafwing_input_manager::prelude::*;
Expand All @@ -29,7 +29,7 @@ fn main() {
.run();
}

#[derive(Actionlike, PartialEq, Eq, Clone, Debug, Hash)]
#[derive(Actionlike, PartialEq, Eq, Clone, Debug, Hash, Copy)]
enum Slot {
Primary,
Secondary,
Expand All @@ -40,7 +40,7 @@ enum Slot {
}

// The list of possible abilities is typically longer than the list of slots
#[derive(Actionlike, PartialEq, Eq, Clone, Debug, Hash)]
#[derive(Actionlike, PartialEq, Eq, Clone, Debug, Copy)]
enum Ability {
Slash,
Shoot,
Expand Down Expand Up @@ -109,11 +109,11 @@ fn copy_action_state(
)>,
) {
for (slot_state, mut ability_state, ability_slot_map) in query.iter_mut() {
for slot in Slot::iter() {
if let Some(matching_ability) = ability_slot_map.get(&slot) {
// This copies the `VirtualButtonState` between the ActionStates,
for slot in Slot::variants() {
if let Some(&matching_ability) = ability_slot_map.get(&slot) {
// This copies the `ActionData` between the ActionStates,
// including information about how long the buttons have been pressed or released
ability_state.set_state(matching_ability, slot_state.state(&slot));
ability_state.set_action_data(matching_ability, slot_state.action_data(slot));
}
}
}
Expand Down
Loading

0 comments on commit 4427392

Please sign in to comment.