Mostly nuking old system
Some checks failed
Build Dusk / build-linux (push) Failing after 1m24s
Build Dusk / run-tests (push) Failing after 1m17s
Build Dusk / build-psp (push) Failing after 1m34s
Build Dusk / build-dolphin (push) Failing after 2m5s

This commit is contained in:
2026-02-13 19:13:26 -06:00
parent b37e5f45ca
commit e5e8c49f6c
97 changed files with 1454 additions and 408 deletions

158
archive/dusk/chunk.py Normal file
View File

@@ -0,0 +1,158 @@
import json
import os
from tools.dusk.event import Event
from tools.dusk.defs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, CHUNK_VERTEX_COUNT_MAX, TILE_SHAPE_NULL
from tools.dusk.tile import Tile
from tools.dusk.entity import Entity
from tools.dusk.region import Region
from tools.editor.map.vertexbuffer import VertexBuffer
from OpenGL.GL import *
class Chunk:
def __init__(self, map, x, y, z):
self.map = map
self.x = x
self.y = y
self.z = z
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):
for tx in range(CHUNK_WIDTH):
self.tiles[tileIndex] = Tile(self, tx, ty, tz, tileIndex)
tileIndex += 1
# Update vertices
self.tileUpdateVertices()
def reload(self, newX, newY, newZ):
self.x = newX
self.y = newY
self.z = newZ
self.entities = {}
for tile in self.tiles.values():
tile.chunkReload(newX, newY, newZ)
self.load()
def tileUpdateVertices(self):
self.vertexBuffer.clear()
for tile in self.tiles.values():
tile.buffer(self.vertexBuffer)
self.vertexBuffer.buildData()
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:
data = json.load(f)
if not 'shapes' in data:
data['shapes'] = []
# For each tile.
for tile in self.tiles.values():
tile.load(data)
# For each entity.
self.entities = {}
if 'entities' in data:
for id, entData in enumerate(data['entities']):
ent = Entity(self)
ent.load(entData)
self.entities[id] = ent
self.tileUpdateVertices()
self.dirty = False
self.onChunkData.invoke(self)
self.map.onEntityData.invoke()
except Exception as e:
raise RuntimeError(f"Failed to load chunk file: {e}")
def save(self):
if not self.isDirty():
return
dataOut = {
'shapes': [],
'entities': []
}
for tile in self.tiles.values():
dataOut['shapes'].append(tile.shape)
for ent in self.entities.values():
entData = {}
ent.save(entData)
dataOut['entities'].append(entData)
fname = self.getFilename()
if not fname:
raise ValueError("No filename specified for saving chunk.")
try:
with open(fname, 'w') as f:
json.dump(dataOut, f)
self.dirty = False
self.onChunkData.invoke(self)
except Exception as e:
raise RuntimeError(f"Failed to save chunk file: {e}")
def new(self):
for tile in self.tiles.values():
tile.shape = TILE_SHAPE_NULL
self.tileUpdateVertices()
self.dirty = False
self.onChunkData.invoke(self)
def isDirty(self):
return self.dirty
def getFilename(self):
if not self.map or not hasattr(self.map, 'getChunkDirectory'):
return None
dirPath = self.map.getChunkDirectory()
if dirPath is None:
return None
return f"{dirPath}/{self.x}_{self.y}_{self.z}.json"
def draw(self):
self.vertexBuffer.draw()
def addEntity(self, localX=0, localY=0, localZ=0):
ent = Entity(self, localX, localY, localZ)
self.entities[len(self.entities)] = ent
self.map.onEntityData.invoke()
self.dirty = True
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()
self.dirty = True
return True
return False

49
archive/dusk/defs.py Normal file
View File

@@ -0,0 +1,49 @@
from dotenv import load_dotenv, dotenv_values
import os
import sys
current_file_path = os.path.abspath(__file__)
duskDefsPath = os.path.join(os.path.dirname(current_file_path), "..", "..", "src", "duskdefs.env")
# Ensure the .env file exists
if not os.path.isfile(duskDefsPath):
print(f"Error: .env file not found at {duskDefsPath}")
sys.exit(1)
load_dotenv(dotenv_path=duskDefsPath)
defs = {key: os.getenv(key) for key in os.environ.keys()}
fileDefs = dotenv_values(dotenv_path=duskDefsPath)
# Parsed out definitions
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
CHUNK_VERTEX_COUNT_MAX = int(defs.get('CHUNK_VERTEX_COUNT_MAX'))
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
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))
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))

90
archive/dusk/entity.py Normal file
View File

