perf(rendering): Added class NonTransformGroup:Group for draw() performance

This commit is contained in:
yairm210 2024-12-01 18:55:25 +02:00
parent ba7c9def64
commit f62919b666
13 changed files with 56 additions and 57 deletions

View File

@ -0,0 +1,13 @@
package com.unciv.ui.components
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.scenes.scene2d.Group
/** Performance optimized for groups with no transform */
open class NonTransformGroup: Group(){
init {
isTransform = false
}
// Reduces need to check isTransform twice in every draw call
override fun draw(batch: Batch?, parentAlpha: Float) = this.drawChildren(batch, parentAlpha)
}

View File

@ -1,19 +1,12 @@
package com.unciv.ui.components.tilegroups
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.components.tilegroups.layers.TileLayerBorders
import com.unciv.ui.components.tilegroups.layers.TileLayerCityButton
import com.unciv.ui.components.tilegroups.layers.TileLayerFeatures
import com.unciv.ui.components.tilegroups.layers.TileLayerMisc
import com.unciv.ui.components.tilegroups.layers.TileLayerOverlay
import com.unciv.ui.components.tilegroups.layers.TileLayerTerrain
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitSprite
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitFlag
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.tilegroups.layers.*
import com.unciv.utils.DebugUtils
import kotlin.math.pow
import kotlin.math.sqrt
@ -22,7 +15,7 @@ open class TileGroup(
var tile: Tile,
val tileSetStrings: TileSetStrings,
groupSize: Float = TileGroupMap.groupSize + 4
) : Group() {
) : NonTransformGroup() {
/*
Layers (reordered in TileGroupMap):
1) Terrain
@ -55,7 +48,6 @@ open class TileGroup(
@Suppress("LeakingThis") val layerCityButton = TileLayerCityButton(this, groupSize)
init {
isTransform = false // performance helper - nothing here is rotated or scaled
this.setSize(groupSize, groupSize)
this.addActor(layerTerrain)

View File

@ -1,20 +1,19 @@
package com.unciv.ui.components.tilegroups.layers
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.tilesets.TileSetCache
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.TileSetStrings
abstract class TileLayer(val tileGroup: TileGroup, size: Float) : Group() {
abstract class TileLayer(val tileGroup: TileGroup, size: Float) : NonTransformGroup() {
init {
touchable = Touchable.disabled
isTransform = false
@Suppress("LeakingThis")
setSize(size, size)
}

View File

@ -2,18 +2,15 @@ package com.unciv.ui.components.tilegroups.layers
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.images.ImageGetter
class UnitSpriteSlot : Group() {
init {
isTransform = false
}
class UnitSpriteSlot : NonTransformGroup() {
var imageLocation = ""
}

View File

@ -12,6 +12,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.utils.Layout
import com.badlogic.gdx.utils.Align
import com.unciv.ui.components.ISortableGridContentProvider
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.addSeparator
import com.unciv.ui.components.extensions.center
@ -303,11 +304,10 @@ class SortableGrid<IT, ACT, CT: ISortableGridContentProvider<IT, ACT>> (
// Note this is not a WidgetGroup and thus does not implement Layout, so all layout details are left to the container
// - in this case, a Table.Cell. This will knowingly place the arrow partly outside the Group bounds.
private inner class IconHeaderElement(column: CT, override val headerActor: Actor) : IHeaderElement {
override val outerActor = Group()
override val outerActor = NonTransformGroup()
override var sortShown = SortDirection.None
init {
outerActor.isTransform = false
outerActor.setSize(iconSize, iconSize)
outerActor.addActor(headerActor)
headerActor.setSize(iconSize, iconSize)

View File

@ -11,6 +11,7 @@ import com.badlogic.gdx.utils.Align
import com.unciv.GUI
import com.unciv.UncivGame
import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.addToCenter
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.colorFromRGB
@ -78,7 +79,7 @@ private class FlagBackground(drawable: TextureRegionDrawable, size: Float) : Ima
}
/** Displays the unit's icon and action */
class UnitIconGroup(val unit: MapUnit, val size: Float) : Group() {
class UnitIconGroup(val unit: MapUnit, val size: Float) : NonTransformGroup() {
var actionGroup: Group? = null
private val flagIcon = ImageGetter.getUnitIcon(unit.baseUnit, unit.civ.nation.getInnerColor())
@ -87,7 +88,6 @@ class UnitIconGroup(val unit: MapUnit, val size: Float) : Group() {
private var flagMask: Image? = getBackgroundMaskForUnit()
init {
isTransform = false // performance helper - nothing here is rotated or scaled
color.a *= UncivGame.Current.settings.unitIconOpacity
val sizeSelectionX = size*1.6f

View File

@ -3,8 +3,8 @@ package com.unciv.ui.images
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.utils.Align
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.center
open class IconCircleGroup(
@ -13,7 +13,7 @@ open class IconCircleGroup(
resizeActor: Boolean = true,
color: Color = Color.WHITE,
circleImage: String = "OtherIcons/Circle"
): Group() {
): NonTransformGroup() {
val circle = ImageGetter.getImage(circleImage).apply {
setSize(size, size)
@ -21,7 +21,6 @@ open class IconCircleGroup(
}
init {
isTransform = false // performance helper - nothing here is rotated or scaled
setSize(size, size)
addActor(circle)
if (resizeActor) actor.setSize(size * 0.75f, size * 0.75f)

View File

@ -25,6 +25,7 @@ import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.skins.SkinCache
import com.unciv.models.tilesets.TileSetCache
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.centerY
@ -312,8 +313,7 @@ object ImageGetter {
return redCross
}
fun getCrossedImage(image: Actor, iconSize: Float) = Group().apply {
isTransform = false
fun getCrossedImage(image: Actor, iconSize: Float) = NonTransformGroup().apply {
setSize(iconSize, iconSize)
image.center(this)
addActor(image)
@ -343,7 +343,7 @@ object ImageGetter {
.setProgress(progressColor, percentComplete, padding = progressPadding)
}
class ProgressBar(width: Float, height: Float, val vertical: Boolean = true) : Group() {
class ProgressBar(width: Float, height: Float, val vertical: Boolean = true) : NonTransformGroup() {
var primaryPercentage: Float = 0f
var secondaryPercentage: Float = 0f
@ -355,7 +355,6 @@ object ImageGetter {
init {
setSize(width, height)
isTransform = false
}
fun setLabel(color: Color, text: String, fontSize: Int = Constants.defaultFontSize) : ProgressBar {

View File

@ -10,6 +10,7 @@ import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.unit.Promotion
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.colorFromRGB
@ -29,7 +30,7 @@ import com.unciv.ui.components.extensions.toLabel
* - It sets its own [size] but **paints outside these bounds** - by [borderSize].
* - Typically, if you want one in a Table Cell, add an extra [borderSize] padding to avoid surprises.
*/
open class Portrait(val type: Type, val imageName: String, val size: Float, val borderSize: Float = 2f) : Group() {
open class Portrait(val type: Type, val imageName: String, val size: Float, val borderSize: Float = 2f) : NonTransformGroup() {
enum class Type(val directory: String) {
Unit("Unit"),
@ -67,8 +68,6 @@ open class Portrait(val type: Type, val imageName: String, val size: Float, val
}
init {
isTransform = false
image = getMainImage()
background = getMainBackground()
@ -109,7 +108,7 @@ open class Portrait(val type: Type, val imageName: String, val size: Float, val
} else {
image.setSize(size*0.75f, size*0.75f)
val bg = Group().apply { isTransform = false }
val bg = NonTransformGroup()
val circleInner = ImageGetter.getCircle()
val circleOuter = ImageGetter.getCircle()

View File

@ -1,7 +1,6 @@
package com.unciv.ui.screens.mapeditorscreen.tabs
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
import com.badlogic.gdx.scenes.scene2d.ui.Table
@ -12,16 +11,13 @@ import com.unciv.logic.map.tile.RoadStatus
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.Terrain
import com.unciv.models.ruleset.tile.TerrainType
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.tile.*
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.onClick
@ -471,9 +467,8 @@ class MapEditorEditRiversTab(
}.makeTileGroup()
private fun getRemoveRiverIcon() =
ImageGetter.getCrossedImage(getTileGroupWithRivers(RiverEdge.All), iconSize)
private fun getRiverIcon(edge: RiverEdge) = Group().apply {
private fun getRiverIcon(edge: RiverEdge) = NonTransformGroup().apply {
// wrap same as getRemoveRiverIcon so the icons align the same (using getTileGroupWithRivers directly works but looks ugly - reason unknown to me)
isTransform = false
setSize(iconSize, iconSize)
val tileGroup = getTileGroupWithRivers(edge)
tileGroup.center(this)

View File

@ -1,11 +1,11 @@
package com.unciv.ui.screens.overviewscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.Constants
import com.unciv.logic.civilization.Civilization
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.addSeparator
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.darken
@ -24,8 +24,7 @@ internal object UnitSupplyTable {
): ExpanderTab {
val stats = viewingPlayer.stats
val deficit = stats.getUnitSupplyDeficit()
val icon = if (deficit <= 0) null else Group().apply {
isTransform = false
val icon = if (deficit <= 0) null else NonTransformGroup().apply {
setSize(36f, 36f)
val image = ImageGetter.getImage("OtherIcons/ExclamationMark")
image.color = Color.FIREBRICK

View File

@ -2,7 +2,6 @@ package com.unciv.ui.screens.pickerscreens
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
@ -15,6 +14,7 @@ import com.unciv.models.UncivSound
import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.extensions.disable
@ -41,8 +41,8 @@ class TechPickerScreen(
private var selectedTech: Technology? = null
private var civTech: TechManager = civInfo.tech
private var tempTechsToResearch: ArrayList<String>
private var lines = Group().apply { isTransform = false }
private var orderIndicators = Group().apply { isTransform = false }
private var lines = NonTransformGroup()
private var orderIndicators = NonTransformGroup()
private var eraLabels = ArrayList<Label>()
/** We need this to be a separate table, and NOT the topTable, because *inhales*

View File

@ -4,11 +4,11 @@ import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.math.Rectangle
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.MapShape
import com.unciv.logic.map.MapSize
import com.unciv.ui.components.NonTransformGroup
import com.unciv.ui.images.ClippingImage
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.worldscreen.worldmap.WorldMapHolder
@ -16,8 +16,15 @@ import kotlin.math.max
import kotlin.math.min
import kotlin.math.sqrt
class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civInfo: Civilization?) : Group() {
private val tileLayer = Group()
class TileLayerGroup: NonTransformGroup(){
override fun draw(batch: Batch?, parentAlpha: Float) = super.draw(batch, parentAlpha)
}
class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civInfo: Civilization?) : NonTransformGroup() {
private val tileLayer = TileLayerGroup()
private val borderLayer = NonTransformGroup()
private val cityLayer = NonTransformGroup()
private val minimapTiles: List<MinimapTile>
private val scrollPositionIndicators: List<ClippingImage>
private var lastViewingCiv: Civilization? = null
@ -27,9 +34,6 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civIn
private var tileMapHeight = 0f
init {
// don't try to resize rotate etc - this table has a LOT of children so that's valuable render time!
isTransform = false
// Set fixed minimap size
val stageMinimapSize = calcMinimapSize(minimapSize)
setSize(stageMinimapSize.x, stageMinimapSize.y)
@ -58,6 +62,8 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civIn
scrollPositionIndicators.forEach(tileLayer::addActor)
addActor(tileLayer)
addActor(borderLayer)
addActor(cityLayer)
mapHolder.onViewportChangedListener = ::updateScrollPosition
}
@ -238,11 +244,12 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civIn
if (shouldBeUnrevealed || !ownerChanged) continue
if (tileInfo.isCityCenter()) {
minimapTile.updateCityCircle().updateActorsIn(this)
minimapTile.updateCityCircle().updateActorsIn(cityLayer)
}
minimapTile.updateBorders().updateActorsIn(this)
minimapTile.updateBorders().updateActorsIn(borderLayer)
}
lastViewingCiv = viewingCiv
}