169 lines
5.1 KiB
Python
169 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
User Profile Manager for Games
|
|
A PySDL2-based profile management system with gamepad-only controls
|
|
Refactored with separated UI and business logic components
|
|
|
|
Features:
|
|
- Create new user profiles
|
|
- Edit existing profiles
|
|
- Delete profiles
|
|
- Select active profile
|
|
- JSON-based storage
|
|
- Gamepad navigation only
|
|
- Modular UI components
|
|
"""
|
|
|
|
import time
|
|
from typing import Dict, Optional
|
|
|
|
import sdl2
|
|
import sdl2.ext
|
|
|
|
# Import separated components
|
|
from ui_components import UIRenderer, GamepadInputHandler
|
|
from profile_data import ProfileDataManager, SettingsManager
|
|
from screens import ModularScreenManager
|
|
|
|
|
|
class ProfileManager:
|
|
"""Main profile management system with separated UI and business logic"""
|
|
|
|
def __init__(self, profiles_file: str = "user_profiles.json"):
|
|
# Business logic components
|
|
self.data_manager = ProfileDataManager(profiles_file)
|
|
|
|
# Input handling
|
|
self.input_handler = GamepadInputHandler()
|
|
|
|
# SDL2 components
|
|
self.window = None
|
|
self.renderer = None
|
|
self.ui_renderer = None
|
|
self.running = True
|
|
|
|
# NEW: Modular screen manager (will be initialized after SDL setup)
|
|
self.screen_manager = None
|
|
|
|
def init_sdl(self):
|
|
"""Initialize SDL2 components"""
|
|
sdl2.ext.init(joystick=True)
|
|
|
|
# Create window
|
|
self.window = sdl2.ext.Window(
|
|
title="Profile Manager",
|
|
size=(640, 480)
|
|
)
|
|
self.window.show()
|
|
|
|
# Create renderer
|
|
self.renderer = sdl2.ext.Renderer(
|
|
self.window,
|
|
flags=sdl2.SDL_RENDERER_ACCELERATED | sdl2.SDL_RENDERER_PRESENTVSYNC
|
|
)
|
|
|
|
# Initialize UI renderer
|
|
self.ui_renderer = UIRenderer(self.renderer, (640, 480))
|
|
|
|
# NEW: Initialize modular screen manager
|
|
self.screen_manager = ModularScreenManager(self.data_manager, self.ui_renderer)
|
|
|
|
def handle_input(self):
|
|
"""Handle all input (simplified with screen delegation)"""
|
|
# Handle SDL events for keyboard
|
|
events = sdl2.ext.get_events()
|
|
for event in events:
|
|
if event.type == sdl2.SDL_QUIT:
|
|
self.running = False
|
|
elif event.type == sdl2.SDL_KEYDOWN:
|
|
action = self._keyboard_to_action(event.key.keysym.sym)
|
|
if action:
|
|
result = self.screen_manager.handle_input(action)
|
|
if not result:
|
|
self.running = False
|
|
|
|
# Handle gamepad input
|
|
gamepad_input = self.input_handler.get_gamepad_input()
|
|
for action, pressed in gamepad_input.items():
|
|
if pressed:
|
|
gamepad_action = self._gamepad_to_action(action)
|
|
if gamepad_action:
|
|
result = self.screen_manager.handle_input(gamepad_action)
|
|
if not result:
|
|
self.running = False
|
|
|
|
def _keyboard_to_action(self, key) -> str:
|
|
"""Convert keyboard input to action"""
|
|
key_map = {
|
|
sdl2.SDLK_UP: 'up',
|
|
sdl2.SDLK_DOWN: 'down',
|
|
sdl2.SDLK_LEFT: 'left',
|
|
sdl2.SDLK_RIGHT: 'right',
|
|
sdl2.SDLK_RETURN: 'confirm',
|
|
sdl2.SDLK_SPACE: 'confirm',
|
|
sdl2.SDLK_ESCAPE: 'back',
|
|
sdl2.SDLK_DELETE: 'delete',
|
|
sdl2.SDLK_BACKSPACE: 'delete'
|
|
}
|
|
return key_map.get(key, '')
|
|
|
|
def _gamepad_to_action(self, gamepad_action: str) -> str:
|
|
"""Convert gamepad input to action"""
|
|
gamepad_map = {
|
|
'up': 'up',
|
|
'down': 'down',
|
|
'left': 'left',
|
|
'right': 'right',
|
|
'button_3': 'confirm', # A/X button
|
|
'button_4': 'back', # B/Circle button
|
|
'button_9': 'delete' # X/Square button
|
|
}
|
|
return gamepad_map.get(gamepad_action, '')
|
|
|
|
def render(self):
|
|
"""Simplified rendering (delegated to screen manager)"""
|
|
# Clear and draw background
|
|
self.ui_renderer.clear_screen('black')
|
|
self.ui_renderer.draw_background_pattern('gradient')
|
|
|
|
# Delegate all screen rendering to screen manager
|
|
self.screen_manager.render()
|
|
|
|
self.ui_renderer.present()
|
|
|
|
def run(self):
|
|
"""Main application loop (unchanged)"""
|
|
self.init_sdl()
|
|
|
|
target_fps = 30
|
|
frame_time = 1000 // target_fps
|
|
|
|
while self.running:
|
|
frame_start = sdl2.SDL_GetTicks()
|
|
|
|
# Handle input
|
|
self.handle_input()
|
|
|
|
# Render
|
|
self.render()
|
|
|
|
# Frame timing
|
|
frame_elapsed = sdl2.SDL_GetTicks() - frame_start
|
|
if frame_elapsed < frame_time:
|
|
sdl2.SDL_Delay(frame_time - frame_elapsed)
|
|
|
|
# Cleanup
|
|
self.input_handler.cleanup()
|
|
sdl2.ext.quit()
|
|
|
|
|
|
# Entry point
|
|
def main():
|
|
"""Main entry point"""
|
|
manager = ProfileManager()
|
|
manager.run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|