Listen for clicks, detect which display was clicked
This commit is contained in:
		@@ -2,7 +2,8 @@
 | 
				
			|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
					# SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import curses
 | 
					import curses
 | 
				
			||||||
from squirrelbattle.display.display import VerticalSplit, HorizontalSplit
 | 
					from squirrelbattle.display.display import VerticalSplit, HorizontalSplit, \
 | 
				
			||||||
 | 
					    Display
 | 
				
			||||||
from squirrelbattle.display.mapdisplay import MapDisplay
 | 
					from squirrelbattle.display.mapdisplay import MapDisplay
 | 
				
			||||||
from squirrelbattle.display.messagedisplay import MessageDisplay
 | 
					from squirrelbattle.display.messagedisplay import MessageDisplay
 | 
				
			||||||
from squirrelbattle.display.statsdisplay import StatsDisplay
 | 
					from squirrelbattle.display.statsdisplay import StatsDisplay
 | 
				
			||||||
@@ -10,7 +11,7 @@ from squirrelbattle.display.menudisplay import MainMenuDisplay, \
 | 
				
			|||||||
    InventoryDisplay, SettingsMenuDisplay
 | 
					    InventoryDisplay, SettingsMenuDisplay
 | 
				
			||||||
from squirrelbattle.display.logsdisplay import LogsDisplay
 | 
					from squirrelbattle.display.logsdisplay import LogsDisplay
 | 
				
			||||||
from squirrelbattle.display.texturepack import TexturePack
 | 
					from squirrelbattle.display.texturepack import TexturePack
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any, List
 | 
				
			||||||
from squirrelbattle.game import Game, GameMode
 | 
					from squirrelbattle.game import Game, GameMode
 | 
				
			||||||
