diff --git a/android/Images/TileSets/FantasyHex/Borders/ConcaveConvexInner.png b/android/Images/TileSets/FantasyHex/Borders/ConcaveConvexInner.png new file mode 100644 index 0000000000..b0c4e479a3 Binary files /dev/null and b/android/Images/TileSets/FantasyHex/Borders/ConcaveConvexInner.png differ diff --git a/android/Images/TileSets/FantasyHex/Borders/ConcaveConvexOuter.png b/android/Images/TileSets/FantasyHex/Borders/ConcaveConvexOuter.png new file mode 100644 index 0000000000..2645da70d6 Binary files /dev/null and b/android/Images/TileSets/FantasyHex/Borders/ConcaveConvexOuter.png differ diff --git a/android/Images/BorderImages/ConcaveInner.png b/android/Images/TileSets/FantasyHex/Borders/ConcaveInner.png similarity index 100% rename from android/Images/BorderImages/ConcaveInner.png rename to android/Images/TileSets/FantasyHex/Borders/ConcaveInner.png diff --git a/android/Images/BorderImages/ConcaveOuter.png b/android/Images/TileSets/FantasyHex/Borders/ConcaveOuter.png similarity index 100% rename from android/Images/BorderImages/ConcaveOuter.png rename to android/Images/TileSets/FantasyHex/Borders/ConcaveOuter.png diff --git a/android/Images/BorderImages/ConvexConcaveInner.png b/android/Images/TileSets/FantasyHex/Borders/ConvexConcaveInner.png similarity index 100% rename from android/Images/BorderImages/ConvexConcaveInner.png rename to android/Images/TileSets/FantasyHex/Borders/ConvexConcaveInner.png diff --git a/android/Images/BorderImages/ConvexConcaveOuter.png b/android/Images/TileSets/FantasyHex/Borders/ConvexConcaveOuter.png similarity index 100% rename from android/Images/BorderImages/ConvexConcaveOuter.png rename to android/Images/TileSets/FantasyHex/Borders/ConvexConcaveOuter.png diff --git a/android/Images/BorderImages/ConvexInner.png b/android/Images/TileSets/FantasyHex/Borders/ConvexInner.png similarity index 100% rename from android/Images/BorderImages/ConvexInner.png rename to android/Images/TileSets/FantasyHex/Borders/ConvexInner.png diff --git a/android/Images/BorderImages/ConvexOuter.png b/android/Images/TileSets/FantasyHex/Borders/ConvexOuter.png similarity index 100% rename from android/Images/BorderImages/ConvexOuter.png rename to android/Images/TileSets/FantasyHex/Borders/ConvexOuter.png diff --git a/core/src/com/unciv/ui/tilegroups/TileGroup.kt b/core/src/com/unciv/ui/tilegroups/TileGroup.kt index 3322ee5d38..9e94398786 100644 --- a/core/src/com/unciv/ui/tilegroups/TileGroup.kt +++ b/core/src/com/unciv/ui/tilegroups/TileGroup.kt @@ -20,6 +20,7 @@ import com.unciv.models.helpers.TintedMapArrow import com.unciv.models.helpers.UnitMovementMemoryType import com.unciv.ui.cityscreen.YieldGroup import com.unciv.ui.utils.* +import java.lang.IllegalStateException import kotlin.math.* import kotlin.random.Random @@ -44,9 +45,12 @@ open class TileGroup(var tileInfo: TileInfo, val tileSetStrings:TileSetStrings, City name */ - // Cache simple but frequent calculations + /** Cache simple but frequent calculations. */ private val hexagonImageWidth = groupSize * 1.5f - private val hexagonImageY = - groupSize / 6 + /** Cache simple but frequent calculations. */ + private val hexagonImageOrigin = Pair(hexagonImageWidth/2f, sqrt((hexagonImageWidth/2f).pow(2) - (hexagonImageWidth/4f).pow(2))) // Pair, not Vector2, for immutability. Second number is triangle height for hex center. + /** Cache simple but frequent calculations. */ + private val hexagonImagePosition = Pair(-hexagonImageOrigin.first/3f, -hexagonImageOrigin.second/4f) // Honestly, I got these numbers empirically by printing `.x` and `.y` after `.center()`, and I'm not totally clear on the stack of transformations that makes them work. But they are still exact ratios, AFAICT. // For recognizing the group in the profiler class BaseLayerGroupClass:ActionlessGroup() @@ -246,13 +250,15 @@ open class TileGroup(var tileInfo: TileInfo, val tileSetStrings:TileSetStrings, else resourceAndImprovementSequence.map { tileSetStrings.orFallback { getTile(it) } }.toList() } - // Used for both the underlying tile and unit overlays, perhaps for other things in the future - // Parent should already be set when calling + /** Used for: Underlying tile, unit overlays, border images, perhaps for other things in the future. + Parent should already be set when calling. */ private fun setHexagonImageSize(hexagonImage: Image) { // Using "scale" can get really confusing when positioning, how about no + // TODO: Make as many images use this as possible— Standardized "Image on tile" placement for consistently moddable crosshairs, circles, etc. hexagonImage.setSize(hexagonImageWidth, hexagonImage.height * hexagonImageWidth / hexagonImage.width) - hexagonImage.centerX(hexagonImage.parent) - hexagonImage.y = hexagonImageY + hexagonImage.setOrigin(hexagonImageOrigin.first, hexagonImageOrigin.second) + hexagonImage.x = hexagonImagePosition.first + hexagonImage.y = hexagonImagePosition.second } private fun updateTileImage(viewingCiv: CivilizationInfo?) { @@ -505,41 +511,33 @@ open class TileGroup(var tileInfo: TileInfo, val tileSetStrings:TileSetStrings, val borderShapeString = when { borderSegment.isLeftConcave && borderSegment.isRightConcave -> "Concave" !borderSegment.isLeftConcave && !borderSegment.isRightConcave -> "Convex" - else -> "ConvexConcave" + !borderSegment.isLeftConcave && borderSegment.isRightConcave -> "ConvexConcave" + borderSegment.isLeftConcave && !borderSegment.isRightConcave -> "ConcaveConvex" + else -> throw IllegalStateException("This shouldn't happen?") } - val isConcaveConvex = borderSegment.isLeftConcave && !borderSegment.isRightConcave val relativeWorldPosition = tileInfo.tileMap.getNeighborTilePositionAsWorldCoords(tileInfo, neighbor) - // This is some crazy voodoo magic so I'll explain. val sign = if (relativeWorldPosition.x < 0) -1 else 1 val angle = sign * (atan(sign * relativeWorldPosition.y / relativeWorldPosition.x) * 180 / PI - 90.0).toFloat() - val innerBorderImage = ImageGetter.getImage("BorderImages/${borderShapeString}Inner") - if (isConcaveConvex) { - innerBorderImage.scaleX = -innerBorderImage.scaleX - } - innerBorderImage.width = hexagonImageWidth - innerBorderImage.setOrigin(Align.center) // THEN the origin is correct, - innerBorderImage.rotateBy(angle) // and the rotation works. - innerBorderImage.center(this) // move to center of tile - innerBorderImage.moveBy(-relativeWorldPosition.x * 15f, -relativeWorldPosition.y * 15f) - innerBorderImage.color = civOuterColor + val innerBorderImage = ImageGetter.getImage( + tileSetStrings.orFallback { getBorder("${borderShapeString}Inner") } + ) miscLayerGroup.addActor(innerBorderImage) images.add(innerBorderImage) + setHexagonImageSize(innerBorderImage) + innerBorderImage.rotateBy(angle) + innerBorderImage.color = civOuterColor - val outerBorderImage = ImageGetter.getImage("BorderImages/${borderShapeString}Outer") - if (isConcaveConvex) { - outerBorderImage.scaleX = -outerBorderImage.scaleX - } - outerBorderImage.width = hexagonImageWidth - outerBorderImage.setOrigin(Align.center) // THEN the origin is correct, - outerBorderImage.rotateBy(angle) // and the rotation works. - outerBorderImage.center(this) // move to center of tile - outerBorderImage.moveBy(-relativeWorldPosition.x * 15f, -relativeWorldPosition.y * 15f) - outerBorderImage.color = civInnerColor + val outerBorderImage = ImageGetter.getImage( + tileSetStrings.orFallback { getBorder("${borderShapeString}Outer") } + ) miscLayerGroup.addActor(outerBorderImage) images.add(outerBorderImage) + setHexagonImageSize(outerBorderImage) + outerBorderImage.rotateBy(angle) + outerBorderImage.color = civInnerColor } } } diff --git a/core/src/com/unciv/ui/tilegroups/TileSetStrings.kt b/core/src/com/unciv/ui/tilegroups/TileSetStrings.kt index 15dfcb0a02..44f26b46d8 100644 --- a/core/src/com/unciv/ui/tilegroups/TileSetStrings.kt +++ b/core/src/com/unciv/ui/tilegroups/TileSetStrings.kt @@ -36,6 +36,8 @@ class TileSetStrings(tileSet: String = UncivGame.Current.settings.tileSet, fallb val landUnit = unitsLocation + "LandUnit" val waterUnit = unitsLocation + "WaterUnit" + val bordersLocation = tileSetLocation + "Borders/" + // There aren't that many tile combinations, and so we end up joining the same strings over and over again. // On large maps, this can end up as quite a lot of space, some tens of MB! // In order to save on space, we have this function that gets several strings and returns their concat, @@ -73,6 +75,8 @@ class TileSetStrings(tileSet: String = UncivGame.Current.settings.tileSet, fallb else return cityTile } + fun getBorder(imageName: String) = getString(bordersLocation, imageName) + /** Fallback [TileSetStrings] to use when the currently chosen tileset is missing an image. */ val fallback by lazy { if (fallbackDepth <= 0 || tileSetConfig.fallbackTileSet == null)