248 lines
8.2 KiB
Python
248 lines
8.2 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""Input handling for Storm Games.
|
|
|
|
Provides functionality for:
|
|
- Text input dialogs
|
|
- Game pause functionality
|
|
- Exit handling
|
|
"""
|
|
|
|
import pygame
|
|
import time
|
|
from .speech import speak
|
|
|
|
def get_input(prompt="Enter text:", text=""):
|
|
"""Display an accessible text input dialog using pygame.
|
|
|
|
Features:
|
|
- Speaks each character as typed
|
|
- Left/Right arrows navigate and speak characters
|
|
- Up/Down arrows read full text content
|
|
- Backspace announces deletions
|
|
- Enter submits, Escape cancels
|
|
- Fully accessible without screen reader dependency
|
|
|
|
Args:
|
|
prompt (str): Prompt text to display (default: "Enter text:")
|
|
text (str): Initial text in input box (default: "")
|
|
|
|
Returns:
|
|
str: User input text, or None if cancelled
|
|
"""
|
|
|
|
# Initialize text buffer and cursor
|
|
text_buffer = list(text) # Use list for easier character manipulation
|
|
cursor_pos = len(text_buffer) # Start at end of initial text
|
|
|
|
# Announce the prompt and initial text
|
|
speak(prompt)
|
|
if text:
|
|
speak(f"Default text: {text}")
|
|
else:
|
|
speak("Empty text field")
|
|
|
|
# Speak initial cursor position
|
|
if cursor_pos == 0:
|
|
speak("Beginning of text")
|
|
elif cursor_pos == len(text_buffer):
|
|
speak("End of text")
|
|
else:
|
|
speak(f"At character: {text_buffer[cursor_pos]}")
|
|
|
|
# Main input loop
|
|
while True:
|
|
event = pygame.event.wait()
|
|
|
|
if event.type == pygame.KEYDOWN:
|
|
if event.key == pygame.K_RETURN:
|
|
# Submit the input
|
|
result = ''.join(text_buffer)
|
|
speak(f"Submitted: {result if result else 'empty'}")
|
|
return result
|
|
|
|
elif event.key == pygame.K_ESCAPE:
|
|
# Cancel input
|
|
speak("Cancelled")
|
|
return None
|
|
|
|
elif event.key == pygame.K_BACKSPACE:
|
|
# Delete character before cursor
|
|
if cursor_pos > 0:
|
|
deleted_char = text_buffer.pop(cursor_pos - 1)
|
|
cursor_pos -= 1
|
|
speak(f"{deleted_char} deleted")
|
|
else:
|
|
speak("Nothing to delete")
|
|
|
|
elif event.key == pygame.K_DELETE:
|
|
# Delete character at cursor
|
|
if cursor_pos < len(text_buffer):
|
|
deleted_char = text_buffer.pop(cursor_pos)
|
|
speak(f"{deleted_char} deleted")
|
|
else:
|
|
speak("Nothing to delete")
|
|
|
|
elif event.key == pygame.K_LEFT:
|
|
# Move cursor left and speak character
|
|
if cursor_pos > 0:
|
|
cursor_pos -= 1
|
|
if cursor_pos == 0:
|
|
speak("Beginning of text")
|
|
else:
|
|
speak(text_buffer[cursor_pos])
|
|
else:
|
|
speak("Beginning of text")
|
|
|
|
elif event.key == pygame.K_RIGHT:
|
|
# Move cursor right and speak character
|
|
if cursor_pos < len(text_buffer):
|
|
speak(text_buffer[cursor_pos])
|
|
cursor_pos += 1
|
|
if cursor_pos == len(text_buffer):
|
|
speak("End of text")
|
|
else:
|
|
speak("End of text")
|
|
|
|
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
|
|
# Read entire text content
|
|
if text_buffer:
|
|
speak(''.join(text_buffer))
|
|
else:
|
|
speak("Empty text field")
|
|
|
|
elif event.key == pygame.K_HOME:
|
|
# Move to beginning
|
|
cursor_pos = 0
|
|
speak("Beginning of text")
|
|
|
|
elif event.key == pygame.K_END:
|
|
# Move to end
|
|
cursor_pos = len(text_buffer)
|
|
speak("End of text")
|
|
|
|
else:
|
|
# Handle regular character input
|
|
if event.unicode and event.unicode.isprintable():
|
|
char = event.unicode
|
|
# Insert character at cursor position
|
|
text_buffer.insert(cursor_pos, char)
|
|
cursor_pos += 1
|
|
|
|
# Speak the character name
|
|
if char == ' ':
|
|
speak("space")
|
|
elif char == '\\':
|
|
speak("backslash")
|
|
elif char == '/':
|
|
speak("slash")
|
|
elif char == '!':
|
|
speak("exclamation mark")
|
|
elif char == '"':
|
|
speak("quotation mark")
|
|
elif char == '#':
|
|
speak("hash")
|
|
elif char == '$':
|
|
speak("dollar sign")
|
|
elif char == '%':
|
|
speak("percent")
|
|
elif char == '&':
|
|
speak("ampersand")
|
|
elif char == "'":
|
|
speak("apostrophe")
|
|
elif char == '(':
|
|
speak("left parenthesis")
|
|
elif char == ')':
|
|
speak("right parenthesis")
|
|
elif char == '*':
|
|
speak("asterisk")
|
|
elif char == '+':
|
|
speak("plus")
|
|
elif char == ',':
|
|
speak("comma")
|
|
elif char == '-':
|
|
speak("minus")
|
|
elif char == '.':
|
|
speak("period")
|
|
elif char == ':':
|
|
speak("colon")
|
|
elif char == ';':
|
|
speak("semicolon")
|
|
elif char == '<':
|
|
speak("less than")
|
|
elif char == '=':
|
|
speak("equals")
|
|
elif char == '>':
|
|
speak("greater than")
|
|
elif char == '?':
|
|
speak("question mark")
|
|
elif char == '@':
|
|
speak("at sign")
|
|
elif char == '[':
|
|
speak("left bracket")
|
|
elif char == ']':
|
|
speak("right bracket")
|
|
elif char == '^':
|
|
speak("caret")
|
|
elif char == '_':
|
|
speak("underscore")
|
|
elif char == '`':
|
|
speak("grave accent")
|
|
elif char == '{':
|
|
speak("left brace")
|
|
elif char == '|':
|
|
speak("pipe")
|
|
elif char == '}':
|
|
speak("right brace")
|
|
elif char == '~':
|
|
speak("tilde")
|
|
else:
|
|
# For regular letters, numbers, and other characters
|
|
speak(char)
|
|
|
|
# Allow other events to be processed
|
|
pygame.event.pump()
|
|
|
|
def pause_game():
|
|
"""Pauses the game until user presses backspace."""
|
|
speak("Game paused, press backspace to resume.")
|
|
pygame.event.clear()
|
|
try:
|
|
pygame.mixer.pause()
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
pygame.mixer.music.pause()
|
|
except:
|
|
pass
|
|
|
|
while True:
|
|
event = pygame.event.wait()
|
|
if event.type == pygame.KEYDOWN and event.key == pygame.K_BACKSPACE:
|
|
break
|
|
|
|
try:
|
|
pygame.mixer.unpause()
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
pygame.mixer.music.unpause()
|
|
except:
|
|
pass
|
|
|
|
pygame.event.pump()
|
|
|
|
def check_for_exit():
|
|
"""Check if user has pressed escape key.
|
|
|
|
Returns:
|
|
bool: True if escape was pressed, False otherwise
|
|
"""
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
|
|
return True
|
|
return False
|
|
pygame.event.pump()
|