# `Cauldron2D.Input.Pad`
[🔗](https://github.com/jaman/cauldron/blob/v0.2.2/cauldron_2d/lib/cauldron_2d/input/pad.ex#L1)

Turns game-controller events into the set of actions a player is holding.

A game declares a padmap from action to controls, in the Xbox layout whatever the
hardware, as `Gamepad.Wire` names them:

    padmap = %{left: [:dpad_left, {:axis, :left_x, :neg}], fire: [:a, :right_bumper]}
    pad = Cauldron2D.Input.Pad.new(padmap, deadzone: 0.3)

Feed it every `{:controller, event}` map with `handle/2`; `held/1` is the set of
actions held and `strength/1` how hard each axis-driven one is pushed. Hand both to
`Cauldron2D.Input.merge/3`.

A control is a button name (`:a`, `:b`, `:x`, `:y`, `:left_bumper`, `:right_bumper`,
`:back`, `:start`, `:guide`, `:left_stick`, `:right_stick`, `:dpad_up`, `:dpad_down`,
`:dpad_left`, `:dpad_right`) or `{:axis, name, :neg | :pos}` for one direction of
`:left_x`, `:left_y`, `:right_x`, `:right_y`, `:left_trigger` or `:right_trigger`.
Axis values run `-1.0..1.0`, up and left negative; a trigger runs `0.0..1.0`.

A button holds its action in full. An axis holds it at its magnitude once past
`:deadzone`. An action held by both is held in full. Every controller's controls
count, and a controller that goes away releases what it held.

A stick may aim instead of holding actions: the padmap's `:aim` bound to
`{:stick, :left}` or `{:stick, :right}` makes `aim/1` the direction that stick is
pushed in, `{dx, dy}` of length one (up and left negative), or `nil` inside the
deadzone, measured radially; a client turns it into an aim point a fixed way from
the focus, as an on-screen thumbstick does. `:aim` holds no action of its own, but
the stick may push one: `{:stick, :left, push: [action: :thrust, beyond: 0.6,
least: 0.3, gain: 1.4]}` holds `:thrust` while the stick is past `beyond` of its
travel, at a strength that starts at `least` and grows by `gain` over the rest of the
travel to `1.0` — the rule an on-screen thumbstick's `push` follows. Defaults:
`beyond: 0.5`, `least: 0.25`, `gain: 1.6`.

# `control`

```elixir
@type control() ::
  atom()
  | {:axis, atom(), :neg | :pos}
  | {:stick, :left | :right}
  | {:stick, :left | :right, [{:push, keyword()}]}
```

# `event`

```elixir
@type event() :: %{:type =&gt; atom(), optional(atom()) =&gt; term()}
```

# `padmap`

```elixir
@type padmap() :: %{required(Cauldron2D.Input.action()) =&gt; [control()]}
```

# `push`

```elixir
@type push() :: %{
  action: Cauldron2D.Input.action(),
  beyond: float(),
  least: float(),
  gain: float()
}
```

# `t`

```elixir
@type t() :: %Cauldron2D.Input.Pad{
  aim_stick: :left | :right | nil,
  axes: %{required({non_neg_integer(), atom()}) =&gt; float()},
  bindings: %{required(control()) =&gt; [Cauldron2D.Input.action()]},
  buttons: %{required({non_neg_integer(), atom()}) =&gt; true},
  deadzone: float(),
  push: push() | nil,
  sticks: %{required({non_neg_integer(), atom()}) =&gt; float()}
}
```

# `aim`

```elixir
@spec aim(t()) :: {float(), float()} | nil
```

Where the aim stick points: a direction of length one, or `nil` with no aim stick or inside the deadzone.

# `aim_stick`

```elixir
@spec aim_stick(t()) :: :left | :right | nil
```

The stick bound to `:aim`, or `nil`.

# `axis`

```elixir
@spec axis(t(), atom()) :: float()
```

Where `axis` stands now, `-1.0..1.0` (`0.0..1.0` for a trigger): the reading furthest
from centre over every controller, or `0.0` while none is past the deadzone.

# `binds_axis?`

```elixir
@spec binds_axis?(t(), atom()) :: boolean()
```

Whether the padmap binds either direction of `axis` to an action.

# `default_map`

```elixir
@spec default_map([Cauldron2D.Input.action()]) :: padmap()
```

The padmap for `actions` that steers with the d-pad and the left stick.

Of the actions given, `:left`, `:right`, `:up` and `:down` are bound to the matching
d-pad button and direction of the left stick; the rest are left unbound.

# `handle`

```elixir
@spec handle(t(), event()) :: t()
```

Apply one controller event.

# `held`

```elixir
@spec held(t()) :: MapSet.t(Cauldron2D.Input.action())
```

The actions held by any controller.

# `new`

```elixir
@spec new(padmap(), keyword()) :: t()
```

A pad reading `padmap`.

## Options

  * `:deadzone` — the axis magnitude below which an axis holds nothing. Default `0.3`

# `push`

```elixir
@spec push(t()) :: push() | nil
```

What the aim stick pushes when pushed far, or `nil`.

# `strength`

```elixir
@spec strength(t()) :: %{required(Cauldron2D.Input.action()) =&gt; float()}
```

How hard each action held only through an axis is pushed, `0.0..1.0`.

An action a button holds is held in full and has no entry.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
