Fix adding tsx files to tilemap

This commit is contained in:
RezMike
2020-04-08 04:46:21 +07:00
parent e46faec0bc
commit 69d00b3486
6 changed files with 60 additions and 59 deletions

View File

@@ -38,22 +38,16 @@ class MapComponent(val tmx: TiledMap) : JComponent() {
field = value
mapRepaint(false)
}
val maxTileGid = tmx.tilesets.map { it.firstgid + it.tileset.textures.size }.max() ?: 0
val tilesSize = tmx.tilesets.sumBy { it.tileset.textures.size }
data class TileInfo(val bmp32: Bitmap32) {
val miniSlice = bmp32.slice()
val isTransparent by lazy { bmp32.all { it.a == 0 } }
}
val tiles = Array<TileInfo?>(maxTileGid) { null }.also { tiles ->
val tiles = HashMap<Int, BitmapSlice<Bitmap32>?>(tilesSize).also { tiles ->
for (tileset in tmx.tilesets) {
for (tileIdx in tileset.tileset.textures.indices) {
val tile = tileset.tileset.textures[tileIdx]
if (tile != null) {
val miniSlice = (tile as BitmapSlice<*>).extract().toBMP32()
tiles[tileset.firstgid + tileIdx] = when {
miniSlice.allFixed { it.a == 0 } -> null // Transparent
else -> TileInfo(miniSlice)
val tileBmp = (tile as BitmapSlice<*>).extract().toBMP32()
if (tileBmp.any { it.a != 0 }) { // not transparent
tiles[tileset.firstgid + tileIdx] = tileBmp.slice()
}
}
}
@@ -169,8 +163,8 @@ class MapComponent(val tmx: TiledMap) : JComponent() {
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
)
val clipBounds = g.clipBounds
val displayTilesX = ((clipBounds.width / TILE_WIDTH / scale) + 3).toInt().coerceIn(0, tmx.width - 1)
val displayTilesY = ((clipBounds.height / TILE_HEIGHT / scale) + 3).toInt().coerceIn(0, tmx.height - 1)
val displayTilesX = ((clipBounds.width / TILE_WIDTH / scale) + 3).toInt().coerceIn(1, tmx.width)
val displayTilesY = ((clipBounds.height / TILE_HEIGHT / scale) + 3).toInt().coerceIn(1, tmx.height)
val offsetX = (clipBounds.x / TILE_WIDTH / scale).toInt()
val offsetY = (clipBounds.y / TILE_HEIGHT / scale).toInt()
@@ -178,7 +172,7 @@ class MapComponent(val tmx: TiledMap) : JComponent() {
offsetX = offsetX, offsetY = offsetY,
displayTilesX = displayTilesX,
displayTilesY = displayTilesY,
TILE_WIDTH = TILE_WIDTH, TILE_HEIGHT = TILE_WIDTH
TILE_WIDTH = TILE_WIDTH, TILE_HEIGHT = TILE_HEIGHT
)) {
val temp = Bitmap32(
(displayTilesX * TILE_WIDTH),
@@ -197,9 +191,9 @@ class MapComponent(val tmx: TiledMap) : JComponent() {
if (ry < 0 || ry >= layer.map.height) continue
val tileIdx = layer.map[rx, ry].value
val tile = tiles.getOrNull(tileIdx)
if (tile != null && !tile.isTransparent) {
temp._fastMix(tile.miniSlice, x * TILE_WIDTH, y * TILE_HEIGHT)
val tile = tiles.getOrDefault(tileIdx, null)
if (tile != null) {
temp._fastMix(tile, x * TILE_WIDTH, y * TILE_HEIGHT)
}
}
}
@@ -314,6 +308,3 @@ fun fastBlend(dst: RGBAPremultiplied, src: RGBAPremultiplied): RGBAPremultiplied
val ag = (colora and 0xFF00FF00L) + ((alpha * (colorb and 0xFF00FF00L)) ushr 8)
return RGBAPremultiplied(((rb and 0xFF00FFL) + (ag and 0xFF00FF00L)).toInt())
}
inline fun Bitmap32.anyFixed(callback: (RGBA) -> Boolean): Boolean = (0 until area).any { callback(data[it]) }
inline fun Bitmap32.allFixed(callback: (RGBA) -> Boolean): Boolean = (0 until area).all { callback(data[it]) }

View File

@@ -83,8 +83,7 @@ data class TileSetData constructor(
//@AsyncFactoryClass(TiledMapFactory::class)
class TiledMap constructor(
var data: TiledMapData,
var tilesets: List<TiledTileset>,
var tileset: TileSet
var tilesets: List<TiledTileset>
) {
val width get() = data.width
val height get() = data.height
@@ -93,11 +92,12 @@ class TiledMap constructor(
val pixelWidth: Int get() = data.pixelWidth
val pixelHeight: Int get() = data.pixelHeight
val allLayers get() = data.allLayers
val patternLayers get() = data.tileLayers
val tileLayers get() = data.tileLayers
val imageLayers get() = data.imageLayers
val objectLayers get() = data.objectLayers
val nextGid get() = tilesets.map { it.firstgid + it.tileset.textures.size }.max() ?: 1
fun clone() = TiledMap(data.clone(), tilesets.map { it.clone() }, tileset.clone())
fun clone() = TiledMap(data.clone(), tilesets.map { it.clone() })
data class TiledTileset(
val tileset: TileSet,
@@ -116,7 +116,7 @@ class TiledMap constructor(
terrains = listOf(),
tiles = tileset.textures.mapIndexed { index, bmpSlice -> TileData(index) }
),
val firstgid: Int = 0
val firstgid: Int = 1
) {
fun clone(): TiledTileset = TiledTileset(tileset.clone(), data.clone(), firstgid)
}
@@ -149,7 +149,7 @@ class TiledMap constructor(
}
abstract fun clone(): Layer
class Tiles constructor(
class Tiles(
var map: Bitmap32 = Bitmap32(0, 0),
var encoding: String = "csv",
var compression: String = ""

View File

@@ -14,7 +14,6 @@ import com.soywiz.korio.serialization.xml.*
import com.soywiz.korio.util.encoding.*
import com.soywiz.korma.geom.*
suspend fun VfsFile.readTiledMap(
hasTransparentColor: Boolean = false,
transparentColor: RGBA = Colors.FUCHSIA,
@@ -40,7 +39,7 @@ suspend fun VfsFile.readTiledMap(
tiledTilesets += tileset.toTiledSet(folder, hasTransparentColor, transparentColor, createBorder)
}
return TiledMap(data, tiledTilesets, tiledTilesets.combine(data.tilewidth, data.tileheight))
return TiledMap(data, tiledTilesets)
}
private fun Xml.parseProperties(): Map<String, Any> {
@@ -148,18 +147,6 @@ suspend fun TileSetData.toTiledSet(
return tiledTileset
}
fun Iterable<TiledMap.TiledTileset>.combine(tilewidth: Int, tileheight: Int): TileSet {
val maxGid = this.map { it.firstgid + it.tileset.textures.size }.max() ?: 1
val combinedTileset = arrayOfNulls<BmpSlice>(maxGid + 1)
for (tileset in this) {
val ptileset = tileset.tileset
for (n in ptileset.textures.indices) {
combinedTileset[tileset.firstgid + n] = ptileset.textures[n]
}
}
return TileSet(combinedTileset.toList(), tilewidth, tileheight)
}
suspend fun VfsFile.readTiledMapData(): TiledMapData {
val log = tilemapLog
val file = this

View File

@@ -60,8 +60,7 @@ fun TileSetData.toXML(): Xml {
// <image source="Overworld.png" width="640" height="576"/>
//</tileset>
return buildXml("tileset",
"version" to 1.2,
"tiledversion" to "1.3.1",
"firstgid" to firstgid,
"name" to name,
"tilewidth" to tilewidth,
"tileheight" to tileheight,

View File

@@ -11,6 +11,7 @@ import com.soywiz.korge.view.tiles.*
import com.soywiz.korim.bitmap.*
import com.soywiz.korim.color.*
import com.soywiz.korim.format.*
import com.soywiz.korio.file.*
import com.soywiz.korma.geom.*
import kotlinx.coroutines.*
import javax.swing.*
@@ -25,10 +26,10 @@ fun Styled<out JTabbedPane>.tilesetTab(
fill()
uiSequence({ tilemap.tilesets }, tilesetsUpdated) { tileset ->
println("TAB.TILESET: $tileset")
tab("Untitled") {
tab(tileset.data.name) {
val tilemap = tileset.pickerTilemap()
val mapComponent = MapComponent(tilemap)
val patternLayer = tilemap.patternLayers.first()
val tileLayer = tilemap.tileLayers.first()
mapComponent.selectedRange(0, 0)
var downStart: PointInt? = null
val zoomLevel =
@@ -60,7 +61,7 @@ fun Styled<out JTabbedPane>.tilesetTab(
val width = xmax - xmin + 1
val height = ymax - ymin + 1
val bmp =
Bitmap32(width, height) { x, y -> RGBA(patternLayer.map[xmin + x, ymin + y].value) }
Bitmap32(width, height) { x, y -> RGBA(tileLayer.map[xmin + x, ymin + y].value) }
picked.value = PickedSelection(bmp)
mapComponent.selectedRange(xmin, ymin, bmp.width, bmp.height)
}
@@ -69,28 +70,28 @@ fun Styled<out JTabbedPane>.tilesetTab(
}
}
toolbar {
iconButton(toolbarIcon("add.png")) {
iconButton(toolbarIcon("add.png"), "Add tileset file or image") {
click {
val file = projectContext.chooseFile()
if (file != null) {
val vfsFile = file.toVfs()
val vfsFile = projectContext.chooseFile()?.toVfs()
if (vfsFile != null) {
runBlocking {
val tileset = try {
val firstgid = tilemap.nextGid
val tileset = if (vfsFile.extensionLC != "tsx") {
val bmp = vfsFile.readBitmap()
TiledMap.TiledTileset(TileSet(bmp.slice().split(32, 32), 32, 32, bmp))
} catch (e: Throwable) {
vfsFile.readTileSetData().toTiledSet(vfsFile.parent)
tiledsetFromBitmap(vfsFile.baseName, 32, 32, bmp, firstgid)
} else {
vfsFile.readTileSetData(firstgid).toTiledSet(vfsFile.parent)
}
val oldMap = tilemap
history.addAndDo("ADD TILESET") { redo ->
if (redo) {
tilemap.data.tilesets += tileset.data
tilemap.tilesets += tileset
tilemap.tileset = tileset.tileset
tilesetsUpdated(Unit)
} else {
TODO("Unsupported now")
tilemap.data.tilesets -= tileset.data
tilemap.tilesets -= tileset
tilesetsUpdated(Unit)
}
}
}
@@ -124,6 +125,29 @@ private fun TiledMap.TiledTileset.pickerTilemap(): TiledMap {
return TiledMap(TiledMapData(
width = mapWidth, height = mapHeight,
tilewidth = tileset.width, tileheight = tileset.height,
allLayers = arrayListOf(TiledMap.Layer.Tiles(Bitmap32(mapWidth.coerceAtLeast(1), mapHeight.coerceAtLeast(1)) { x, y -> RGBA(y * mapWidth + x) }))
), listOf(this), tileset)
allLayers = arrayListOf(TiledMap.Layer.Tiles(
Bitmap32(mapWidth.coerceAtLeast(1), mapHeight.coerceAtLeast(1)) { x, y -> RGBA(y * mapWidth + x + firstgid) }
))
), listOf(this))
}
private fun tiledsetFromBitmap(name: String, tileWidth: Int, tileHeight: Int, bmp: Bitmap, firstgid: Int): TiledMap.TiledTileset {
val tileset = TileSet(bmp.slice().split(tileWidth, tileHeight), tileWidth, tileHeight)
return TiledMap.TiledTileset(tileset,
TileSetData(
name = name.substringBeforeLast("."),
firstgid = firstgid,
tilewidth = tileset.width,
tileheight = tileset.height,
tilecount = tileset.textures.size,
columns = tileset.base.width / tileset.width,
image = null,
imageSource = name,
width = tileset.base.width,
height = tileset.base.height,
tilesetSource = null,
terrains = listOf(),
tiles = tileset.textures.mapIndexed { index, bmpSlice -> TileData(index) }
)
)
}

View File

@@ -101,7 +101,7 @@ fun Styled<out Container>.toolbar(direction: Direction = Direction.HORIZONTAL, p
}
fun Styled<out Container>.tabs(block: @UIDslMarker Styled<JBTabbedPane>.() -> Unit = {}): JBTabbedPane {
val container = JBTabbedPane(JBTabbedPane.TOP)
val container = JBTabbedPane(JBTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT)
component.add(container)
block(container.styled)
return container