Skip to content

Commit b77dd98

Browse files
committed
Improve buffer reuse logic in UIBufferedComponent and subclasses
1 parent 5cc5404 commit b77dd98

10 files changed

Lines changed: 88 additions & 37 deletions

File tree

src/com/reco1l/andengine/buffered/UIBufferedComponent.kt

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,19 @@ import javax.microedition.khronos.opengles.GL10
1313
*/
1414
abstract class UIBufferedComponent<T : IBuffer> : UIComponent() {
1515

16+
override var radius: Float
17+
get() = super.radius
18+
set(value) {
19+
if (super.radius != value) {
20+
super.radius = value
21+
requestBufferUpdate()
22+
}
23+
}
24+
1625
/**
1726
* The buffer itself.
1827
*/
19-
open var buffer: T? = null
28+
var buffer: T? = null
2029
set(value) {
2130
if (field != value) {
2231
field?.finalize()
@@ -29,11 +38,6 @@ abstract class UIBufferedComponent<T : IBuffer> : UIComponent() {
2938
*/
3039
var allowBufferCache = true
3140

32-
/**
33-
* Whether to allow the buffer to be updated dynamically.
34-
*/
35-
var allowBufferDynamicUpdate = true
36-
3741
/**
3842
* The blend information of the entity.
3943
*/
@@ -70,7 +74,18 @@ abstract class UIBufferedComponent<T : IBuffer> : UIComponent() {
7074
protected abstract fun generateBufferCacheKey(): String
7175

7276
/**
73-
* Called when the buffer needs to be built.
77+
* Determines if the current buffer can be reused instead of creating a new one.
78+
*
79+
* Override this method to implement custom buffer reuse logic based on buffer properties.
80+
* Return `true` if the existing buffer is compatible and can be reused, `false` otherwise.
81+
*
82+
* @param buffer The current buffer to check for reusability
83+
* @return `true` if the buffer can be reused, `false` if a new buffer should be created
84+
*/
85+
protected open fun canReuseBuffer(buffer: T): Boolean = false
86+
87+
/**
88+
* Called when a new buffer needs to be created.
7489
*/
7590
protected abstract fun createBuffer(): T
7691

@@ -96,7 +111,8 @@ abstract class UIBufferedComponent<T : IBuffer> : UIComponent() {
96111
requestBufferUpdate()
97112
}
98113

99-
override fun onManagedDraw(gl: GL10, camera: Camera) {
114+
override fun onHandleInvalidations() {
115+
super.onHandleInvalidations()
100116

101117
// Buffer update is done after invalidations are handled so we can
102118
// refer the buffer in those invalidations.
@@ -105,34 +121,38 @@ abstract class UIBufferedComponent<T : IBuffer> : UIComponent() {
105121

106122
val cacheKey = generateBufferCacheKey()
107123

108-
if (bufferCacheKey != cacheKey) {
109-
110-
if (allowBufferCache) {
111-
val newBuffer = UIEngine.current.resources.getOrStoreBuffer(cacheKey) { createBuffer() }
124+
if (allowBufferCache) {
125+
if (bufferCacheKey != cacheKey) {
126+
val newBuffer = UIEngine.current.resources.getOrStoreBuffer(cacheKey) {
127+
val currentBuffer = buffer
128+
if (currentBuffer != null && canReuseBuffer(currentBuffer)) {
129+
currentBuffer
130+
} else {
131+
createBuffer()
132+
}
133+
}
112134

113135
val oldBuffer = buffer
114-
if (oldBuffer != null) {
136+
if (oldBuffer != null && oldBuffer !== newBuffer) {
115137
UIEngine.current.resources.unsubscribeFromBuffer(oldBuffer, this)
116138
}
117139

118140
UIEngine.current.resources.subscribeToBuffer(newBuffer, this)
119141

120142
@Suppress("UNCHECKED_CAST")
121143
buffer = newBuffer as T?
122-
} else {
123-
if (!allowBufferDynamicUpdate || buffer == null) {
124-
buffer = createBuffer()
125-
}
144+
bufferCacheKey = cacheKey
145+
}
146+
} else {
147+
val currentBuffer = buffer
148+
if (currentBuffer == null || !canReuseBuffer(currentBuffer)) {
149+
buffer = createBuffer()
126150
}
127-
128-
bufferCacheKey = cacheKey
129151
}
130152

131153
onUpdateBuffer()
132154
buffer?.invalidateOnHardware()
133155
}
134-
135-
super.onManagedDraw(gl, camera)
136156
}
137157

138158
override fun doDraw(gl: GL10, camera: Camera) {

src/com/reco1l/andengine/component/UIComponent.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ abstract class UIComponent : Entity(0f, 0f), ITouchArea, IModifierChain {
401401
/**
402402
* The corner radius of this component.
403403
*/
404-
var radius = 0f
404+
open var radius = 0f
405405
set(value) {
406406
if (field != value) {
407407
field = value

src/com/reco1l/andengine/shape/UIBox.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,23 @@ open class UIBox : UIBufferedComponent<BoxVBO>() {
3232
var lineWidth = 1f
3333

3434

35+
private val safeRadius
36+
get() = radius.coerceAtMost(min(width, height) / 2f).coerceAtLeast(0f)
37+
3538
private val segments
36-
get() = if (radius > 0f) calculateArcResolution(radius, radius, 90f) else 0
39+
get() = if (safeRadius > 0f) calculateArcResolution(safeRadius, safeRadius, 90f) else 0
3740

3841

3942
override fun createBuffer(): BoxVBO {
40-
return BoxVBO(radius, segments, paintStyle)
43+
return BoxVBO(segments, paintStyle)
44+
}
45+
46+
override fun canReuseBuffer(buffer: BoxVBO): Boolean {
47+
return buffer.segments == segments && buffer.paintStyle == paintStyle
4148
}
4249

4350
override fun generateBufferCacheKey(): String {
44-
return "BoxVBO@$width,$height,$radius,$segments,$paintStyle"
51+
return "BoxVBO@$width,$height,$segments,$paintStyle"
4552
}
4653

4754
override fun onUpdateBuffer() {
@@ -58,7 +65,6 @@ open class UIBox : UIBufferedComponent<BoxVBO>() {
5865

5966

6067
class BoxVBO(
61-
val radius: Float,
6268
val segments: Int,
6369
val paintStyle: PaintStyle
6470
) : VertexBuffer(
@@ -90,7 +96,7 @@ open class UIBox : UIBufferedComponent<BoxVBO>() {
9096
putVertex(position++, width / 2f, height / 2f)
9197
}
9298

93-
val radius = radius.coerceAtMost(min(width, height) / 2f).coerceAtLeast(0f)
99+
val radius = entity.radius.coerceAtMost(min(width, height) / 2f).coerceAtLeast(0f)
94100

95101
// [1]
96102
position = addArc(position, radius, radius, -90f, 0f, radius, radius, segments)

src/com/reco1l/andengine/shape/UICircle.kt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ open class UICircle : UIBufferedComponent<CircleVertexBuffer>() {
5555
}
5656
}
5757

58+
59+
private val segments
60+
get() = calculateArcResolution(width, height)
61+
62+
5863
/**
5964
* Sets the portion of the circle to be drawn starting from the start angle.
6065
*
@@ -72,12 +77,14 @@ open class UICircle : UIBufferedComponent<CircleVertexBuffer>() {
7277
}
7378

7479
override fun createBuffer(): CircleVertexBuffer {
75-
val segments = calculateArcResolution(width, height)
7680
return CircleVertexBuffer(segments, paintStyle)
7781
}
7882

83+
override fun canReuseBuffer(buffer: CircleVertexBuffer): Boolean {
84+
return buffer.segments == segments && buffer.paintStyle == paintStyle
85+
}
86+
7987
override fun generateBufferCacheKey(): String {
80-
val segments = calculateArcResolution(width, height)
8188
return "CircleVBO@$segments,$paintStyle"
8289
}
8390

@@ -126,13 +133,5 @@ open class UICircle : UIBufferedComponent<CircleVertexBuffer>() {
126133
return max(3, segments)
127134
}
128135

129-
@Deprecated(
130-
message = "Use calculateArcResolution instead",
131-
replaceWith = ReplaceWith("calculateArcResolution(width, height, maximumAngle)")
132-
)
133-
fun approximateSegments(width: Float, height: Float, maximumAngle: Float = 360f): Int {
134-
return calculateArcResolution(width, height, maximumAngle)
135-
}
136-
137136
}
138137
}

src/com/reco1l/andengine/shape/UILine.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class UILine : UIBufferedComponent<LineVertexBuffer>() {
4444
return LineVertexBuffer()
4545
}
4646

47+
override fun canReuseBuffer(buffer: LineVertexBuffer): Boolean {
48+
return true
49+
}
50+
4751
override fun generateBufferCacheKey(): String {
4852
return "LineVBO@$fromPoint,$toPoint"
4953
}

src/com/reco1l/andengine/shape/UITriangle.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ open class UITriangle : UIBufferedComponent<TriangleVBO>() {
2727
return TriangleVBO()
2828
}
2929

30+
override fun canReuseBuffer(buffer: TriangleVBO): Boolean {
31+
return true
32+
}
33+
3034
override fun generateBufferCacheKey(): String {
3135
return "TriangleVBO@$width,$height"
3236
}

src/com/reco1l/andengine/sprite/UISprite.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ open class UISprite(textureRegion: TextureRegion? = null) : UIBufferedComponent<
122122
return SpriteVBO()
123123
}
124124

125+
override fun canReuseBuffer(buffer: SpriteVBO): Boolean {
126+
return true
127+
}
128+
125129
override fun generateBufferCacheKey(): String {
126130
return "SpriteVBO@$width,$height,$scaleType"
127131
}

src/com/reco1l/andengine/text/FontAwesomeIcon.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ open class FontAwesomeIcon(icon: Int) : UIBufferedComponent<CompoundBuffer>() {
107107
return CompoundBuffer(IconTextureBuffer(), IconVertexBuffer())
108108
}
109109

110+
override fun canReuseBuffer(buffer: CompoundBuffer): Boolean {
111+
return true
112+
}
113+
110114
override fun generateBufferCacheKey(): String {
111115
return "IconVBO@$iconSize,$iconVariant,$icon"
112116
}

src/com/reco1l/andengine/text/UIText.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,12 @@ open class UIText : UIBufferedComponent<CompoundBuffer>() {
296296
return UITextCompoundBuffer(capacity)
297297
}
298298

299+
override fun canReuseBuffer(buffer: CompoundBuffer): Boolean {
300+
val capacity = nextPowerOfTwo(currentLength)
301+
val vertexBuffer = buffer.getFirstOf<TextVertexBuffer>()
302+
return vertexBuffer.vertexCount == capacity * VERTICES_PER_CHARACTER
303+
}
304+
299305
override fun generateBufferCacheKey(): String {
300306
val capacity = nextPowerOfTwo(currentLength)
301307
return "UITextVBO@$capacity,$fontSize,$fontFamily"

src/com/reco1l/andengine/text/UITextureText.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ open class UITextureText(val characters: MutableMap<Char, TextureRegion>) : UIBu
136136
return TextureTextVertexBuffer()
137137
}
138138

139+
override fun canReuseBuffer(buffer: TextureTextVertexBuffer): Boolean {
140+
return true
141+
}
142+
139143
override fun generateBufferCacheKey(): String {
140144
return "TextureTextVBO@${textureRegions.size}"
141145
}

0 commit comments

Comments
 (0)