Verified Commit 5654e8ce authored by Jakob Moser's avatar Jakob Moser
Browse files

Implement PygameMockDisplay

While I think the file was created by Big Pickle, I guess now 99% of the code are by me, especially the entire "MockDisplayThread" logic which is necessary because only the thread initializing the display can refresh it later.
parent 5526d391
Loading
Loading
Loading
Loading
+64 −0
Changes for poolpay/display/PygameMockDisplay.py: 64 added lines, 0 removed lines.
Original line number Diff line number Diff line
from __future__ import annotations

from dataclasses import dataclass, field
from functools import cached_property
from queue import SimpleQueue
from threading import Thread
from typing import Literal

import pygame
from pygame import Surface

from poolpay.display.Display import Display

type Request = tuple[int, int] | Literal["refresh"]
type Response = Surface


class MockDisplayThread(Thread):
    def __init__(self) -> None:
        super().__init__(name="mock_display")
        self._request_queue: SimpleQueue[Request] = SimpleQueue()
        self._response_queue: SimpleQueue[Response] = SimpleQueue()

    def get_response(self) -> Response:
        return self._response_queue.get(block=True)

    def request(self, request: Request) -> None:
        self._request_queue.put(request)

    def run(self) -> None:
        pygame.init()

        while True:
            request = self._request_queue.get(block=True)

            match request:
                case (width, height):
                    screen = pygame.display.set_mode((width, height))
                    self._response_queue.put(screen)
                case "refresh":
                    pygame.display.flip()


@dataclass(frozen=True)
class PygameMockDisplay(Display):
    _display_thread: MockDisplayThread = field(
        init=False, default_factory=MockDisplayThread
    )

    @cached_property
    def surface(self) -> Surface:
        self._display_thread.start()
        self._display_thread.request((self.width, self.height))

        return self._display_thread.get_response()

    def refresh(self) -> None:
        self._display_thread.request("refresh")

    def show(self, picture: bytes) -> None:
        pass


__all__ = ["PygameMockDisplay"]