from squirrelbattle.enums import DisplayActions
 | 
					from squirrelbattle.enums import DisplayActions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,11 +37,13 @@ class DisplayManager:
 | 
				
			|||||||
                         self.logsdisplay, self.messagedisplay]
 | 
					                         self.logsdisplay, self.messagedisplay]
 | 
				
			||||||
        self.update_game_components()
 | 
					        self.update_game_components()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_display_action(self, action: DisplayActions) -> None:
 | 
					    def handle_display_action(self, action: DisplayActions, *params) -> None:
 | 
				
			||||||
        if action == DisplayActions.REFRESH:
 | 
					        if action == DisplayActions.REFRESH:
 | 
				
			||||||
            self.refresh()
 | 
					            self.refresh()
 | 
				
			||||||
        elif action == DisplayActions.UPDATE:
 | 
					        elif action == DisplayActions.UPDATE:
 | 
				
			||||||
            self.update_game_components()
 | 
					            self.update_game_components()
 | 
				
			||||||
 | 
					        elif action == DisplayActions.MOUSE:
 | 
				
			||||||
 | 
					            self.handle_mouse_click(*params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_game_components(self) -> None:
 | 
					    def update_game_components(self) -> None:
 | 
				
			||||||
        for d in self.displays:
 | 
					        for d in self.displays:
 | 
				
			||||||
@@ -52,7 +55,20 @@ class DisplayManager:
 | 
				
			|||||||
        self.logsdisplay.update_logs(self.game.logs)
 | 
					        self.logsdisplay.update_logs(self.game.logs)
 | 
				
			||||||
        self.messagedisplay.update_message(self.game.message)
 | 
					        self.messagedisplay.update_message(self.game.message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def refresh(self) -> None:
 | 
					    def handle_mouse_click(self, y: int, x: int) -> None:
 | 
				
			||||||
 | 
					        displays = self.refresh()
 | 
				
			||||||
 | 
					        display = None
 | 
				
			||||||
 | 
					        for d in displays:
 | 
				
			||||||
 | 
					            top_y, top_x, height, width = d.y, d.x, d.height, d.width
 | 
				
			||||||
 | 
					            if top_y <= y < top_y + height and top_x <= x < top_x + width:
 | 
				
			||||||
 | 
					                # The click coordinates correspond to the coordinates
 | 
				
			||||||
 | 
					                # of that display
 | 
				
			||||||
 | 
					                display = d
 | 
				
			||||||
 | 
					        raise Exception(f"click at ({y}, {x})", display)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def refresh(self) -> List[Display]:
 | 
				
			||||||
 | 
					        displays = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.game.state == GameMode.PLAY \
 | 
					        if self.game.state == GameMode.PLAY \
 | 
				
			||||||
                or self.game.state == GameMode.INVENTORY:
 | 
					                or self.game.state == GameMode.INVENTORY:
 | 
				
			||||||
            # The map pad has already the good size
 | 
					            # The map pad has already the good size
 | 
				
			||||||
@@ -67,15 +83,22 @@ class DisplayManager:
 | 
				
			|||||||
                                     self.rows // 5 - 1, self.cols * 4 // 5)
 | 
					                                     self.rows // 5 - 1, self.cols * 4 // 5)
 | 
				
			||||||
            self.hbar.refresh(self.rows * 4 // 5, 0, 1, self.cols * 4 // 5)
 | 
					            self.hbar.refresh(self.rows * 4 // 5, 0, 1, self.cols * 4 // 5)
 | 
				
			||||||
            self.vbar.refresh(0, self.cols * 4 // 5, self.rows, 1)
 | 
					            self.vbar.refresh(0, self.cols * 4 // 5, self.rows, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            displays += [self.mapdisplay, self.statsdisplay, self.logsdisplay,
 | 
				
			||||||
 | 
					                         self.hbar, self.vbar]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.game.state == GameMode.INVENTORY:
 | 
					            if self.game.state == GameMode.INVENTORY:
 | 
				
			||||||
                self.inventorydisplay.refresh(self.rows // 10,
 | 
					                self.inventorydisplay.refresh(self.rows // 10,
 | 
				
			||||||
                                              self.cols // 2,
 | 
					                                              self.cols // 2,
 | 
				
			||||||
                                              8 * self.rows // 10,
 | 
					                                              8 * self.rows // 10,
 | 
				
			||||||
                                              2 * self.cols // 5)
 | 
					                                              2 * self.cols // 5)
 | 
				
			||||||
 | 
					                displays.append(self.inventorydisplay)
 | 
				
			||||||
        elif self.game.state == GameMode.MAINMENU:
 | 
					        elif self.game.state == GameMode.MAINMENU:
 | 
				
			||||||
            self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
					            self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
				
			||||||
 | 
					            displays.append(self.mainmenudisplay)
 | 
				
			||||||
        elif self.game.state == GameMode.SETTINGS:
 | 
					        elif self.game.state == GameMode.SETTINGS:
 | 
				
			||||||
            self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
					            self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
				
			||||||
 | 
					            displays.append(self.settingsmenudisplay)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.game.message:
 | 
					        if self.game.message:
 | 
				
			||||||
            height, width = 0, 0
 | 
					            height, width = 0, 0
 | 
				
			||||||
@@ -84,9 +107,12 @@ class DisplayManager:
 | 
				
			|||||||
                width = max(width, len(line))
 | 
					                width = max(width, len(line))
 | 
				
			||||||
            y, x = (self.rows - height) // 2, (self.cols - width) // 2
 | 
					            y, x = (self.rows - height) // 2, (self.cols - width) // 2
 | 
				
			||||||
            self.messagedisplay.refresh(y, x, height, width)
 | 
					            self.messagedisplay.refresh(y, x, height, width)
 | 
				
			||||||
 | 
					            displays.append(self.messagedisplay)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.resize_window()
 | 
					        self.resize_window()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return displays
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def resize_window(self) -> bool:
 | 
					    def resize_window(self) -> bool:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        If the window got resized, ensure that the screen size got updated.
 | 
					        If the window got resized, ensure that the screen size got updated.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ class DisplayActions(Enum):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    REFRESH = auto()
 | 
					    REFRESH = auto()
 | 
				
			||||||
    UPDATE = auto()
 | 
					    UPDATE = auto()
 | 
				
			||||||
 | 
					    MOUSE = auto()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GameMode(Enum):
 | 
					class GameMode(Enum):
 | 
				
			||||||
@@ -32,6 +33,7 @@ class KeyValues(Enum):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    Key values options used in the game
 | 
					    Key values options used in the game
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    MOUSE = auto()
 | 
				
			||||||
    UP = auto()
 | 
					    UP = auto()
 | 
				
			||||||
    DOWN = auto()
 | 
					    DOWN = auto()
 | 
				
			||||||
    LEFT = auto()
 | 
					    LEFT = auto()
 | 
				
			||||||
@@ -48,8 +50,10 @@ class KeyValues(Enum):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        Translate the raw string key into an enum value that we can use.
 | 
					        Translate the raw string key into an enum value that we can use.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if key in (settings.KEY_DOWN_SECONDARY,
 | 
					        if key == "KEY_MOUSE":
 | 
				
			||||||
                   settings.KEY_DOWN_PRIMARY):
 | 
					            return KeyValues.MOUSE
 | 
				
			||||||
 | 
					        elif key in (settings.KEY_DOWN_SECONDARY,
 | 
				
			||||||
 | 
					                     settings.KEY_DOWN_PRIMARY):
 | 
				
			||||||
            return KeyValues.DOWN
 | 
					            return KeyValues.DOWN
 | 
				
			||||||
        elif key in (settings.KEY_LEFT_PRIMARY,
 | 
					        elif key in (settings.KEY_LEFT_PRIMARY,
 | 
				
			||||||
                     settings.KEY_LEFT_SECONDARY):
 | 
					                     settings.KEY_LEFT_SECONDARY):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@
 | 
				
			|||||||
from json import JSONDecodeError
 | 
					from json import JSONDecodeError
 | 
				
			||||||
from random import randint
 | 
					from random import randint
 | 
				
			||||||
from typing import Any, Optional
 | 
					from typing import Any, Optional
 | 
				
			||||||
 | 
					import curses
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
@@ -15,7 +16,6 @@ from .resources import ResourceManager
 | 
				
			|||||||
from .settings import Settings
 | 
					from .settings import Settings
 | 
				
			||||||
from . import menus
 | 
					from . import menus
 | 
				
			||||||
from .translations import gettext as _, Translator
 | 
					from .translations import gettext as _, Translator
 | 
				
			||||||
from typing import Callable
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Game:
 | 
					class Game:
 | 
				
			||||||
@@ -25,7 +25,7 @@ class Game:
 | 
				
			|||||||
    map: Map
 | 
					    map: Map
 | 
				
			||||||
    player: Player
 | 
					    player: Player
 | 
				
			||||||
    # display_actions is a display interface set by the bootstrapper
 | 
					    # display_actions is a display interface set by the bootstrapper
 | 
				
			||||||
    display_actions: Callable[[DisplayActions], None]
 | 
					    display_actions: callable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self) -> None:
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -82,6 +82,11 @@ class Game:
 | 
				
			|||||||
            self.display_actions(DisplayActions.REFRESH)
 | 
					            self.display_actions(DisplayActions.REFRESH)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if key == KeyValues.MOUSE:
 | 
				
			||||||
 | 
					            _ignored1, x, y, _ignored2, _ignored3 = curses.getmouse()
 | 
				
			||||||
 | 
					            self.display_actions(DisplayActions.MOUSE, y, x)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.state == GameMode.PLAY:
 | 
					        if self.state == GameMode.PLAY:
 | 
				
			||||||
            self.handle_key_pressed_play(key)
 | 
					            self.handle_key_pressed_play(key)
 | 
				
			||||||
        elif self.state == GameMode.INVENTORY:
 | 
					        elif self.state == GameMode.INVENTORY:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,8 @@ class TermManager:  # pragma: no cover
 | 
				
			|||||||
        curses.cbreak()
 | 
					        curses.cbreak()
 | 
				
			||||||
        # make cursor invisible
 | 
					        # make cursor invisible
 | 
				
			||||||
        curses.curs_set(False)
 | 
					        curses.curs_set(False)
 | 
				
			||||||
 | 
					        # Catch mouse events
 | 
				
			||||||
 | 
					        curses.mousemask(True)
 | 
				
			||||||
        # Enable colors
 | 
					        # Enable colors
 | 
				
			||||||
        curses.start_color()
 | 
					        curses.start_color()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user