from __future__ import annotations
from PySide6.QtGui import QColor
from PySide6.QtCore import Qt, QPoint, Slot, QPointF
from PySide6.QtWidgets import QGraphicsView, QGraphicsScene, QApplication, QFileDialog
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from RWESharp.Modify.Module import Module
from RWESharp.Core.Manager import Manager
from RWESharp.Level.RWELevel import RWELevel
from RWESharp.info import CELLSIZE, PATH_LEVELS
[docs]
class ViewPort(QGraphicsView):
"""
Viewport for visualizing level and editors
:param level: level to load
:param manager: rwe# manager
:param parent: widget parent
"""
[docs]
def __init__(self, level: RWELevel, manager, parent=None):
super().__init__(parent)
self.level: RWELevel = level
self.level.viewport = self
self.manager: Manager = manager
self.workscene: QGraphicsScene = QGraphicsScene(self)
self.setScene(self.workscene)
self.zoom = 1
# self.origin = self.workscene.addEllipse(0, 0, 1, 1, QColor(0, 0, 0, 0))
self.topleft = self.workscene.addEllipse(0, 0, 1, 1, QColor(0, 0, 0, 0))
self.uselessthing = self.workscene.addRect(0, 0, 9999, 9999, QColor(0, 0, 0, 0)) # just a big rect to keep shit working
self.verticalScrollBar().sliderReleased.connect(self.redraw)
self.horizontalScrollBar().sliderReleased.connect(self.redraw)
self.setMouseTracking(True)
self._lmb = False
self._rmb = False
self._mmb = False
self.mouse_pos = QPoint()
self.modules: list[Module] = []
self.modulenames: dict[str, Module] = {}
self.setAcceptDrops(True)
# self.setBackgroundBrush(QBrush(QColor(30, 30, 30), Qt.BrushStyle.SolidPattern))
for i in self.manager.mods:
i.level_opened(self)
[docs]
def reset_viewport(self):
self.topleft.setPos(0, 0)
self.zoom = 1
self.verticalScrollBar().setValue(0)
self.horizontalScrollBar().setValue(0)
for i in self.modules:
i.move_event()
i.zoom_event()
[docs]
def level_resized(self, newrect):
for i in self.modules:
i.level_resized(newrect)
if self.editor.viewport == self:
self.editor.level_resized(newrect)
[docs]
def dragEnterEvent(self, event):
self.manager.window.ui.tabWidget.dragEnterEvent(event)
[docs]
def dragMoveEvent(self, event):
self.manager.window.ui.tabWidget.dragMoveEvent(event)
[docs]
def dropEvent(self, event, /):
self.manager.window.ui.tabWidget.dropEvent(event)
[docs]
@Slot()
def redraw(self):
self.repaint()
[docs]
def add_module(self, module: Module, name=None, editor=False):
if not editor:
self.modules.append(module)
if name is not None:
self.modulenames[name] = module
module.viewport = self
module.init_scene_items(self)
for i in module.renderables:
i.init_graphics(self)
for i in module.renderables:
i.post_init_graphics(self)
self.repaint()
module.zoom_event()
module.move_event()
[docs]
def remove_module(self, module: Module):
if module in self.modules:
self.modules.remove(module)
if module in self.modulenames.values():
del self.modulenames[list(self.modulenames.keys())[list(self.modulenames.values()).index(module)]]
module.remove_items_from_scene(self)
for i in module.renderables:
i.remove_graphics(self)
module.viewport = None
self.repaint()
[docs]
def mousePressEvent(self, event):
super().mousePressEvent(event)
if self.scene().mouseGrabberItem() is not None:
return
if event.buttons() & self.manager.basemod.bmconfig.main_button.value:
self._lmb = True
self.editor.mouse_left_press()
self.update_cursor()
if event.buttons() & self.manager.basemod.bmconfig.sec_button.value:
self._rmb = True
self.editor.mouse_right_press()
self.update_cursor()
if event.buttons() & self.manager.basemod.bmconfig.movement_button.value:
self._mmb = True
self.editor.mouse_middle_press()
self.setCursor(Qt.CursorShape.SizeAllCursor)
self.editor.mouse_press_event(event)
[docs]
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
if self.scene().mouseGrabberItem() is not None:
return
if event.button() & self.manager.basemod.bmconfig.main_button.value:
self._lmb = False
self.editor.mouse_left_release()
self.update_cursor()
if event.button() & self.manager.basemod.bmconfig.sec_button.value:
self._rmb = False
self.editor.mouse_right_release()
self.update_cursor()
if event.button() & self.manager.basemod.bmconfig.movement_button.value:
self._mmb = False
self.editor.mouse_middle_release()
self.update_cursor()
self.editor.mouse_release_event(event)
@property
def mouse_left(self) -> bool:
return self._lmb
@property
def mouse_right(self) -> bool:
return self._rmb
@property
def mouse_middle(self):
return self._mmb
@property
def editor(self):
return self.manager.editor
[docs]
def setTabName(self):
i = self.manager.window.ui.tabWidget.indexOf(self)
self.manager.window.ui.tabWidget.setTabText(i, self.level.shortname)
[docs]
def close_viewport(self):
self.workscene.clear()
[docs]
def clean(self):
self.workscene.update(0, 0, 10000, 10000) # that'l do
[docs]
def update_cursor(self):
self.setCursor(Qt.CursorShape.ArrowCursor if self.editor is None else self.editor.defaultcursor)
[docs]
def wheelEvent(self, event):
if self.scene().mouseGrabberItem() is not None:
super().wheelEvent(event)
return
mods = QApplication.keyboardModifiers()
#print(self.map.scale() + (event.angleDelta().y() / 80))
if mods == mods.ShiftModifier:
event.setModifiers(Qt.KeyboardModifier.NoModifier)
self.verticalScrollBar().wheelEvent(event)
return
elif mods == mods.ControlModifier:
event.setModifiers(Qt.KeyboardModifier.NoModifier)
self.horizontalScrollBar().wheelEvent(event)
return
self.do_zoom(event.angleDelta().y() * (-1 if event.inverted() else 1) / 800)
self.editor.mouse_wheel_event(event)
self.editor.mouse_move_event(event)
#self.verticalScrollBar().size
#self.horizontalScrollBar().adjustSize()
[docs]
def do_zoom(self, zoom):
pointbefore = self.viewport_to_editor_float(self.mouse_pos.toPointF())
self.zoom = max(0.01, self.zoom + zoom * self.zoom)
offset = (self.viewport_to_editor_float(self.mouse_pos.toPointF()) - pointbefore) * CELLSIZE * self.zoom
self.topleft.setPos(self.topleft.pos() + offset)
for i in self.modules:
i.zoom_event()
i.move_event()
self.editor.zoom_event()
self.editor.move_event()
[docs]
def mouseMoveEvent(self, event):
if self.scene().mouseGrabberItem() is not None:
super().mouseMoveEvent(event)
return
offset = event.pos() - self.mouse_pos
if self.mouse_middle:
# self.origin.setX(self.origin.x() + offset.x())
# self.origin.setY(self.origin.y() + offset.y())
self.topleft.setPos(self.topleft.pos() + offset)
for i in self.modules:
i.move_event()
self.mouse_pos = event.pos()
self.editor.mouse_move_event(event)
self.editor.move_event()
#super().mouseMoveEvent(event)
[docs]
def viewport_to_editor(self, point: QPoint) -> QPoint:
npoint = point.toPointF() + QPointF(self.horizontalScrollBar().value(), self.verticalScrollBar().value()) - self.topleft.pos()
npoint.setX(npoint.x() / (CELLSIZE * self.zoom))
npoint.setY(npoint.y() / (CELLSIZE * self.zoom))
npoint -= QPointF(.5, .5)
return npoint.toPoint()
[docs]
def viewport_to_editor_float(self, point: QPointF) -> QPointF:
npoint = point + QPointF(self.horizontalScrollBar().value(), self.verticalScrollBar().value()) - self.topleft.pos()
npoint.setX(npoint.x() / (CELLSIZE * self.zoom))
npoint.setY(npoint.y() / (CELLSIZE * self.zoom))
return npoint
[docs]
def editor_to_viewport(self, point: QPoint) -> QPoint:
return (point * CELLSIZE * self.zoom) + self.topleft.pos().toPoint()
[docs]
def editor_to_viewport_float(self, point: QPointF) -> QPointF:
return (point * CELLSIZE * self.zoom) + self.topleft.pos()
[docs]
def save_level(self):
for i in self.manager.mods:
i.on_save(self)
if self.level.file is None:
dialog = QFileDialog.getSaveFileName(self.manager.window, "Save a level...", PATH_LEVELS, "Level files (*.txt *.wep *.rwl)", selectedFilter=".wep")
if dialog[0] == "":
return
self.level.file = dialog[0]
self.level.save_file()
self.setTabName()
[docs]
def save_level_as(self):
dialog = QFileDialog.getSaveFileName(self.manager.window, "Save a level...", PATH_LEVELS, "Level files (*.txt *.wep *.rwl)", selectedFilter=".wep")
if dialog[0] == "":
return
self.level.file = dialog[0]
self.level.save_file()
self.setTabName()