from __future__ import annotations
from PySide6.QtCore import QPoint, QRect
from BaseMod.tiles.tileUtils import can_place, place_tile, TileHistory, remove_tile, PlacedTileBody
from RWS.Modify import HistoryElement
from RWS.Loaders import Tile
from RWS.Utils import draw_line, draw_rect, draw_ellipse
[docs]
class TilePen(TileHistory):
[docs]
def __init__(self, history, start: QPoint, tile: Tile, layer: int,
delete=False, force_place=False, force_geometry=False, strict=True):
super().__init__(history, tile, layer, force_place, force_geometry)
self.positions = []
self.start = start
self.delete = delete
self.strict = strict
if delete:
tile = remove_tile(history.level, start, layer, strict)
if tile is not None:
self.savedtiles.append(tile)
elif can_place(self.history.level, start, layer, tile, self.fp, self.fg, self.area, self.area2):
tile = place_tile(self.history.level, start, layer, tile, self.area, self.area2, self.fp, self.fg)
if tile is not None:
self.savedtiles.append(tile)
self.redraw()
[docs]
def add_move(self, position):
start = self.start
if len(self.positions) > 0:
start = self.positions[-1]
self.positions.append(position)
points = []
draw_line(start, position, lambda p: points.append(p))
points.pop(0)
for point in points:
if self.delete:
tile = remove_tile(self.history.level, point, self.layer, self.strict)
if tile is not None:
self.savedtiles.append(tile)
elif can_place(self.history.level, point, self.layer, self.tile, self.fp, self.fg, self.area, self.area2):
tile = place_tile(self.history.level, point, self.layer, self.tile, self.area, self.area2, self.fp, self.fg)
if tile is not None:
self.savedtiles.append(tile)
self.redraw()
[docs]
class TileBrush(TileHistory):
[docs]
def __init__(self, history, start: QPoint, tile: Tile, layer: int, radius: float,
delete=False, force_place=False, force_geometry=False, strict=True):
super().__init__(history, tile, layer, force_place, force_geometry)
self.positions = []
self.start = start
self.delete = delete
self.strict = strict
self.radius = radius
r2 = round(self.radius / 2)
rect = QRect(start.x() - r2, start.y() - r2, self.radius, self.radius)
draw_ellipse(rect, False, self.paint_circle)
self.redraw()
[docs]
def add_move(self, position):
start = self.start
if len(self.positions) > 0:
start = self.positions[-1]
self.positions.append(position)
points = []
draw_line(start, position, lambda p: points.append(p))
points.pop(0)
r2 = round(self.radius / 2)
for point in points:
rect = QRect(point.x() - r2, point.y() - r2, self.radius, self.radius)
draw_ellipse(rect, False, self.paint_circle)
self.redraw()
[docs]
def paint_circle(self, point: QPoint):
if self.delete:
tile = remove_tile(self.history.level, point, self.layer, self.strict)
if tile is not None:
self.savedtiles.append(tile)
elif can_place(self.history.level, point, self.layer, self.tile, self.fp, self.fg, self.area, self.area2):
tile = place_tile(self.history.level, point, self.layer, self.tile, self.area, self.area2, self.fp, self.fg)
if tile is not None:
self.savedtiles.append(tile)
[docs]
class TileRectangle(TileHistory):
[docs]
def __init__(self, history, rect: QRect, tile: Tile, layer: int, hollow=False,
delete=False, force_place=False, force_geometry=False, strict=True):
super().__init__(history, tile, layer, force_place, force_geometry)
self.positions = []
self.rect = rect
self.delete = delete
self.strict = strict
self.hollow = hollow
draw_rect(rect, hollow, self.place_tile)
self.redraw()
[docs]
def place_tile(self, point: QPoint):
if self.delete:
tile = remove_tile(self.history.level, point, self.layer, self.strict)
if tile is not None:
self.savedtiles.append(tile)
elif can_place(self.history.level, point, self.layer, self.tile, self.fp, self.fg, self.area, self.area2):
tile = place_tile(self.history.level, point, self.layer, self.tile, self.area, self.area2, self.fp, self.fg)
if tile is not None:
self.savedtiles.append(tile)
[docs]
class TileEllipse(TileHistory):
[docs]
def __init__(self, history, rect: QRect, tile: Tile, layer: int, hollow=False,
delete=False, force_place=False, force_geometry=False, strict=True):
super().__init__(history, tile, layer, force_place, force_geometry)
self.positions = []
self.rect = rect
self.delete = delete
self.strict = strict
self.hollow = hollow
draw_ellipse(rect, hollow, self.place_tile)
self.redraw()
[docs]
def place_tile(self, point: QPoint):
if self.delete:
tile = remove_tile(self.history.level, point, self.layer, self.strict)
if tile is not None:
self.savedtiles.append(tile)
elif can_place(self.history.level, point, self.layer, self.tile, self.fp, self.fg, self.area, self.area2):
tile = place_tile(self.history.level, point, self.layer, self.tile, self.area, self.area2, self.fp, self.fg)
if tile is not None:
self.savedtiles.append(tile)
[docs]
class TileLine(TileBrush):
[docs]
def __init__(self, history, start: QPoint, end: QPoint, tile: Tile, layer: int,
radius: int, delete=False, force_place=False, force_geometry=False, strict=True):
super().__init__(history, start, tile, layer, radius, delete, force_place, force_geometry, strict)
self.start = start
self.end = end
self.add_move(end)
self.redraw()
[docs]
class LevelResizedTiles(HistoryElement):
[docs]
def __init__(self, history, changerect: QRect):
super().__init__(history)
self.changerect = changerect
self.oldtiles = None
self.module = self.level.viewport.modulenames["tiles"]
self.redo_changes()
[docs]
def undo_changes(self):
self.module.l1.clear_scene()
self.module.l2.clear_scene()
self.module.l3.clear_scene()
self.level.l_tiles.tiles = self.oldtiles # definitely gonna have some memory issues later
self.module.l1.fill_scene()
self.module.l2.fill_scene()
self.module.l3.fill_scene()
[docs]
def redo_changes(self):
self.module.l1.clear_scene()
self.module.l2.clear_scene()
self.module.l3.clear_scene()
newtiles = []
for x in range(self.changerect.width()):
newtiles.append([])
for y in range(self.changerect.height()):
newtiles[-1].append(self.getnewpixel(x, y))
self.oldtiles, self.level.l_tiles.tiles = self.level.l_tiles.tiles, newtiles
self.module.l1.fill_scene()
self.module.l2.fill_scene()
self.module.l3.fill_scene()
[docs]
def getnewpixel(self, x, y):
if x < -self.changerect.x() or y < -self.changerect.y():
return [None, None, None]
newpoints = [x + self.changerect.x(), y + self.changerect.y()]
if newpoints[0] >= len(self.level.l_tiles.tiles) or newpoints[1] >= len(self.level.l_tiles.tiles[0]):
return [None, None, None]
return [self.copytile(newpoints[0], newpoints[1], 0),
self.copytile(newpoints[0], newpoints[1], 1),
self.copytile(newpoints[0], newpoints[1], 2)]
[docs]
def copytile(self, x, y, l):
thing = self.level.l_tiles.tiles[x][y][l]
if isinstance(thing, PlacedTileBody) and not self.level.inside(thing.headpos):
return None
if thing is None:
return None
return thing.copy()
[docs]
class DefaultMaterialChange(HistoryElement):
[docs]
def __init__(self, history, material: str):
super().__init__(history)
self.before = self.level.l_tiles.default_material
self.after = material
self.redo_changes()
[docs]
def undo_changes(self):
self.level.l_tiles.default_material = self.before
self.manager.basemod.tileui.set_default_material()
[docs]
def redo_changes(self):
self.level.l_tiles.default_material = self.after
self.manager.basemod.tileui.set_default_material()