@@ -0,0 +1,90 @@
from tools.dusk.defs import ENTITY_TYPE_NULL, ENTITY_TYPE_NPC, CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH
from tools.editor.map.vertexbuffer import VertexBuffer
class Entity:
def __init__(self, chunk, localX=0, localY=0, localZ=0):
self.type = ENTITY_TYPE_NPC
self.name = "Unititled"
self.localX = localX % CHUNK_WIDTH
self.localY = localY % CHUNK_HEIGHT
self.localZ = localZ % CHUNK_DEPTH
self.chunk = chunk
self.vertexBuffer = VertexBuffer()
pass
def load(self, obj):
self.type = obj.get('type', ENTITY_TYPE_NULL)
self.localX = obj.get('x', 0)
self.localY = obj.get('y', 0)
self.localZ = obj.get('z', 0)
self.name = obj.get('name', "Untitled")
pass
def save(self, obj):
obj['type'] = self.type
obj['name'] = self.name
obj['x'] = self.localX
obj['y'] = self.localY
obj['z'] = self.localZ
pass
def setType(self, entityType):
if self.type == entityType:
return
self.type = entityType
self.chunk.dirty = True
self.chunk.map.onEntityData.invoke()
def setName(self, name):
if self.name == name:
return
self.name = name
self.chunk.dirty = True
self.chunk.map.onEntityData.invoke()
def draw(self):
self.vertexBuffer.clear()
startX = (self.chunk.x * CHUNK_WIDTH + self.localX) * TILE_WIDTH
startY = (self.chunk.y * CHUNK_HEIGHT + self.localY) * TILE_HEIGHT
startZ = (self.chunk.z * CHUNK_DEPTH + self.localZ) * TILE_DEPTH
w = TILE_WIDTH
h = TILE_HEIGHT
d = TILE_DEPTH
# Center
startX -= w / 2
startY -= h / 2
startZ -= d / 2
# Offset upwards a little
startZ += 1
# Buffer simple quad at current position (need 6 positions)
self.vertexBuffer.vertices = [
startX, startY, startZ,
startX + w, startY, startZ,
startX + w, startY + h, startZ,
startX, startY, startZ,
startX + w, startY + h, startZ,
startX, startY + h, startZ,
]
self.vertexBuffer.colors = [
1.0, 0.0, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
]
self.vertexBuffer.uvs = [
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 0.0,
1.0, 1.0,
0.0, 1.0,
]
self.vertexBuffer.buildData()
self.vertexBuffer.draw()

18
archive/dusk/event.py Normal file
View File

@@ -0,0 +1,18 @@
class Event:
def __init__(self):
self._subscribers = []
def sub(self, callback):
"""Subscribe a callback to the event."""
if callback not in self._subscribers:
self._subscribers.append(callback)
def unsub(self, callback):
"""Unsubscribe a callback from the event."""
if callback in self._subscribers:
self._subscribers.remove(callback)
def invoke(self, *args, **kwargs):
"""Invoke all subscribers with the given arguments."""
for callback in self._subscribers:
callback(*args, **kwargs)

259
archive/dusk/map.py Normal file
View File

