diff --git a/tools/assetstool/processmap.py b/tools/assetstool/processmap.py index 406d47c..d483511 100644 --- a/tools/assetstool/processmap.py +++ b/tools/assetstool/processmap.py @@ -5,16 +5,7 @@ import json from assetstool.args import args from assetstool.assetcache import assetCache, assetGetCache from assetstool.assethelpers import getAssetRelativePath -from dusk.defs import defs - -CHUNK_WIDTH = int(defs.get('CHUNK_WIDTH')) -CHUNK_HEIGHT = int(defs.get('CHUNK_HEIGHT')) -CHUNK_DEPTH = int(defs.get('CHUNK_DEPTH')) -CHUNK_TILE_COUNT = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH - -TILE_WIDTH = float(defs.get('TILE_WIDTH')) -TILE_HEIGHT = float(defs.get('TILE_HEIGHT')) -TILE_DEPTH = float(defs.get('TILE_DEPTH')) +from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH, CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, CHUNK_TILE_COUNT def processTile(tileIndex, x=0, y=0, z=0, chunkX=0, chunkY=0, chunkZ=0): vertices = [] diff --git a/tools/editortool/map/ChunkData.py b/tools/editortool/map/ChunkData.py deleted file mode 100644 index 4681375..0000000 --- a/tools/editortool/map/ChunkData.py +++ /dev/null @@ -1,36 +0,0 @@ -import json - -class ChunkData: - def __init__(self): - self.current = {} - self.original = {} - self.filename = None - - def load(self, filename): - try: - with open(filename, 'r') as f: - self.current = json.load(f) - self.filename = filename - self.original = json.loads(json.dumps(self.current)) # Deep copy - except Exception as e: - raise RuntimeError(f"Failed to load chunk file: {e}") - - def save(self, filename=None): - fname = filename if filename else self.filename - if not fname: - raise ValueError("No filename specified for saving chunk.") - try: - with open(fname, 'w') as f: - json.dump(self.current, f, indent=2) - self.original = json.loads(json.dumps(self.current)) # Deep copy - self.filename = fname - except Exception as e: - raise RuntimeError(f"Failed to save chunk file: {e}") - - def new(self): - self.current = {} - self.original = {} - self.filename = None - - def isDirty(self): - return json.dumps(self.current, sort_keys=True) != json.dumps(self.original, sort_keys=True) diff --git a/tools/editortool/map/camera.py b/tools/editortool/map/camera.py index 288642e..962175f 100644 --- a/tools/editortool/map/camera.py +++ b/tools/editortool/map/camera.py @@ -2,14 +2,14 @@ import math import time from OpenGL.GL import * from OpenGL.GLU import * -from dusk.defs import defs -from editortool.map.map import map +from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH, RPG_CAMERA_PIXELS_PER_UNIT, RPG_CAMERA_Z_OFFSET, RPG_CAMERA_FOV class Camera: - def __init__(self): - self.pixelsPerUnit = float(defs.get('RPG_CAMERA_PIXELS_PER_UNIT')) - self.yOffset = float(defs.get('RPG_CAMERA_Z_OFFSET')) - self.fov = float(defs.get('RPG_CAMERA_FOV')) + def __init__(self, parent): + self.parent = parent + self.pixelsPerUnit = RPG_CAMERA_PIXELS_PER_UNIT + self.yOffset = RPG_CAMERA_Z_OFFSET + self.fov = RPG_CAMERA_FOV self.scale = 8.0 self.lastTime = time.time() self.lookAtTarget = [0.0, 0.0, 0.0] @@ -25,13 +25,12 @@ class Camera: (self.pixelsPerUnit * self.scale) * math.tan(math.radians(self.fov / 2.0)) ) lookAt = [ - map.position[0] * float(defs.get('TILE_WIDTH')), - map.position[1] * float(defs.get('TILE_HEIGHT')), - map.position[2] * float(defs.get('TILE_DEPTH')), + self.parent.parent.map.position[0] * TILE_WIDTH, + self.parent.parent.map.position[1] * TILE_HEIGHT, + self.parent.parent.map.position[2] * TILE_DEPTH, ] aspectRatio = vw / vh - # Ease the lookAt target for i in range(3): self.lookAtTarget[i] += (lookAt[i] - self.lookAtTarget[i]) * ease @@ -39,13 +38,14 @@ class Camera: # Camera position is now based on the eased lookAtTarget cameraPosition = ( self.lookAtTarget[0], - self.lookAtTarget[1] - self.yOffset, + self.lookAtTarget[1] + self.yOffset, self.lookAtTarget[2] + z ) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(self.fov, aspectRatio, 0.1, 1000.0) + glScalef(1.0, -1.0, 1.0) # Flip the projection matrix upside down glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt( diff --git a/tools/editortool/map/chunkpanel.py b/tools/editortool/map/chunkpanel.py index 52b6163..74197fa 100644 --- a/tools/editortool/map/chunkpanel.py +++ b/tools/editortool/map/chunkpanel.py @@ -1,13 +1,14 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton, QGridLayout, QTreeWidget, QTreeWidgetItem -from editortool.map.map import map class ChunkPanel(QWidget): - def __init__(self, parent=None): + def __init__(self, parent): super().__init__(parent) + self.parent = parent layout = QVBoxLayout(self) self.chunkInfoLabel = QLabel("Tile Information") layout.addWidget(self.chunkInfoLabel) + # Nav buttons grid = QGridLayout() self.btnUp = QPushButton("U") self.btnN = QPushButton("N") @@ -16,7 +17,6 @@ class ChunkPanel(QWidget): self.btnS = QPushButton("S") self.btnE = QPushButton("E") - # Arrange buttons: U N D on top row, W S E on bottom row grid.addWidget(self.btnUp, 0, 0) grid.addWidget(self.btnN, 0, 1) grid.addWidget(self.btnDown, 0, 2) @@ -38,17 +38,10 @@ class ChunkPanel(QWidget): self.tree.expandAll() # Expand by default, remove if you want collapsed layout.addWidget(self.tree, 1) # Give tree stretch factor so it expands - self.btnN.clicked.connect(lambda: map.moveRelative(0, 1, 0)) - self.btnS.clicked.connect(lambda: map.moveRelative(0, -1, 0)) - self.btnE.clicked.connect(lambda: map.moveRelative(1, 0, 0)) - self.btnW.clicked.connect(lambda: map.moveRelative(-1, 0, 0)) - self.btnUp.clicked.connect(lambda: map.moveRelative(0, 0, 1)) - self.btnDown.clicked.connect(lambda: map.moveRelative(0, 0, -1)) - - # Subscribe to parent's fileSaving event - if parent is not None and hasattr(parent, 'fileSaving'): - parent.fileSaving.subscribe(self.onFileSaving) - - def onFileSaving(self, objOut): - # Inject 'name' into the object - objOut['name'] = 'ChunkPanel' \ No newline at end of file + # Event subscriptions + self.btnN.clicked.connect(lambda: self.parent.map.moveRelative(0, -1, 0)) + self.btnS.clicked.connect(lambda: self.parent.map.moveRelative(0, 1, 0)) + self.btnE.clicked.connect(lambda: self.parent.map.moveRelative(1, 0, 0)) + self.btnW.clicked.connect(lambda: self.parent.map.moveRelative(-1, 0, 0)) + self.btnUp.clicked.connect(lambda: self.parent.map.moveRelative(0, 0, 1)) + self.btnDown.clicked.connect(lambda: self.parent.map.moveRelative(0, 0, -1)) \ No newline at end of file diff --git a/tools/editortool/map/glwidget.py b/tools/editortool/map/glwidget.py index c8e17ae..211cbfd 100644 --- a/tools/editortool/map/glwidget.py +++ b/tools/editortool/map/glwidget.py @@ -2,18 +2,20 @@ from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import QOpenGLWidget from OpenGL.GL import * from OpenGL.GLU import * -from editortool.map.selectbox import drawSelectBox +from editortool.map.selectbox import SelectBox from editortool.map.camera import Camera from editortool.map.grid import Grid class GLWidget(QOpenGLWidget): - def __init__(self, parent=None): + def __init__(self, parent): super().__init__(parent) + self.parent = parent self.timer = QTimer(self) self.timer.timeout.connect(self.update) self.timer.start(16) # ~60 FPS - self.camera = Camera() + self.camera = Camera(self) self.grid = Grid() + self.selectBox = SelectBox(self) def initializeGL(self): glClearColor(0.392, 0.584, 0.929, 1.0) @@ -37,4 +39,4 @@ class GLWidget(QOpenGLWidget): self.camera.setup(w, h) self.grid.draw() - drawSelectBox() \ No newline at end of file + self.selectBox.draw() \ No newline at end of file diff --git a/tools/editortool/map/grid.py b/tools/editortool/map/grid.py index 41277ca..be08276 100644 --- a/tools/editortool/map/grid.py +++ b/tools/editortool/map/grid.py @@ -1,10 +1,10 @@ from OpenGL.GL import * -from dusk.defs import defs +from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH class Grid: def __init__(self, lines=1000): - self.cellWidth = float(defs.get('TILE_WIDTH')) - self.cellHeight = float(defs.get('TILE_HEIGHT')) + self.cellWidth = TILE_WIDTH + self.cellHeight = TILE_HEIGHT self.lines = lines self.enabled = True diff --git a/tools/editortool/map/map.py b/tools/editortool/map/map.py index f3711df..03b8da7 100644 --- a/tools/editortool/map/map.py +++ b/tools/editortool/map/map.py @@ -2,10 +2,10 @@ from dusk.event import Event from editortool.map.mapdata import MAP_WIDTH, MAP_HEIGHT, MAP_DEPTH class Map: - def __init__(self): + def __init__(self, parent): + self.parent = parent self.position = [0, 0, 0] # x, y, z self.positionEvent = Event() - self.chunks = [] def moveTo(self, x, y, z): self.position = [x, y, z] @@ -16,7 +16,4 @@ class Map: self.position[0] + x, self.position[1] + y, self.position[2] + z - ) - -# Singleton instance -map = Map() \ No newline at end of file + ) \ No newline at end of file diff --git a/tools/editortool/map/mapdata.py b/tools/editortool/map/mapdata.py index 15f912d..d86efa3 100644 --- a/tools/editortool/map/mapdata.py +++ b/tools/editortool/map/mapdata.py @@ -4,13 +4,11 @@ from PyQt5.QtWidgets import QFileDialog, QMessageBox from PyQt5.QtCore import QTimer import os from editortool.map.chunkdata import ChunkData +from editortool.map.mapdefs import MAP_WIDTH, MAP_HEIGHT, MAP_DEPTH +import traceback MAP_DEFAULT_PATH = os.path.join(os.path.dirname(__file__), '../../../assets/map/') EDITOR_CONFIG_PATH = os.path.join(os.path.dirname(__file__), '.editor') -MAP_WIDTH = 5 -MAP_HEIGHT = 5 -MAP_DEPTH = 3 -MAP_CHUNK_COUNT = MAP_WIDTH * MAP_HEIGHT * MAP_DEPTH class MapData: def __init__(self): @@ -72,6 +70,7 @@ class MapData: chunk.save() self.updateEditorConfig() except Exception as e: + traceback.print_exc() QMessageBox.critical(None, "Save Error", f"Failed to save map file:\n{e}") def load(self, fileName): @@ -85,6 +84,7 @@ class MapData: self.onMapData.invoke(self.data) self.updateEditorConfig() except Exception as e: + traceback.print_exc() QMessageBox.critical(None, "Load Error", f"Failed to load map file:\n{e}") def isMapFileDirty(self): diff --git a/tools/editortool/map/mapdefs.py b/tools/editortool/map/mapdefs.py new file mode 100644 index 0000000..27a09a2 --- /dev/null +++ b/tools/editortool/map/mapdefs.py @@ -0,0 +1,20 @@ +from dusk.defs import defs + + +CHUNK_WIDTH = int(defs.get('CHUNK_WIDTH')) +CHUNK_HEIGHT = int(defs.get('CHUNK_HEIGHT')) +CHUNK_DEPTH = int(defs.get('CHUNK_DEPTH')) +CHUNK_TILE_COUNT = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH + +TILE_WIDTH = float(defs.get('TILE_WIDTH')) +TILE_HEIGHT = float(defs.get('TILE_HEIGHT')) +TILE_DEPTH = float(defs.get('TILE_DEPTH')) + +RPG_CAMERA_PIXELS_PER_UNIT = float(defs.get('RPG_CAMERA_PIXELS_PER_UNIT')) +RPG_CAMERA_Z_OFFSET = float(defs.get('RPG_CAMERA_Z_OFFSET')) +RPG_CAMERA_FOV = float(defs.get('RPG_CAMERA_FOV')) + +MAP_WIDTH = 5 +MAP_HEIGHT = 5 +MAP_DEPTH = 3 +MAP_CHUNK_COUNT = MAP_WIDTH * MAP_HEIGHT * MAP_DEPTH \ No newline at end of file diff --git a/tools/editortool/map/mapinfopanel.py b/tools/editortool/map/mapinfopanel.py index 67d1fc8..e7df2f5 100644 --- a/tools/editortool/map/mapinfopanel.py +++ b/tools/editortool/map/mapinfopanel.py @@ -1,15 +1,9 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton, QHBoxLayout, QMessageBox -from editortool.map.map import map -from dusk.defs import defs - -chunkWidth = int(defs.get('CHUNK_WIDTH')) -chunkHeight = int(defs.get('CHUNK_HEIGHT')) -chunkDepth = int(defs.get('CHUNK_DEPTH')) +from editortool.map.mapdefs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH class MapInfoPanel(QWidget): - def __init__(self, parent=None): + def __init__(self, parent): super().__init__(parent) - self.parent = parent # Components @@ -36,9 +30,9 @@ class MapInfoPanel(QWidget): tilePositionRow.addWidget(self.tileGo) layout.addLayout(tilePositionRow) - self.chunkPosLabel = QLabel("Chunk Position: 0, 0, 0") + self.chunkPosLabel = QLabel() layout.addWidget(self.chunkPosLabel) - self.chunkLabel = QLabel("Chunk: 0, 0, 0") + self.chunkLabel = QLabel() layout.addWidget(self.chunkLabel) layout.addStretch() @@ -49,13 +43,12 @@ class MapInfoPanel(QWidget): self.tileXInput.returnPressed.connect(self.goToPosition) self.tileYInput.returnPressed.connect(self.goToPosition) self.tileZInput.returnPressed.connect(self.goToPosition) - map.positionEvent.sub(self.updatePositionLabels) - parent.mapData.onMapData.sub(self.onMapData) - + self.parent.map.positionEvent.sub(self.updatePositionLabels) + self.parent.mapData.onMapData.sub(self.onMapData) self.mapTitleInput.textChanged.connect(self.onMapNameChange) # Initial label setting - self.updatePositionLabels(map.position) + self.updatePositionLabels(self.parent.map.position) def goToPosition(self): try: @@ -70,11 +63,20 @@ class MapInfoPanel(QWidget): self.tileXInput.setText(str(pos[0])) self.tileYInput.setText(str(pos[1])) self.tileZInput.setText(str(pos[2])) - self.chunkPosLabel.setText(f"Chunk Position: {pos[0] % chunkWidth}, {pos[1] % chunkHeight}, {pos[2] % chunkDepth}") - self.chunkLabel.setText(f"Chunk: {pos[0] // chunkWidth}, {pos[1] // chunkHeight}, {pos[2] // chunkDepth}") + + chunkTileX = pos[0] % CHUNK_WIDTH + chunkTileY = pos[1] % CHUNK_HEIGHT + chunkTileZ = pos[2] % CHUNK_DEPTH + chunkTileIndex = chunkTileX + chunkTileY * CHUNK_WIDTH + chunkTileZ * CHUNK_WIDTH * CHUNK_HEIGHT + self.chunkPosLabel.setText(f"Chunk Position: {chunkTileX}, {chunkTileY}, {chunkTileZ} ({chunkTileIndex})") + + chunkX = pos[0] // CHUNK_WIDTH + chunkY = pos[1] // CHUNK_HEIGHT + chunkZ = pos[2] // CHUNK_DEPTH + self.chunkLabel.setText(f"Chunk: {chunkX}, {chunkY}, {chunkZ}") def onMapData(self, data): - self.updatePositionLabels(map.position) + self.updatePositionLabels(self.parent.map.position) self.mapTitleInput.setText(data.get("mapName", "")) def onMapNameChange(self, text): diff --git a/tools/editortool/map/selectbox.py b/tools/editortool/map/selectbox.py index dd1c094..0e538ec 100644 --- a/tools/editortool/map/selectbox.py +++ b/tools/editortool/map/selectbox.py @@ -1,46 +1,44 @@ import OpenGL.GL as gl from dusk.defs import defs import colorsys -from editortool.map.map import map +from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH -hue = [0.0] # Mutable container for static hue +class SelectBox: + def __init__(self, parent): + self.parent = parent + self.hue = 0.0 -def drawSelectBox(): - w = float(defs.get('TILE_WIDTH')) - h = float(defs.get('TILE_HEIGHT')) - d = float(defs.get('TILE_DEPTH')) - position = [ - map.position[0] * w - (w / 2.0), - map.position[1] * h - (h / 2.0), - map.position[2] * d - (d / 2.0) - ] + def draw(self): + position = [ + self.parent.parent.map.position[0] * TILE_WIDTH - (TILE_WIDTH / 2.0), + self.parent.parent.map.position[1] * TILE_HEIGHT - (TILE_HEIGHT / 2.0), + self.parent.parent.map.position[2] * TILE_DEPTH - (TILE_DEPTH / 2.0) + ] - # Define the 8 vertices of the cube with w=h=d=1 - vertices = [ - (position[0], position[1], position[2]), # 0: min corner - (position[0]+w, position[1], position[2]), # 1 - (position[0]+w, position[1]+h, position[2]), # 2 - (position[0], position[1]+h, position[2]), # 3 - (position[0], position[1], position[2]+d), # 4 - (position[0]+w, position[1], position[2]+d), # 5 - (position[0]+w, position[1]+h, position[2]+d), # 6 - (position[0], position[1]+h, position[2]+d) # 7 - ] - # List of edges as pairs of vertex indices - edges = [ - (0, 1), (1, 2), (2, 3), (3, 0), # bottom face - (4, 5), (5, 6), (6, 7), (7, 4), # top face - (4, 5), (5, 6), (6, 7), (7, 4), # top face - (0, 4), (1, 5), (2, 6), (3, 7) # vertical edges - ] + vertices = [ + (position[0], position[1], position[2]), + (position[0]+TILE_WIDTH, position[1], position[2]), + (position[0]+TILE_WIDTH, position[1]+TILE_HEIGHT, position[2]), + (position[0], position[1]+TILE_HEIGHT, position[2]), + (position[0], position[1], position[2]+TILE_DEPTH), + (position[0]+TILE_WIDTH, position[1], position[2]+TILE_DEPTH), + (position[0]+TILE_WIDTH, position[1]+TILE_HEIGHT, position[2]+TILE_DEPTH), + (position[0], position[1]+TILE_HEIGHT, position[2]+TILE_DEPTH) + ] + edges = [ + (0, 1), (1, 2), (2, 3), (3, 0), # bottom face + (4, 5), (5, 6), (6, 7), (7, 4), # top face + (4, 5), (5, 6), (6, 7), (7, 4), # top face + (0, 4), (1, 5), (2, 6), (3, 7) # vertical edges + ] - # Cycle hue - hue[0] = (hue[0] + 0.01) % 1.0 - r, g, b = colorsys.hsv_to_rgb(hue[0], 1.0, 1.0) - gl.glColor3f(r, g, b) - gl.glLineWidth(2.0) - gl.glBegin(gl.GL_LINES) - for edge in edges: - for vertex in edge: + # Cycle hue + self.hue = (self.hue + 0.01) % 1.0 + r, g, b = colorsys.hsv_to_rgb(self.hue, 1.0, 1.0) + gl.glColor3f(r, g, b) + gl.glLineWidth(2.0) + gl.glBegin(gl.GL_LINES) + for edge in edges: + for vertex in edge: gl.glVertex3f(*vertices[vertex]) - gl.glEnd() \ No newline at end of file + gl.glEnd() \ No newline at end of file diff --git a/tools/editortool/map/statusbar.py b/tools/editortool/map/statusbar.py index 7ed455f..a65c03d 100644 --- a/tools/editortool/map/statusbar.py +++ b/tools/editortool/map/statusbar.py @@ -4,7 +4,7 @@ class StatusBar(QStatusBar): def __init__(self, parent=None): super().__init__(parent) self.parent = parent - self.leftLabel = QLabel("Ready") + self.leftLabel = QLabel("") self.rightLabel = QLabel("") self.addWidget(self.leftLabel, 1) self.addPermanentWidget(self.rightLabel) diff --git a/tools/editortool/map/tile.py b/tools/editortool/map/tile.py index 5cf9cf4..ea2d3e2 100644 --- a/tools/editortool/map/tile.py +++ b/tools/editortool/map/tile.py @@ -1,14 +1,14 @@ from OpenGL.GL import * -from dusk.defs import defs +from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH class Tile: def __init__(self): self.tile_id = 0 def draw(self, x, y, z): - w = float(defs.get('TILE_WIDTH')) - h = float(defs.get('TILE_HEIGHT')) - d = float(defs.get('TILE_DEPTH')) + w = TILE_WIDTH + h = TILE_HEIGHT + d = TILE_DEPTH x = x * w y = y * h diff --git a/tools/editortool/maptool.py b/tools/editortool/maptool.py index 802a24a..b4434eb 100644 --- a/tools/editortool/maptool.py +++ b/tools/editortool/maptool.py @@ -1,12 +1,14 @@ import os from PyQt5.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QMessageBox +from PyQt5.QtCore import Qt from editortool.map.glwidget import GLWidget from editortool.map.chunkpanel import ChunkPanel from editortool.map.mapinfopanel import MapInfoPanel from editortool.map.mapdata import MapData from editortool.map.toolbar import MapToolbar from editortool.map.statusbar import StatusBar - +from editortool.map.map import Map +from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH class MapWindow(QMainWindow): def __init__(self): @@ -14,6 +16,7 @@ class MapWindow(QMainWindow): # Subclasses self.mapData = MapData() + self.map = Map(self) # Window setup self.setWindowTitle("Dusk Map Editor") @@ -28,7 +31,7 @@ class MapWindow(QMainWindow): mainLayout = QHBoxLayout(central) # Left panel (ChunkPanel) - self.chunkPanel = ChunkPanel() + self.chunkPanel = ChunkPanel(self) leftWidget = QWidget() leftWidget.setLayout(self.chunkPanel.layout()) leftWidget.setFixedWidth(200) @@ -48,6 +51,14 @@ class MapWindow(QMainWindow): self.statusBar = StatusBar(self) self.setStatusBar(self.statusBar) + self.installEventFilter(self) + self._install_event_filter_recursive(self) + + def _install_event_filter_recursive(self, widget): + for child in widget.findChildren(QWidget): + child.installEventFilter(self) + self._install_event_filter_recursive(child) + def generateData(self): objOut = {} self.fileSaving.invoke(objOut) @@ -74,4 +85,33 @@ class MapWindow(QMainWindow): elif reply == QMessageBox.Cancel: event.ignore() return - event.accept() \ No newline at end of file + event.accept() + + def eventFilter(self, obj, event): + if event.type() == event.KeyPress: + amtX, amtY, amtZ = 0, 0, 0 + + key = event.key() + if key == Qt.Key_Left: + amtX = -1 + elif key == Qt.Key_Right: + amtX = 1 + elif key == Qt.Key_Up: + amtY = -1 + elif key == Qt.Key_Down: + amtY = 1 + elif key == Qt.Key_PageUp: + amtZ = 1 + elif key == Qt.Key_PageDown: + amtZ = -1 + + if event.modifiers() & Qt.ShiftModifier: + amtX *= int(TILE_WIDTH) + amtY *= int(TILE_HEIGHT) + amtZ *= int(TILE_DEPTH) + + if amtX != 0 or amtY != 0 or amtZ != 0: + self.map.moveRelative(amtX, amtY, amtZ) + event.accept() + return True + return super().eventFilter(obj, event) \ No newline at end of file