Fixed some stuff, procrastinating the real problem
All checks were successful
Build Dusk / build-linux (push) Successful in 47s
Build Dusk / build-psp (push) Successful in 1m6s

This commit is contained in:
2025-11-16 16:18:01 -06:00
parent 9a59c22288
commit c874e6c197
14 changed files with 161 additions and 154 deletions

View File

@@ -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)

View File

@@ -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(

View File

@@ -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'
# 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))

View File

@@ -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()
self.selectBox.draw()

View File

@@ -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

View File

@@ -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()
)

View File

@@ -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):

View File

@@ -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

View File

@@ -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):

View File

@@ -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()
gl.glEnd()

View File

@@ -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)

View File

@@ -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