@@ -0,0 +1,259 @@
import json
import sys
from tools.dusk.event import Event
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtCore import QTimer
import os
from tools.dusk.chunk import Chunk
from tools.dusk.defs import MAP_WIDTH, MAP_HEIGHT, MAP_DEPTH, CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_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:
def __init__(self, parent):
self.parent = parent
self.data = {}
self.dataOriginal = {}
self.position = [None, None, None] # x, y, z
self.topLeftX = None
self.topLeftY = None
self.topLeftZ = None
self.chunks = {}
self.onMapData = Event()
self.onPositionChange = Event()
self.onEntityData = Event()
self.mapFileName = None
self.lastFile = None
self.firstLoad = True
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
# Only in editor instances:
self.moveTo(0, 0, 0)
if parent is not None:
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')
leftPanelIndex = config.get('leftPanelIndex')
if lastFile and os.path.exists(lastFile):
self.load(lastFile)
if lastPosition and isinstance(lastPosition, list) and len(lastPosition) == 3:
self.moveTo(*lastPosition)
if leftPanelIndex is not None:
self.parent.leftPanel.tabs.setCurrentIndex(leftPanelIndex)
except Exception:
traceback.print_exc()
def updateEditorConfig(self):
if self.parent is None:
return
try:
mapFileName = self.getMapFilename()
config = {
'lastFile': mapFileName if mapFileName else "",
'lastPosition': self.position,
'leftPanelIndex': self.parent.leftPanel.tabs.currentIndex()
}
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):
if self.mapFileName is None:
return None
dirname = os.path.dirname(self.mapFileName)
return dirname
def getChunkDirectory(self):
dirName = self.getMapDirectory()
if dirName is None:
return None
return os.path.join(dirName, 'chunks')
def anyChunksDirty(self):
for chunk in self.chunks.values():
if chunk.isDirty():
return True
return False
def moveTo(self, x, y, z):
if self.position == [x, y, z]:
return
# We need to decide if the chunks should be unloaded here or not.
newTopLeftChunkX = x // CHUNK_WIDTH - (MAP_WIDTH // 2)
newTopLeftChunkY = y // CHUNK_HEIGHT - (MAP_HEIGHT // 2)
newTopLeftChunkZ = z // CHUNK_DEPTH - (MAP_DEPTH // 2)
if (newTopLeftChunkX != self.topLeftX or
newTopLeftChunkY != self.topLeftY or
newTopLeftChunkZ != self.topLeftZ):
chunksToUnload = []
chunksToKeep = []
for chunk in self.chunks.values():
chunkWorldX = chunk.x
chunkWorldY = chunk.y
chunkWorldZ = chunk.z
if (chunkWorldX < newTopLeftChunkX or
chunkWorldX >= newTopLeftChunkX + MAP_WIDTH or
chunkWorldY < newTopLeftChunkY or
chunkWorldY >= newTopLeftChunkY + MAP_HEIGHT or
chunkWorldZ < newTopLeftChunkZ or
chunkWorldZ >= newTopLeftChunkZ + MAP_DEPTH):
chunksToUnload.append(chunk)
else:
chunksToKeep.append(chunk)
# Unload chunks that are out of the new bounds.
for chunk in chunksToUnload:
if chunk.isDirty():
print(f"Can't move map, some chunks are dirty: ({chunk.x}, {chunk.y}, {chunk.z})")
return
# Now we can safely unload the chunks.
chunkIndex = 0
newChunks = {}
for chunk in chunksToKeep:
newChunks[chunkIndex] = chunk
chunkIndex += 1
for xPos in range(newTopLeftChunkX, newTopLeftChunkX + MAP_WIDTH):
for yPos in range(newTopLeftChunkY, newTopLeftChunkY + MAP_HEIGHT):
for zPos in range(newTopLeftChunkZ, newTopLeftChunkZ + MAP_DEPTH):
# Check if we already have this chunk.
found = False
for chunk in chunksToKeep:
if chunk.x == xPos and chunk.y == yPos and chunk.z == zPos:
found = True
break
if not found:
# Create a new chunk.
newChunk = chunksToUnload.pop()
newChunk.reload(xPos, yPos, zPos)
newChunks[chunkIndex] = newChunk
chunkIndex += 1
self.chunks = newChunks
self.topLeftX = newTopLeftChunkX
self.topLeftY = newTopLeftChunkY
self.topLeftZ = newTopLeftChunkZ
self.position = [x, y, z]
self.onPositionChange.invoke(self.position)
if not self.firstLoad:
self.updateEditorConfig()
self.firstLoad = False
def moveRelative(self, x, y, z):
self.moveTo(
self.position[0] + x,
self.position[1] + y,
self.position[2] + z
)
def draw(self):
for chunk in self.chunks.values():
chunk.draw()
for chunk in self.chunks.values():
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
chunkZ = z // CHUNK_DEPTH
for chunk in self.chunks.values():
if chunk.x == chunkX and chunk.y == chunkY and chunk.z == chunkZ:
return chunk
return None
def getTileAtWorldPos(self, x, y, z):
chunk = self.getChunkAtWorldPos(x, y, z)
if not chunk:
print("No chunk found at position:", (x, y, z))
return None
tileX = x % CHUNK_WIDTH
tileY = y % CHUNK_HEIGHT
tileZ = z % CHUNK_DEPTH
tileIndex = tileX + tileY * CHUNK_WIDTH + tileZ * CHUNK_WIDTH * CHUNK_HEIGHT
return chunk.tiles.get(tileIndex)

141
archive/dusk/region.py Normal file
View File

@@ -0,0 +1,141 @@
from tools.dusk.defs import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH
from tools.editor.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()

206
archive/dusk/tile.py Normal file
View File

