Begin adding entities to editor
Some checks failed
Build Dusk / build-linux (push) Failing after 56s
Build Dusk / build-psp (push) Failing after 1m8s

This commit is contained in:
2025-11-22 10:38:16 -06:00
parent 3697cc3eef
commit 6f33522c1c
17 changed files with 261 additions and 56 deletions

View File

@@ -54,6 +54,7 @@ def processChunk(chunk):
buffer.extend(b'DCF')# Header
buffer.extend(len(chunk.tiles).to_bytes(4, 'little')) # Number of tiles
buffer.extend(len(models).to_bytes(1, 'little')) # Number of models
buffer.extend(len(chunk.entities).to_bytes(1, 'little')) # Number of entities
# Buffer tile data as array of uint8_t
for tileIndex, tile in chunk.tiles.items():
@@ -79,6 +80,14 @@ def processChunk(chunk):
buffer.extend(bytearray(struct.pack('<f', vertex[0])))
buffer.extend(bytearray(struct.pack('<f', vertex[1])))
buffer.extend(bytearray(struct.pack('<f', vertex[2])))
# For each entity
for entity in chunk.entities.values():
buffer.extend(entity.type.to_bytes(1, 'little'))
buffer.extend(entity.localX.to_bytes(1, 'little'))
buffer.extend(entity.localY.to_bytes(1, 'little'))
buffer.extend(entity.localZ.to_bytes(1, 'little'))
pass
# Write out map file
relative = getAssetRelativePath(chunk.getFilename())

View File

@@ -3,6 +3,7 @@ import os
from dusk.event import Event
from dusk.defs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, CHUNK_VERTEX_COUNT_MAX, TILE_SHAPE_NULL
from dusk.tile import Tile
from dusk.entity import Entity
from editortool.map.vertexbuffer import VertexBuffer
from OpenGL.GL import *
@@ -14,12 +15,16 @@ class Chunk:
self.z = z
self.current = {}
self.original = {}
self.entities = {}
self.onChunkData = Event()
self.dirty = False
self.tiles = {}
self.vertexBuffer = VertexBuffer()
# TEST
self.addEntity()
tileIndex = 0
for tz in range(CHUNK_DEPTH):
for ty in range(CHUNK_HEIGHT):
@@ -100,4 +105,18 @@ class Chunk:
return f"{dir_path}/{self.x}_{self.y}_{self.z}.json"
def draw(self):
self.vertexBuffer.draw()
self.vertexBuffer.draw()
def addEntity(self):
ent = Entity()
self.entities[len(self.entities)] = ent
self.map.onEntityData.invoke()
return ent
def removeEntity(self, entity):
for key, val in list(self.entities.items()):
if val == entity:
del self.entities[key]
self.map.onEntityData.invoke()
return True
return False

View File

@@ -37,4 +37,11 @@ TILE_SHAPES = {}
for key in defs.keys():
if key.startswith('TILE_SHAPE_'):
globals()[key] = int(defs.get(key))
TILE_SHAPES[key] = int(defs.get(key))
TILE_SHAPES[key] = int(defs.get(key))
ENTITY_TYPES = {}
for key in defs.keys():
if key.startswith('ENTITY_TYPE_'):
globals()[key] = int(defs.get(key))
if key != 'ENTITY_TYPE_COUNT':
ENTITY_TYPES[key] = int(defs.get(key))

9
tools/dusk/entity.py Normal file
View File

@@ -0,0 +1,9 @@
from dusk.defs import ENTITY_TYPE_NULL, ENTITY_TYPE_NPC
class Entity:
def __init__(self):
self.type = ENTITY_TYPE_NPC
self.localX = 0
self.localY = 8
self.localZ = 1
pass

View File

@@ -19,6 +19,7 @@ class Map:
self.chunks = {}
self.onMapData = Event()
self.onPositionChange = Event()
self.onEntityData = Event()
self.mapFileName = None
self.lastFile = None

View File

@@ -1,4 +1,4 @@
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton, QGridLayout, QTreeWidget, QTreeWidgetItem, QComboBox
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QGridLayout, QTreeWidget, QTreeWidgetItem, QComboBox
from dusk.defs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, TILE_SHAPES
class ChunkPanel(QWidget):
@@ -6,25 +6,6 @@ class ChunkPanel(QWidget):
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")
self.btnDown = QPushButton("D")
self.btnW = QPushButton("W")
self.btnS = QPushButton("S")
self.btnE = QPushButton("E")
grid.addWidget(self.btnUp, 0, 0)
grid.addWidget(self.btnN, 0, 1)
grid.addWidget(self.btnDown, 0, 2)
grid.addWidget(self.btnW, 1, 0)
grid.addWidget(self.btnS, 1, 1)
grid.addWidget(self.btnE, 1, 2)
layout.addLayout(grid)
# Tile shape dropdown
self.tileShapeDropdown = QComboBox()
@@ -39,16 +20,9 @@ class ChunkPanel(QWidget):
layout.addWidget(self.tree) # Removed invalid stretch factor
# Add stretch so tree expands
layout.setStretchFactor(grid, 0)
layout.setStretchFactor(self.tree, 1)
# 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))
self.parent.map.onMapData.sub(self.onMapData)
self.parent.map.onPositionChange.sub(self.onPositionChange)
self.tileShapeDropdown.currentTextChanged.connect(self.onTileShapeChanged)

