Fixed crash
This commit is contained in:
@@ -25,9 +25,9 @@ class Camera:
|
|||||||
(self.pixelsPerUnit * self.scale) * math.tan(math.radians(self.fov / 2.0))
|
(self.pixelsPerUnit * self.scale) * math.tan(math.radians(self.fov / 2.0))
|
||||||
)
|
)
|
||||||
lookAt = [
|
lookAt = [
|
||||||
self.parent.parent.map.position[0] * TILE_WIDTH,
|
self.parent.map.position[0] * TILE_WIDTH,
|
||||||
self.parent.parent.map.position[1] * TILE_HEIGHT,
|
self.parent.map.position[1] * TILE_HEIGHT,
|
||||||
self.parent.parent.map.position[2] * TILE_DEPTH,
|
self.parent.map.position[2] * TILE_DEPTH,
|
||||||
]
|
]
|
||||||
aspectRatio = vw / vh
|
aspectRatio = vw / vh
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,53 @@
|
|||||||
from editortool.map.chunk import Tile
|
import json
|
||||||
|
import os
|
||||||
|
from dusk.event import Event
|
||||||
|
|
||||||
class Chunk:
|
class Chunk:
|
||||||
def __init__(self, x=0, y=0, z=0, size_x=1, size_y=1, size_z=1):
|
def __init__(self, map, x, y, z):
|
||||||
|
self.map = map
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
self.z = z
|
self.z = z
|
||||||
self.data = [[[Tile() for _ in range(size_z)] for _ in range(size_y)] for _ in range(size_x)]
|
self.current = {}
|
||||||
|
self.original = {}
|
||||||
|
self.onChunkData = Event()
|
||||||
|
|
||||||
def draw(self):
|
def load(self):
|
||||||
for x in range(len(self.data)):
|
fname = self.getFilename()
|
||||||
for y in range(len(self.data[x])):
|
if not fname or not os.path.exists(fname):
|
||||||
for z in range(len(self.data[x][y])):
|
self.new()
|
||||||
self.data[x][y][z].draw(x, y, z)
|
return
|
||||||
|
try:
|
||||||
|
with open(fname, 'r') as f:
|
||||||
|
self.current = json.load(f)
|
||||||
|
self.original = json.loads(json.dumps(self.current)) # Deep copy
|
||||||
|
self.onChunkData.invoke(self.current)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError(f"Failed to load chunk file: {e}")
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
fname = self.getFilename()
|
||||||
|
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
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError(f"Failed to save chunk file: {e}")
|
||||||
|
|
||||||
|
def new(self):
|
||||||
|
self.current = {}
|
||||||
|
self.original = {}
|
||||||
|
self.onChunkData.invoke(self.current)
|
||||||
|
|
||||||
|
def isDirty(self):
|
||||||
|
return json.dumps(self.current, sort_keys=True) != json.dumps(self.original, sort_keys=True)
|
||||||
|
|
||||||
|
def getFilename(self):
|
||||||
|
if not self.map or not hasattr(self.map, 'getMapDirectory'):
|
||||||
|
return None
|
||||||
|
dir_path = self.map.getMapDirectory()
|
||||||
|
if dir_path is None:
|
||||||
|
return None
|
||||||
|
return f"{dir_path}/{self.x}_{self.y}_{self.z}.json"
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
from dusk.event import Event
|
|
||||||
|
|
||||||
class ChunkData:
|
|
||||||
def __init__(self, mapData, x, y, z):
|
|
||||||
self.mapData = mapData
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.z = z
|
|
||||||
self.current = {}
|
|
||||||
self.original = {}
|
|
||||||
self.onChunkData = Event()
|
|
||||||
|
|
||||||
def load(self):
|
|
||||||
fname = self.getFilename()
|
|
||||||
if not fname or not os.path.exists(fname):
|
|
||||||
self.new()
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
with open(fname, 'r') as f:
|
|
||||||
self.current = json.load(f)
|
|
||||||
self.original = json.loads(json.dumps(self.current)) # Deep copy
|
|
||||||
self.onChunkData.invoke(self.current)
|
|
||||||
except Exception as e:
|
|
||||||
raise RuntimeError(f"Failed to load chunk file: {e}")
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
fname = self.getFilename()
|
|
||||||
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
|
|
||||||
except Exception as e:
|
|
||||||
raise RuntimeError(f"Failed to save chunk file: {e}")
|
|
||||||
|
|
||||||
def new(self):
|
|
||||||
self.current = {}
|
|
||||||
self.original = {}
|
|
||||||
self.onChunkData.invoke(self.current)
|
|
||||||
|
|
||||||
def isDirty(self):
|
|
||||||
return json.dumps(self.current, sort_keys=True) != json.dumps(self.original, sort_keys=True)
|
|
||||||
|
|
||||||
def getFilename(self):
|
|
||||||
if not self.mapData or not hasattr(self.mapData, 'getMapDirectory'):
|
|
||||||
return None
|
|
||||||
dir_path = self.mapData.getMapDirectory()
|
|
||||||
if dir_path is None:
|
|
||||||
return None
|
|
||||||
return f"{dir_path}/{self.x}_{self.y}_{self.z}.json"
|
|
||||||
@@ -36,7 +36,11 @@ class ChunkPanel(QWidget):
|
|||||||
QTreeWidgetItem(parentItem2, ["Tile C"])
|
QTreeWidgetItem(parentItem2, ["Tile C"])
|
||||||
QTreeWidgetItem(parentItem2, ["Tile D"])
|
QTreeWidgetItem(parentItem2, ["Tile D"])
|
||||||
self.tree.expandAll() # Expand by default, remove if you want collapsed
|
self.tree.expandAll() # Expand by default, remove if you want collapsed
|
||||||
layout.addWidget(self.tree, 1) # Give tree stretch factor so it expands
|
layout.addWidget(self.tree) # Removed invalid stretch factor
|
||||||
|
|
||||||
|
# Add stretch so tree expands
|
||||||
|
layout.setStretchFactor(grid, 0)
|
||||||
|
layout.setStretchFactor(self.tree, 1)
|
||||||
|
|
||||||
# Event subscriptions
|
# Event subscriptions
|
||||||
self.btnN.clicked.connect(lambda: self.parent.map.moveRelative(0, -1, 0))
|
self.btnN.clicked.connect(lambda: self.parent.map.moveRelative(0, -1, 0))
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ from PyQt5.QtCore import QTimer
|
|||||||
from PyQt5.QtWidgets import QOpenGLWidget
|
from PyQt5.QtWidgets import QOpenGLWidget
|
||||||
from OpenGL.GL import *
|
from OpenGL.GL import *
|
||||||
from OpenGL.GLU import *
|
from OpenGL.GLU import *
|
||||||
from editortool.map.selectbox import SelectBox
|
|
||||||
from editortool.map.camera import Camera
|
|
||||||
from editortool.map.grid import Grid
|
|
||||||
|
|
||||||
class GLWidget(QOpenGLWidget):
|
class GLWidget(QOpenGLWidget):
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
@@ -13,9 +10,6 @@ class GLWidget(QOpenGLWidget):
|
|||||||
self.timer = QTimer(self)
|
self.timer = QTimer(self)
|
||||||
self.timer.timeout.connect(self.update)
|
self.timer.timeout.connect(self.update)
|
||||||
self.timer.start(16) # ~60 FPS
|
self.timer.start(16) # ~60 FPS
|
||||||
self.camera = Camera(self)
|
|
||||||
self.grid = Grid()
|
|
||||||
self.selectBox = SelectBox(self)
|
|
||||||
|
|
||||||
def initializeGL(self):
|
def initializeGL(self):
|
||||||
glClearColor(0.392, 0.584, 0.929, 1.0)
|
glClearColor(0.392, 0.584, 0.929, 1.0)
|
||||||
@@ -36,7 +30,6 @@ class GLWidget(QOpenGLWidget):
|
|||||||
w = 1
|
w = 1
|
||||||
|
|
||||||
glViewport(0, 0, w, h)
|
glViewport(0, 0, w, h)
|
||||||
self.camera.setup(w, h)
|
self.parent.camera.setup(w, h)
|
||||||
|
self.parent.grid.draw()
|
||||||
self.grid.draw()
|
self.parent.selectBox.draw()
|
||||||
self.selectBox.draw()
|
|
||||||
@@ -1,15 +1,135 @@
|
|||||||
|
import json
|
||||||
from dusk.event import Event
|
from dusk.event import Event
|
||||||
from editortool.map.mapdata import MAP_WIDTH, MAP_HEIGHT, MAP_DEPTH
|
from PyQt5.QtWidgets import QFileDialog, QMessageBox
|
||||||
|
from PyQt5.QtCore import QTimer
|
||||||
|
import os
|
||||||
|
from editortool.map.chunk import Chunk
|
||||||
|
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')
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.data = {}
|
||||||
|
self.dataOriginal = {}
|
||||||
self.position = [0, 0, 0] # x, y, z
|
self.position = [0, 0, 0] # x, y, z
|
||||||
self.positionEvent = Event()
|
self.chunks = {}
|
||||||
|
self.onMapData = Event()
|
||||||
|
self.onPositionChange = Event()
|
||||||
|
self.mapFileName = None
|
||||||
|
self.lastFile = None
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
for x in range(MAP_WIDTH):
|
||||||
|
for y in range(MAP_HEIGHT):
|
||||||
|
for z in range(MAP_DEPTH):
|
||||||
|
self.chunks[index] = Chunk(self, x, y, z)
|
||||||
|
index += 1
|
||||||
|
QTimer.singleShot(16, self.loadLastFile)
|
||||||
|
|
||||||
|
def loadLastFile(self):
|
||||||
|
if not os.path.exists(EDITOR_CONFIG_PATH):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
with open(EDITOR_CONFIG_PATH, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
lastFile = config.get('lastFile')
|
||||||
|
lastPosition = config.get('lastPosition')
|
||||||
|
if lastFile and os.path.exists(lastFile):
|
||||||
|
self.load(lastFile)
|
||||||
|
if lastPosition and isinstance(lastPosition, list) and len(lastPosition) == 3:
|
||||||
|
self.moveTo(*lastPosition)
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def updateEditorConfig(self):
|
||||||
|
print("Updating editor config...")
|
||||||
|
try:
|
||||||
|
mapFileName = self.getMapFilename()
|
||||||
|
config = {
|
||||||
|
'lastFile': mapFileName if mapFileName else "",
|
||||||
|
'lastPosition': self.position
|
||||||
|
}
|
||||||
|
config_dir = os.path.dirname(EDITOR_CONFIG_PATH)
|
||||||
|
if not os.path.exists(config_dir):
|
||||||
|
os.makedirs(config_dir, exist_ok=True)
|
||||||
|
with open(EDITOR_CONFIG_PATH, 'w') as f:
|
||||||
|
json.dump(config, f, indent=2)
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def newFile(self):
|
||||||
|
self.data = {}
|
||||||
|
self.dataOriginal = {}
|
||||||
|
self.mapFileName = None
|
||||||
|
self.lastFile = None
|
||||||
|
for chunk in self.chunks.values():
|
||||||
|
chunk.new()
|
||||||
|
self.moveTo(0, 0, 0)
|
||||||
|
self.onMapData.invoke(self.data)
|
||||||
|
self.updateEditorConfig()
|
||||||
|
|
||||||
|
def save(self, fname=None):
|
||||||
|
if not self.getMapFilename() and fname is None:
|
||||||
|
filePath, _ = QFileDialog.getSaveFileName(None, "Save Map File", MAP_DEFAULT_PATH, "Map Files (*.json)")
|
||||||
|
if not filePath:
|
||||||
|
return
|
||||||
|
self.mapFileName = filePath
|
||||||
|
if fname:
|
||||||
|
self.mapFileName = fname
|
||||||
|
try:
|
||||||
|
with open(self.getMapFilename(), 'w') as f:
|
||||||
|
json.dump(self.data, f, indent=2)
|
||||||
|
self.dataOriginal = json.loads(json.dumps(self.data)) # Deep copy
|
||||||
|
for chunk in self.chunks.values():
|
||||||
|
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):
|
||||||
|
try:
|
||||||
|
with open(fileName, 'r') as f:
|
||||||
|
self.data = json.load(f)
|
||||||
|
self.mapFileName = fileName
|
||||||
|
self.dataOriginal = json.loads(json.dumps(self.data)) # Deep copy
|
||||||
|
for chunk in self.chunks.values():
|
||||||
|
chunk.load()
|
||||||
|
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):
|
||||||
|
return json.dumps(self.data, sort_keys=True) != json.dumps(self.dataOriginal, sort_keys=True)
|
||||||
|
|
||||||
|
def isDirty(self):
|
||||||
|
return self.isMapFileDirty() or self.anyChunksDirty()
|
||||||
|
|
||||||
|
def getMapFilename(self):
|
||||||
|
return self.mapFileName if self.mapFileName and os.path.exists(self.mapFileName) else None
|
||||||
|
|
||||||
|
def getMapDirectory(self):
|
||||||
|
fname = self.getMapFilename()
|
||||||
|
if not fname or not fname.endswith('.json'):
|
||||||
|
return None
|
||||||
|
return fname[:-5] # Remove '.json' extension
|
||||||
|
|
||||||
|
def anyChunksDirty(self):
|
||||||
|
for chunk in self.chunks.values():
|
||||||
|
if chunk.isDirty():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def moveTo(self, x, y, z):
|
def moveTo(self, x, y, z):
|
||||||
self.position = [x, y, z]
|
self.position = [x, y, z]
|
||||||
self.positionEvent.invoke(self.position)
|
self.onPositionChange.invoke(self.position)
|
||||||
|
self.updateEditorConfig()
|
||||||
|
|
||||||
def moveRelative(self, x, y, z):
|
def moveRelative(self, x, y, z):
|
||||||
self.moveTo(
|
self.moveTo(
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
import json
|
|
||||||
from dusk.event import Event
|
|
||||||
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')
|
|
||||||
|
|
||||||
class MapData:
|
|
||||||
def __init__(self):
|
|
||||||
self.data = {}
|
|
||||||
self.dataOriginal = {}
|
|
||||||
self.onMapData = Event()
|
|
||||||
self.mapFileName = None
|
|
||||||
self.chunks = {}
|
|
||||||
|
|
||||||
index = 0
|
|
||||||
for x in range(MAP_WIDTH):
|
|
||||||
for y in range(MAP_HEIGHT):
|
|
||||||
for z in range(MAP_DEPTH):
|
|
||||||
self.chunks[index] = ChunkData(self, x, y, z)
|
|
||||||
index += 1
|
|
||||||
QTimer.singleShot(16, self.loadLastFile)
|
|
||||||
|
|
||||||
def loadLastFile(self):
|
|
||||||
if os.path.exists(EDITOR_CONFIG_PATH):
|
|
||||||
try:
|
|
||||||
with open(EDITOR_CONFIG_PATH, 'r') as f:
|
|
||||||
config = json.load(f)
|
|
||||||
lastFile = config.get('lastFile')
|
|
||||||
if lastFile and os.path.exists(lastFile):
|
|
||||||
self.load(lastFile)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def updateEditorConfig(self):
|
|
||||||
try:
|
|
||||||
config = {'lastFile': self.getMapFilename() if self.getMapFilename() else ""}
|
|
||||||
with open(EDITOR_CONFIG_PATH, 'w') as f:
|
|
||||||
json.dump(config, f, indent=2)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def newFile(self):
|
|
||||||
self.data = {}
|
|
||||||
self.dataOriginal = {}
|
|
||||||
self.mapFileName = None
|
|
||||||
for chunk in self.chunks.values():
|
|
||||||
chunk.new()
|
|
||||||
self.onMapData.invoke(self.data)
|
|
||||||
self.updateEditorConfig()
|
|
||||||
|
|
||||||
def save(self, fname=None):
|
|
||||||
if not self.getMapFilename() and fname is None:
|
|
||||||
filePath, _ = QFileDialog.getSaveFileName(None, "Save Map File", MAP_DEFAULT_PATH, "Map Files (*.json)")
|
|
||||||
if not filePath:
|
|
||||||
return
|
|
||||||
self.mapFileName = filePath
|
|
||||||
if fname:
|
|
||||||
self.mapFileName = fname
|
|
||||||
try:
|
|
||||||
with open(self.getMapFilename(), 'w') as f:
|
|
||||||
json.dump(self.data, f, indent=2)
|
|
||||||
self.dataOriginal = json.loads(json.dumps(self.data)) # Deep copy
|
|
||||||
for chunk in self.chunks.values():
|
|
||||||
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):
|
|
||||||
try:
|
|
||||||
with open(fileName, 'r') as f:
|
|
||||||
self.data = json.load(f)
|
|
||||||
self.mapFileName = fileName
|
|
||||||
self.dataOriginal = json.loads(json.dumps(self.data)) # Deep copy
|
|
||||||
for chunk in self.chunks.values():
|
|
||||||
chunk.load()
|
|
||||||
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):
|
|
||||||
return json.dumps(self.data, sort_keys=True) != json.dumps(self.dataOriginal, sort_keys=True)
|
|
||||||
|
|
||||||
def isDirty(self):
|
|
||||||
return self.isMapFileDirty() or self.anyChunksDirty()
|
|
||||||
|
|
||||||
def getMapFilename(self):
|
|
||||||
return self.mapFileName if self.mapFileName else None
|
|
||||||
|
|
||||||
def getMapDirectory(self):
|
|
||||||
fname = self.getMapFilename()
|
|
||||||
if not fname or not fname.endswith('.json'):
|
|
||||||
return None
|
|
||||||
return fname[:-5] # Remove '.json' extension
|
|
||||||
|
|
||||||
def anyChunksDirty(self):
|
|
||||||
for chunk in self.chunks.values():
|
|
||||||
if chunk.isDirty():
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
@@ -43,8 +43,8 @@ class MapInfoPanel(QWidget):
|
|||||||
self.tileXInput.returnPressed.connect(self.goToPosition)
|
self.tileXInput.returnPressed.connect(self.goToPosition)
|
||||||
self.tileYInput.returnPressed.connect(self.goToPosition)
|
self.tileYInput.returnPressed.connect(self.goToPosition)
|
||||||
self.tileZInput.returnPressed.connect(self.goToPosition)
|
self.tileZInput.returnPressed.connect(self.goToPosition)
|
||||||
self.parent.map.positionEvent.sub(self.updatePositionLabels)
|
self.parent.map.onPositionChange.sub(self.updatePositionLabels)
|
||||||
self.parent.mapData.onMapData.sub(self.onMapData)
|
self.parent.map.onMapData.sub(self.onMapData)
|
||||||
self.mapTitleInput.textChanged.connect(self.onMapNameChange)
|
self.mapTitleInput.textChanged.connect(self.onMapNameChange)
|
||||||
|
|
||||||
# Initial label setting
|
# Initial label setting
|
||||||
@@ -55,7 +55,7 @@ class MapInfoPanel(QWidget):
|
|||||||
x = int(self.tileXInput.text())
|
x = int(self.tileXInput.text())
|
||||||
y = int(self.tileYInput.text())
|
y = int(self.tileYInput.text())
|
||||||
z = int(self.tileZInput.text())
|
z = int(self.tileZInput.text())
|
||||||
map.moveTo(x, y, z)
|
self.parent.map.moveTo(x, y, z)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
QMessageBox.warning(self, "Invalid Input", "Please enter valid integer coordinates.")
|
QMessageBox.warning(self, "Invalid Input", "Please enter valid integer coordinates.")
|
||||||
|
|
||||||
@@ -80,4 +80,4 @@ class MapInfoPanel(QWidget):
|
|||||||
self.mapTitleInput.setText(data.get("mapName", ""))
|
self.mapTitleInput.setText(data.get("mapName", ""))
|
||||||
|
|
||||||
def onMapNameChange(self, text):
|
def onMapNameChange(self, text):
|
||||||
self.parent.mapData.data['mapName'] = text
|
self.parent.map.data['mapName'] = text
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import os
|
import os
|
||||||
from PyQt5.QtWidgets import QAction, QMenuBar, QFileDialog
|
from PyQt5.QtWidgets import QAction, QMenuBar, QFileDialog
|
||||||
from editortool.map.mapdata import MAP_DEFAULT_PATH
|
from editortool.map.map import MAP_DEFAULT_PATH
|
||||||
|
|
||||||
class MapToolbar:
|
class MapMenubar:
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.menubar = parent.menuBar()
|
self.menubar = QMenuBar(parent)
|
||||||
self.fileMenu = self.menubar.addMenu("File")
|
parent.setMenuBar(self.menubar)
|
||||||
|
|
||||||
|
self.fileMenu = self.menubar.addMenu("File")
|
||||||
self.actionNew = QAction("New", parent)
|
self.actionNew = QAction("New", parent)
|
||||||
self.actionOpen = QAction("Open", parent)
|
self.actionOpen = QAction("Open", parent)
|
||||||
self.actionSave = QAction("Save", parent)
|
self.actionSave = QAction("Save", parent)
|
||||||
@@ -23,17 +24,17 @@ class MapToolbar:
|
|||||||
self.fileMenu.addAction(self.actionSaveAs)
|
self.fileMenu.addAction(self.actionSaveAs)
|
||||||
|
|
||||||
def newFile(self):
|
def newFile(self):
|
||||||
self.parent.mapData.newFile()
|
self.parent.map.newFile()
|
||||||
|
|
||||||
def openFile(self):
|
def openFile(self):
|
||||||
filePath, _ = QFileDialog.getOpenFileName(self.menubar, "Open Map File", MAP_DEFAULT_PATH, "Map Files (*.json)")
|
filePath, _ = QFileDialog.getOpenFileName(self.menubar, "Open Map File", MAP_DEFAULT_PATH, "Map Files (*.json)")
|
||||||
if filePath:
|
if filePath:
|
||||||
self.parent.mapData.load(filePath)
|
self.parent.map.load(filePath)
|
||||||
|
|
||||||
def saveFile(self):
|
def saveFile(self):
|
||||||
self.parent.mapData.save()
|
self.parent.map.save()
|
||||||
|
|
||||||
def saveAsFile(self):
|
def saveAsFile(self):
|
||||||
filePath, _ = QFileDialog.getSaveFileName(self.menubar, "Save Map File As", MAP_DEFAULT_PATH, "Map Files (*.json)")
|
filePath, _ = QFileDialog.getSaveFileName(self.menubar, "Save Map File As", MAP_DEFAULT_PATH, "Map Files (*.json)")
|
||||||
if filePath:
|
if filePath:
|
||||||
self.parent.mapData.save(filePath)
|
self.parent.map.save(filePath)
|
||||||
@@ -10,9 +10,9 @@ class SelectBox:
|
|||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
position = [
|
position = [
|
||||||
self.parent.parent.map.position[0] * TILE_WIDTH - (TILE_WIDTH / 2.0),
|
self.parent.map.position[0] * TILE_WIDTH - (TILE_WIDTH / 2.0),
|
||||||
self.parent.parent.map.position[1] * TILE_HEIGHT - (TILE_HEIGHT / 2.0),
|
self.parent.map.position[1] * TILE_HEIGHT - (TILE_HEIGHT / 2.0),
|
||||||
self.parent.parent.map.position[2] * TILE_DEPTH - (TILE_DEPTH / 2.0)
|
self.parent.map.position[2] * TILE_DEPTH - (TILE_DEPTH / 2.0)
|
||||||
]
|
]
|
||||||
|
|
||||||
vertices = [
|
vertices = [
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ class StatusBar(QStatusBar):
|
|||||||
self.addWidget(self.leftLabel, 1)
|
self.addWidget(self.leftLabel, 1)
|
||||||
self.addPermanentWidget(self.rightLabel)
|
self.addPermanentWidget(self.rightLabel)
|
||||||
|
|
||||||
parent.mapData.onMapData.sub(self.onMapData)
|
parent.map.onMapData.sub(self.onMapData)
|
||||||
|
|
||||||
def setStatus(self, message):
|
def setStatus(self, message):
|
||||||
self.leftLabel.setText(message)
|
self.leftLabel.setText(message)
|
||||||
|
|
||||||
def onMapData(self, data):
|
def onMapData(self, data):
|
||||||
self.rightLabel.setText(self.parent.mapData.mapFileName if self.parent.mapData.mapFileName else "Untitled.json")
|
self.rightLabel.setText(self.parent.map.mapFileName if self.parent.map.mapFileName else "Untitled.json")
|
||||||
@@ -4,38 +4,39 @@ from PyQt5.QtCore import Qt
|
|||||||
from editortool.map.glwidget import GLWidget
|
from editortool.map.glwidget import GLWidget
|
||||||
from editortool.map.chunkpanel import ChunkPanel
|
from editortool.map.chunkpanel import ChunkPanel
|
||||||
from editortool.map.mapinfopanel import MapInfoPanel
|
from editortool.map.mapinfopanel import MapInfoPanel
|
||||||
from editortool.map.mapdata import MapData
|
from editortool.map.menubar import MapMenubar
|
||||||
from editortool.map.toolbar import MapToolbar
|
|
||||||
from editortool.map.statusbar import StatusBar
|
from editortool.map.statusbar import StatusBar
|
||||||
from editortool.map.map import Map
|
from editortool.map.map import Map
|
||||||
from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH
|
from editortool.map.mapdefs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH
|
||||||
|
from editortool.map.selectbox import SelectBox
|
||||||
|
from editortool.map.camera import Camera
|
||||||
|
from editortool.map.grid import Grid
|
||||||
|
|
||||||
class MapWindow(QMainWindow):
|
class MapWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
# Subclasses
|
# Subclasses
|
||||||
self.mapData = MapData()
|
|
||||||
self.map = Map(self)
|
self.map = Map(self)
|
||||||
|
self.camera = Camera(self)
|
||||||
|
self.grid = Grid()
|
||||||
|
self.selectBox = SelectBox(self)
|
||||||
|
|
||||||
# Window setup
|
# Window setup
|
||||||
self.setWindowTitle("Dusk Map Editor")
|
self.setWindowTitle("Dusk Map Editor")
|
||||||
self.resize(1280, 720)
|
self.resize(1280, 720)
|
||||||
|
|
||||||
# Components
|
# Menubar (TESTING)
|
||||||
self.toolbar = MapToolbar(self)
|
self.menubar = MapMenubar(self)
|
||||||
|
|
||||||
central = QWidget()
|
central = QWidget()
|
||||||
self.setCentralWidget(central)
|
self.setCentralWidget(central)
|
||||||
|
|
||||||
mainLayout = QHBoxLayout(central)
|
mainLayout = QHBoxLayout(central)
|
||||||
|
|
||||||
# Left panel (ChunkPanel)
|
# Left panel (ChunkPanel)
|
||||||
self.chunkPanel = ChunkPanel(self)
|
self.chunkPanel = ChunkPanel(self)
|
||||||
leftWidget = QWidget()
|
self.chunkPanel.setFixedWidth(200)
|
||||||
leftWidget.setLayout(self.chunkPanel.layout())
|
mainLayout.addWidget(self.chunkPanel)
|
||||||
leftWidget.setFixedWidth(200)
|
|
||||||
mainLayout.addWidget(leftWidget)
|
|
||||||
|
|
||||||
# Center panel (GLWidget + controls)
|
# Center panel (GLWidget + controls)
|
||||||
self.glWidget = GLWidget(self)
|
self.glWidget = GLWidget(self)
|
||||||
@@ -52,21 +53,15 @@ class MapWindow(QMainWindow):
|
|||||||
self.setStatusBar(self.statusBar)
|
self.setStatusBar(self.statusBar)
|
||||||
|
|
||||||
self.installEventFilter(self)
|
self.installEventFilter(self)
|
||||||
self._install_event_filter_recursive(self)
|
self.installEventFilterRecursively(self)
|
||||||
|
|
||||||
def _install_event_filter_recursive(self, widget):
|
def installEventFilterRecursively(self, widget):
|
||||||
for child in widget.findChildren(QWidget):
|
for child in widget.findChildren(QWidget):
|
||||||
child.installEventFilter(self)
|
child.installEventFilter(self)
|
||||||
self._install_event_filter_recursive(child)
|
self.installEventFilterRecursively(child)
|
||||||
|
|
||||||
def generateData(self):
|
|
||||||
objOut = {}
|
|
||||||
self.fileSaving.invoke(objOut)
|
|
||||||
self.mapData.data = objOut
|
|
||||||
return objOut
|
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
if not self.mapData.isDirty():
|
if not self.map.isDirty():
|
||||||
event.accept()
|
event.accept()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -79,7 +74,7 @@ class MapWindow(QMainWindow):
|
|||||||
)
|
)
|
||||||
if reply == QMessageBox.Save:
|
if reply == QMessageBox.Save:
|
||||||
self.saveFile()
|
self.saveFile()
|
||||||
if self.mapData.isDirty():
|
if self.map.isDirty():
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return
|
return
|
||||||
elif reply == QMessageBox.Cancel:
|
elif reply == QMessageBox.Cancel:
|
||||||
|
|||||||
Reference in New Issue
Block a user