from __future__ import annotations
from enum import Enum, auto
from typing import TYPE_CHECKING
from PySide6.QtCore import QRect, QPoint, QLine
from PySide6.QtGui import QMoveEvent, QMouseEvent, QColor
from BaseMod.tiles.tileExplorer import TileExplorer
from BaseMod.tiles.tileHistory import TilePen, TileRectangle, TileEllipse, TileLine, TileBrush
from BaseMod.tiles.tileUtils import can_place
from RWS.Configurable import IntConfigurable, BoolConfigurable, EnumConfigurable
from RWS.Core import CELLSIZE
from RWS.Loaders import Tile
from RWS.Modify import Editor
from RWS.Renderable import RenderTile, RenderRect, RenderEllipse, RenderLine
from RWS.Utils import fit_rect
if TYPE_CHECKING:
from BaseMod.baseMod import BaseMod
[docs]
class TileEditor(Editor):
[docs]
def __init__(self, mod):
super().__init__(mod)
mod: BaseMod
self.module = None
self.show_collisions = BoolConfigurable(mod, "EDIT_tiles.show_collisions", True, "Show collisions")
self.vis_layer = IntConfigurable(mod, "EDIT_tiles.layer", 1, "Layer to place tiles on")
self.strictmode = IntConfigurable(mod, "EDIT_tiles.strict", 0,
"If mode is Strict, all tilebodies that refer to tilehead will be removed\n"
"if mode is Full, all tilebodies in tilehead area will be removed\n"
"Might be helpful when dealing with broken levels")
self.toolleft = EnumConfigurable(mod, "EDIT_tiles.lmb", TileTools.Pen, TileTools, "Current geo tool for LMB")
self.toolright = EnumConfigurable(mod, "EDIT_tiles.rmb", TileTools.Rect, TileTools, "Current geo tool for RMB")
self.deleteleft = BoolConfigurable(mod, "EDIT_tiles.deletelmb", False, "Delete tiles with LMB")
self.deleteright = BoolConfigurable(mod, "EDIT_tiles.deletermb", False, "Delete tiles with RMB")
self.force_place = BoolConfigurable(mod, "EDIT_tiles.fp", False, "Force place")
self.force_geo = BoolConfigurable(mod, "EDIT_tiles.fg", False, "Force geometry")
self.brushsize = IntConfigurable(mod, "EDIT_tiles.brushsize", 4, "Brush size")
self.explorer = TileExplorer(self, self.manager.window)
self.tile: Tile | None = mod.manager.tiles.find_tile("Four Holes")
self.tile_item = RenderTile(self, 0, self.layer)
self.tile_rect = RenderRect(self, -10, QRect())
self.rect_rect = RenderRect(self, -5, QRect()) # uh whatever at this point
self.rect_ellipse = RenderEllipse(self, -5, QRect()) # gosh i'm so original
self.rect_line = RenderLine(self, -5, QLine()) # this doesn't even make sense i got sick
self.rect_brush = RenderEllipse(self, -5, QRect()) # i guess
self.rect_rect.setOpacity(0)
self.rect_ellipse.setOpacity(0)
self.rect_line.setOpacity(0)
self.rect_brush.setOpacity(0)
# self.tile_cols_image = QPixmap(1, 1)
# self.tile_cols_painter = QPainter(self.tile_cols_image)
# self.tile_item: QGraphicsPixmapItem | None = None
# self.tile_cols_item: QGraphicsPixmapItem | None = None
self.show_collisions.valueChanged.connect(self.hide_collisions)
self.mod.tileview.drawoption.valueChanged.connect(self.redraw_tile)
self.mod.tileview.render.connect(self.redraw_tile)
self.mod.tileview.fadepalettepath.valueChanged.connect(self.redraw_tile)
self.vis_layer.valueChanged.connect(self.redraw_tile)
self.lastpos = QPoint()
self.lastclick = QPoint()
self.toolright.valueChanged.connect(self.tool_changed)
self.toolleft.valueChanged.connect(self.tool_changed)
self.recent_tiles = []
@property
def strict(self):
return self.strictmode.value == 0
@property
def layer(self):
if not hasattr(self.mod, "tileui"):
return self.vis_layer.value - 1
return self.module.layer if self.mod.tileui.follow_layer.value else self.vis_layer.value - 1
@layer.setter
def layer(self, value):
self.vis_layer.update_value(value)
[docs]
def add_tile(self, tiles: list[Tile]):
self.tile = tiles[0]
self.redraw_tile()
if self.tile in self.recent_tiles:
self.recent_tiles.remove(self.tile)
self.recent_tiles.insert(0, self.tile)
if len(self.recent_tiles) > 90: # just in case someone really likes editing
self.recent_tiles.pop(-1)
self.basemod.tileui.reloadrecent()
[docs]
def redraw_tile(self):
if self.tile is None or self.tile_item.renderedtexture is None:
return
self.tile_item.layer = self.layer
self.tile_item.set_tile(self.tile, self.mod.tileview.colortable, self.tile_preview_option)
[docs]
def hide_collisions(self, value):
self.tile_item.colsimage_rendered.setOpacity(1 if value else 0)
@property
def tile_preview_option(self):
return self.basemod.tileview.drawoption.value
[docs]
def mouse_move_event(self, event: QMoveEvent):
if self.tile is None:
return
curpos = self.viewport.viewport_to_editor(self.mouse_pos)
cellpos = curpos - self.tile.top_left
self.tile_item.setPos(cellpos * CELLSIZE)
if self.mouse_left:
self.tool_specific_update(self.toolleft.value, self.deleteleft.value)
if self.mouse_right:
self.tool_specific_update(self.toolright.value, self.deleteright.value)
if self.manager.selected_viewport.level.inside(cellpos):
# self.manager.set_status(f"x: {cellpos.x()}, y: {cellpos.y()}, {self.manager.selected_viewport.level['TE']['tlMatrix'][cellpos.x()][cellpos.y()]}")
layers = []
for i in self.manager.selected_viewport.level.l_tiles[cellpos]:
if i is None:
layers.append("Empty")
continue
layers.append(i.tostring(self.level))
self.manager.set_status(f"x: {cellpos.x()}, y: {cellpos.y()}, [{', '.join(layers)}]")
# self.tile_item.setPos(pos)
# self.tile_rect.setPos(self.tile_item.offset)
# rect.setTopLeft(rect.topLeft() - QPoint(3, 3))
# rect.setBottomRight(rect.bottomRight() + QPoint(3, 3))
fpos = self.viewport.viewport_to_editor(self.mouse_pos) - self.tile.top_left
rect = QRect(fpos * CELLSIZE, self.tile.size * CELLSIZE)
rect.adjust(-3, -3, 3, 3)
self.tile_rect.setRect(rect)
b2 = round(self.brushsize.value / 2 * CELLSIZE)
brushrect = QRect(curpos.x() * CELLSIZE - b2, curpos.y() * CELLSIZE - b2, self.brushsize.value * CELLSIZE, self.brushsize.value * CELLSIZE)
self.rect_brush.setRect(brushrect)
# self.tile_rect.setScale(self.tile_item.scale)
self.tile_rect.drawrect.setPen(QColor(0, 255, 0) if can_place(self.level, fpos, self.layer, self.tile, self.force_place.value, self.force_geo.value) else QColor(255, 0, 0))
self.lastpos = fpos
[docs]
def init_scene_items(self, viewport):
super().init_scene_items(viewport)
self.module = viewport.modulenames["tiles"]
self.basemod.tileview.drawoption.valueChanged.connect(self.redraw_tile)
self.basemod.tileui.set_default_material()
self.redraw_tile()
[docs]
def remove_items_from_scene(self, viewport):
super().remove_items_from_scene(viewport)
self.module = None
[docs]
def mouse_press_event(self, event: QMouseEvent):
self.lastclick = self.mouse_pos
if self.mouse_left:
#self.level.l_tiles.tile_data(self.viewport.viewport_to_editor(self.mouse_pos), self.layer).remove(self.level)
self.tool_specific_press(self.toolleft.value, self.deleteleft.value)
elif self.mouse_right:
self.tool_specific_press(self.toolright.value, self.deleteright.value)
[docs]
def mouse_left_release(self):
self.tool_specific_release(self.toolleft.value, self.deleteleft.value)
[docs]
def mouse_right_release(self):
if self.mouse_left:
return
self.tool_specific_release(self.toolright.value, self.deleteright.value)