From b01c0d37b01ddc8f72df866588016e9f900401cf Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 28 Nov 2025 08:48:42 -0600 Subject: [PATCH] Region editor --- tools/dusk/chunk.py | 13 +++ tools/dusk/map.py | 6 ++ tools/dusk/region.py | 141 +++++++++++++++++++++++++++ tools/editor.py | 4 +- tools/editortool/map/entitypanel.py | 2 +- tools/editortool/map/glwidget.py | 7 +- tools/editortool/map/grid.py | 2 +- tools/editortool/map/mapleftpanel.py | 3 + tools/editortool/map/regionpanel.py | 15 +++ 9 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 tools/dusk/region.py create mode 100644 tools/editortool/map/regionpanel.py diff --git a/tools/dusk/chunk.py b/tools/dusk/chunk.py index 56446e4..16298ed 100644 --- a/tools/dusk/chunk.py +++ b/tools/dusk/chunk.py @@ -4,6 +4,7 @@ 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 dusk.region import Region from editortool.map.vertexbuffer import VertexBuffer from OpenGL.GL import * @@ -16,12 +17,24 @@ class Chunk: self.current = {} self.original = {} self.entities = {} + self.regions = {} self.onChunkData = Event() self.dirty = False self.tiles = {} self.vertexBuffer = VertexBuffer() + # Test Region + region = self.regions[0] = Region(self) + region.minX = 0 + region.minY = 0 + region.minZ = 0 + region.maxX = 32 + region.maxY = 32 + region.maxZ = 32 + region.updateVertexs() + + # Gen tiles. tileIndex = 0 for tz in range(CHUNK_DEPTH): for ty in range(CHUNK_HEIGHT): diff --git a/tools/dusk/map.py b/tools/dusk/map.py index 8d8ef04..23a3357 100644 --- a/tools/dusk/map.py +++ b/tools/dusk/map.py @@ -222,6 +222,12 @@ class Map: for entity in chunk.entities.values(): entity.draw() + # Only render on Region tab + if self.parent.leftPanel.tabs.currentWidget() == self.parent.leftPanel.regionPanel: + for chunk in self.chunks.values(): + for region in chunk.regions.values(): + region.draw() + def getChunkAtWorldPos(self, x, y, z): chunkX = x // CHUNK_WIDTH chunkY = y // CHUNK_HEIGHT diff --git a/tools/dusk/region.py b/tools/dusk/region.py new file mode 100644 index 0000000..e4b4511 --- /dev/null +++ b/tools/dusk/region.py @@ -0,0 +1,141 @@ +from dusk.defs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH +from editortool.map.vertexbuffer import VertexBuffer +from OpenGL.GL import * +from OpenGL.GLU import * + +class Region: + def __init__(self, chunk): + self.minX = 0 + self.minY = 0 + self.minZ = 0 + self.maxX = 0 + self.maxY = 0 + self.maxZ = 0 + self.chunk = chunk + self.vertexBuffer = VertexBuffer() + self.color = (1.0, 0.0, 0.0) + self.updateVertexs() + pass + + def updateVertexs(self): + # Draw a quad, semi transparent with solid outlines + vminX = (self.minX * CHUNK_WIDTH) * TILE_WIDTH + vminY = (self.minY * CHUNK_HEIGHT) * TILE_HEIGHT + vminZ = (self.minZ * CHUNK_DEPTH) * TILE_DEPTH + vmaxX = (self.maxX * CHUNK_WIDTH) * TILE_WIDTH + vmaxY = (self.maxY * CHUNK_HEIGHT) * TILE_HEIGHT + vmaxZ = (self.maxZ * CHUNK_DEPTH) * TILE_DEPTH + alpha = 0.25 + + # Move back half a tile width + vminX -= TILE_WIDTH / 2 + vmaxX -= TILE_WIDTH / 2 + vminY -= TILE_HEIGHT / 2 + vmaxY -= TILE_HEIGHT / 2 + vminZ -= TILE_DEPTH / 2 + vmaxZ -= TILE_DEPTH / 2 + + # Cube (6 verts per face) + self.vertexBuffer.vertices = [ + # Front face + vminX, vminY, vmaxZ, + vmaxX, vminY, vmaxZ, + vmaxX, vmaxY, vmaxZ, + vminX, vminY, vmaxZ, + vmaxX, vmaxY, vmaxZ, + vminX, vmaxY, vmaxZ, + + # Back face + vmaxX, vminY, vminZ, + vminX, vminY, vminZ, + vminX, vmaxY, vminZ, + vmaxX, vminY, vminZ, + vminX, vmaxY, vminZ, + vmaxX, vmaxY, vminZ, + + # Left face + vminX, vminY, vminZ, + vminX, vminY, vmaxZ, + vminX, vmaxY, vmaxZ, + vminX, vminY, vminZ, + vminX, vmaxY, vmaxZ, + vminX, vmaxY, vminZ, + + # Right face + vmaxX, vminY, vmaxZ, + vmaxX, vminY, vminZ, + vmaxX, vmaxY, vminZ, + vmaxX, vminY, vmaxZ, + vmaxX, vmaxY, vminZ, + vmaxX, vmaxY, vmaxZ, + + # Top face + vminX, vmaxY, vmaxZ, + vmaxX, vmaxY, vmaxZ, + vmaxX, vmaxY, vminZ, + vminX, vmaxY, vmaxZ, + vmaxX, vmaxY, vminZ, + vminX, vmaxY, vminZ, + + # Bottom face + vminX, vminY, vminZ, + vmaxX, vminY, vminZ, + vmaxX, vminY, vmaxZ, + vminX, vminY, vminZ, + vmaxX, vminY, vmaxZ, + vminX, vminY, vmaxZ, + ] + + self.vertexBuffer.colors = [ + # Front face + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + + # Back face + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + + # Left face + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + + # Right face + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + + # Top face + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + + # Bottom face + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + self.color[0], self.color[1], self.color[2], alpha, + ] + self.vertexBuffer.buildData() + + def draw(self): + self.vertexBuffer.draw() \ No newline at end of file diff --git a/tools/editor.py b/tools/editor.py index 646cd1d..705bcd9 100755 --- a/tools/editor.py +++ b/tools/editor.py @@ -11,8 +11,8 @@ from editortool.langtool import LangToolWindow from editortool.cutscenetool import CutsceneToolWindow DEFAULT_TOOL = None -# DEFAULT_TOOL = "map" -DEFAULT_TOOL = "cutscene" +DEFAULT_TOOL = "map" +# DEFAULT_TOOL = "cutscene" TOOLS = [ ("Map Editor", "map", MapWindow), diff --git a/tools/editortool/map/entitypanel.py b/tools/editortool/map/entitypanel.py index 02031c6..495807c 100644 --- a/tools/editortool/map/entitypanel.py +++ b/tools/editortool/map/entitypanel.py @@ -11,7 +11,7 @@ class EntityPanel(QWidget): self.setLayout(layout) # Top panel placeholder - topWidget = QLabel("Entity Editor (top)") + topWidget = QLabel("Entity Editor") layout.addWidget(topWidget) # Name input diff --git a/tools/editortool/map/glwidget.py b/tools/editortool/map/glwidget.py index 7072255..3f18d31 100644 --- a/tools/editortool/map/glwidget.py +++ b/tools/editortool/map/glwidget.py @@ -14,6 +14,11 @@ class GLWidget(QOpenGLWidget): def initializeGL(self): glClearColor(0.392, 0.584, 0.929, 1.0) glEnable(GL_DEPTH_TEST) + glEnable(GL_BLEND) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + glEnable(GL_POLYGON_OFFSET_FILL) + glPolygonOffset(1.0, 1.0) + glDisable(GL_POLYGON_OFFSET_FILL) def resizeGL(self, w, h): pass @@ -31,6 +36,6 @@ class GLWidget(QOpenGLWidget): glViewport(0, 0, w, h) self.parent.camera.setup(w, h) - self.parent.map.draw() self.parent.grid.draw() + self.parent.map.draw() self.parent.selectBox.draw() \ No newline at end of file diff --git a/tools/editortool/map/grid.py b/tools/editortool/map/grid.py index 51a0d09..6908bb7 100644 --- a/tools/editortool/map/grid.py +++ b/tools/editortool/map/grid.py @@ -11,7 +11,7 @@ class Grid: def draw(self): if not self.enabled: return - center = [0, 0, 0] + center = [0.01,0.01,0.01] halfWidth = self.cellWidth * self.lines // 2 halfHeight = self.cellHeight * self.lines // 2 # Draw origin axes diff --git a/tools/editortool/map/mapleftpanel.py b/tools/editortool/map/mapleftpanel.py index 99d953e..ee33527 100644 --- a/tools/editortool/map/mapleftpanel.py +++ b/tools/editortool/map/mapleftpanel.py @@ -1,6 +1,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QGridLayout, QPushButton, QTabWidget, QLabel from editortool.map.chunkpanel import ChunkPanel from editortool.map.entitypanel import EntityPanel +from editortool.map.regionpanel import RegionPanel class MapLeftPanel(QWidget): def __init__(self, parent): @@ -31,11 +32,13 @@ class MapLeftPanel(QWidget): # Panels self.chunkPanel = ChunkPanel(self.parent) self.entityPanel = EntityPanel(self.parent) + self.regionPanel = RegionPanel(self.parent) # Tabs self.tabs = QTabWidget() self.tabs.addTab(self.chunkPanel, "Tiles") self.tabs.addTab(self.entityPanel, "Entities") + self.tabs.addTab(self.regionPanel, "Regions") self.tabs.addTab(None, "Triggers") layout.addWidget(self.tabs) diff --git a/tools/editortool/map/regionpanel.py b/tools/editortool/map/regionpanel.py new file mode 100644 index 0000000..5a0f2b9 --- /dev/null +++ b/tools/editortool/map/regionpanel.py @@ -0,0 +1,15 @@ +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QComboBox, QHBoxLayout, QPushButton, QLineEdit, QListWidget, QListWidgetItem +from PyQt5.QtCore import Qt +from dusk.entity import Entity +from dusk.defs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, ENTITY_TYPES, ENTITY_TYPE_NULL + +class RegionPanel(QWidget): + def __init__(self, parent): + super().__init__(parent) + self.parent = parent + layout = QVBoxLayout(self) + self.setLayout(layout) + + # Top panel placeholder + topWidget = QLabel("Region Editor") + layout.addWidget(topWidget) \ No newline at end of file