> For the complete documentation index, see [llms.txt](https://dante-3.gitbook.io/dante-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dante-3.gitbook.io/dante-docs/modular-input-system/core-concepts/input-buffer.md).

# Input Buffer

| Types                                                           | Header                                          |
| --------------------------------------------------------------- | ----------------------------------------------- |
| `FMIPS_InputBuffer`, `FMIPS_AcceptedInput`, `FMIPS_BufferQuery` | `Runtime/MIPS_InputBuffer.h`                    |
| `FMIPS_BufferWindowDefinition`                                  | `Config/MIPS_InputConfig.h`                     |
| `UMIPS_AnimNotifyState_BufferWindow`                            | `Animation/MIPS_AnimNotifyState_BufferWindow.h` |

***

## The Buffer

Each Modular Input Component has a buffer: a ring of **held input events**, oldest first. It holds events that are waiting to be acted on:

| Source                                 | When                                                                                                                          |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| A gate's **Buffer** verdict            | A gate chose to hold the event rather than drop it.                                                                           |
| The mode's **Buffer On Block**         | A gate blocked the event and the mode keeps blocked events (*Always*, or *When Window Open* while an open window accepts it). |
| A capturing **buffer window**          | The event was allowed, but an open window collected it instead of dispatching it.                                             |
| The mode's **Buffer Unhandled Inputs** | The event was allowed and no processor handled it.                                                                            |

Anything can then take events out by tag and age: abilities, anim notifies, State Tree tasks, your own processors.

### Capacity and Age

| Component property  | Default | Effect                                                                |
| ------------------- | ------- | --------------------------------------------------------------------- |
| **Buffer Capacity** | 16      | When full, pushing a new event drops the oldest.                      |
| **Max Buffer Age**  | 1.0 s   | Events older than this are dropped. Zero keeps them until pushed out. |

Ages are measured from the event's **capture** time. Removing an event from the middle keeps the capture order of the rest.

***

## Taking Events Out

All buffer calls exist on the component, and the most common ones also as actor shortcuts in the Blueprint library.

| Call                                                                            | What it does                                                                                                                          |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Consume Buffered Input** `(Tag, MaxAge, OutEvent, TriggerEvent = Started)`    | Removes and returns the **newest** held event for the tag (or a child tag) with that trigger event. Trigger event *None* matches any. |
| **Consume Any Buffered Input** `(AcceptedInputs, Resolution, MaxAge, OutEvent)` | Removes and returns the event the resolution picks among several accepted inputs: newest, oldest or highest priority.                 |
| **Peek Buffered Input** `(Tag, MaxAge, OutEvent, TriggerEvent = Started)`       | Like consume, but leaves the event in the buffer.                                                                                     |
| **Get Buffered Inputs**                                                         | Every held event, oldest first.                                                                                                       |
| **Clear Buffer**                                                                | Empties the buffer.                                                                                                                   |

**MaxAge** limits how old an event may be. Zero or less uses the component's Max Buffer Age, and a larger value is capped by it.

### Accepted Inputs

`FMIPS_AcceptedInput` describes one input a query or a window accepts:

| Field              | Default | Description                                                             |
| ------------------ | ------- | ----------------------------------------------------------------------- |
| **Input Tag**      |         | Matches this tag and its children. Empty matches any input.             |
| **Trigger Events** | Started | Trigger events that count.                                              |
| **Priority**       | 0       | Weight under *Highest Priority* resolution. Ties go to the newer event. |

***

## Press History

**Was Pressed Recently** `(Tag, WithinSeconds)` answers *"did the player press this in the last N seconds?"* whatever the pipeline did with the press: allowed, blocked or held. **Was Trigger Event Recent** does the same for any trigger event.

Press history is kept **apart from the buffer**. A held button raises Triggered every frame and would push waiting presses out of a fixed-size ring; press history keeps only the last capture time per input and trigger event.

* The tag is matched **exactly**, not by parent.
* Only live events count; replays from a buffer window are not new presses.
* **Was Pressed Recently** looks at *Started*, so Started must be bound for that input in the config.

***

## Buffer Windows

A buffer window is a named stretch of time during which inputs are **collected rather than acted on**, such as the tail of an attack where the next attack can be queued. When it closes, one of the collected inputs is picked and, optionally, run through the pipeline again.

Windows are defined in an [Input Config](broken://pages/013281433557072993e674e43bce732501ca926b) and opened by tag.

### Definition

| Field                          | Default | Description                                                                                                                                                                                                                                  |
| ------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Window Tag**                 |         | Name used to open and close the window.                                                                                                                                                                                                      |
| **Accepted Inputs**            |         | Inputs the window works with. A window that accepts nothing holds nothing.                                                                                                                                                                   |
| **Lead Time**                  | 0 s     | Accepted inputs already held up to this long **before** the window opened count too, so a slightly early press still makes it. Something must have held them: a gate with a Buffer verdict, or a mode buffering blocked or unhandled inputs. |
| **Capture Accepted Inputs**    | On      | While open, accepted inputs that get past the gates are held instead of dispatched.                                                                                                                                                          |
| **Resolution**                 | Newest  | Which held input wins when the window closes.                                                                                                                                                                                                |
| **Replay On Close**            | On      | Runs the winner through the pipeline again when the window closes.                                                                                                                                                                           |
| **Discard Remaining On Close** | On      | Also drops the other accepted inputs held since the window opened (lead time included).                                                                                                                                                      |

### Opening and Closing

| From          | How                                                                                             |
| ------------- | ----------------------------------------------------------------------------------------------- |
| **Animation** | The **Input Buffer Window** anim notify state keeps a window open for the length of the notify. |
| **Input**     | The **Open Buffer Window** processor opens a window on an input, for a duration.                |
| **Blueprint** | **Open Buffer Window** / **Close Buffer Window** actor shortcuts, or the component functions.   |
| **C++**       | `OpenBufferWindow`, `OpenBufferWindowForDuration`, `CloseBufferWindow`, `CancelBufferWindow`.   |

* Opening a window that is already open keeps what it collected and only restarts its timer.
* Opening a tag that no bound config defines logs a warning and does nothing.
* **Close** picks the winner (if any) and replays it when the window says so.
* **Cancel** closes the window without picking or replaying anything, for example when an attack is interrupted. *Discard Remaining On Close* still applies.

### What Happens While a Window Is Open

```
Event allowed by the gates
  └─ an open window with Capture Accepted Inputs accepts it?
        yes ─► held in the buffer   (verdict Buffer, reason ModularInput.Reason.BufferWindow)
        no  ─► dispatched to the processors as usual

Event blocked by a gate
  └─ mode's Buffer On Block = When Window Open, and an open window accepts it?
        yes ─► held in the buffer
```

### What Happens When It Closes

```
CloseBufferWindow(Window.Combo)
  ├─ Look at held events captured since (OpenedAt - LeadTime) that match Accepted Inputs
  ├─ Resolution picks one (Newest · Oldest · Highest Priority) and takes it out
  ├─ Discard Remaining On Close ─► the other matching events are dropped
  ├─ On Buffer Window Closed (WindowTag, bResolved, ResolvedEvent) fires
  └─ Replay On Close and something was picked ─► the event runs through the pipeline again
        (current mode, bReplayedFromBuffer = true, not recorded as a new press)
```

### Events

| Event                       | Parameters                                                                                                                                                |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **On Buffer Window Opened** | `WindowTag`                                                                                                                                               |
| **On Buffer Window Closed** | `WindowTag`, `bResolved` (whether an input was picked), `ResolvedEvent`. It fires after the pick and the discard, and just before the winner is replayed. |

***

## Input Buffer Window (Anim Notify State)

`UMIPS_AnimNotifyState_BufferWindow`, shown in the notify menu as **Input Buffer Window**.

| Property           | Default | Description                                                                                           |
| ------------------ | ------- | ----------------------------------------------------------------------------------------------------- |
| **Window Tag**     |         | A window defined in one of the component's configs.                                                   |
| **Resolve On End** | On      | When the notify ends, pick and replay an input as the window defines. Off cancels the window instead. |

The notify finds the Modular Input Component on the mesh owner, its controller or its pawn. Without one (for example in animation previews) it does nothing. The notify is labelled `Buffer: <WindowTag>` in the timeline.

See [Buffered Combos with Anim Notifies](broken://pages/342b1e50fc9d0c24035c0b75b6bc099f64b165d7) for a full example.

***

## Patterns

### Combo queueing

Open a window over the tail of an attack that accepts the attack input. Presses during the window are collected; when the window closes, the newest press replays and starts the next attack. See the [combo guide](broken://pages/342b1e50fc9d0c24035c0b75b6bc099f64b165d7).

### Jump buffering

Let a jump pressed just before landing still count:

{% stepper %}
{% step %}

## Put a **Tag Query** gate on `Input.Jump`

Require the pawn not to be airborne (for example `State.Airborne`, supplied through `IMIPS_TagProvider`), with **Fail Verdict = Buffer**.
{% endstep %}

{% step %}

## Consume the buffered jump on landing

In the character's **On Landed** event, call **Consume Buffered Input** (`Input.Jump`, Max Age `0.15`) and jump if it returns true.
{% endstep %}
{% endstepper %}

### Polling from abilities or State Trees

Turn on **Buffer Unhandled Inputs** on a mode, and have an ability or State Tree task call **Consume Buffered Input** when it is ready to react, for example at the end of a recovery animation. Inputs nothing handled in the meantime are still there.

***

## Next Steps

{% content-ref url="/pages/342b1e50fc9d0c24035c0b75b6bc099f64b165d7" %}
[Broken mention](broken://pages/342b1e50fc9d0c24035c0b75b6bc099f64b165d7)
{% endcontent-ref %}

{% content-ref url="/pages/a80da96226263142c66afe050450b5ece2b06e07" %}
[Broken mention](broken://pages/a80da96226263142c66afe050450b5ece2b06e07)
{% endcontent-ref %}
