THUAI8/map-generator/Python/Classes/MapRenderer.py

166 lines
5.8 KiB
Python

from __future__ import annotations
from queue import Queue
from typing import Any, Generator, NoReturn
from easygui import choicebox, msgbox
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.axes import Axes
from matplotlib.patches import Rectangle
from matplotlib.ticker import MultipleLocator
from matplotlib.backend_bases import MouseEvent, KeyEvent
from System import String
from GameClass.MapGenerator import MapStruct
from Preparation.Utility import PlaceType as PT
from Classes.RandomCore import RandomCore
class MapRenderer:
class RenderUnit:
r: int
c: int
tp: str
def __init__(self, _r: int, _c: int, _tp: str) -> None:
self.r = _r
self.c = _c
self.tp = _tp
class CurrentRender:
__cur_gen: Generator[PT, Any, NoReturn]
__cur: PT
def __init__(self, _areas: dict[PT, str]) -> None:
_keys = list(_areas.keys())
self.__cur = _keys[0]
def g():
while True:
for k in _keys:
yield k
self.__cur_gen = g()
def Get(self) -> PT:
return self.__cur
def Switch(self) -> None:
self.__cur = next(self.__cur_gen)
title: str
map: MapStruct
areas: dict[PT, str]
mapf: String
fig: Figure
ax: Axes
rects: list[list[Rectangle]]
queue_render: Queue[RenderUnit]
randomCores: list[RandomCore]
isCursorLift: int # 0: 未提起; 1: 提起未选定; 2: 提起并选定
cursorLift: tuple[int] # 提起坐标
cur: CurrentRender
@property
def Queue_Render(self) -> RenderUnit:
return self.queue_render.get(timeout=0.1)
@Queue_Render.setter
def Queue_Render(self, value: RenderUnit) -> None:
self.queue_render.put(value, timeout=0.1)
def __init__(self, _title, _mapStruct: MapStruct, _areas: dict[PT, str],
_mapf: str, _randoms: list[RandomCore]) -> None:
self.title = _title
self.map = _mapStruct
self.areas = _areas
self.mapf = _mapf
self.randomCores = _randoms
self.fig, self.ax = plt.subplots()
self.rects = [[Rectangle((j, i), 1, 1, facecolor=self.areas[self.map[i, j]])
for j in range(self.map.width)]
for i in range(self.map.height)]
self.queue_render = Queue()
self.isCursorLift = 0
self.cursorLift = None
self.cur = MapRenderer.CurrentRender(_areas)
def MainFrame(self) -> None:
self.fig.set_size_inches(self.map.width, self.map.height)
self.ax.set_xlim(0, self.map.width)
self.ax.set_ylim(self.map.height, 0)
self.ax.xaxis.set_major_locator(MultipleLocator(1))
self.ax.yaxis.set_major_locator(MultipleLocator(1))
self.ax.set_aspect(1)
for i in range(self.map.height):
for j in range(self.map.width):
self.ax.add_patch(self.rects[i][j])
plt.hlines(range(self.map.height + 1), 0, self.map.width)
plt.vlines(range(self.map.width + 1), 0, self.map.height)
self.fig.canvas.mpl_connect('button_press_event', self.on_click)
self.fig.canvas.mpl_connect('key_press_event', self.on_press)
plt.show()
def on_click(self, event: MouseEvent) -> None:
if not event.button:
return
match event.button:
case 1:
r, c = int(event.ydata), int(event.xdata)
match self.isCursorLift:
case 0:
self.map[r, c] = self.cur.Get()
self.Queue_Render = MapRenderer.RenderUnit(r, c, self.areas[self.cur.Get()])
self.Render()
case 1:
self.cursorLift = (r, c)
self.isCursorLift = 2
case 2:
liftr, liftc = self.cursorLift
dir_r, dir_c = (1 if liftr <= r else -1), (1 if liftc <= c else -1)
for i in range(liftr, r + dir_r, dir_r):
for j in range(liftc, c + dir_c, dir_c):
self.map[i, j] = self.cur.Get()
self.Queue_Render = MapRenderer.RenderUnit(i, j, self.areas[self.cur.Get()])
self.Render()
self.isCursorLift = 0
case 3:
self.cur.Switch()
case _:
return
def on_press(self, event: KeyEvent) -> None:
if not event.key:
return
match event.key:
case 'z':
self.isCursorLift = 1
case 'c':
MapStruct.ToFile(self.mapf, self.map)
msgbox(msg='Your map has been saved.', title=self.title)
case 'p':
opt = choicebox(msg='Choose random', title=self.title, choices=[x.Name for x in self.randomCores])
if opt is None:
return
for x in self.randomCores:
if x.Name == opt:
if x.Menu():
x.Random(self.map)
for r in range(self.map.height):
for c in range(self.map.width):
self.Queue_Render = MapRenderer.RenderUnit(r, c, self.areas[self.map[r, c]])
self.Render()
case _:
return
def Render(self) -> None:
while not self.queue_render.empty():
cur = self.Queue_Render
self._render(cur.r, cur.c, cur.tp)
plt.show(block=False)
def _render(self, r: int, c: int, tp: str) -> None:
self.rects[r][c].set_color(tp)
self.ax.draw_artist(self.rects[r][c])