Skip to content

Commit

Permalink
Move MapPack tiles into MapPack class
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraq committed Aug 2, 2024
1 parent ea0d3a9 commit 354678f
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ShpFileWriter extends FileWriter<ImageFile, ShpFileWriterOptions> {
output.writeShort(0) // flags

// Split the image file data into multiple smaller images
def imagesData = source.imageData.splitImage(source.width, source.height, width, height)
def imagesData = source.imageData.split(source.width, source.height, width, height)

def lcw = new LCW()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class ShpFileWriterDune2 extends FileWriter<ImageFile, ShpFileWriterDune2Options
Arrays.fill(heights, height)

// Split the image file data into multiple smaller images
def imagesData = source.imageData.splitImage(source.width, source.height, width, height)
def imagesData = source.imageData.split(source.width, source.height, width, height)

def rleZero = new RLEZero()
// def lcw = new LCW()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,9 @@ class Map extends Node<Map> {
protected final Matrix4f transformCopy = new Matrix4f()
protected final PalettedSpriteMaterial materialCopy = new PalettedSpriteMaterial()

private final TileSet tileSet
private final ResourceManager resourceManager
private final RulesFile rules

private CompletableFuture<SpriteSheet> tileSetSpriteSheetFuture

/**
* Constructor, create a new map from a map file.
*/
Expand All @@ -115,8 +112,6 @@ class Map extends Node<Map> {
set(MAX_BOUNDS)
}

tileSet = new TileSet()

// Rules file needed for some object configuration
var rulesIni = resourceManager.loadFile('rules.ini', IniFile)
rules = rulesIni as RulesFile
Expand Down Expand Up @@ -148,57 +143,6 @@ class Map extends Node<Map> {
})
}

@Override
CompletableFuture<Void> onSceneAddedAsync(Scene scene) {

tileSetSpriteSheetFuture = CompletableFuture.supplyAsync { ->
return tileSet.tileFileList
.collect { tileFile ->
if (tileFile.width > TILE_WIDTH || tileFile.height > TILE_HEIGHT) {
throw new IllegalArgumentException('Cannot use a tile file whose dimensions exceed 24x24')
}

var imagesData = tileFile.imagesData

// Place smaller images in the center of a blank tile
if (tileFile.width < TILE_WIDTH || tileFile.height < TILE_HEIGHT) {
imagesData = imagesData.collect { imageData ->
var newTileImageData = ByteBuffer.allocateNative(TILE_WIDTH * TILE_HEIGHT)
var xOffset = Math.floor((TILE_WIDTH - tileFile.width) / 2) as int
var yOffset = Math.floor((TILE_HEIGHT - tileFile.height) / 2) as int
tileFile.height.times { y ->
tileFile.width.times { x ->
newTileImageData.put(((yOffset + y) * TILE_WIDTH) + (xOffset + x), imageData.get((y * tileFile.width) + x))
}
}
return newTileImageData
}
}

return imagesData
}
.flatten() as ByteBuffer[]
}
.thenComposeAsync { allTileImageData ->
return scene.requestCreateOrGet(new SpriteSheetRequest(TILE_WIDTH, TILE_HEIGHT, ColourFormat.FORMAT_INDEXED, allTileImageData))
}
.thenApplyAsync { newSpriteSheet ->
tileSet.spriteSheet = newSpriteSheet
return newSpriteSheet
}

return CompletableFuture.allOf(tileSetSpriteSheetFuture)
}

@Override
CompletableFuture<Void> onSceneRemovedAsync(Scene scene) {

if (tileSet.numTiles) {
return scene.requestDelete(tileSet.spriteSheet)
}
return CompletableFuture.completedFuture()
}