@@ -0,0 +1,206 @@
from OpenGL.GL import *
from tools.dusk.defs import (
TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH,
CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH,
TILE_SHAPE_NULL, TILE_SHAPE_FLOOR,
TILE_SHAPE_RAMP_NORTH, TILE_SHAPE_RAMP_SOUTH,
TILE_SHAPE_RAMP_EAST, TILE_SHAPE_RAMP_WEST,
TILE_SHAPE_RAMP_SOUTHWEST, TILE_SHAPE_RAMP_SOUTHEAST,
TILE_SHAPE_RAMP_NORTHWEST, TILE_SHAPE_RAMP_NORTHEAST
)
def getItem(arr, index, default):
if index < len(arr):
return arr[index]
return default
class Tile:
def __init__(self, chunk, x, y, z, tileIndex):
self.shape = TILE_SHAPE_NULL
self.chunk = chunk
self.x = x
self.y = y
self.z = z
self.index = tileIndex
self.posX = x * TILE_WIDTH + chunk.x * CHUNK_WIDTH * TILE_WIDTH
self.posY = y * TILE_HEIGHT + chunk.y * CHUNK_HEIGHT * TILE_HEIGHT
self.posZ = z * TILE_DEPTH + chunk.z * CHUNK_DEPTH * TILE_DEPTH
def chunkReload(self, newX, newY, newZ):
self.posX = self.x * TILE_WIDTH + newX * CHUNK_WIDTH * TILE_WIDTH
self.posY = self.y * TILE_HEIGHT + newY * CHUNK_HEIGHT * TILE_HEIGHT
self.posZ = self.z * TILE_DEPTH + newZ * CHUNK_DEPTH * TILE_DEPTH
def load(self, chunkData):
self.shape = getItem(chunkData['shapes'], self.index, TILE_SHAPE_NULL)
def setShape(self, shape):
if shape == self.shape:
return
self.shape = shape
self.chunk.dirty = True
self.chunk.tileUpdateVertices()
self.chunk.onChunkData.invoke(self.chunk)
def getBaseTileModel(self):
vertices = []
indices = []
uvs = []
colors = []
if self.shape == TILE_SHAPE_NULL:
pass
elif self.shape == TILE_SHAPE_FLOOR:
vertices = [
(self.posX, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ),
(self.posX, self.posY + TILE_HEIGHT, self.posZ)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (255, 255, 255, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_NORTH:
vertices = [
(self.posX, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ),
(self.posX, self.posY + TILE_HEIGHT, self.posZ)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (255, 0, 0, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_SOUTH:
vertices = [
(self.posX, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH),
(self.posX, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (0, 255, 0, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_EAST:
vertices = [
(self.posX, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH),
(self.posX, self.posY + TILE_HEIGHT, self.posZ)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (0, 0, 255, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_WEST:
vertices = [
(self.posX, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ),
(self.posX, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (255, 255, 0, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_SOUTHWEST:
vertices = [
(self.posX, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH),
(self.posX, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (255, 128, 0, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_NORTHWEST:
vertices = [
(self.posX, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ),
(self.posX, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (128, 255, 0, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_NORTHEAST:
vertices = [
(self.posX, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH),
(self.posX, self.posY + TILE_HEIGHT, self.posZ)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (0, 255, 128, 255) ] * 4
elif self.shape == TILE_SHAPE_RAMP_SOUTHEAST:
vertices = [
(self.posX, self.posY, self.posZ),
(self.posX + TILE_WIDTH, self.posY, self.posZ + TILE_DEPTH),
(self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH),
(self.posX, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH)
]
indices = [0, 1, 2, 0, 2, 3]
uvs = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
colors = [ (255, 128, 255, 255) ] * 4
else:
# Solid black cube for unknown shape
x0, y0, z0 = self.posX, self.posY, self.posZ
x1, y1, z1 = self.posX + TILE_WIDTH, self.posY + TILE_HEIGHT, self.posZ + TILE_DEPTH
vertices = [
(x0, y0, z0), (x1, y0, z0), (x1, y1, z0), (x0, y1, z0), # bottom
(x0, y0, z1), (x1, y0, z1), (x1, y1, z1), (x0, y1, z1) # top
]
indices = [
0,1,2, 0,2,3, # bottom
4,5,6, 4,6,7, # top
0,1,5, 0,5,4, # front
2,3,7, 2,7,6, # back
1,2,6, 1,6,5, # right
3,0,4, 3,4,7 # left
]
uvs = [ (0,0) ] * 8
colors = [ (0,0,0,255) ] * 8
return {
'vertices': vertices,
'indices': indices,
'uvs': uvs,
'colors': colors
}
def buffer(self, vertexBuffer):
if self.shape == TILE_SHAPE_NULL:
return
# New code:
baseData = self.getBaseTileModel()
# Base data is indiced but we need to buffer unindiced data
for index in baseData['indices']:
verts = baseData['vertices'][index]
uv = baseData['uvs'][index]
color = baseData['colors'][index]
vertexBuffer.vertices.extend([
verts[0] - (TILE_WIDTH / 2.0),
verts[1] - (TILE_HEIGHT / 2.0),
verts[2] - (TILE_DEPTH / 2.0)
])
vertexBuffer.colors.extend([
color[0] / 255.0,
color[1] / 255.0,
color[2] / 255.0,
color[3] / 255.0
])