View File

@@ -0,0 +1,70 @@
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QListWidget, QHBoxLayout, QPushButton, QLineEdit
from PyQt5.QtCore import Qt
from dusk.entity import Entity
class EntityPanel(QWidget):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
layout = QVBoxLayout(self)
self.setLayout(layout)
# Top panel placeholder
topWidget = QLabel("Entity Editor (top)")
layout.addWidget(topWidget)
# Name input
nameLayout = QHBoxLayout()
nameLabel = QLabel("Name:")
self.nameInput = QLineEdit()
nameLayout.addWidget(nameLabel)
nameLayout.addWidget(self.nameInput)
layout.addLayout(nameLayout)
# Entity list and buttons
self.entityList = QListWidget()
self.entityList.addItems(["Entity 1", "Entity 2", "Entity 3"])
layout.addWidget(self.entityList, stretch=1)
btnLayout = QHBoxLayout()
self.btnAdd = QPushButton("Add")
self.btnRemove = QPushButton("Remove")
btnLayout.addWidget(self.btnAdd)
btnLayout.addWidget(self.btnRemove)
layout.addLayout(btnLayout)
# Events
self.btnAdd.clicked.connect(self.onAddEntity)
self.btnRemove.clicked.connect(self.onRemoveEntity)
self.parent.map.onEntityData.sub(self.onEntityData)
self.entityList.itemClicked.connect(self.onEntityClicked)
self.entityList.itemDoubleClicked.connect(self.onEntityDoubleClicked)
# Call once to populate
self.onEntityData()
self.onEntityUnselect()
def onEntityUnselect(self):
self.nameInput.setText("")
def onEntityDoubleClicked(self, item):
print(f"Double clicked: {item.text()}")
def onEntityClicked(self, item):
print(f"Clicked: {item.text()}")
def onAddEntity(self):
chunk = self.parent.map.getChunkAtWorldPos(*self.parent.map.position)
if chunk is None:
return
chunk.addEntity()
def onRemoveEntity(self):
pass
def onEntityData(self):
self.onEntityUnselect()
self.entityList.clear()
for chunk in self.parent.map.chunks.values():
for entity_id, entity in chunk.entities.items():
self.entityList.addItem(f"Entity {entity_id}")

View File

@@ -0,0 +1,46 @@
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QGridLayout, QPushButton, QTabWidget, QLabel
from editortool.map.chunkpanel import ChunkPanel
from editortool.map.entitypanel import EntityPanel
class MapLeftPanel(QWidget):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
layout = QVBoxLayout(self)
self.setLayout(layout)
# Nav buttons
self.chunkInfoLabel = QLabel("Tile Information")
layout.addWidget(self.chunkInfoLabel)
grid = QGridLayout()
self.btnUp = QPushButton("U")
self.btnN = QPushButton("N")
self.btnDown = QPushButton("D")
self.btnW = QPushButton("W")
self.btnS = QPushButton("S")
self.btnE = QPushButton("E")
grid.addWidget(self.btnUp, 0, 0)
grid.addWidget(self.btnN, 0, 1)
grid.addWidget(self.btnDown, 0, 2)
grid.addWidget(self.btnW, 1, 0)
grid.addWidget(self.btnS, 1, 1)
grid.addWidget(self.btnE, 1, 2)
layout.addLayout(grid)
# Tabs
self.tabs = QTabWidget()
self.chunkPanel = ChunkPanel(self.parent)
self.chunkPanel.setFixedWidth(250)
self.tabs.addTab(self.chunkPanel, "Tiles")
self.entityPanel = EntityPanel(self.parent)
self.tabs.addTab(self.entityPanel, "Entities")
layout.addWidget(self.tabs)
# 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

@@ -1,8 +1,8 @@
import os
from PyQt5.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QMessageBox, QTabWidget
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.mapleftpanel import MapLeftPanel
from editortool.map.mapinfopanel import MapInfoPanel
from editortool.map.menubar import MapMenubar
from editortool.map.statusbar import StatusBar
@@ -36,14 +36,10 @@ class MapWindow(QMainWindow):
self.setCentralWidget(central)
mainLayout = QHBoxLayout(central)
# Tabs (left)
self.tabs = QTabWidget()
self.chunkPanel = ChunkPanel(self)
self.chunkPanel.setFixedWidth(200)
self.tabs.addTab(self.chunkPanel, "Tile Editor")
mainLayout.addWidget(self.tabs)
# Left panel (tabs + nav buttons)
self.leftPanel = MapLeftPanel(self)
self.leftPanel.setFixedWidth(250)
mainLayout.addWidget(self.leftPanel)
# Center panel (GLWidget + controls)
self.glWidget = GLWidget(self)