Update "Input-and-Events"

John McCardle 2025-11-29 23:11:51 +00:00
parent 9ce4d4d425
commit af3c216722
1 changed files with 162 additions and 0 deletions

162
Input-and-Events.md Normal file

@ -0,0 +1,162 @@
# Input and Events
McRogueFace provides keyboard, mouse, and window event handling through Python callbacks. Events are dispatched through the scene system, allowing different scenes to have different input handlers.
**Related Pages:**
- [[UI-Widget-Patterns]] - Modal dialogs, buttons, hotbars
- [[Grid-Interaction-Patterns]] - Entity selection, movement, context menus
- [[Writing-Tests]] - Testing input with automation API
**Key Files:**
- `src/GameEngine.cpp::processEvent()` - Event dispatch
- `src/Scene.cpp::sUserInput()` - Scene input handling
- `src/McRFPy_API.cpp` - Python callback registration
---
## Keyboard Input
Register a scene-level callback that fires on every key press/release:
```python
import mcrfpy
def handle_key(key: str, pressed: bool):
"""
key: Key name (e.g., "W", "Space", "Escape", "Up")
pressed: True on press, False on release
"""
if key == "Escape" and pressed:
mcrfpy.setScene("menu")
mcrfpy.keypressScene(handle_key)
```
### Key Names
Common key names from SFML:
- Letters: `"A"` through `"Z"`
- Numbers: `"Num0"` through `"Num9"`
- Arrows: `"Up"`, `"Down"`, `"Left"`, `"Right"`
- Special: `"Space"`, `"Enter"`, `"Escape"`, `"Tab"`, `"LShift"`, `"RShift"`, `"LControl"`, `"RControl"`
- Function: `"F1"` through `"F12"`
---
## Mouse Input
### Element Event Handlers
All UIDrawables support mouse event callbacks:
| Property | Signature | When Called |
|----------|-----------|-------------|
| `on_click` | `(x, y, button) -> None` | Mouse button pressed on element |
| `on_enter` | `() -> None` | Mouse enters element bounds |
| `on_exit` | `() -> None` | Mouse leaves element bounds |
| `on_move` | `(x, y) -> None` | Mouse moves within element |
```python
frame = mcrfpy.Frame(pos=(100, 100), size=(200, 50))
frame.on_click = lambda x, y, btn: print(f"Clicked at ({x}, {y}) with button {btn}")
frame.on_enter = lambda: print("Mouse entered")
frame.on_exit = lambda: print("Mouse exited")
```
The `hovered` property (read-only) indicates whether the mouse is currently over an element.
### Grid Cell Events
Grids provide cell-level mouse events in addition to element events:
| Property | Signature | Description |
|----------|-----------|-------------|
| `on_cell_click` | `(grid_x, grid_y, button) -> None` | Cell clicked |
| `on_cell_enter` | `(grid_x, grid_y) -> None` | Mouse enters cell |
| `on_cell_exit` | `(grid_x, grid_y) -> None` | Mouse leaves cell |
| `hovered_cell` | `(x, y)` or `None` | Currently hovered cell (read-only) |
See [[Grid-Interaction-Patterns]] for usage examples.
### Mouse Position
```python
# Window coordinates (pixels)
x, y = mcrfpy.getMousePos()
```
---
## Event Priority
### Click Dispatch Order
Clicks are dispatched in reverse render order (front to back):
1. **UI elements with highest z_index** receive clicks first
2. If handled (callback returns truthy), propagation stops
3. **Entities on grids** receive clicks next
4. **Grid cells** receive clicks last
### Keyboard Priority
Keyboard events go only to the current scene's registered callback. There is no concept of "focused" UI elements for keyboard input.
---
## Window Events
### Resize Events
Window resize events are not currently exposed directly. Workaround using timer polling:
```python
last_size = mcrfpy.getWindowSize()
def check_resize(dt):
global last_size
current = mcrfpy.getWindowSize()
if current != last_size:
on_resize(current)
last_size = current
mcrfpy.setTimer("resize_check", check_resize, 100)
```
---
## Testing Input
Use the automation API to simulate input in tests:
```python
from mcrfpy import automation
automation.keypress("W", True) # Press W
automation.keypress("W", False) # Release W
automation.click(100, 200, button=0) # Left-click at position
```
See [[Writing-Tests]] for complete testing patterns.
---
## API Reference
**Module Functions:**
- `mcrfpy.keypressScene(callback)` - Register keyboard handler
- `mcrfpy.getMousePos() -> (int, int)` - Get mouse position
- `mcrfpy.getWindowSize() -> (int, int)` - Get window dimensions
**UIDrawable Properties:**
- `on_click`, `on_enter`, `on_exit`, `on_move` - Event handlers
- `hovered` - Mouse hover state (read-only)
**Grid Properties:**
- `on_cell_click`, `on_cell_enter`, `on_cell_exit` - Cell event handlers
- `hovered_cell` - Currently hovered cell (read-only)
---
*Last updated: 2025-11-29*