/**
* Return some information about this map.
*
Expand Down Expand Up @@ -230,6 +174,10 @@ class Map extends Node<Map> {
*/
void addTiles(ImagesFile tilesFile) {

if (tilesFile.width > TILE_WIDTH || tilesFile.height > TILE_HEIGHT) {
throw new IllegalArgumentException('Cannot use a tile file whose dimensions exceed 24x24')
}

if (!tileFileList.contains(tilesFile)) {
tileFileList << tilesFile
tileFileMap << [(tilesFile): numTiles]
Expand Down Expand Up @@ -286,7 +234,7 @@ class Map extends Node<Map> {
var tileFile = resourceManager.loadFile(clearTileName, TmpFileRA)

// Create a sprite sheet for the 5x4 background tile
var imageData = tileFile.imagesData.combineImages(tileFile.width, tileFile.height, tileFile.format, theater.clearX)
var imageData = tileFile.imagesData.combine(tileFile.width, tileFile.height, tileFile.format, theater.clearX)
var spriteWidth = tileFile.width * theater.clearX
var spriteHeight = tileFile.height * theater.clearY

Expand Down Expand Up @@ -320,6 +268,7 @@ class Map extends Node<Map> {
final PartitionHint partitionHint = PartitionHint.LARGE_AREA
final UpdateHint updateHint = UpdateHint.NEVER

private final TileSet tileSet = new TileSet()
private final List<MapTile> mapTiles = []
private Mesh fullMesh
private Shader shader
Expand Down Expand Up @@ -382,18 +331,43 @@ class Map extends Node<Map> {

return CompletableFuture.allOf(
CompletableFuture.supplyAsync { ->
List<Vector2f> allVertices = []
List<Vector2f> allTextureUVs = []
List<Integer> allIndices = []
var indexOffset = 0
mapTiles.each { mapTile ->
allVertices.addAll(new Rectanglef(0, 0, TILE_WIDTH, TILE_HEIGHT).translate(mapTile.position()) as Vector2f[])
allTextureUVs.addAll(tileSet.spriteSheet[mapTile.frameInTileSet()] as Vector2f[])
allIndices.addAll([0, 1, 2, 0, 2, 3].collect { index -> index + indexOffset })
indexOffset += 4
}
return new Tuple3<Vector2f[], Vector2f[], int[]>(allVertices as Vector2f[], allTextureUVs as Vector2f[], allIndices as int[])
return tileSet.tileFileList
.collect { tileFile ->
return tileFile.imagesData.collect { imageData ->
return imageData.center(tileFile.width, tileFile.height, TILE_WIDTH, TILE_HEIGHT)
}
}
.flatten() as ByteBuffer[]
}
.thenComposeAsync { allTileImageData ->
return scene.requestCreateOrGet(new SpriteSheetRequest(TILE_WIDTH, TILE_HEIGHT, ColourFormat.FORMAT_INDEXED, allTileImageData))
}
.thenApplyAsync { newSpriteSheet ->
tileSet.spriteSheet = newSpriteSheet
material.with {
texture = newSpriteSheet.texture
frame = 0
frameStepX = newSpriteSheet.frameStepX
frameStepY = newSpriteSheet.frameStepY
framesHorizontal = newSpriteSheet.framesHorizontal
framesVertical = newSpriteSheet.framesVertical
}
return newSpriteSheet
}
// TODO: This can be some batching request method
.thenApplyAsync { spriteSheet ->
List<Vector2f> allVertices = []
List<Vector2f> allTextureUVs = []
List<Integer> allIndices = []
var indexOffset = 0
mapTiles.each { mapTile ->
allVertices.addAll(new Rectanglef(0, 0, TILE_WIDTH, TILE_HEIGHT).translate(mapTile.position()) as Vector2f[])
allTextureUVs.addAll(spriteSheet[mapTile.frameInTileSet()] as Vector2f[])
allIndices.addAll([0, 1, 2, 0, 2, 3].collect { index -> index + indexOffset })
indexOffset += 4
}
return new Tuple3<Vector2f[], Vector2f[], int[]>(allVertices as Vector2f[], allTextureUVs as Vector2f[], allIndices as int[])
}
.thenComposeAsync { meshData ->
def (allVertices, allTextureUVs, allIndices) = meshData
return scene
Expand All @@ -408,28 +382,16 @@ class Map extends Node<Map> {
.requestCreateOrGet(new ShaderRequest(Shaders.palettedSpriteShader))
.thenAcceptAsync { requestedShader ->
shader = requestedShader
},
tileSetSpriteSheetFuture.thenApplyAsync { spriteSheet ->
material.with {
texture = spriteSheet.texture
frame = 0
frameStepX = spriteSheet.frameStepX
frameStepY = spriteSheet.frameStepY
framesHorizontal = spriteSheet.framesHorizontal
framesVertical = spriteSheet.framesVertical
}
return spriteSheet
}
)
}

@Override
CompletableFuture<Void> onSceneRemovedAsync(Scene scene) {

return scene.requestDelete(fullMesh)
return scene.requestDelete(fullMesh, tileSet.spriteSheet)
}


@Override
RenderCommand renderCommand() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class Unit extends Node<Unit> implements FactionColours, Rotatable, Temporal {

var structureWidthInCells = Math.ceil(width / TILE_WIDTH) as int

var bibImageData = bibFile.imagesData.combineImages(bibFile.width, bibFile.height, bibFile.format, structureWidthInCells)
var bibImageData = bibFile.imagesData.combine(bibFile.width, bibFile.height, bibFile.format, structureWidthInCells)
var bibWidth = TILE_WIDTH * structureWidthInCells
var bibHeight = TILE_HEIGHT * 2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class OpenGLRenderer implements GraphicsRenderer {

var imagesAsSpriteSheet = data
.flipVertical(width, height, format)
.combineImages(width, height, format, framesHorizontal)
.combine(width, height, format, framesHorizontal)
var texture = createTexture(spriteSheetWidth, spriteSheetHeight, format, imagesAsSpriteSheet)

return new SpriteSheet(texture, framesHorizontal, framesVertical, frameStepX, frameStepY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ class Explorer {
*/
private void preview(TmpFileRA tileFile, String objectId) {

var singleImageData = tileFile.imagesData.combineImages(tileFile.width, tileFile.height, tileFile.format, tileFile.tilesX)
var singleImageData = tileFile.imagesData.combine(tileFile.width, tileFile.height, tileFile.format, tileFile.tilesX)
var singleImageWidth = tileFile.tilesX * tileFile.width
var singleImageHeight = tileFile.tilesY * tileFile.height

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,39 @@ class ByteBufferImageExtensions {
return dest.flip()
}

/**
* If an image buffer contains an image less than the specified dimensions,
* return an image buffer padded with 0s such that it will appear in the
* center.
*/
static ByteBuffer center(ByteBuffer self, int imageWidth, int imageHeight, int targetWidth, int targetHeight) {

if (imageWidth < targetWidth || imageHeight < targetHeight) {
var newTileImageData = ByteBuffer.allocateNative(targetWidth * targetHeight)
var xOffset = Math.floor((targetWidth - imageWidth) / 2 as int) as int
var yOffset = Math.floor((targetHeight - imageHeight) / 2 as int) as int
imageHeight.times { y ->
imageWidth.times { x ->
newTileImageData.put(((yOffset + y) * targetWidth) + (xOffset + x), self.get((y * imageWidth) + x))
}
}
return newTileImageData
}
return self
}

/**
* Creates a single overall image buffer from a series of smaller image
* buffers.
*
* @param self
* @param width Width of each image.
* @param height Height of each image
* @param width Width of each image.
* @param height Height of each image
* @param format
* @param imagesX Number of images to fit on the X axis.
* @return Single combined image buffer.
*/
static ByteBuffer combineImages(ByteBuffer[] self, int width, int height, ColourFormat format, int imagesX) {
static ByteBuffer combine(ByteBuffer[] self, int width, int height, ColourFormat format, int imagesX) {

var imagesY = Math.ceil((self.length / imagesX).doubleValue()) as int
var compileWidth = width * format.value * imagesX as int
Expand Down Expand Up @@ -89,7 +110,7 @@ class ByteBufferImageExtensions {
* means the bottom row of pixels.
*
* @param self
* @param width Width of the image.
* @param width Width of the image.
* @param height Height of the image.
* @param format The number of colour channels in each pixel.
* @return A new buffer with the horizontal pixel data flipped.
Expand All @@ -109,7 +130,7 @@ class ByteBufferImageExtensions {
* buffer in the array.
*
* @param self
* @param width Width of each image.
* @param width Width of each image.
* @param height Height of each image.
* @param format The number of colour channels in each pixel.
* @return A new array of buffers whose pixel data has been flipped.
Expand All @@ -122,15 +143,8 @@ class ByteBufferImageExtensions {
/**
* Take the image data for a single image and split it into several smaller
* images of the given dimensions.
*
* @param self
* @param sourceWidth
* @param sourceHeight
* @param targetWidth
* @param targetHeight
* @return
*/
static ByteBuffer[] splitImage(ByteBuffer self, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) {
static ByteBuffer[] split(ByteBuffer self, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) {

def imagesAcross = sourceWidth / targetWidth as int
def numImages = imagesAcross * (sourceHeight / targetHeight) as int
Expand Down

0 comments on commit 354678f

Please sign in to comment.