squirrel-battle/squirrelbattle/menus.py

181 lines
5.2 KiB
Python

# Copyright (C) 2020-2021 by ÿnérant, eichhornchen, nicomarg, charlse
# SPDX-License-Identifier: GPL-3.0-or-later
from enum import Enum
from typing import Any, Optional
from .display.texturepack import TexturePack
from .entities.friendly import Chest, Merchant
from .entities.player import Player
from .enums import DisplayActions, GameMode, KeyValues
from .settings import Settings
from .translations import gettext as _, Translator
class Menu:
"""
A Menu object is the logical representation of a menu in the game.
"""
values: list
def __init__(self):
self.position = 0
def go_up(self) -> None:
"""
Moves the pointer of the menu on the previous value.
"""
self.position = max(0, self.position - 1)
def go_down(self) -> None:
"""
Moves the pointer of the menu on the next value.
"""
self.position = min(len(self.values) - 1, self.position + 1)
def validate(self) -> Any:
"""
Selects the value that is pointed by the menu pointer.
"""
return self.values[self.position]
class MainMenuValues(Enum):
"""
Values of the main menu.
"""
START = "New game"
RESUME = "Resume"
SAVE = "Save"
LOAD = "Load"
SETTINGS = "Settings"
EXIT = "Exit"
def __str__(self):
return _(self.value)
class MainMenu(Menu):
"""
A special instance of a menu : the main menu.
"""
values = [e for e in MainMenuValues]
class SettingsMenu(Menu):
"""
A special instance of a menu : the settings menu.
"""
waiting_for_key: bool = False
def update_values(self, settings: Settings) -> None:
self.values = list(settings.__dict__.items())
self.values.append(("RETURN", ["", _("Back")]))
def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str,
game: Any) -> None:
"""
In the setting menu, we can select a setting and change it.
"""
if not self.waiting_for_key:
# Navigate normally through the menu.
if key == KeyValues.SPACE or \
key == KeyValues.ENTER and \
self.position == len(self.values) - 1:
# Go back
game.display_actions(DisplayActions.UPDATE)
game.state = GameMode.MAINMENU
if key == KeyValues.DOWN:
self.go_down()
if key == KeyValues.UP:
self.go_up()
if key == KeyValues.ENTER and self.position < len(self.values) - 1:
# Change a setting
option = self.values[self.position][0]
if option == "TEXTURE_PACK":
game.settings.TEXTURE_PACK = \
TexturePack.get_next_pack_name(
game.settings.TEXTURE_PACK)
game.settings.write_settings()
self.update_values(game.settings)
elif option == "LOCALE":
game.settings.LOCALE = 'fr' if game.settings.LOCALE == 'en'\
else 'de' if game.settings.LOCALE == 'fr' else 'es' \
if game.settings.LOCALE == 'de' else 'en'
Translator.setlocale(game.settings.LOCALE)
game.settings.write_settings()
self.update_values(game.settings)
else:
self.waiting_for_key = True
self.update_values(game.settings)
else:
option = self.values[self.position][0]
# Don't use an already mapped key
if any(getattr(game.settings, opt) == raw_key
for opt in game.settings.settings_keys if opt != option):
return
setattr(game.settings, option, raw_key)
game.settings.write_settings()
self.waiting_for_key = False
self.update_values(game.settings)
class InventoryMenu(Menu):
"""
A special instance of a menu : the menu for the inventory of the player.
"""
player: Player
def update_player(self, player: Player) -> None:
"""
Updates the player.
"""
self.player = player
@property
def values(self) -> list:
"""
Returns the values of the menu.
"""
return self.player.inventory
class StoreMenu(Menu):
"""
A special instance of a menu : the menu for the inventory of a merchant.
"""
merchant: Merchant = None
def update_merchant(self, merchant: Merchant) -> None:
"""
Updates the merchant.
"""
self.merchant = merchant
@property
def values(self) -> list:
"""
Returns the values of the menu.
"""
return self.merchant.inventory if self.merchant else []
class ChestMenu(Menu):
"""
A special instance of a menu : the menu for the inventory of a chest.
"""
chest: Chest = None
def update_chest(self, chest: Chest) -> None:
"""
Updates the player.
"""
self.chest = chest
@property
def values(self) -> list:
"""
Returns the values of the menu.
"""
return self.chest.inventory if self.chest else []