From 61b379cb9ed54c5eecd07db1ae1f76f3d04ec234 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Wed, 18 Dec 2024 11:16:23 -0300 Subject: [PATCH 01/73] Introduce relative size axes --- src/com/reco1l/andengine/Axes.kt | 15 ++- src/com/reco1l/andengine/ExtendedEntity.kt | 105 +++++++++++++++--- .../andengine/container/LinearContainer.kt | 4 +- .../container/ScrollableContainer.kt | 26 ++--- src/com/reco1l/andengine/shape/Box.kt | 6 +- src/com/reco1l/andengine/shape/Circle.kt | 4 +- src/com/reco1l/osu/playfield/Counters.kt | 8 +- src/com/reco1l/osu/playfield/GameplayHUD.kt | 2 +- src/com/reco1l/osu/playfield/HealthBar.kt | 10 +- .../ccfit/zuev/osu/game/GameplaySpinner.java | 2 +- 10 files changed, 135 insertions(+), 47 deletions(-) diff --git a/src/com/reco1l/andengine/Axes.kt b/src/com/reco1l/andengine/Axes.kt index 9d9ca0f79..6e6f363c0 100644 --- a/src/com/reco1l/andengine/Axes.kt +++ b/src/com/reco1l/andengine/Axes.kt @@ -23,5 +23,18 @@ enum class Axes { /** * None of the axes. */ - None + None; + + + /** + * Whether this axis [Y] or [Both]. + */ + val isVertical: Boolean + get() = this == Y || this == Both + + /** + * Whether this axis is [X] or [Both]. + */ + val isHorizontal: Boolean + get() = this == X || this == Both } \ No newline at end of file diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index c09670497..2d08ffc27 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -40,6 +40,17 @@ abstract class ExtendedEntity( } } + /** + * Determines which axes the entity should adjust its size relative to its parent. + */ + open var relativeSizeAxes = Axes.None + set(value) { + if (field != value) { + field = value + onContentSizeMeasured() + } + } + /** * The origin factor of the entity in the X axis. */ @@ -123,7 +134,6 @@ abstract class ExtendedEntity( } } - /** * The width of the content inside the entity. */ @@ -146,6 +156,36 @@ abstract class ExtendedEntity( } } + /** + * The real width of the entity in pixels. + * + * Due to compatibility reason, this doesn't take into account transformations like rotation or scaling. + * @see [getWidthScaled] + */ + open val drawWidth: Float + get() { + val parent = parent + if (relativeSizeAxes.isHorizontal && parent is IShape) { + return parent.width * width + } + return width + } + + /** + * The real height of the entity in pixels. + * + * Due to compatibility reason, this doesn't take into account transformations like rotation or scaling. + * @see [getHeightScaled] + */ + open val drawHeight: Float + get() { + val parent = parent + if (relativeSizeAxes.isVertical && parent is IShape) { + return parent.height * height + } + return height + } + /** * The raw X position of the entity. * This is the position without taking into account the origin, anchor, or translation. @@ -403,7 +443,6 @@ abstract class ExtendedEntity( } - // Vertex buffer override fun updateVertexBuffer() { @@ -415,7 +454,6 @@ abstract class ExtendedEntity( onUpdateVertexBuffer() } - /** * Sets the vertex buffer of the entity. * @@ -448,12 +486,22 @@ abstract class ExtendedEntity( if (contentWidth != width || contentHeight != height) { - if (autoSizeAxes == Axes.X || autoSizeAxes == Axes.Both) { - width = contentWidth + val parent = parent + + if (autoSizeAxes.isHorizontal) { + width = if (relativeSizeAxes.isHorizontal && parent is IShape) { + contentWidth / parent.width + } else { + contentWidth + } } - if (autoSizeAxes == Axes.Y || autoSizeAxes == Axes.Both) { - height = contentHeight + if (autoSizeAxes.isVertical) { + height = if (relativeSizeAxes.isVertical && parent is IShape) { + contentHeight / parent.height + } else { + contentHeight + } } updateVertexBuffer() @@ -478,16 +526,15 @@ abstract class ExtendedEntity( if (width != newWidth || height != newHeight) { - if (autoSizeAxes == Axes.None || autoSizeAxes == Axes.Y) { + if (!autoSizeAxes.isHorizontal) { width = newWidth } - if (autoSizeAxes == Axes.None || autoSizeAxes == Axes.X) { + if (!autoSizeAxes.isVertical) { height = newHeight } updateVertexBuffer() - (parent as? Container)?.onChildSizeChanged(this) return true } @@ -495,21 +542,49 @@ abstract class ExtendedEntity( } open fun setWidth(value: Float) { - setSize(value, height) - } + if (autoSizeAxes.isVertical) { + Log.w("ExtendedEntity", "Cannot set width when autoSizeAxes is set to Both or X.") + return + } - override fun getWidth(): Float { - return width + if (width != value) { + width = value + + updateVertexBuffer() + (parent as? Container)?.onChildSizeChanged(this) + } } open fun setHeight(value: Float) { - setSize(width, value) + if (autoSizeAxes.isHorizontal) { + Log.w("ExtendedEntity", "Cannot set height when autoSizeAxes is set to Both or Y.") + return + } + + if (height != value) { + height = value + + updateVertexBuffer() + (parent as? Container)?.onChildSizeChanged(this) + } + } + + override fun getWidth(): Float { + return width } override fun getHeight(): Float { return height } + override fun getWidthScaled(): Float { + return drawWidth * scaleX + } + + override fun getHeightScaled(): Float { + return drawHeight * scaleY + } + // Unsupported methods diff --git a/src/com/reco1l/andengine/container/LinearContainer.kt b/src/com/reco1l/andengine/container/LinearContainer.kt index 80240b4f9..27b90f451 100644 --- a/src/com/reco1l/andengine/container/LinearContainer.kt +++ b/src/com/reco1l/andengine/container/LinearContainer.kt @@ -83,7 +83,7 @@ open class LinearContainer : Container() { } val drawX = lastDrawOffset + super.getChildDrawX(child) - lastDrawOffset += child.width + spacing + lastDrawOffset += child.drawWidth + spacing return drawX } @@ -95,7 +95,7 @@ open class LinearContainer : Container() { } val drawY = lastDrawOffset + super.getChildDrawY(child) - lastDrawOffset += child.height + spacing + lastDrawOffset += child.drawHeight + spacing return drawY } diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index 45afd5aa5..57bea7a76 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -104,7 +104,7 @@ open class ScrollableContainer : Container() { * This does not take into account the overscroll. */ val maxScrollX - get() = max(0f, scrollableContentWidth - width) + get() = max(0f, scrollableContentWidth - drawWidth) /** * The maximum scroll position on the y-axis. @@ -112,21 +112,21 @@ open class ScrollableContainer : Container() { * This does not take into account the overscroll. */ val maxScrollY - get() = max(0f, scrollableContentHeight - height) + get() = max(0f, scrollableContentHeight - drawHeight) /** * The width of the content that can be scrolled. That is [contentWidth] minus * the width of the vertical indicator. */ val scrollableContentWidth - get() = max(0f, contentWidth - (indicatorY?.width ?: 0f)) + get() = max(0f, contentWidth - (indicatorY?.drawWidth ?: 0f)) /** * The height of the content that can be scrolled. That is [contentHeight] minus * the height of the horizontal indicator. */ val scrollableContentHeight - get() = max(0f, contentHeight - (indicatorX?.height ?: 0f)) + get() = max(0f, contentHeight - (indicatorX?.drawHeight ?: 0f)) private var initialX = 0f @@ -215,7 +215,7 @@ open class ScrollableContainer : Container() { indicatorY?.let { it.isVisible = scrollAxes == Axes.Both || scrollAxes == Axes.Y - it.y = scrollY * (height / scrollableContentHeight) + it.y = scrollY * (drawHeight / scrollableContentHeight) if (it.alpha > 0f && velocityY == 0f) { it.alpha -= deltaTimeSec * 0.5f @@ -234,8 +234,8 @@ open class ScrollableContainer : Container() { it.isVisible = scrollAxes == Axes.Both || scrollAxes == Axes.X - it.x = scrollX * (width / scrollableContentWidth) - it.y = height - it.height + it.x = scrollX * (drawWidth / scrollableContentWidth) + it.y = drawHeight - it.drawHeight if (it.alpha > 0f && velocityX == 0f) { it.alpha -= deltaTimeSec * 0.5f @@ -258,17 +258,17 @@ open class ScrollableContainer : Container() { super.onMeasureContentSize() indicatorY?.let { - it.height = height * (height / scrollableContentHeight) + it.height = drawHeight * (drawHeight / scrollableContentHeight) it.x = contentWidth + 5f - contentWidth += it.width + 5f + contentWidth += it.drawWidth + 5f } indicatorX?.let { - it.width = width * (width / scrollableContentWidth) + it.width = drawWidth * (drawWidth / scrollableContentWidth) it.y = contentHeight + 5f - contentHeight += it.height + 5f + contentHeight += it.drawHeight + 5f } if (indicatorX != null || indicatorY != null) { @@ -308,8 +308,8 @@ open class ScrollableContainer : Container() { isDragging = true // Coerce the delta values to the width and height of the container because the user can't scroll more than that. - var deltaX = (event.x - initialX).coerceAtMost(width) - var deltaY = (event.y - initialY).coerceAtMost(height) + var deltaX = (event.x - initialX).coerceAtMost(drawWidth) + var deltaY = (event.y - initialY).coerceAtMost(drawHeight) val length = hypot(deltaX, deltaY) diff --git a/src/com/reco1l/andengine/shape/Box.kt b/src/com/reco1l/andengine/shape/Box.kt index 39443c396..0450337fe 100644 --- a/src/com/reco1l/andengine/shape/Box.kt +++ b/src/com/reco1l/andengine/shape/Box.kt @@ -26,7 +26,7 @@ open class Box : ExtendedEntity(vertexBuffer = BoxVertexBuffer()) { override fun onUpdateVertexBuffer() { - (vertexBuffer as BoxVertexBuffer).update(width, height) + (vertexBuffer as BoxVertexBuffer).update(drawWidth, drawHeight) } override fun drawVertices(gl: GL10, camera: Camera) { @@ -103,7 +103,7 @@ open class RoundedBox(segmentsPerArc: Int = 10) : ExtendedEntity(RoundedBoxVerte override fun onUpdateVertexBuffer() { - val cornerRadius = cornerRadius.coerceIn(0f, min(width, height) / 2f) + val cornerRadius = cornerRadius.coerceIn(0f, min(drawWidth, drawHeight) / 2f) if (shouldRebuildVertexBuffer) { shouldRebuildVertexBuffer = false @@ -114,7 +114,7 @@ open class RoundedBox(segmentsPerArc: Int = 10) : ExtendedEntity(RoundedBoxVerte setVertexBuffer(RoundedBoxVertexBuffer(segmentsPerArc)) } - (vertexBuffer as RoundedBoxVertexBuffer).update(width, height, cornerRadius) + (vertexBuffer as RoundedBoxVertexBuffer).update(drawWidth, drawHeight, cornerRadius) } override fun drawVertices(pGL: GL10, pCamera: Camera) { diff --git a/src/com/reco1l/andengine/shape/Circle.kt b/src/com/reco1l/andengine/shape/Circle.kt index 51ec4ba1d..8aefb2ca1 100644 --- a/src/com/reco1l/andengine/shape/Circle.kt +++ b/src/com/reco1l/andengine/shape/Circle.kt @@ -85,12 +85,12 @@ class Circle : ExtendedEntity() { if (shouldRebuildVertexBuffer) { shouldRebuildVertexBuffer = false - val segments = approximateSegments(width, height) + val segments = approximateSegments(drawWidth, drawHeight) setVertexBuffer(CircleVertexBuffer(segments)) } - (vertexBuffer as CircleVertexBuffer).update(width, height, startAngle, endAngle) + (vertexBuffer as CircleVertexBuffer).update(drawWidth, drawHeight, startAngle, endAngle) } override fun drawVertices(pGL: GL10, pCamera: Camera) { diff --git a/src/com/reco1l/osu/playfield/Counters.kt b/src/com/reco1l/osu/playfield/Counters.kt index 25bee82d8..3d9e15cde 100644 --- a/src/com/reco1l/osu/playfield/Counters.kt +++ b/src/com/reco1l/osu/playfield/Counters.kt @@ -82,9 +82,9 @@ class ComboCounter : Container() { // In stable, the bigger pop out scales a bit to the left it.translationX = -3f - it.translationY = -(FONT_HEIGHT_RATIO * it.height + VERTICAL_OFFSET) + it.translationY = -(FONT_HEIGHT_RATIO * it.drawHeight + VERTICAL_OFFSET) - it.y = -(1 - FONT_HEIGHT_RATIO) * it.height + VERTICAL_OFFSET + it.y = -(1 - FONT_HEIGHT_RATIO) * it.drawHeight + VERTICAL_OFFSET it.spacing = -OsuSkin.get().comboOverlap attachChild(it) @@ -97,9 +97,9 @@ class ComboCounter : Container() { it.setAnchor(Anchor.BottomLeft) it.setOrigin(Anchor.BottomLeft) - it.translationY = -(FONT_HEIGHT_RATIO * it.height + VERTICAL_OFFSET) + it.translationY = -(FONT_HEIGHT_RATIO * it.drawHeight + VERTICAL_OFFSET) - it.y = -(1 - FONT_HEIGHT_RATIO) * it.height + VERTICAL_OFFSET + it.y = -(1 - FONT_HEIGHT_RATIO) * it.drawHeight + VERTICAL_OFFSET it.spacing = -OsuSkin.get().comboOverlap attachChild(it, 0) diff --git a/src/com/reco1l/osu/playfield/GameplayHUD.kt b/src/com/reco1l/osu/playfield/GameplayHUD.kt index 0d63e04c5..886729d2c 100644 --- a/src/com/reco1l/osu/playfield/GameplayHUD.kt +++ b/src/com/reco1l/osu/playfield/GameplayHUD.kt @@ -74,7 +74,7 @@ class GameplayHUD(private val stat: StatisticV2, private val game: GameScene, pr scoreCounter!!.setScore(stat.totalScoreWithMultiplier) accuracyCounter!!.setAccuracy(stat.accuracy) - accuracyCounter.y = 9f + scoreCounter.y + scoreCounter.height + accuracyCounter.y = 9f + scoreCounter.y + scoreCounter.drawHeight if (Config.getProgressIndicatorType() == PIE) { pieSongProgress!!.x = accuracyCounter.x - accuracyCounter.widthScaled - 18f diff --git a/src/com/reco1l/osu/playfield/HealthBar.kt b/src/com/reco1l/osu/playfield/HealthBar.kt index 6e910c33e..5bc8cee63 100644 --- a/src/com/reco1l/osu/playfield/HealthBar.kt +++ b/src/com/reco1l/osu/playfield/HealthBar.kt @@ -91,17 +91,17 @@ class HealthBar(private val statistics: StatisticV2) : Container() { } fillClear.width = 0f - fillClear.height = fill.height - fillClear.setPosition(fill.x + fill.width, fill.y) + fillClear.height = fill.drawHeight + fillClear.setPosition(fill.x + fill.drawWidth, fill.y) } override fun onManagedUpdate(pSecondsElapsed: Float) { - fillClear.width = Interpolation.floatAt(pSecondsElapsed.coerceIn(0f, 0.2f), fillClear.width, (1f - statistics.hp) * fill.width, 0f, 0.2f, Easing.OutQuint) + fillClear.width = Interpolation.floatAt(pSecondsElapsed.coerceIn(0f, 0.2f), fillClear.drawWidth, (1f - statistics.hp) * fill.drawWidth, 0f, 0.2f, Easing.OutQuint) - marker.x = fill.x + fill.width - fillClear.width - marker.y = fill.y + (if (isNewStyle) fill.height / 2 else 0f) + marker.x = fill.x + fill.drawWidth - fillClear.drawWidth + marker.y = fill.y + (if (isNewStyle) fill.drawHeight / 2 else 0f) explode.setPosition(marker) diff --git a/src/ru/nsu/ccfit/zuev/osu/game/GameplaySpinner.java b/src/ru/nsu/ccfit/zuev/osu/game/GameplaySpinner.java index 0bf48c3ee..6ad1fd6b1 100644 --- a/src/ru/nsu/ccfit/zuev/osu/game/GameplaySpinner.java +++ b/src/ru/nsu/ccfit/zuev/osu/game/GameplaySpinner.java @@ -64,7 +64,7 @@ public GameplaySpinner() { background.setOrigin(Anchor.Center); background.setPosition(center.x, center.y); background.setTextureRegion(ResourceManager.getInstance().getTexture("spinner-background")); - background.setScale(Config.getRES_WIDTH() / background.getWidth()); + background.setScale(Config.getRES_WIDTH() / background.getDrawWidth()); circle = new ExtendedSprite(); circle.setOrigin(Anchor.Center); From e001f6e7f2cbd06e8e87e9648a08c268af2b6a95 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Wed, 18 Dec 2024 12:09:51 -0300 Subject: [PATCH 02/73] Fix ExtendedEntity collision checks --- .../org/anddev/andengine/entity/Entity.java | 15 ++-- src/com/reco1l/andengine/EntityCollision.kt | 37 +++++++++ src/com/reco1l/andengine/ExtendedEntity.kt | 79 ++++++++++++++++--- 3 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 src/com/reco1l/andengine/EntityCollision.kt diff --git a/AndEngine/src/org/anddev/andengine/entity/Entity.java b/AndEngine/src/org/anddev/andengine/entity/Entity.java index 6b7eb87d3..95bb17828 100644 --- a/AndEngine/src/org/anddev/andengine/entity/Entity.java +++ b/AndEngine/src/org/anddev/andengine/entity/Entity.java @@ -88,14 +88,17 @@ public void call(final IEntity pEntity) { protected float mScaleCenterX = 0; protected float mScaleCenterY = 0; - private boolean mLocalToParentTransformationDirty = true; - private boolean mParentToLocalTransformationDirty = true; + // BEGIN osu!droid modified: Make these fields protected + /*private*/ protected boolean mLocalToParentTransformationDirty = true; + /*private*/ protected boolean mParentToLocalTransformationDirty = true; - private Transformation mLocalToParentTransformation; - private Transformation mParentToLocalTransformation; + /*private*/ protected Transformation mLocalToParentTransformation; + /*private*/ protected Transformation mParentToLocalTransformation; + + /*private*/ protected Transformation mLocalToSceneTransformation; + /*private*/ protected Transformation mSceneToLocalTransformation; + // END osu!droid modified - private Transformation mLocalToSceneTransformation; - private Transformation mSceneToLocalTransformation; private Object mUserData; diff --git a/src/com/reco1l/andengine/EntityCollision.kt b/src/com/reco1l/andengine/EntityCollision.kt new file mode 100644 index 000000000..a6432d368 --- /dev/null +++ b/src/com/reco1l/andengine/EntityCollision.kt @@ -0,0 +1,37 @@ +package com.reco1l.andengine + +import org.anddev.andengine.collision.ShapeCollisionChecker +import org.anddev.andengine.util.constants.Constants.VERTEX_INDEX_X +import org.anddev.andengine.util.constants.Constants.VERTEX_INDEX_Y + +object EntityCollision { + + + private val vertices = FloatArray(8) + + + fun contains(entity: ExtendedEntity, x: Float, y: Float): Boolean { + + val left = 0f + val top = 0f + val right = entity.drawWidth + val bottom = entity.drawHeight + + vertices[0 + VERTEX_INDEX_X] = left + vertices[0 + VERTEX_INDEX_Y] = top + + vertices[2 + VERTEX_INDEX_X] = right + vertices[2 + VERTEX_INDEX_Y] = top + + vertices[4 + VERTEX_INDEX_X] = right + vertices[4 + VERTEX_INDEX_Y] = bottom + + vertices[6 + VERTEX_INDEX_X] = left + vertices[6 + VERTEX_INDEX_Y] = bottom + + entity.getLocalToSceneTransformation().transform(vertices) + + return ShapeCollisionChecker.checkContains(vertices, vertices.size, x, y) + } + +} \ No newline at end of file diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 2d08ffc27..41b4f3e2f 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -5,15 +5,14 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* -import org.anddev.andengine.collision.* import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* -import org.anddev.andengine.entity.primitive.* import org.anddev.andengine.entity.scene.CameraScene import org.anddev.andengine.entity.scene.Scene import org.anddev.andengine.entity.shape.* import org.anddev.andengine.opengl.util.* import org.anddev.andengine.opengl.vertex.* +import org.anddev.andengine.util.Transformation import javax.microedition.khronos.opengles.* import javax.microedition.khronos.opengles.GL10.* @@ -615,29 +614,83 @@ abstract class ExtendedEntity( // Collision - override fun collidesWith(shape: IShape): Boolean = when (shape) { - - is RectangularShape -> RectangularShapeCollisionChecker.checkCollision(this, shape) - is Line -> RectangularShapeCollisionChecker.checkCollision(this, shape) - - else -> false + override fun collidesWith(shape: IShape): Boolean { + Log.w("ExtendedEntity", "Collision detection is not supported in ExtendedEntity.") + return false } override fun contains(x: Float, y: Float): Boolean { + if (width == 0f || height == 0f) { return false } - return RectangularShapeCollisionChecker.checkContains(this, x - totalOffsetX, y - totalOffsetY) + return EntityCollision.contains(this, x, y) } override fun isCulled(pCamera: Camera): Boolean { - return drawX > pCamera.maxX || drawX + width < pCamera.minX - || drawY > pCamera.maxY || drawY + height < pCamera.minY + return drawX > pCamera.maxX || drawX + drawWidth < pCamera.minX + || drawY > pCamera.maxY || drawY + drawHeight < pCamera.minY + } + + override fun getLocalToParentTransformation(): Transformation { + + if (mLocalToParentTransformation == null) { + mLocalToParentTransformation = Transformation() + } + + if (mLocalToParentTransformationDirty) { + mLocalToParentTransformation.setToIdentity() + + if (scaleX != 1f || scaleY != 1f || rotation != 0f) { + mLocalToParentTransformation.postTranslate(originOffsetX, originOffsetY) + + if (scaleX != 1f || scaleY != 1f) { + mLocalToParentTransformation.postScale(scaleX, scaleY) + } + + if (rotation != 0f) { + mLocalToParentTransformation.postRotate(rotation) + } + + mLocalToParentTransformation.postTranslate(-originOffsetX, -originOffsetY) + } + + mLocalToParentTransformation.postTranslate(drawX, drawY) + mLocalToParentTransformationDirty = false + } + + return mLocalToParentTransformation } - override fun getSceneCenterCoordinates(): FloatArray { - return this.convertLocalToSceneCoordinates(width * 0.5f, height * 0.5f) + override fun getParentToLocalTransformation(): Transformation { + + if (mParentToLocalTransformation == null) { + mParentToLocalTransformation = Transformation() + } + + if (mParentToLocalTransformationDirty) { + mParentToLocalTransformation.setToIdentity() + mParentToLocalTransformation.postTranslate(-drawX, -drawY) + + if (scaleX != 1f || scaleY != 1f || rotation != 0f) { + mParentToLocalTransformation.postTranslate(originOffsetX, originOffsetY) + + if (rotation != 0f) { + mParentToLocalTransformation.postRotate(-rotation) + } + + if (scaleX != 1f || scaleY != 1f) { + mParentToLocalTransformation.postScale(1 / scaleX, 1 / scaleY) + } + + mParentToLocalTransformation.postTranslate(-originOffsetX, -originOffsetY) + } + + mParentToLocalTransformationDirty = false + } + + return mParentToLocalTransformation } From f9579f4ec7f75411ac29b12d8aa36842b5b972c3 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Wed, 18 Dec 2024 12:54:55 -0300 Subject: [PATCH 03/73] Invalidate transformations properly --- src/com/reco1l/andengine/ExtendedEntity.kt | 71 +++++++++++++++++----- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 41b4f3e2f..61682d241 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -1,6 +1,5 @@ package com.reco1l.andengine -import android.graphics.PointF import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* @@ -54,11 +53,23 @@ abstract class ExtendedEntity( * The origin factor of the entity in the X axis. */ open var originX = 0f + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } /** * The origin factor of the entity in the Y axis. */ open var originY = 0f + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } /** * The anchor factor of the entity in the X axis. @@ -67,6 +78,12 @@ abstract class ExtendedEntity( * Note: This will not take effect if the entity is not a child of a [Container]. */ open var anchorX = 0f + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } /** * The anchor factor of the entity in the Y axis. @@ -75,16 +92,34 @@ abstract class ExtendedEntity( * Note: This will not take effect if the entity is not a child of a [Container]. */ open var anchorY = 0f + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } /** * The translation in the X axis. */ open var translationX = 0f + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } /** * The translation in the Y axis. */ open var translationY = 0f + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } /** * Whether the color should be inherited from all the parents in the hierarchy. @@ -282,32 +317,42 @@ abstract class ExtendedEntity( originY = origin.factorY } - fun setPosition(position: PointF) { - setPosition(position.x, position.y) - } - - override fun setPosition(pX: Float, pY: Float) { - if (mX != pX || mY != pY) { - super.setPosition(pX, pY) + override fun setPosition(x: Float, y: Float) { + if (mX != x || mY != y) { + mX = x + mY = y + invalidateTransformations() (parent as? Container)?.onChildPositionChanged(this) } } open fun setX(value: Float) { if (mX != value) { - setPosition(value, mY) + mX = value + invalidateTransformations() + (parent as? Container)?.onChildPositionChanged(this) } } open fun setY(value: Float) { if (mY != value) { - setPosition(mX, value) + mY = value + invalidateTransformations() + (parent as? Container)?.onChildPositionChanged(this) } } open fun setTranslation(x: Float, y: Float) { - translationX = x - translationY = y + if (translationX != x || translationY != y) { + translationX = x + translationY = y + invalidateTransformations() + } + } + + open fun invalidateTransformations() { + mLocalToParentTransformationDirty = true + mParentToLocalTransformationDirty = true } @@ -434,11 +479,9 @@ abstract class ExtendedEntity( } override fun onApplyVertices(pGL: GL10) { - if (vertexBuffer != null) { super.onApplyVertices(pGL) } - } From 33ab259072cdfe24ca0e836e9e575ccec2bf6cbd Mon Sep 17 00:00:00 2001 From: Reco1l Date: Wed, 18 Dec 2024 21:53:25 -0300 Subject: [PATCH 04/73] Introduce relativePositionAxes feature and add helper functions to get dimensions --- src/com/reco1l/andengine/ExtendedEntity.kt | 147 +++++++++++++++------ 1 file changed, 103 insertions(+), 44 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 61682d241..1bdded248 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -49,6 +49,17 @@ abstract class ExtendedEntity( } } + /** + * Determines which axes the entity should adjust its position relative to its parent. + */ + open var relativePositionAxes = Axes.None + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } + /** * The origin factor of the entity in the X axis. */ @@ -198,9 +209,8 @@ abstract class ExtendedEntity( */ open val drawWidth: Float get() { - val parent = parent - if (relativeSizeAxes.isHorizontal && parent is IShape) { - return parent.width * width + if (relativeSizeAxes.isHorizontal) { + return getParentWidth() * width } return width } @@ -213,9 +223,8 @@ abstract class ExtendedEntity( */ open val drawHeight: Float get() { - val parent = parent - if (relativeSizeAxes.isVertical && parent is IShape) { - return parent.height * height + if (relativeSizeAxes.isVertical) { + return getParentHeight() * height } return height } @@ -226,21 +235,34 @@ abstract class ExtendedEntity( */ open val drawX: Float get() { + val parent = parent if (parent is Container) { - return (parent as Container).getChildDrawX(this) + return parent.getChildDrawX(this) } + + if (relativePositionAxes.isHorizontal) { + return getParentWidth() * x + totalOffsetX + } + return x + totalOffsetX } + /** * The raw Y position of the entity. * This is the position without taking into account the origin, anchor, or translation. */ open val drawY: Float get() { + val parent = parent if (parent is Container) { - return (parent as Container).getChildDrawY(this) + return parent.getChildDrawY(this) + } + + if (relativePositionAxes.isVertical) { + return getParentHeight() * y + totalOffsetY } + return y + totalOffsetY } @@ -248,33 +270,25 @@ abstract class ExtendedEntity( * The offset applied to the X axis according to the origin factor. */ open val originOffsetX: Float - get() = -(width * originX) + get() = -(drawWidth * originX) /** * The offset applied to the Y axis according to the origin factor. */ open val originOffsetY: Float - get() = -(height * originY) + get() = -(drawWidth * originY) /** * The offset applied to the X axis according to the anchor factor. */ open val anchorOffsetX: Float - get() = when (parent) { - is IShape -> (parent as IShape).width * anchorX - is CameraScene -> ((parent as CameraScene).camera?.widthRaw ?: 0f) * anchorX - else -> 0f - } + get() = getParentWidth() * anchorX /** * The offset applied to the Y axis according to the anchor factor. */ open val anchorOffsetY: Float - get() = when (parent) { - is IShape -> (parent as IShape).height * anchorY - is CameraScene -> ((parent as CameraScene).camera?.heightRaw ?: 0f) * anchorY - else -> 0f - } + get() = getParentHeight() * anchorY /** * The total offset applied to the X axis. @@ -371,8 +385,8 @@ abstract class ExtendedEntity( override fun applyRotation(pGL: GL10) { // This will ensure getSceneCenterCoordinates() applies the correct transformation. - mRotationCenterX = width * originX - mRotationCenterY = height * originY + mRotationCenterX = drawWidth * originX + mRotationCenterY = drawHeight * originY if (rotation != 0f) { pGL.glRotatef(rotation, 0f, 0f, 1f) @@ -382,8 +396,8 @@ abstract class ExtendedEntity( override fun applyScale(pGL: GL10) { // This will ensure getSceneCenterCoordinates() applies the correct transformation. - mScaleCenterX = width * originX - mScaleCenterY = height * originY + mScaleCenterX = drawWidth * originX + mScaleCenterY = drawHeight * originY if (scaleX != 1f || scaleY != 1f) { pGL.glScalef(scaleX, scaleY, 1f) @@ -528,22 +542,12 @@ abstract class ExtendedEntity( if (contentWidth != width || contentHeight != height) { - val parent = parent - if (autoSizeAxes.isHorizontal) { - width = if (relativeSizeAxes.isHorizontal && parent is IShape) { - contentWidth / parent.width - } else { - contentWidth - } + width = if (relativeSizeAxes.isHorizontal) contentWidth / getParentWidth() else contentWidth } if (autoSizeAxes.isVertical) { - height = if (relativeSizeAxes.isVertical && parent is IShape) { - contentHeight / parent.height - } else { - contentHeight - } + height = if (relativeSizeAxes.isVertical) contentHeight / getParentHeight() else contentHeight } updateVertexBuffer() @@ -562,8 +566,7 @@ abstract class ExtendedEntity( open fun setSize(newWidth: Float, newHeight: Float): Boolean { if (autoSizeAxes == Axes.Both) { - Log.w("ExtendedEntity", "Cannot set size when autoSizeAxes is set to Both.") - return false + throw IllegalArgumentException("Cannot set size when autoSizeAxes is set to Both.") } if (width != newWidth || height != newHeight) { @@ -584,9 +587,9 @@ abstract class ExtendedEntity( } open fun setWidth(value: Float) { - if (autoSizeAxes.isVertical) { - Log.w("ExtendedEntity", "Cannot set width when autoSizeAxes is set to Both or X.") - return + + if (autoSizeAxes.isHorizontal) { + throw IllegalArgumentException("Cannot set width when autoSizeAxes is set to Both or X.") } if (width != value) { @@ -598,9 +601,9 @@ abstract class ExtendedEntity( } open fun setHeight(value: Float) { - if (autoSizeAxes.isHorizontal) { - Log.w("ExtendedEntity", "Cannot set height when autoSizeAxes is set to Both or Y.") - return + + if (autoSizeAxes.isVertical) { + throw IllegalArgumentException("Cannot set height when autoSizeAxes is set to Both or Y.") } if (height != value) { @@ -757,3 +760,59 @@ abstract class ExtendedEntity( } +/** + * Returns the width of the parent entity. + */ +fun ExtendedEntity.getParentWidth() = when (val parent = parent) { + is ExtendedEntity -> parent.drawWidth + is CameraScene -> parent.camera.widthRaw + is IShape -> parent.width + else -> 0f +} + +/** + * Returns the height of the parent entity. + */ +fun ExtendedEntity.getParentHeight() = when (val parent = parent) { + is ExtendedEntity -> parent.drawHeight + is CameraScene -> parent.camera.heightRaw + is IShape -> parent.height + else -> 0f +} + +/** + * Returns the draw width of the entity. + */ +fun IEntity.getDrawWidth(): Float = when (this) { + is ExtendedEntity -> drawWidth + is IShape -> width + else -> 0f +} + +/** + * Returns the draw height of the entity. + */ +fun IEntity.getDrawHeight(): Float = when (this) { + is ExtendedEntity -> drawHeight + is IShape -> height + else -> 0f +} + +/** + * Returns the draw X position of the entity. + */ +fun IEntity.getDrawX(): Float = when (this) { + is ExtendedEntity -> drawX + is IShape -> x + else -> 0f +} + +/** + * Returns the draw Y position of the entity. + */ +fun IEntity.getDrawY(): Float = when (this) { + is ExtendedEntity -> drawY + is IShape -> y + else -> 0f +} + From 6e366e6641429b6fc4e1183f85f87e0c5591c9e7 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Wed, 18 Dec 2024 21:54:07 -0300 Subject: [PATCH 05/73] Use drawWidth and drawHeight dimensions to compute container measurements --- .../container/ConstraintContainer.kt | 18 ++++++-- .../reco1l/andengine/container/Container.kt | 45 +++++++++++++------ .../andengine/container/LinearContainer.kt | 8 ++-- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index 70d08da6c..ff0084634 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -18,17 +18,27 @@ class ConstraintContainer : Container() { override fun getChildDrawX(child: ExtendedEntity): Float { val constraint = constraints[child] ?: this - val anchorOffsetX = constraint.width * child.anchorX + val anchorOffsetX = constraint.getDrawWidth() * child.anchorX - return child.x + child.originOffsetX + anchorOffsetX + child.translationX + val x = if (child.relativePositionAxes.isHorizontal) + child.x * drawWidth + else + child.x + + return x + child.originOffsetX + anchorOffsetX + child.translationX } override fun getChildDrawY(child: ExtendedEntity): Float { val constraint = constraints[child] ?: this - val anchorOffsetY = constraint.height * child.anchorY + val anchorOffsetY = constraint.getDrawHeight() * child.anchorY + + val y = if (child.relativePositionAxes.isVertical) + child.y * drawHeight + else + child.y - return child.y + child.originOffsetY + anchorOffsetY + child.translationY + return y + child.originOffsetY + anchorOffsetY + child.translationY } diff --git a/src/com/reco1l/andengine/container/Container.kt b/src/com/reco1l/andengine/container/Container.kt index 611f1554b..b320fe566 100644 --- a/src/com/reco1l/andengine/container/Container.kt +++ b/src/com/reco1l/andengine/container/Container.kt @@ -62,10 +62,20 @@ open class Container : ExtendedEntity() { open fun getChildDrawX(child: ExtendedEntity): Float { + + if (child.relativePositionAxes.isHorizontal) { + return child.x * drawWidth + child.totalOffsetX + } + return child.x + child.totalOffsetX } open fun getChildDrawY(child: ExtendedEntity): Float { + + if (child.relativePositionAxes.isVertical) { + return child.y * drawHeight + child.totalOffsetY + } + return child.y + child.totalOffsetY } @@ -86,21 +96,11 @@ open class Container : ExtendedEntity() { val child = mChildren.getOrNull(i) ?: continue - var offsetX = child.x - var offsetY = child.y - - if (child is ExtendedEntity) { - offsetX += child.originOffsetX - offsetY += child.originOffsetY - } - - offsetX = max(0f, offsetX) - offsetY = max(0f, offsetY) + val x = max(0f, child.getDrawX()) + val y = max(0f, child.getDrawY()) - if (child is IShape) { - contentWidth = max(contentWidth, offsetX + child.width) - contentHeight = max(contentHeight, offsetY + child.height) - } + contentWidth = max(contentWidth, x + child.getDrawWidth()) + contentHeight = max(contentHeight, y + child.getDrawHeight()) } } @@ -187,3 +187,20 @@ open class Container : ExtendedEntity() { } } + +operator fun Container.get(index: Int): T { + @Suppress("UNCHECKED_CAST") + return getChild(index) as T +} + +operator fun Container.set(index: Int, entity: IEntity) { + attachChild(entity, index) +} + +operator fun Container.plusAssign(entity: IEntity) { + attachChild(entity) +} + +operator fun Container.minusAssign(entity: IEntity) { + detachChild(entity) +} \ No newline at end of file diff --git a/src/com/reco1l/andengine/container/LinearContainer.kt b/src/com/reco1l/andengine/container/LinearContainer.kt index 27b90f451..f09a24afb 100644 --- a/src/com/reco1l/andengine/container/LinearContainer.kt +++ b/src/com/reco1l/andengine/container/LinearContainer.kt @@ -55,13 +55,13 @@ open class LinearContainer : Container() { when (orientation) { Horizontal -> { - contentWidth += child.width + spacing - contentHeight = max(contentHeight, child.height) + contentWidth += child.getDrawWidth() + spacing + contentHeight = max(contentHeight, child.getDrawHeight()) } Vertical -> { - contentWidth = max(contentWidth, child.width) - contentHeight += child.height + spacing + contentWidth = max(contentWidth, child.getDrawWidth()) + contentHeight += child.getDrawHeight() + spacing } } } From 90234ce9b3c7bc2e280e6ffbd4251ace8e2bfcea Mon Sep 17 00:00:00 2001 From: Reco1l Date: Wed, 18 Dec 2024 21:56:13 -0300 Subject: [PATCH 06/73] Improve ScrollableContainer --- .../container/ScrollableContainer.kt | 186 ++++++++---------- 1 file changed, 86 insertions(+), 100 deletions(-) diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index 57bea7a76..00573fb6f 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -3,6 +3,7 @@ package com.reco1l.andengine.container import com.reco1l.andengine.* import com.reco1l.andengine.shape.* import com.reco1l.framework.* +import com.rian.osu.math.Precision import org.anddev.andengine.engine.camera.* import org.anddev.andengine.input.touch.* import org.anddev.andengine.input.touch.TouchEvent.* @@ -21,9 +22,18 @@ open class ScrollableContainer : Container() { */ var scrollX = 0f set(value) { - if (scrollAxes == Axes.Both || scrollAxes == Axes.X) { - field = value + if (Precision.almostEquals(value, 0f) || !scrollAxes.isHorizontal) { + field = 0f + return } + + if (Precision.almostEquals(value, maxScrollX)) { + field = maxScrollX + return + } + + indicatorX?.alpha = 0.5f + field = value } /** @@ -31,9 +41,18 @@ open class ScrollableContainer : Container() { */ var scrollY = 0f set(value) { - if (scrollAxes == Axes.Both || scrollAxes == Axes.Y) { - field = value + if (Precision.almostEquals(value, 0f) || !scrollAxes.isVertical) { + field = 0f + return } + + if (Precision.almostEquals(value, maxScrollY)) { + field = maxScrollY + return + } + + indicatorY?.alpha = 0.5f + field = value } /** @@ -50,21 +69,25 @@ open class ScrollableContainer : Container() { /** * The maximum velocity in px/s on the x-axis. */ - var maxVelocityX = 10000f + var maxVelocityX = 5000f /** * The maximum velocity in px/s on the y-axis. */ - var maxVelocityY = 10000f + var maxVelocityY = 5000f /** * The velocity in px/s on the x-axis. */ var velocityX = 0f private set(value) { - if (scrollAxes == Axes.Both || scrollAxes == Axes.X) { - field = value.coerceIn(-maxVelocityX, maxVelocityX) + + if (Precision.almostEquals(value, 0f) || !scrollAxes.isHorizontal) { + field = 0f + return } + + field = value.coerceIn(-maxVelocityX, maxVelocityX) } /** @@ -72,9 +95,13 @@ open class ScrollableContainer : Container() { */ var velocityY = 0f private set(value) { - if (scrollAxes == Axes.Both || scrollAxes == Axes.Y) { - field = value.coerceIn(-maxVelocityY, maxVelocityY) + + if (Precision.almostEquals(value, 0f) || !scrollAxes.isVertical) { + field = 0f + return } + + field = value.coerceIn(-maxVelocityY, maxVelocityY) } /** @@ -143,10 +170,8 @@ open class ScrollableContainer : Container() { super.onManagedUpdate(deltaTimeSec) // Seems like AndEngine doesn't handle ACTION_OUTSIDE events properly so we have to set a dragging timeout. - if (isDragging && elapsedTimeSec - lastDragTimeSec > 1f) { + if (isDragging && elapsedTimeSec - lastDragTimeSec > 0.1f) { isDragging = false - velocityX = 0f - velocityY = 0f } if (!isDragging && (velocityX != 0f || velocityY != 0f)) { @@ -156,14 +181,6 @@ open class ScrollableContainer : Container() { velocityX *= deceleration velocityY *= deceleration - - if (abs(velocityX) < INSIGNIFICANT_DISTANCE) { - velocityX = 0f - } - - if (abs(velocityY) < INSIGNIFICANT_DISTANCE) { - velocityY = 0f - } } // Back smoothly to the max scroll position if the scroll position is out of bounds. @@ -171,82 +188,56 @@ open class ScrollableContainer : Container() { if (scrollX > maxScrollX) { velocityX = 0f - - val deltaX = scrollX - maxScrollX - scrollX -= deltaX * 0.1f - - if (abs(deltaX) < INSIGNIFICANT_DISTANCE) { - scrollX = maxScrollX - } + scrollX -= (scrollX - maxScrollX) * 0.1f } if (scrollY > maxScrollY) { velocityY = 0f - - val deltaY = scrollY - maxScrollY - scrollY -= deltaY * 0.1f - - if (abs(deltaY) < INSIGNIFICANT_DISTANCE) { - scrollY = maxScrollY - } + scrollY -= (scrollY - maxScrollY) * 0.1f } if (scrollY < 0) { velocityY = 0f scrollY += -scrollY * 0.1f - - if (abs(scrollY) < INSIGNIFICANT_DISTANCE) { - scrollY = 0f - } } if (scrollX < 0) { velocityX = 0f scrollX += -scrollX * 0.1f - - if (abs(scrollX) < INSIGNIFICANT_DISTANCE) { - scrollX = 0f - } } } // Updating progress indicators - indicatorY?.let { + indicatorY?.let { indicator -> - it.isVisible = scrollAxes == Axes.Both || scrollAxes == Axes.Y - it.y = scrollY * (drawHeight / scrollableContentHeight) + indicator.isVisible = scrollAxes == Axes.Both || scrollAxes == Axes.Y - if (it.alpha > 0f && velocityY == 0f) { - it.alpha -= deltaTimeSec * 0.5f + indicator.x = drawWidth - indicator.drawWidth + indicator.y = scrollY * (drawHeight / scrollableContentHeight) - if (it.alpha < 0f) { - it.alpha = 0f - } + if (indicator.alpha > 0f && velocityY == 0f) { + indicator.alpha = (indicator.alpha - deltaTimeSec * 0.5f).coerceAtLeast(0f) } - if (it.isVisible) { - it.onUpdate(deltaTimeSec) + if (indicator.isVisible) { + indicator.onUpdate(deltaTimeSec) } } - indicatorX?.let { - - it.isVisible = scrollAxes == Axes.Both || scrollAxes == Axes.X + indicatorX?.let { indicator -> - it.x = scrollX * (drawWidth / scrollableContentWidth) - it.y = drawHeight - it.drawHeight + indicator.isVisible = scrollAxes == Axes.Both || scrollAxes == Axes.X - if (it.alpha > 0f && velocityX == 0f) { - it.alpha -= deltaTimeSec * 0.5f + indicator.x = scrollX * (drawWidth / scrollableContentWidth) + indicator.y = drawHeight - indicator.drawHeight - if (it.alpha < 0f) { - it.alpha = 0f - } + if (indicator.alpha > 0f && velocityX == 0f) { + indicator.alpha = (indicator.alpha - deltaTimeSec * 0.5f).coerceAtLeast(0f) } - if (it.isVisible) { - it.onUpdate(deltaTimeSec) + if (indicator.isVisible) { + indicator.onUpdate(deltaTimeSec) } } @@ -257,18 +248,20 @@ open class ScrollableContainer : Container() { override fun onMeasureContentSize() { super.onMeasureContentSize() - indicatorY?.let { - it.height = drawHeight * (drawHeight / scrollableContentHeight) - it.x = contentWidth + 5f + indicatorY?.let { indicator -> + + indicator.height = drawHeight * (drawHeight / scrollableContentHeight) + indicator.x = contentWidth + 5f - contentWidth += it.drawWidth + 5f + contentWidth += indicator.drawWidth + 5f } - indicatorX?.let { - it.width = drawWidth * (drawWidth / scrollableContentWidth) - it.y = contentHeight + 5f + indicatorX?.let { indicator -> + + indicator.width = drawWidth * (drawWidth / scrollableContentWidth) + indicator.y = contentHeight + 5f - contentHeight += it.drawHeight + 5f + contentHeight += indicator.drawHeight + 5f } if (indicatorX != null || indicatorY != null) { @@ -291,8 +284,8 @@ open class ScrollableContainer : Container() { ACTION_DOWN -> { isDragging = true - initialX = event.x - initialY = event.y + initialX = localX + initialY = localY velocityX = 0f velocityY = 0f @@ -300,16 +293,12 @@ open class ScrollableContainer : Container() { lastDragTimeSec = elapsedTimeSec } - ACTION_UP, ACTION_CANCEL, ACTION_OUTSIDE -> { - isDragging = false - } - - else -> { + ACTION_MOVE -> { isDragging = true // Coerce the delta values to the width and height of the container because the user can't scroll more than that. - var deltaX = (event.x - initialX).coerceAtMost(drawWidth) - var deltaY = (event.y - initialY).coerceAtMost(drawHeight) + var deltaX = localX - initialX + var deltaY = localY - initialY val length = hypot(deltaX, deltaY) @@ -322,30 +311,27 @@ open class ScrollableContainer : Container() { deltaY *= if (length <= 0) 0f else length.pow(0.7f) / length } - if (deltaX.isNaN() || abs(deltaX) < INSIGNIFICANT_DISTANCE) { - deltaX = 0f - } + val dragTimeSec = elapsedTimeSec - lastDragTimeSec - if (deltaY.isNaN() || abs(deltaY) < INSIGNIFICANT_DISTANCE) { - deltaY = 0f - } + if (abs(deltaX) > 0.1f) { + scrollX -= deltaX + velocityX = abs(deltaX / dragTimeSec) * sign(deltaX) - if (deltaX != 0f || deltaY != 0f) { - indicatorX?.alpha = 0.5f - indicatorY?.alpha = 0.5f + initialX = localX + lastDragTimeSec = elapsedTimeSec } - scrollX -= deltaX - scrollY -= deltaY - - val dragTime = elapsedTimeSec - lastDragTimeSec - velocityX = deltaX / dragTime - velocityY = deltaY / dragTime + if (abs(deltaY) > 0.1f) { + scrollY -= deltaY + velocityY = abs(deltaY / dragTimeSec) * sign(deltaY) - initialX = event.x - initialY = event.y + initialY = localY + lastDragTimeSec = elapsedTimeSec + } + } - lastDragTimeSec = elapsedTimeSec + else -> { + isDragging = false } } From 30ff3e8e5acbc313d061258c6b32691d3ad722cd Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 14:03:25 -0300 Subject: [PATCH 07/73] Improve documentation --- src/com/reco1l/andengine/ExtendedEntity.kt | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 1bdded248..4fb0de6f1 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,6 +4,8 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* +import com.reco1l.extendedEntityBoundsRectangle +import com.reco1l.showExtendedEntityBounds import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.scene.CameraScene @@ -29,6 +31,10 @@ abstract class ExtendedEntity( /** * Determines which axes the entity should automatically adjust its size to. + * + * In this case the size will equal to the content size of the entity. Some + * types of entities requieres the user to manually set the size, in those + * cases this property might be ignored. */ open var autoSizeAxes = Axes.None set(value) { @@ -40,17 +46,45 @@ abstract class ExtendedEntity( /** * Determines which axes the entity should adjust its size relative to its parent. + * + * Depending on the type, the entity's width and height will be taken as a multiplier + * for the parent's width and height in order to calculate the final size. + * + * Example: + * + * If relativeSizeAxes is set to [Axes.Both] and we set the size to 0.5, the entity's + * size will be half the size of the parent. + * + * Note: autoSizeAxes has priority over relativeSizeAxes. As for example if autoSizeAxes + * is set to [Axes.Both] and relativeSizeAxes is set to [Axes.Both], relativeSizeAxes + * will be ignored. */ open var relativeSizeAxes = Axes.None set(value) { if (field != value) { field = value + + if (value.isHorizontal && autoSizeAxes.isHorizontal || value.isVertical && autoSizeAxes.isVertical) { + Log.w( + "ExtendedEntity", "relativeSizeAxes.${relativeSizeAxes.name} is incompatible" + + " with autoSizeAxes.${autoSizeAxes.name} and it will be ignored." + ) + } + onContentSizeMeasured() } } /** * Determines which axes the entity should adjust its position relative to its parent. + * + * Depending on the type, the entity's position will be taken as a multiplier applied to + * the parent's width and height in order to calculate the final position. + * + * Example: + * + * If relativePositionAxes is set to [Axes.Both] and we set the position to 0.5 for both axes, + * the entity's position will be at the center of the parent. */ open var relativePositionAxes = Axes.None set(value) { From 811e2f2a5d0087209e55f8ffe4dd23846948ed00 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 14:03:49 -0300 Subject: [PATCH 08/73] Add whitespace --- src/com/reco1l/andengine/Axes.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/reco1l/andengine/Axes.kt b/src/com/reco1l/andengine/Axes.kt index 6e6f363c0..55f049a43 100644 --- a/src/com/reco1l/andengine/Axes.kt +++ b/src/com/reco1l/andengine/Axes.kt @@ -37,4 +37,6 @@ enum class Axes { */ val isHorizontal: Boolean get() = this == X || this == Both + + } \ No newline at end of file From 381d4a551f77287a2aa6540ccd3a1c9e26f2b32b Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 16:06:41 -0300 Subject: [PATCH 09/73] Fix critical bug --- src/com/reco1l/andengine/ExtendedEntity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 4fb0de6f1..db6358135 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -310,7 +310,7 @@ abstract class ExtendedEntity( * The offset applied to the Y axis according to the origin factor. */ open val originOffsetY: Float - get() = -(drawWidth * originY) + get() = -(drawHeight * originY) /** * The offset applied to the X axis according to the anchor factor. From 8541066dbaa7759e6775e57569edaff7c6333445 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 16:07:31 -0300 Subject: [PATCH 10/73] Set opposite when changing relativeSizeAxes and autoSizeAxes --- src/com/reco1l/andengine/ExtendedEntity.kt | 38 ++++++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index db6358135..f5e303f7d 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,8 +4,6 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* -import com.reco1l.extendedEntityBoundsRectangle -import com.reco1l.showExtendedEntityBounds import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.scene.CameraScene @@ -40,6 +38,23 @@ abstract class ExtendedEntity( set(value) { if (field != value) { field = value + + // Setting the opposite value for relativeSizeAxes to avoid conflicts. + if (relativeSizeAxes != Axes.None) { + + if (value == Axes.Both) { + relativeSizeAxes = Axes.None + } + + if (value == Axes.X && relativeSizeAxes == Axes.Y) { + relativeSizeAxes = Axes.Y + } + + if (value == Axes.Y && relativeSizeAxes == Axes.X) { + relativeSizeAxes = Axes.X + } + } + onContentSizeMeasured() } } @@ -64,11 +79,20 @@ abstract class ExtendedEntity( if (field != value) { field = value - if (value.isHorizontal && autoSizeAxes.isHorizontal || value.isVertical && autoSizeAxes.isVertical) { - Log.w( - "ExtendedEntity", "relativeSizeAxes.${relativeSizeAxes.name} is incompatible" + - " with autoSizeAxes.${autoSizeAxes.name} and it will be ignored." - ) + // Setting the opposite value for autoSizeAxes to avoid conflicts. + if (autoSizeAxes != Axes.None) { + + if (value == Axes.Both) { + autoSizeAxes = Axes.None + } + + if (value == Axes.X && autoSizeAxes == Axes.Y) { + autoSizeAxes = Axes.Y + } + + if (value == Axes.Y && autoSizeAxes == Axes.X) { + autoSizeAxes = Axes.X + } } onContentSizeMeasured() From 0d61dcdcb1a5aacaaeb8f3d602601493331460cc Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 16:08:45 -0300 Subject: [PATCH 11/73] Introduce `clipChildren` --- src/com/reco1l/andengine/Camera.kt | 31 +++++++++++++ src/com/reco1l/andengine/ExtendedEntity.kt | 45 ++++++++++++++++++- .../container/ScrollableContainer.kt | 6 +-- 3 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 src/com/reco1l/andengine/Camera.kt diff --git a/src/com/reco1l/andengine/Camera.kt b/src/com/reco1l/andengine/Camera.kt new file mode 100644 index 000000000..d43065c3d --- /dev/null +++ b/src/com/reco1l/andengine/Camera.kt @@ -0,0 +1,31 @@ +package com.reco1l.andengine + +import org.anddev.andengine.engine.camera.Camera +import org.anddev.andengine.util.MathUtils + + +fun Camera.getScreenSpaceCoordinates(coordinates: FloatArray): FloatArray { + + var (x, y) = coordinates + + val relativeX = (x - minX) / (maxX - minX) + val relativeY = 1f - (y - minY) / (maxY - minY) + + x = relativeX * surfaceWidth + y = relativeY * surfaceHeight + + if (rotation != 0f) { + + if (rotation == 180f) { + coordinates[0] = surfaceHeight - y + coordinates[1] = surfaceWidth - x + } else { + MathUtils.revertRotateAroundCenter(coordinates, -rotation, surfaceWidth.shr(1).toFloat(), surfaceHeight.shr(1).toFloat()) + } + } else { + coordinates[0] = x + coordinates[1] = y + } + + return coordinates +} diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index f5e303f7d..44d7ea536 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -191,9 +191,9 @@ abstract class ExtendedEntity( } /** - * Whether the color should be inherited from all the parents in the hierarchy. + * Whether the entity should clip its children. */ - open var inheritColor = true + open var clipChildren = false /** * Whether the depth buffer should be cleared before drawing the entity. @@ -222,6 +222,11 @@ abstract class ExtendedEntity( mAlpha = value.alpha } + /** + * Whether the color should be inherited from all the parents in the hierarchy. + */ + open var inheritColor = true + /** * The color blending function. */ @@ -526,6 +531,42 @@ abstract class ExtendedEntity( applyBlending(pGL) } + override fun onManagedDraw(gl: GL10, camera: Camera) { + + if (clipChildren) { + GLHelper.enableScissorTest(gl) + + var (bottomLeftX, bottomLeftY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(0f, 0f)) + var (topLeftX, topLeftY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(0f, drawHeight)) + var (topRightX, topRightY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(drawWidth, drawHeight)) + var (bottomRightX, bottomRightY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(drawWidth, 0f)) + + // Flip the Y axis to match the OpenGL coordinate system. + bottomLeftY = camera.surfaceHeight - bottomLeftY + topLeftY = camera.surfaceHeight - topLeftY + topRightY = camera.surfaceHeight - topRightY + bottomRightY = camera.surfaceHeight - bottomRightY + + val minClippingX = minOf(bottomLeftX, topLeftX, topRightX, bottomRightX) + val minClippingY = minOf(bottomLeftY, topLeftY, topRightY, bottomRightY) + + val maxClippingX = maxOf(bottomLeftX, topLeftX, topRightX, bottomRightX) + val maxClippingY = maxOf(bottomLeftY, topLeftY, topRightY, bottomRightY) + + gl.glScissor( + minClippingX.toInt(), + minClippingY.toInt(), + (maxClippingX - minClippingX).toInt(), + (maxClippingY - minClippingY).toInt() + ) + } + + super.onManagedDraw(gl, camera) + + if (clipChildren) { + GLHelper.disableScissorTest(gl) + } + } override fun onManagedUpdate(pSecondsElapsed: Float) { diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index 00573fb6f..2db646dbf 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -269,12 +269,10 @@ open class ScrollableContainer : Container() { } } - - override fun onDrawChildren(pGL: GL10, pCamera: Camera) { - super.onDrawChildren(pGL, pCamera) - + override fun onManagedDrawChildren(pGL: GL10, pCamera: Camera) { indicatorX?.onDraw(pGL, pCamera) indicatorY?.onDraw(pGL, pCamera) + super.onManagedDrawChildren(pGL, pCamera) } override fun onAreaTouched(event: TouchEvent, localX: Float, localY: Float): Boolean { From 3db74655a034a2067944fc755131ec79ddf35a55 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 16:54:34 -0300 Subject: [PATCH 12/73] Fix ConstraintContainer misplacement of constraints --- .../container/ConstraintContainer.kt | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index ff0084634..e13699c94 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -17,28 +17,38 @@ class ConstraintContainer : Container() { override fun getChildDrawX(child: ExtendedEntity): Float { - val constraint = constraints[child] ?: this - val anchorOffsetX = constraint.getDrawWidth() * child.anchorX + val target = constraints[child] ?: this - val x = if (child.relativePositionAxes.isHorizontal) - child.x * drawWidth - else - child.x + val targetX = target.getDrawX() + val anchorOffsetX = target.getDrawWidth() * child.anchorX - return x + child.originOffsetX + anchorOffsetX + child.translationX + var childX = child.x + + // Relative positions will be multiplied by the remaining space since the + // target's position to the edge of the container. + if (child.relativePositionAxes.isHorizontal) { + childX *= drawWidth - targetX + } + + return targetX + childX + child.originOffsetX + anchorOffsetX + child.translationX } override fun getChildDrawY(child: ExtendedEntity): Float { - val constraint = constraints[child] ?: this - val anchorOffsetY = constraint.getDrawHeight() * child.anchorY + val target = constraints[child] ?: this - val y = if (child.relativePositionAxes.isVertical) - child.y * drawHeight - else - child.y + val targetY = target.getDrawY() + val anchorOffsetY = target.getDrawHeight() * child.anchorY + + var childY = child.y + + // Relative positions will be multiplied by the remaining space since the + // target's position to the edge of the container. + if (child.relativePositionAxes.isVertical) { + childY *= drawHeight - targetY + } - return y + child.originOffsetY + anchorOffsetY + child.translationY + return targetY + childY + child.originOffsetY + anchorOffsetY + child.translationY } From 61c7a427f03db24448022b0a3605502dcc107245 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 19 Dec 2024 19:58:46 -0300 Subject: [PATCH 13/73] Add setRelativePosition() function --- src/com/reco1l/andengine/ExtendedEntity.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 44d7ea536..115629a21 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -394,6 +394,11 @@ abstract class ExtendedEntity( originY = origin.factorY } + fun setRelativePosition(x: Float, y: Float) { + relativePositionAxes = Axes.Both + setPosition(x, y) + } + override fun setPosition(x: Float, y: Float) { if (mX != x || mY != y) { mX = x @@ -657,6 +662,16 @@ abstract class ExtendedEntity( return false } + + /** + * Sets a relative size for the entity. + * This will set the [relativeSizeAxes] property to [Axes.Both] automaticall. + */ + fun setRelativeSize(width: Float, height: Float) { + relativeSizeAxes = Axes.Both + setSize(width, height) + } + /** * Sets the size of the entity. * From 0f28e163d70f8ce185a00c3418d2f7105a64a5af Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 01:00:56 -0300 Subject: [PATCH 14/73] Replace exceptions by automatic handling behavior --- src/com/reco1l/andengine/ExtendedEntity.kt | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 115629a21..ac698b6d2 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -675,26 +675,28 @@ abstract class ExtendedEntity( /** * Sets the size of the entity. * + * Note: This will change the [autoSizeAxes] property to [Axes.None] automatically. + * * @return Whether the size of the entity was changed or not, this depends on the [autoSizeAxes] property. */ open fun setSize(newWidth: Float, newHeight: Float): Boolean { - if (autoSizeAxes == Axes.Both) { - throw IllegalArgumentException("Cannot set size when autoSizeAxes is set to Both.") + if (autoSizeAxes != Axes.None) { + Log.w("ExtendedEntity", "autoSizeAxes is set to ${autoSizeAxes.name} while changing the size manually.") + autoSizeAxes = Axes.None } if (width != newWidth || height != newHeight) { + width = newWidth + height = newHeight - if (!autoSizeAxes.isHorizontal) { - width = newWidth - } + updateVertexBuffer() - if (!autoSizeAxes.isVertical) { - height = newHeight + val parent = parent + if (parent is Container) { + parent.onChildSizeChanged(this) } - updateVertexBuffer() - (parent as? Container)?.onChildSizeChanged(this) return true } return false @@ -703,7 +705,8 @@ abstract class ExtendedEntity( open fun setWidth(value: Float) { if (autoSizeAxes.isHorizontal) { - throw IllegalArgumentException("Cannot set width when autoSizeAxes is set to Both or X.") + Log.w("ExtendedEntity", "autoSizeAxes is set to ${autoSizeAxes.name} while changing the width manually.") + autoSizeAxes = if (autoSizeAxes == Axes.Both) Axes.Y else Axes.None } if (width != value) { @@ -717,7 +720,8 @@ abstract class ExtendedEntity( open fun setHeight(value: Float) { if (autoSizeAxes.isVertical) { - throw IllegalArgumentException("Cannot set height when autoSizeAxes is set to Both or Y.") + Log.w("ExtendedEntity", "autoSizeAxes is set to ${autoSizeAxes.name} while changing the height manually.") + autoSizeAxes = if (autoSizeAxes == Axes.Both) Axes.X else Axes.None } if (height != value) { From 93e15e842343616c6d856d0f53a5c7ce6bb62ec3 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 01:01:20 -0300 Subject: [PATCH 15/73] Introduce GradientCircle --- .../reco1l/andengine/shape/GradientCircle.kt | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/com/reco1l/andengine/shape/GradientCircle.kt diff --git a/src/com/reco1l/andengine/shape/GradientCircle.kt b/src/com/reco1l/andengine/shape/GradientCircle.kt new file mode 100644 index 000000000..c004157da --- /dev/null +++ b/src/com/reco1l/andengine/shape/GradientCircle.kt @@ -0,0 +1,124 @@ +package com.reco1l.andengine.shape + +import androidx.annotation.IntRange +import com.reco1l.framework.ColorARGB +import com.reco1l.framework.Colors +import com.reco1l.toolkt.* +import java.nio.ByteBuffer +import java.nio.ByteOrder +import java.nio.FloatBuffer +import javax.microedition.khronos.opengles.* +import kotlin.math.* + + +/** + * A circle shape. + * + * @author Reco1l + */ +class GradientCircle : Circle() { + + + /** + * The color at the start angle. + */ + var startColor: ColorARGB = ColorARGB.Black + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The color at the end angle. + */ + var endColor = ColorARGB.White + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + + private var shouldRebuildVertexBuffer = true + + + override fun onUpdateVertexBuffer() { + + if (shouldRebuildVertexBuffer) { + shouldRebuildVertexBuffer = false + + val segments = approximateSegments(drawWidth, drawHeight) + setVertexBuffer(GradientCircleVertexBuffer(segments)) + } + + (vertexBuffer as GradientCircleVertexBuffer).update( + drawWidth, + drawHeight, + startAngle, + endAngle, + startColor, + endColor + ) + } + +} + + +class GradientCircleVertexBuffer(@IntRange(from = 1) segments: Int) : CircleVertexBuffer(segments) { + + /** + * The buffer that holds the color data. + */ + val colorBuffer: FloatBuffer = ByteBuffer.allocateDirect((segments + 2) * 4 * Float.SIZE_BYTES) + .order(ByteOrder.nativeOrder()) + .asFloatBuffer() + + + fun update( + width: Float, + height: Float, + startAngle: Float, + endAngle: Float, + startColor: ColorARGB, + endColor: ColorARGB + ) { + super.update(width, height, startAngle, endAngle) + + colorBuffer.put(0, startColor.red) + colorBuffer.put(1, startColor.green) + colorBuffer.put(2, startColor.blue) + colorBuffer.put(3, 1f) + + val halfSegments = segments / 2 + + // The first vertex is the center of the circle. + for (i in 1..segments + 1) { + + var j = i - 1f + if (j > halfSegments) { + j = halfSegments - (j - halfSegments) + } + + val color = Colors.interpolate(j, startColor, endColor, 0f, halfSegments.toFloat()) + + colorBuffer.put(i * 4 + 0, color.red) + colorBuffer.put(i * 4 + 1, color.green) + colorBuffer.put(i * 4 + 2, color.blue) + colorBuffer.put(i * 4 + 3, 1f) + } + + setHardwareBufferNeedsUpdate() + } + + override fun draw(pGL: GL10) { + pGL.glEnableClientState(GL10.GL_COLOR_ARRAY) + pGL.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer) + super.draw(pGL) + pGL.glDisableClientState(GL10.GL_COLOR_ARRAY) + } + +} + From 7a1d953a568775dde22fe956140b513089abb5e3 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 01:01:48 -0300 Subject: [PATCH 16/73] Make Circle open --- src/com/reco1l/andengine/shape/Circle.kt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/com/reco1l/andengine/shape/Circle.kt b/src/com/reco1l/andengine/shape/Circle.kt index 8aefb2ca1..f2ec7b64b 100644 --- a/src/com/reco1l/andengine/shape/Circle.kt +++ b/src/com/reco1l/andengine/shape/Circle.kt @@ -16,7 +16,7 @@ import kotlin.math.* * * @author Reco1l */ -class Circle : ExtendedEntity() { +open class Circle : ExtendedEntity() { /** * The angle where the circle starts to draw in degrees. By default, it is -90 degrees. @@ -86,15 +86,20 @@ class Circle : ExtendedEntity() { shouldRebuildVertexBuffer = false val segments = approximateSegments(drawWidth, drawHeight) - setVertexBuffer(CircleVertexBuffer(segments)) } - (vertexBuffer as CircleVertexBuffer).update(drawWidth, drawHeight, startAngle, endAngle) + val vertexBuffer = vertexBuffer + if (vertexBuffer is CircleVertexBuffer) { + vertexBuffer.update(drawWidth, drawHeight, startAngle, endAngle) + } } override fun drawVertices(pGL: GL10, pCamera: Camera) { - (vertexBuffer as? CircleVertexBuffer)?.draw(pGL) + val vertexBuffer = vertexBuffer + if (vertexBuffer is CircleVertexBuffer) { + vertexBuffer.draw(pGL) + } } @@ -103,7 +108,7 @@ class Circle : ExtendedEntity() { fun approximateSegments(width: Float, height: Float, maximumAngle: Float = 360f): Int { val averageRadius = (width + height) / 4f - val minSegmentAngle = min(10f, 360f / averageRadius.toRadians()) + val minSegmentAngle = min(5f, 360f / averageRadius.toRadians()) return max(3, (maximumAngle / minSegmentAngle).toInt()) } @@ -113,7 +118,7 @@ class Circle : ExtendedEntity() { } -class CircleVertexBuffer(@IntRange(from = 1) val segments: Int) : VertexBuffer( +open class CircleVertexBuffer(@IntRange(from = 1) val segments: Int) : VertexBuffer( // Explanation: Segments + 2 because the first vertex that is the center of the circle is not included in the segment // count and we add it twice so that the last vertex connects to the first one. @@ -153,7 +158,7 @@ class CircleVertexBuffer(@IntRange(from = 1) val segments: Int) : VertexBuffer( setHardwareBufferNeedsUpdate() } - fun draw(pGL: GL10) { + open fun draw(pGL: GL10) { pGL.glDrawArrays(GL11.GL_TRIANGLE_FAN, 0, segments + 2) } From a58863d55566149a486216c7738d06228e7fa73f Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 22:13:33 -0300 Subject: [PATCH 17/73] Don't auto assign the texture region at constructor --- src/com/reco1l/andengine/sprite/ExtendedSprite.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/com/reco1l/andengine/sprite/ExtendedSprite.kt b/src/com/reco1l/andengine/sprite/ExtendedSprite.kt index e00a35794..6f5e20266 100644 --- a/src/com/reco1l/andengine/sprite/ExtendedSprite.kt +++ b/src/com/reco1l/andengine/sprite/ExtendedSprite.kt @@ -94,8 +94,13 @@ open class ExtendedSprite(textureRegion: TextureRegion? = null) : Box() { init { - @Suppress("LeakingThis") - this.textureRegion = textureRegion + run { + textureRegion?.setTexturePosition(textureX, textureY) + textureRegion?.isFlippedVertical = flippedVertical + textureRegion?.isFlippedHorizontal = flippedHorizontal + + onContentSizeMeasured() + } } From f7f0d8ee6ea0ebe7a8c7448a68f95f2d81b4bdef Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 22:35:06 -0300 Subject: [PATCH 18/73] Implement long constructor --- src/com/reco1l/framework/ColorComponent.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/reco1l/framework/ColorComponent.kt b/src/com/reco1l/framework/ColorComponent.kt index f4b33c776..b89c00b0b 100644 --- a/src/com/reco1l/framework/ColorComponent.kt +++ b/src/com/reco1l/framework/ColorComponent.kt @@ -5,6 +5,8 @@ import android.graphics.* @JvmInline value class ColorARGB(private val hex: Int) { + constructor(hex: Long): this(hex.toInt()) + @JvmOverloads constructor(red: Int, green: Int, blue: Int, alpha: Int = 255): this(Color.argb(alpha, red, green, blue)) From 2d09d50c47aed3b9ad42e9df27efc9920b242a5a Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 23:23:51 -0300 Subject: [PATCH 19/73] Introduce Triangle shape --- src/com/reco1l/andengine/shape/Triangle.kt | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/com/reco1l/andengine/shape/Triangle.kt diff --git a/src/com/reco1l/andengine/shape/Triangle.kt b/src/com/reco1l/andengine/shape/Triangle.kt new file mode 100644 index 000000000..eea71ad37 --- /dev/null +++ b/src/com/reco1l/andengine/shape/Triangle.kt @@ -0,0 +1,52 @@ +package com.reco1l.andengine.shape + +import com.reco1l.andengine.* +import org.anddev.andengine.engine.camera.* +import org.anddev.andengine.opengl.util.GLHelper +import org.anddev.andengine.opengl.vertex.VertexBuffer +import javax.microedition.khronos.opengles.* +import javax.microedition.khronos.opengles.GL10.* + +/** + * A triangle shape. + */ +open class Triangle : ExtendedEntity(vertexBuffer = TriangleVertexBuffer()) { + + + override fun onInitDraw(pGL: GL10) { + super.onInitDraw(pGL) + + GLHelper.disableCulling(pGL) + GLHelper.disableTextures(pGL) + GLHelper.disableTexCoordArray(pGL) + } + + + override fun onUpdateVertexBuffer() { + (vertexBuffer as TriangleVertexBuffer).update(drawWidth, drawHeight) + } + + override fun drawVertices(gl: GL10, camera: Camera) { + gl.glDrawArrays(GL_TRIANGLE_FAN, 0, 3) + } + + + class TriangleVertexBuffer : VertexBuffer(3 * 2, GL11.GL_STATIC_DRAW, false) { + + fun update(width: Float, height: Float) { + + floatBuffer.put(0, width / 2f) + floatBuffer.put(1, 0f) + + floatBuffer.put(2, 0f) + floatBuffer.put(3, height) + + floatBuffer.put(4, width) + floatBuffer.put(5, height) + + setHardwareBufferNeedsUpdate() + } + + } + +} From 59846bf0b74f5108042ba62c9116bee6300490a6 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 20 Dec 2024 23:24:13 -0300 Subject: [PATCH 20/73] Introduce TextSprite and TextTexture --- src/com/reco1l/andengine/text/TextSprite.kt | 148 +++++++++++++++++++ src/com/reco1l/andengine/text/TextTexture.kt | 124 ++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 src/com/reco1l/andengine/text/TextSprite.kt create mode 100644 src/com/reco1l/andengine/text/TextTexture.kt diff --git a/src/com/reco1l/andengine/text/TextSprite.kt b/src/com/reco1l/andengine/text/TextSprite.kt new file mode 100644 index 000000000..a92afb25b --- /dev/null +++ b/src/com/reco1l/andengine/text/TextSprite.kt @@ -0,0 +1,148 @@ +package com.reco1l.andengine.text + +import android.graphics.Shader +import android.graphics.Typeface +import android.util.Log +import com.reco1l.andengine.Axes +import com.reco1l.andengine.sprite.ExtendedSprite +import com.reco1l.framework.ColorARGB +import org.anddev.andengine.opengl.texture.region.TextureRegion +import ru.nsu.ccfit.zuev.osu.GlobalManager + +/** + * A sprite that displays text. + * + * Differently from the original [Text] class, this is a sprite that pre-renders the entire text + * to a texture, it is not as efficient as the original [Text] class, but it is more flexible and + * allows for more customization. + * + * It is not recommended to use this on places where the text changes frequently, as it will + * generate a new texture every time the text changes. + */ +class TextSprite : ExtendedSprite() { + + + override var autoSizeAxes = Axes.Both + + override var textureRegion: TextureRegion? = TextTextureRegion(TextTexture()) + set(_) { + Log.e("ExtendedText", "textureRegion is read-only for ExtendedText") + } + + + /** + * The text to be displayed. + */ + var text = "" + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The color of the background of the text. + */ + var backgroundColor = ColorARGB.Transparent + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The color of the text stroke. + */ + var strokeColor = ColorARGB.Transparent + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The width of the text stroke. + */ + var strokeWidth = 0f + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The size of the text in pixels. + */ + var size = 12f + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The typeface of the text. + */ + var typeFace = Typeface.DEFAULT + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The style of the text. + */ + var typeStyle = Typeface.NORMAL + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * The shader to be applied to the text. + */ + var shader: Shader? = null + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + + val lineWidth + get() = size * text.length + + + + private val texture = textureRegion!!.texture as TextTexture + + + init { + GlobalManager.getInstance().engine.textureManager.loadTexture(texture) + } + + + override fun onUpdateVertexBuffer() { + val typeface = Typeface.create(typeFace, typeStyle) + (textureRegion as TextTextureRegion).update(text, color, backgroundColor, strokeColor, strokeWidth, size, typeface, shader) + onContentSizeMeasured() + super.onUpdateVertexBuffer() + } + + + override fun finalize() { + GlobalManager.getInstance().engine.textureManager.unloadTexture(texture) + super.finalize() + } + +} diff --git a/src/com/reco1l/andengine/text/TextTexture.kt b/src/com/reco1l/andengine/text/TextTexture.kt new file mode 100644 index 000000000..5778201aa --- /dev/null +++ b/src/com/reco1l/andengine/text/TextTexture.kt @@ -0,0 +1,124 @@ +package com.reco1l.andengine.text + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.Shader +import android.graphics.Typeface +import android.opengl.GLUtils +import androidx.core.graphics.alpha +import com.reco1l.framework.ColorARGB +import org.anddev.andengine.opengl.texture.Texture +import org.anddev.andengine.opengl.texture.TextureOptions +import org.anddev.andengine.opengl.texture.region.TextureRegion +import javax.microedition.khronos.opengles.GL10 + + +class TextTexture : Texture(PixelFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, null) { + + + private val paint = Paint() + + private val backgroundPaint = Paint() + + private val strokePaint = Paint() + + private val bounds = Rect() + + private val canvas = Canvas() + + + private var text: String = "" + + + fun update( + newText: String, + color: ColorARGB, + backgroundColor: ColorARGB, + strokeColor: ColorARGB, + strokeWidth: Float, + size: Float, + typeFace: Typeface, + shader: Shader? + ) { + paint.isAntiAlias = true + paint.color = color.toInt() + paint.shader = shader + paint.textSize = size + paint.typeface = typeFace + + backgroundPaint.style = Paint.Style.FILL + backgroundPaint.color = backgroundColor.toInt() + + strokePaint.style = Paint.Style.STROKE + strokePaint.color = strokeColor.toInt() + strokePaint.isAntiAlias = true + strokePaint.textSize = size + strokePaint.typeface = typeFace + strokePaint.strokeWidth = strokeWidth + + paint.getTextBounds(newText, 0, newText.length, bounds) + + text = newText + isUpdateOnHardwareNeeded = true + } + + + override fun writeTextureToHardware(pGL: GL10) { + + if (width == 0 || height == 0) { + return + } + + val bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888) + canvas.setBitmap(bitmap) + + val offsetX = -bounds.left.toFloat() + val offsetY = -bounds.top.toFloat() + + if (backgroundPaint.color.alpha > 0f) { + canvas.drawRect(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat(), backgroundPaint) + } + + canvas.drawText(text, offsetX, offsetY, paint) + + if (strokePaint.strokeWidth > 0 && strokePaint.color.alpha > 0) { + canvas.drawText(text, offsetX, offsetY, strokePaint) + } + + GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0) + bitmap.recycle() + } + + + override fun getWidth(): Int { + return bounds.width() + } + + override fun getHeight(): Int { + return bounds.height() + } + +} + +class TextTextureRegion(private val textTexture: TextTexture): TextureRegion(textTexture, 0, 0, textTexture.width, textTexture.height) { + + + fun update( + text: String, + color: ColorARGB, + backgroundColor: ColorARGB, + strokeColor: ColorARGB, + strokeWidth: Float, + size: Float, + typeFace: Typeface, + shader: Shader? + ) { + textTexture.update(text, color, backgroundColor, strokeColor, strokeWidth, size, typeFace, shader) + mWidth = textTexture.width + mHeight = textTexture.height + updateTextureRegionBuffer() + } + +} \ No newline at end of file From 4aefc4107d44749e4b4af323caf08d9d2783a72f Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 21 Dec 2024 00:32:57 -0300 Subject: [PATCH 21/73] Introduce DepthInfo specification --- .../osu/support/slider/SliderBody.java | 12 ++-- src/com/reco1l/andengine/DepthInfo.kt | 59 +++++++++++++++++++ src/com/reco1l/andengine/ExtendedEntity.kt | 20 +------ .../osu/playfield/CircularSongProgress.kt | 5 +- src/com/reco1l/osu/playfield/HealthBar.kt | 5 +- 5 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 src/com/reco1l/andengine/DepthInfo.kt diff --git a/src/com/edlplan/osu/support/slider/SliderBody.java b/src/com/edlplan/osu/support/slider/SliderBody.java index f331733df..6160e2224 100644 --- a/src/com/edlplan/osu/support/slider/SliderBody.java +++ b/src/com/edlplan/osu/support/slider/SliderBody.java @@ -2,6 +2,7 @@ import com.edlplan.andengine.TriangleBuilder; import com.edlplan.framework.math.line.LinePath; +import com.reco1l.andengine.DepthInfo; import com.reco1l.andengine.shape.TriangleMesh; import com.reco1l.andengine.container.Container; import com.rian.osu.math.Vector2; @@ -38,18 +39,17 @@ public SliderBody(boolean allowHint) { if (allowHint) { hint = new TriangleMesh(); hint.setVisible(false); - hint.setTestWithDepthBuffer(true); - hint.setClearDepthBufferBeforeDraw(true); + hint.setDepthInfo(DepthInfo.Clear); } else { hint = null; } border = new TriangleMesh(); - border.setTestWithDepthBuffer(true); + border.setDepthInfo(DepthInfo.Default); attachChild(border, 0); background = new TriangleMesh(); - background.setTestWithDepthBuffer(true); + background.setDepthInfo(DepthInfo.Default); attachChild(background, 0); if (hint != null) { @@ -90,9 +90,9 @@ public void setBackgroundColor(float r, float g, float b, float a) { public void setHintVisible(boolean visible) { if (hint != null) { hint.setVisible(visible); - background.setClearDepthBufferBeforeDraw(!visible); + background.setDepthInfo(visible ? DepthInfo.Default : DepthInfo.Clear); } else { - background.setClearDepthBufferBeforeDraw(true); + background.setDepthInfo(DepthInfo.Clear); } } diff --git a/src/com/reco1l/andengine/DepthInfo.kt b/src/com/reco1l/andengine/DepthInfo.kt new file mode 100644 index 000000000..10e01097b --- /dev/null +++ b/src/com/reco1l/andengine/DepthInfo.kt @@ -0,0 +1,59 @@ +package com.reco1l.andengine + +import org.anddev.andengine.opengl.util.GLHelper +import javax.microedition.khronos.opengles.GL10 + +data class DepthInfo( + + val function: DepthFunction, + + val mask: Boolean, + + val clear: Boolean + +) { + + + fun apply(gl: GL10) { + gl.glDepthFunc(function.glType) + gl.glDepthMask(mask) + + if (clear) { + gl.glClear(GL10.GL_DEPTH_BUFFER_BIT) + } + + GLHelper.enableDepthTest(gl) + } + + + companion object { + + @JvmField + val Clear = DepthInfo( + function = DepthFunction.Less, + mask = true, + clear = true + ) + + @JvmField + val Default = DepthInfo( + function = DepthFunction.Less, + mask = true, + clear = false + ) + + } + +} + + +enum class DepthFunction(val glType: Int) { + Never(GL10.GL_NEVER), + Less(GL10.GL_LESS), + Equal(GL10.GL_EQUAL), + LessOrEqual(GL10.GL_LEQUAL), + Greater(GL10.GL_GREATER), + NotEqual(GL10.GL_NOTEQUAL), + GreaterOrEqual(GL10.GL_GEQUAL), + Always(GL10.GL_ALWAYS) +} \ No newline at end of file diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index ac698b6d2..6ecac59ad 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -196,19 +196,9 @@ abstract class ExtendedEntity( open var clipChildren = false /** - * Whether the depth buffer should be cleared before drawing the entity. - * This is useful when the entity is drawn on top of other entities by overlapping them. - * - * It will only take effect if the entities on the front have the depth buffer test enabled. - * - * @see [testWithDepthBuffer] + * The depth information of the entity. */ - open var clearDepthBufferBeforeDraw = false - - /** - * Whether the entity should be tested with the depth buffer. - */ - open var testWithDepthBuffer = false + open var depthInfo: DepthInfo? = null /** * The color of the entity boxed in a [ColorARGB] object. @@ -589,11 +579,7 @@ abstract class ExtendedEntity( GLHelper.enableVertexArray(pGL) } - if (clearDepthBufferBeforeDraw) { - pGL.glClear(GL_DEPTH_BUFFER_BIT) - } - - GLHelper.setDepthTest(pGL, testWithDepthBuffer) + depthInfo?.apply(pGL) ?: GLHelper.disableDepthTest(pGL) } override fun onApplyVertices(pGL: GL10) { diff --git a/src/com/reco1l/osu/playfield/CircularSongProgress.kt b/src/com/reco1l/osu/playfield/CircularSongProgress.kt index 1437aa6ce..d955ab748 100644 --- a/src/com/reco1l/osu/playfield/CircularSongProgress.kt +++ b/src/com/reco1l/osu/playfield/CircularSongProgress.kt @@ -24,8 +24,7 @@ class CircularSongProgress : Container() { clear.setAnchor(Anchor.Center) clear.setOrigin(Anchor.Center) clear.color = ColorARGB.Transparent - clear.testWithDepthBuffer = true - clear.clearDepthBufferBeforeDraw = true + clear.depthInfo = DepthInfo.Clear attachChild(clear) } @@ -36,7 +35,7 @@ class CircularSongProgress : Container() { background.setAnchor(Anchor.Center) background.setOrigin(Anchor.Center) background.color = ColorARGB.White - background.testWithDepthBuffer = true + background.depthInfo = DepthInfo.Default attachChild(background) } diff --git a/src/com/reco1l/osu/playfield/HealthBar.kt b/src/com/reco1l/osu/playfield/HealthBar.kt index 5bc8cee63..31849ed08 100644 --- a/src/com/reco1l/osu/playfield/HealthBar.kt +++ b/src/com/reco1l/osu/playfield/HealthBar.kt @@ -50,13 +50,12 @@ class HealthBar(private val statistics: StatisticV2) : Container() { fillClear = Box() fillClear.setOrigin(Anchor.TopRight) - fillClear.clearDepthBufferBeforeDraw = true - fillClear.testWithDepthBuffer = true + fillClear.depthInfo = DepthInfo.Clear fillClear.alpha = 0f attachChild(fillClear) fill = AnimatedSprite("scorebar-colour", true, OsuSkin.get().animationFramerate) - fill.testWithDepthBuffer = true + fill.depthInfo = DepthInfo.Default fill.autoSizeAxes = Axes.None // Preserve the first frame width. attachChild(fill) From f78f5db8a41cd4c67a115d56131476e86e173c86 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 21 Dec 2024 00:33:36 -0300 Subject: [PATCH 22/73] Make GradientCircle compatible with inherited alpha --- .../reco1l/andengine/shape/GradientCircle.kt | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/com/reco1l/andengine/shape/GradientCircle.kt b/src/com/reco1l/andengine/shape/GradientCircle.kt index c004157da..2a8c66f82 100644 --- a/src/com/reco1l/andengine/shape/GradientCircle.kt +++ b/src/com/reco1l/andengine/shape/GradientCircle.kt @@ -3,12 +3,10 @@ package com.reco1l.andengine.shape import androidx.annotation.IntRange import com.reco1l.framework.ColorARGB import com.reco1l.framework.Colors -import com.reco1l.toolkt.* import java.nio.ByteBuffer import java.nio.ByteOrder import java.nio.FloatBuffer import javax.microedition.khronos.opengles.* -import kotlin.math.* /** @@ -41,10 +39,16 @@ class GradientCircle : Circle() { } } - private var shouldRebuildVertexBuffer = true + override fun setAlpha(pAlpha: Float) { + if (mAlpha != pAlpha) { + super.setAlpha(pAlpha) + updateVertexBuffer() + } + } + override fun onUpdateVertexBuffer() { if (shouldRebuildVertexBuffer) { @@ -54,16 +58,24 @@ class GradientCircle : Circle() { setVertexBuffer(GradientCircleVertexBuffer(segments)) } + // Getting inherited alpha. + var alpha = mAlpha + var parent = parent + while (parent != null) { + alpha *= parent.alpha + parent = parent.parent + } + (vertexBuffer as GradientCircleVertexBuffer).update( drawWidth, drawHeight, startAngle, endAngle, startColor, - endColor + endColor, + alpha ) } - } @@ -83,14 +95,15 @@ class GradientCircleVertexBuffer(@IntRange(from = 1) segments: Int) : CircleVert startAngle: Float, endAngle: Float, startColor: ColorARGB, - endColor: ColorARGB + endColor: ColorARGB, + alpha: Float ) { super.update(width, height, startAngle, endAngle) colorBuffer.put(0, startColor.red) colorBuffer.put(1, startColor.green) colorBuffer.put(2, startColor.blue) - colorBuffer.put(3, 1f) + colorBuffer.put(3, alpha) val halfSegments = segments / 2 @@ -107,7 +120,7 @@ class GradientCircleVertexBuffer(@IntRange(from = 1) segments: Int) : CircleVert colorBuffer.put(i * 4 + 0, color.red) colorBuffer.put(i * 4 + 1, color.green) colorBuffer.put(i * 4 + 2, color.blue) - colorBuffer.put(i * 4 + 3, 1f) + colorBuffer.put(i * 4 + 3, alpha) } setHardwareBufferNeedsUpdate() From 3e4d3aa832d91a07460898c1cedb63c89d45ba34 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 21 Dec 2024 00:34:01 -0300 Subject: [PATCH 23/73] Implement relativeSize to TextSprite --- src/com/reco1l/andengine/text/TextSprite.kt | 38 +++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/com/reco1l/andengine/text/TextSprite.kt b/src/com/reco1l/andengine/text/TextSprite.kt index a92afb25b..30c412769 100644 --- a/src/com/reco1l/andengine/text/TextSprite.kt +++ b/src/com/reco1l/andengine/text/TextSprite.kt @@ -4,10 +4,13 @@ import android.graphics.Shader import android.graphics.Typeface import android.util.Log import com.reco1l.andengine.Axes +import com.reco1l.andengine.getDrawHeight +import com.reco1l.andengine.getDrawWidth import com.reco1l.andengine.sprite.ExtendedSprite import com.reco1l.framework.ColorARGB import org.anddev.andengine.opengl.texture.region.TextureRegion import ru.nsu.ccfit.zuev.osu.GlobalManager +import kotlin.math.max /** * A sprite that displays text. @@ -78,6 +81,23 @@ class TextSprite : ExtendedSprite() { * The size of the text in pixels. */ var size = 12f + get() { + if (relativeSize && parent != null) { + return field * max(parent.getDrawWidth(), parent.getDrawHeight()) + } + return field + } + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + /** + * Whether the size of the text is relative to the size of the parent. + */ + var relativeSize = false set(value) { if (field != value) { field = value @@ -119,11 +139,13 @@ class TextSprite : ExtendedSprite() { } + /** + * The width of the text line. + */ val lineWidth get() = size * text.length - private val texture = textureRegion!!.texture as TextTexture @@ -133,8 +155,18 @@ class TextSprite : ExtendedSprite() { override fun onUpdateVertexBuffer() { - val typeface = Typeface.create(typeFace, typeStyle) - (textureRegion as TextTextureRegion).update(text, color, backgroundColor, strokeColor, strokeWidth, size, typeface, shader) + + (textureRegion as TextTextureRegion).update( + text, + color, + backgroundColor, + strokeColor, + strokeWidth, + size, + Typeface.create(typeFace, typeStyle), + shader + ) + onContentSizeMeasured() super.onUpdateVertexBuffer() } From 0f9f29ed507c5a9c450e2ffa4e932fb704815d3c Mon Sep 17 00:00:00 2001 From: Reco1l Date: Mon, 23 Dec 2024 12:25:42 -0300 Subject: [PATCH 24/73] Move texture classes to the same file --- src/com/reco1l/andengine/text/TextSprite.kt | 158 +++++++++++++++++-- src/com/reco1l/andengine/text/TextTexture.kt | 124 --------------- 2 files changed, 142 insertions(+), 140 deletions(-) delete mode 100644 src/com/reco1l/andengine/text/TextTexture.kt diff --git a/src/com/reco1l/andengine/text/TextSprite.kt b/src/com/reco1l/andengine/text/TextSprite.kt index 30c412769..17bd1c8f2 100644 --- a/src/com/reco1l/andengine/text/TextSprite.kt +++ b/src/com/reco1l/andengine/text/TextSprite.kt @@ -1,15 +1,26 @@ package com.reco1l.andengine.text +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.LinearGradient +import android.graphics.Paint +import android.graphics.Rect import android.graphics.Shader +import android.graphics.Shader.TileMode import android.graphics.Typeface +import android.opengl.GLUtils import android.util.Log +import androidx.core.graphics.alpha import com.reco1l.andengine.Axes import com.reco1l.andengine.getDrawHeight import com.reco1l.andengine.getDrawWidth import com.reco1l.andengine.sprite.ExtendedSprite import com.reco1l.framework.ColorARGB +import org.anddev.andengine.opengl.texture.Texture +import org.anddev.andengine.opengl.texture.TextureOptions import org.anddev.andengine.opengl.texture.region.TextureRegion import ru.nsu.ccfit.zuev.osu.GlobalManager +import javax.microedition.khronos.opengles.GL10 import kotlin.math.max /** @@ -127,23 +138,8 @@ class TextSprite : ExtendedSprite() { } } - /** - * The shader to be applied to the text. - */ - var shader: Shader? = null - set(value) { - if (field != value) { - field = value - updateVertexBuffer() - } - } - - /** - * The width of the text line. - */ - val lineWidth - get() = size * text.length + private var shader: Shader? = null private val texture = textureRegion!!.texture as TextTexture @@ -172,9 +168,139 @@ class TextSprite : ExtendedSprite() { } + // Shaders + + /** + * Sets a linear gradient color to the text. + * + * The gradient is defined by two points (x0, y0) and (x1, y1) in the range [0, 1] and two colors (startColor, endColor). + */ + fun setGradient(x0: Float, y0: Float, x1: Float, y1: Float, startColor: ColorARGB, endColor: ColorARGB, tileMode: TileMode = TileMode.MIRROR) { + shader = LinearGradient( + x0 * drawWidth, + y0 * drawHeight, + x1 * drawWidth, + y1 * drawHeight, + startColor.toInt(), + endColor.toInt(), + tileMode + ) + updateVertexBuffer() + } + + override fun finalize() { GlobalManager.getInstance().engine.textureManager.unloadTexture(texture) super.finalize() } } + +class TextTexture : Texture(PixelFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, null) { + + + private val paint = Paint() + + private val backgroundPaint = Paint() + + private val strokePaint = Paint() + + private val bounds = Rect() + + private val canvas = Canvas() + + + private var text: String = "" + + + fun update( + newText: String, + color: ColorARGB, + backgroundColor: ColorARGB, + strokeColor: ColorARGB, + strokeWidth: Float, + size: Float, + typeFace: Typeface, + shader: Shader? + ) { + paint.isAntiAlias = true + paint.color = color.toInt() + paint.shader = null + paint.shader = shader + paint.textSize = size + paint.typeface = typeFace + + backgroundPaint.style = Paint.Style.FILL + backgroundPaint.color = backgroundColor.toInt() + + strokePaint.style = Paint.Style.STROKE + strokePaint.color = strokeColor.toInt() + strokePaint.isAntiAlias = true + strokePaint.textSize = size + strokePaint.typeface = typeFace + strokePaint.strokeWidth = strokeWidth + + paint.getTextBounds(newText, 0, newText.length, bounds) + + text = newText + isUpdateOnHardwareNeeded = true + } + + + override fun writeTextureToHardware(pGL: GL10) { + + if (width == 0 || height == 0) { + return + } + + val bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888) + canvas.setBitmap(bitmap) + + val offsetX = -bounds.left.toFloat() + val offsetY = -bounds.top.toFloat() + + if (backgroundPaint.color.alpha > 0f) { + canvas.drawRect(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat(), backgroundPaint) + } + + canvas.drawText(text, offsetX, offsetY, paint) + + if (strokePaint.strokeWidth > 0 && strokePaint.color.alpha > 0) { + canvas.drawText(text, offsetX, offsetY, strokePaint) + } + + GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0) + bitmap.recycle() + } + + + override fun getWidth(): Int { + return bounds.width() + } + + override fun getHeight(): Int { + return bounds.height() + } + +} + +class TextTextureRegion(private val textTexture: TextTexture): TextureRegion(textTexture, 0, 0, textTexture.width, textTexture.height) { + + + fun update( + text: String, + color: ColorARGB, + backgroundColor: ColorARGB, + strokeColor: ColorARGB, + strokeWidth: Float, + size: Float, + typeFace: Typeface, + shader: Shader? + ) { + textTexture.update(text, color, backgroundColor, strokeColor, strokeWidth, size, typeFace, shader) + mWidth = textTexture.width + mHeight = textTexture.height + updateTextureRegionBuffer() + } + +} \ No newline at end of file diff --git a/src/com/reco1l/andengine/text/TextTexture.kt b/src/com/reco1l/andengine/text/TextTexture.kt deleted file mode 100644 index 5778201aa..000000000 --- a/src/com/reco1l/andengine/text/TextTexture.kt +++ /dev/null @@ -1,124 +0,0 @@ -package com.reco1l.andengine.text - -import android.graphics.Bitmap -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.Shader -import android.graphics.Typeface -import android.opengl.GLUtils -import androidx.core.graphics.alpha -import com.reco1l.framework.ColorARGB -import org.anddev.andengine.opengl.texture.Texture -import org.anddev.andengine.opengl.texture.TextureOptions -import org.anddev.andengine.opengl.texture.region.TextureRegion -import javax.microedition.khronos.opengles.GL10 - - -class TextTexture : Texture(PixelFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, null) { - - - private val paint = Paint() - - private val backgroundPaint = Paint() - - private val strokePaint = Paint() - - private val bounds = Rect() - - private val canvas = Canvas() - - - private var text: String = "" - - - fun update( - newText: String, - color: ColorARGB, - backgroundColor: ColorARGB, - strokeColor: ColorARGB, - strokeWidth: Float, - size: Float, - typeFace: Typeface, - shader: Shader? - ) { - paint.isAntiAlias = true - paint.color = color.toInt() - paint.shader = shader - paint.textSize = size - paint.typeface = typeFace - - backgroundPaint.style = Paint.Style.FILL - backgroundPaint.color = backgroundColor.toInt() - - strokePaint.style = Paint.Style.STROKE - strokePaint.color = strokeColor.toInt() - strokePaint.isAntiAlias = true - strokePaint.textSize = size - strokePaint.typeface = typeFace - strokePaint.strokeWidth = strokeWidth - - paint.getTextBounds(newText, 0, newText.length, bounds) - - text = newText - isUpdateOnHardwareNeeded = true - } - - - override fun writeTextureToHardware(pGL: GL10) { - - if (width == 0 || height == 0) { - return - } - - val bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888) - canvas.setBitmap(bitmap) - - val offsetX = -bounds.left.toFloat() - val offsetY = -bounds.top.toFloat() - - if (backgroundPaint.color.alpha > 0f) { - canvas.drawRect(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat(), backgroundPaint) - } - - canvas.drawText(text, offsetX, offsetY, paint) - - if (strokePaint.strokeWidth > 0 && strokePaint.color.alpha > 0) { - canvas.drawText(text, offsetX, offsetY, strokePaint) - } - - GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0) - bitmap.recycle() - } - - - override fun getWidth(): Int { - return bounds.width() - } - - override fun getHeight(): Int { - return bounds.height() - } - -} - -class TextTextureRegion(private val textTexture: TextTexture): TextureRegion(textTexture, 0, 0, textTexture.width, textTexture.height) { - - - fun update( - text: String, - color: ColorARGB, - backgroundColor: ColorARGB, - strokeColor: ColorARGB, - strokeWidth: Float, - size: Float, - typeFace: Typeface, - shader: Shader? - ) { - textTexture.update(text, color, backgroundColor, strokeColor, strokeWidth, size, typeFace, shader) - mWidth = textTexture.width - mHeight = textTexture.height - updateTextureRegionBuffer() - } - -} \ No newline at end of file From 529bd38231c3d6e3713b071b797d4400c36097fb Mon Sep 17 00:00:00 2001 From: Reco1l Date: Mon, 23 Dec 2024 12:31:12 -0300 Subject: [PATCH 25/73] Rename function --- src/com/reco1l/andengine/text/TextSprite.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/text/TextSprite.kt b/src/com/reco1l/andengine/text/TextSprite.kt index 17bd1c8f2..f6faa4fc7 100644 --- a/src/com/reco1l/andengine/text/TextSprite.kt +++ b/src/com/reco1l/andengine/text/TextSprite.kt @@ -4,6 +4,7 @@ import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.LinearGradient import android.graphics.Paint +import android.graphics.RadialGradient import android.graphics.Rect import android.graphics.Shader import android.graphics.Shader.TileMode @@ -175,7 +176,15 @@ class TextSprite : ExtendedSprite() { * * The gradient is defined by two points (x0, y0) and (x1, y1) in the range [0, 1] and two colors (startColor, endColor). */ - fun setGradient(x0: Float, y0: Float, x1: Float, y1: Float, startColor: ColorARGB, endColor: ColorARGB, tileMode: TileMode = TileMode.MIRROR) { + fun setLinearGradient(x0: Float, y0: Float, x1: Float, y1: Float, startColor: ColorARGB, endColor: ColorARGB, tileMode: TileMode = TileMode.MIRROR) { + shader = RadialGradient( + x0 * drawWidth, + y0 * drawHeight, + max(drawWidth, drawHeight), + startColor.toInt(), + endColor.toInt(), + tileMode + ) shader = LinearGradient( x0 * drawWidth, y0 * drawHeight, From 4ae7953a13095325132192f3af9ee6f702674425 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Mon, 23 Dec 2024 13:04:34 -0300 Subject: [PATCH 26/73] Remove test code --- src/com/reco1l/andengine/text/TextSprite.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/com/reco1l/andengine/text/TextSprite.kt b/src/com/reco1l/andengine/text/TextSprite.kt index f6faa4fc7..d9a2ae2d9 100644 --- a/src/com/reco1l/andengine/text/TextSprite.kt +++ b/src/com/reco1l/andengine/text/TextSprite.kt @@ -4,7 +4,6 @@ import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.LinearGradient import android.graphics.Paint -import android.graphics.RadialGradient import android.graphics.Rect import android.graphics.Shader import android.graphics.Shader.TileMode @@ -177,14 +176,6 @@ class TextSprite : ExtendedSprite() { * The gradient is defined by two points (x0, y0) and (x1, y1) in the range [0, 1] and two colors (startColor, endColor). */ fun setLinearGradient(x0: Float, y0: Float, x1: Float, y1: Float, startColor: ColorARGB, endColor: ColorARGB, tileMode: TileMode = TileMode.MIRROR) { - shader = RadialGradient( - x0 * drawWidth, - y0 * drawHeight, - max(drawWidth, drawHeight), - startColor.toInt(), - endColor.toInt(), - tileMode - ) shader = LinearGradient( x0 * drawWidth, y0 * drawHeight, From db3c9d3fccc354e3f7c1b961a1abf5f7964940de Mon Sep 17 00:00:00 2001 From: Reco1l Date: Mon, 23 Dec 2024 16:32:05 -0300 Subject: [PATCH 27/73] Update vertex buffer in draw thread --- src/com/reco1l/andengine/ExtendedEntity.kt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 6ecac59ad..fc759ef0a 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -528,6 +528,11 @@ abstract class ExtendedEntity( override fun onManagedDraw(gl: GL10, camera: Camera) { + if (isVertexBufferDirty) { + isVertexBufferDirty = false + onUpdateVertexBuffer() + } + if (clipChildren) { GLHelper.enableScissorTest(gl) @@ -563,16 +568,6 @@ abstract class ExtendedEntity( } } - override fun onManagedUpdate(pSecondsElapsed: Float) { - - if (isVertexBufferDirty) { - isVertexBufferDirty = false - onUpdateVertexBuffer() - } - - super.onManagedUpdate(pSecondsElapsed) - } - override fun onInitDraw(pGL: GL10) { if (vertexBuffer != null) { From 6ddb7a655bd57fcd530f02be867f1ab11b4d4f8e Mon Sep 17 00:00:00 2001 From: Reco1l Date: Mon, 23 Dec 2024 16:32:51 -0300 Subject: [PATCH 28/73] Introduce ExtendedText --- src/com/reco1l/andengine/text/ExtendedText.kt | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/com/reco1l/andengine/text/ExtendedText.kt diff --git a/src/com/reco1l/andengine/text/ExtendedText.kt b/src/com/reco1l/andengine/text/ExtendedText.kt new file mode 100644 index 000000000..9951fdd6c --- /dev/null +++ b/src/com/reco1l/andengine/text/ExtendedText.kt @@ -0,0 +1,163 @@ +package com.reco1l.andengine.text + +import com.reco1l.andengine.Axes +import com.reco1l.andengine.ExtendedEntity +import com.reco1l.toolkt.kotlin.fastForEachIndexed +import org.anddev.andengine.engine.camera.* +import org.anddev.andengine.opengl.font.* +import org.anddev.andengine.opengl.texture.buffer.* +import org.anddev.andengine.opengl.util.* +import org.anddev.andengine.opengl.vertex.* +import org.anddev.andengine.opengl.vertex.TextVertexBuffer.VERTICES_PER_CHARACTER +import org.anddev.andengine.util.* +import javax.microedition.khronos.opengles.* +import javax.microedition.khronos.opengles.GL11.GL_STATIC_DRAW +import kotlin.math.* + +/** + * A text entity that can be displayed on the screen. + */ +open class ExtendedText : ExtendedEntity() { + + + override var autoSizeAxes = Axes.Both + + + /** + * The text to be displayed + */ + var text: String = "" + set(value) { + if (field != value) { + field = value + if (value.length > maximumSize) { + shouldRebuildVertexBuffer = true + shouldRebuildTextureBuffer = true + } + updateVertexBuffer() + } + } + + /** + * The font to use for this text. + * It must be already loaded and ready to use before setting it. + */ + var font: Font? = null + set(value) { + if (field != value) { + field = value + shouldRebuildTextureBuffer = true + updateVertexBuffer() + } + } + + /** + * The horizontal alignment of the text. + */ + var horizontalAlign = HorizontalAlign.LEFT + set(value) { + if (field != value) { + field = value + updateVertexBuffer() + } + } + + + private var textureBuffer: TextTextureBuffer? = null + + private var shouldRebuildVertexBuffer = true + + private var shouldRebuildTextureBuffer = true + + private var maximumSize = 0 + + private var currentSize = 0 + + + override fun onInitDraw(pGL: GL10) { + super.onInitDraw(pGL) + GLHelper.enableTextures(pGL) + GLHelper.enableTexCoordArray(pGL) + } + + override fun drawVertices(gl: GL10, pCamera: Camera?) { + val vertexBuffer = vertexBuffer + if (vertexBuffer != null) { + gl.glDrawArrays(GL10.GL_TRIANGLES, 0, currentSize * VERTICES_PER_CHARACTER) + } + } + + override fun onApplyVertices(gl: GL10) { + + val font = font + val textureBuffer = textureBuffer + + if (font != null && textureBuffer != null) { + font.texture.bind(gl) + GLHelper.texCoordPointer(gl, textureBuffer.floatBuffer) + } + + super.onApplyVertices(gl) + } + + override fun onUpdateVertexBuffer() { + + val text = text + currentSize = text.length + + if (text.length > maximumSize) { + shouldRebuildVertexBuffer = true + shouldRebuildTextureBuffer = true + maximumSize = text.length + } + + if (shouldRebuildVertexBuffer) { + shouldRebuildVertexBuffer = false + + setVertexBuffer(TextVertexBuffer(maximumSize, horizontalAlign, GL_STATIC_DRAW, true)) + } + + if (shouldRebuildTextureBuffer) { + shouldRebuildTextureBuffer = false + + textureBuffer = TextTextureBuffer(2 * VERTICES_PER_CHARACTER * maximumSize, GL_STATIC_DRAW, true) + + if (font!!.texture.textureOptions.mPreMultipyAlpha) { + setBlendFunction(BLENDFUNCTION_SOURCE_PREMULTIPLYALPHA_DEFAULT, BLENDFUNCTION_DESTINATION_PREMULTIPLYALPHA_DEFAULT) + } else { + setBlendFunction(BLENDFUNCTION_SOURCE_DEFAULT, BLENDFUNCTION_DESTINATION_DEFAULT) + } + } + + val lines = text.split('\n').toTypedArray() + val linesWidth = IntArray(lines.size) + + var maximumLineWidth = 0 + + lines.fastForEachIndexed { i, line -> + linesWidth[i] = font!!.getStringWidth(line) + maximumLineWidth = max(maximumLineWidth, linesWidth[i]) + } + + contentWidth = maximumLineWidth.toFloat() + contentHeight = (lines.size * font!!.lineHeight + (lines.size - 1) * font!!.lineGap).toFloat() + onContentSizeMeasured() + + textureBuffer!!.update(font!!, lines) + vertexBuffer!!.update(font!!, maximumLineWidth, linesWidth, lines, horizontalAlign) + } + + + override fun getVertexBuffer(): TextVertexBuffer? { + return super.getVertexBuffer() as TextVertexBuffer? + } + + + override fun finalize() { + if (textureBuffer!!.isManaged) { + textureBuffer!!.unloadFromActiveBufferObjectManager() + } + super.finalize() + } + +} \ No newline at end of file From 3e52bfbe0ee7cbe73398837396dbf09379ce28f5 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Mon, 23 Dec 2024 16:33:10 -0300 Subject: [PATCH 29/73] Pass HorizontalAlign through update method in TextVertexBuffer --- .../anddev/andengine/opengl/vertex/TextVertexBuffer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/AndEngine/src/org/anddev/andengine/opengl/vertex/TextVertexBuffer.java b/AndEngine/src/org/anddev/andengine/opengl/vertex/TextVertexBuffer.java index d9fc9e8ac..57c3d76c1 100644 --- a/AndEngine/src/org/anddev/andengine/opengl/vertex/TextVertexBuffer.java +++ b/AndEngine/src/org/anddev/andengine/opengl/vertex/TextVertexBuffer.java @@ -48,7 +48,13 @@ public TextVertexBuffer(final int pCharacterCount, final HorizontalAlign pHorizo // Methods // =========================================================== + // BEGIN osu!droid modified - Pass horizontal alignment through to update method. public synchronized void update(final Font font, final int pMaximumLineWidth, final int[] pWidths, final String[] pLines) { + this.update(font, pMaximumLineWidth, pWidths, pLines, this.mHorizontalAlign); + } + // END osu!droid modified + + public synchronized void update(final Font font, final int pMaximumLineWidth, final int[] pWidths, final String[] pLines, HorizontalAlign pHorizontalAlign) { final FloatBuffer floatBuffer = this.mFloatBuffer; int i = 0; @@ -59,7 +65,7 @@ public synchronized void update(final Font font, final int pMaximumLineWidth, fi final String line = pLines[lineIndex]; float lineX; - switch(this.mHorizontalAlign) { + switch(pHorizontalAlign) { case RIGHT: lineX = pMaximumLineWidth - pWidths[lineIndex]; break; From 271e0f5ed7e261a2067d7c629a32acd7bd7b8895 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Tue, 24 Dec 2024 01:17:56 -0300 Subject: [PATCH 30/73] Fix constructor's textureRegion not being used --- src/com/reco1l/andengine/sprite/ExtendedSprite.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/reco1l/andengine/sprite/ExtendedSprite.kt b/src/com/reco1l/andengine/sprite/ExtendedSprite.kt index 6f5e20266..24c00b158 100644 --- a/src/com/reco1l/andengine/sprite/ExtendedSprite.kt +++ b/src/com/reco1l/andengine/sprite/ExtendedSprite.kt @@ -5,7 +5,6 @@ import com.reco1l.andengine.* import com.reco1l.andengine.shape.* import org.anddev.andengine.opengl.texture.region.* import org.anddev.andengine.opengl.util.* -import org.anddev.andengine.opengl.vertex.* import javax.microedition.khronos.opengles.* /** @@ -54,7 +53,7 @@ open class ExtendedSprite(textureRegion: TextureRegion? = null) : Box() { /** * The texture region of the sprite. */ - open var textureRegion: TextureRegion? = null + open var textureRegion: TextureRegion? = textureRegion set(value) { if (field == value) { From 102dbcf518d539f1f22414a2786bb050250b317e Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:18:55 -0300 Subject: [PATCH 31/73] Document DepthInfo --- src/com/reco1l/andengine/DepthInfo.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/com/reco1l/andengine/DepthInfo.kt b/src/com/reco1l/andengine/DepthInfo.kt index 10e01097b..697bf103d 100644 --- a/src/com/reco1l/andengine/DepthInfo.kt +++ b/src/com/reco1l/andengine/DepthInfo.kt @@ -3,12 +3,24 @@ package com.reco1l.andengine import org.anddev.andengine.opengl.util.GLHelper import javax.microedition.khronos.opengles.GL10 +/** + * Information about how to behave with the depth buffer. + */ data class DepthInfo( + /** + * The depth function to use. + */ val function: DepthFunction, + /** + * Whether to write to the depth buffer. + */ val mask: Boolean, + /** + * Whether to clear the depth buffer. + */ val clear: Boolean ) { From 98d4df38ed0dbc950788bb91f9626a921884b5ba Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:19:24 -0300 Subject: [PATCH 32/73] Remove RoundedBox vertex buffer pre-initialization --- src/com/reco1l/andengine/shape/Box.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/shape/Box.kt b/src/com/reco1l/andengine/shape/Box.kt index 0450337fe..b8a30de39 100644 --- a/src/com/reco1l/andengine/shape/Box.kt +++ b/src/com/reco1l/andengine/shape/Box.kt @@ -59,7 +59,7 @@ open class Box : ExtendedEntity(vertexBuffer = BoxVertexBuffer()) { } -open class RoundedBox(segmentsPerArc: Int = 10) : ExtendedEntity(RoundedBoxVertexBuffer(segmentsPerArc)) { +open class RoundedBox : ExtendedEntity() { /** * The corner radius of the rectangle. From 7d8a720fd4b45a995dbb2b32b59afcbb2ff5217f Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:20:22 -0300 Subject: [PATCH 33/73] Register touch area to all `Scene` types --- src/com/reco1l/andengine/ExtendedEntity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index fc759ef0a..620906199 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -368,7 +368,7 @@ abstract class ExtendedEntity( override fun setParent(pEntity: IEntity?) { (parent as? Scene)?.unregisterTouchArea(this) super.setParent(pEntity) - (pEntity as? ExtendedScene)?.registerTouchArea(this) + (pEntity as? Scene)?.registerTouchArea(this) } From f37d0e3bb0700f7b8d90bf326bc1bb479e63f626 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:24:18 -0300 Subject: [PATCH 34/73] Inherit colors only if parents are of type `ExtendedEntity` --- src/com/reco1l/andengine/ExtendedEntity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 620906199..42285afec 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -472,7 +472,7 @@ abstract class ExtendedEntity( if (inheritColor) { var parent = parent - while (parent != null) { + while (parent is ExtendedEntity && parent.inheritColor) { red *= parent.red green *= parent.green From 11db3197cf9b53867f01d6fd1ccee7b880d815d2 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:25:09 -0300 Subject: [PATCH 35/73] Propagate input events along children in ExtendedEntity --- src/com/reco1l/andengine/ExtendedEntity.kt | 30 +++++++++++++++++++ .../reco1l/andengine/container/Container.kt | 19 ------------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 42285afec..e8b1eb74e 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -856,6 +856,36 @@ abstract class ExtendedEntity( return modifier } + + // Input + + override fun onAreaTouched( + event: TouchEvent, + localX: Float, + localY: Float + ): Boolean { + + try { + for (i in childCount - 1 downTo 0) { + val child = getChild(i) + + val transformedX = localX - child.getDrawX() + val transformedY = localY - child.getDrawY() + + if (child is ITouchArea && child.contains(transformedX, transformedY)) { + + if (child.onAreaTouched(event, transformedX, transformedY)) { + return true + } + } + } + } catch (e: IndexOutOfBoundsException) { + Log.e("ExtendedEntity", "A child entity was removed during touch event propagation.", e) + } + + return false + } + } diff --git a/src/com/reco1l/andengine/container/Container.kt b/src/com/reco1l/andengine/container/Container.kt index b320fe566..822f8452c 100644 --- a/src/com/reco1l/andengine/container/Container.kt +++ b/src/com/reco1l/andengine/container/Container.kt @@ -166,25 +166,6 @@ open class Container : ExtendedEntity() { override fun onUpdateVertexBuffer() {} override fun drawVertices(pGL: GL10, pCamera: Camera) {} - - // Input - - override fun onAreaTouched(event: TouchEvent, localX: Float, localY: Float): Boolean { - - if (mChildren != null) { - try { - mChildren.fastForEach { - if (it is ITouchArea && it.contains(localX, localY)) { - return it.onAreaTouched(event, localX, localY) - } - } - } catch (e: IndexOutOfBoundsException) { - Log.e("Container", "A child entity was removed during touch event propagation.") - } - } - - return false - } } From 5693ba355c601cccf846fbf84cb4bb13908b04f3 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:25:46 -0300 Subject: [PATCH 36/73] Use `Vector2` to represent entities anchor and origin properties --- src/com/reco1l/andengine/Anchor.kt | 34 +++-- src/com/reco1l/andengine/ExtendedEntity.kt | 142 +++++++++------------ 2 files changed, 83 insertions(+), 93 deletions(-) diff --git a/src/com/reco1l/andengine/Anchor.kt b/src/com/reco1l/andengine/Anchor.kt index e3eaa05d8..448d33638 100644 --- a/src/com/reco1l/andengine/Anchor.kt +++ b/src/com/reco1l/andengine/Anchor.kt @@ -1,26 +1,34 @@ package com.reco1l.andengine -/** - * The anchor points in the range of [0, 1]. - */ -enum class Anchor(val factorX: Float, val factorY: Float) { +import com.rian.osu.math.Vector2 - TopLeft(0f, 0f), +object Anchor { - TopCenter(0.5f, 0f), + @JvmField + val TopLeft = Vector2(0f, 0f) - TopRight(1f, 0f), + @JvmField + val TopCenter = Vector2(0.5f, 0f) - CenterLeft(0f, 0.5f), + @JvmField + val TopRight = Vector2(1f, 0f) - Center(0.5f, 0.5f), + @JvmField + val CenterLeft = Vector2(0f, 0.5f) - CenterRight(1f, 0.5f), + @JvmField + val Center = Vector2(0.5f, 0.5f) - BottomLeft(0f, 1f), + @JvmField + val CenterRight = Vector2(1f, 0.5f) - BottomCenter(0.5f, 1f), + @JvmField + val BottomLeft = Vector2(0f, 1f) - BottomRight(1f, 1f) + @JvmField + val BottomCenter = Vector2(0.5f, 1f) + + @JvmField + val BottomRight = Vector2(1f, 1f) } \ No newline at end of file diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index e8b1eb74e..2dde6a853 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,16 +4,18 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* +import com.rian.osu.math.Vector2 import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.scene.CameraScene import org.anddev.andengine.entity.scene.Scene +import org.anddev.andengine.entity.scene.Scene.ITouchArea import org.anddev.andengine.entity.shape.* +import org.anddev.andengine.input.touch.TouchEvent import org.anddev.andengine.opengl.util.* import org.anddev.andengine.opengl.vertex.* import org.anddev.andengine.util.Transformation import javax.microedition.khronos.opengles.* -import javax.microedition.khronos.opengles.GL10.* /** @@ -31,7 +33,7 @@ abstract class ExtendedEntity( * Determines which axes the entity should automatically adjust its size to. * * In this case the size will equal to the content size of the entity. Some - * types of entities requieres the user to manually set the size, in those + * types of entities requires the user to manually set the size, in those * cases this property might be ignored. */ open var autoSizeAxes = Axes.None @@ -119,9 +121,9 @@ abstract class ExtendedEntity( } /** - * The origin factor of the entity in the X axis. + * Where the entity should be anchored in the parent. */ - open var originX = 0f + open var anchor = Anchor.TopLeft set(value) { if (field != value) { field = value @@ -130,37 +132,9 @@ abstract class ExtendedEntity( } /** - * The origin factor of the entity in the Y axis. + * Where the entity's origin should be. */ - open var originY = 0f - set(value) { - if (field != value) { - field = value - invalidateTransformations() - } - } - - /** - * The anchor factor of the entity in the X axis. - * This is used to determine the position of the entity in a container. - * - * Note: This will not take effect if the entity is not a child of a [Container]. - */ - open var anchorX = 0f - set(value) { - if (field != value) { - field = value - invalidateTransformations() - } - } - - /** - * The anchor factor of the entity in the Y axis. - * This is used to determine the position of the entity in a container. - * - * Note: This will not take effect if the entity is not a child of a [Container]. - */ - open var anchorY = 0f + open var origin = Anchor.TopLeft set(value) { if (field != value) { field = value @@ -319,42 +293,6 @@ abstract class ExtendedEntity( return y + totalOffsetY } - /** - * The offset applied to the X axis according to the origin factor. - */ - open val originOffsetX: Float - get() = -(drawWidth * originX) - - /** - * The offset applied to the Y axis according to the origin factor. - */ - open val originOffsetY: Float - get() = -(drawHeight * originY) - - /** - * The offset applied to the X axis according to the anchor factor. - */ - open val anchorOffsetX: Float - get() = getParentWidth() * anchorX - - /** - * The offset applied to the Y axis according to the anchor factor. - */ - open val anchorOffsetY: Float - get() = getParentHeight() * anchorY - - /** - * The total offset applied to the X axis. - */ - open val totalOffsetX - get() = originOffsetX + anchorOffsetX + translationX - - /** - * The total offset applied to the Y axis. - */ - open val totalOffsetY - get() = originOffsetY + anchorOffsetY + translationY - private var width = 0f @@ -374,14 +312,14 @@ abstract class ExtendedEntity( // Positions - open fun setAnchor(anchor: Anchor) { - anchorX = anchor.factorX - anchorY = anchor.factorY + open fun setAnchor(value: Vector2): ExtendedEntity { + anchor = value + return this } - open fun setOrigin(origin: Anchor) { - originX = origin.factorX - originY = origin.factorY + open fun setOrigin(value: Vector2): ExtendedEntity { + origin = value + return this } fun setRelativePosition(x: Float, y: Float) { @@ -443,8 +381,8 @@ abstract class ExtendedEntity( override fun applyRotation(pGL: GL10) { // This will ensure getSceneCenterCoordinates() applies the correct transformation. - mRotationCenterX = drawWidth * originX - mRotationCenterY = drawHeight * originY + mRotationCenterX = -originOffsetX + mRotationCenterY = -originOffsetY if (rotation != 0f) { pGL.glRotatef(rotation, 0f, 0f, 1f) @@ -454,8 +392,8 @@ abstract class ExtendedEntity( override fun applyScale(pGL: GL10) { // This will ensure getSceneCenterCoordinates() applies the correct transformation. - mScaleCenterX = drawWidth * originX - mScaleCenterY = drawHeight * originY + mScaleCenterX = -originOffsetX + mScaleCenterY = -originOffsetY if (scaleX != 1f || scaleY != 1f) { pGL.glScalef(scaleX, scaleY, 1f) @@ -889,6 +827,42 @@ abstract class ExtendedEntity( } +/** + * The total offset applied to the X axis. + */ +val ExtendedEntity.totalOffsetX + get() = originOffsetX + anchorOffsetX + translationX + +/** + * The total offset applied to the Y axis. + */ +val ExtendedEntity.totalOffsetY + get() = originOffsetY + anchorOffsetY + translationY + +/** + * The offset applied to the X axis according to the anchor factor. + */ +val ExtendedEntity.anchorOffsetX: Float + get() = getParentWidth() * anchor.x + +/** + * The offset applied to the Y axis according to the anchor factor. + */ +val ExtendedEntity.anchorOffsetY: Float + get() = getParentHeight() * anchor.y + +/** + * The offset applied to the X axis according to the origin factor. + */ +val ExtendedEntity.originOffsetX: Float + get() = -(drawWidth * origin.y) + +/** + * The offset applied to the Y axis according to the origin factor. + */ +val ExtendedEntity.originOffsetY: Float + get() = -(drawHeight * origin.y) + /** * Returns the width of the parent entity. */ @@ -945,3 +919,11 @@ fun IEntity.getDrawY(): Float = when (this) { else -> 0f } +/** + * Attaches the entity to a parent. + */ +infix fun T.attachTo(parent: IEntity): T { + parent.attachChild(this) + return this +} + From 88dc64e133b6ea03b16774f6326f2cd9f19ec683 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 16:38:34 -0300 Subject: [PATCH 37/73] Fix compilation errors --- src/com/reco1l/andengine/ExtendedEntity.kt | 12 +--------- .../container/ConstraintContainer.kt | 4 ++-- src/com/reco1l/osu/hitobjects/FollowPoints.kt | 2 +- src/com/reco1l/osu/hitobjects/SliderTicks.kt | 4 ++-- src/com/reco1l/osu/playfield/CirclePiece.kt | 17 +++++++------ .../osu/playfield/CircularSongProgress.kt | 20 ++++++++-------- src/com/reco1l/osu/playfield/Counters.kt | 24 +++++++++---------- src/com/reco1l/osu/playfield/HealthBar.kt | 6 ++--- 8 files changed, 39 insertions(+), 50 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 2dde6a853..9c5216e6c 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -312,16 +312,6 @@ abstract class ExtendedEntity( // Positions - open fun setAnchor(value: Vector2): ExtendedEntity { - anchor = value - return this - } - - open fun setOrigin(value: Vector2): ExtendedEntity { - origin = value - return this - } - fun setRelativePosition(x: Float, y: Float) { relativePositionAxes = Axes.Both setPosition(x, y) @@ -855,7 +845,7 @@ val ExtendedEntity.anchorOffsetY: Float * The offset applied to the X axis according to the origin factor. */ val ExtendedEntity.originOffsetX: Float - get() = -(drawWidth * origin.y) + get() = -(drawWidth * origin.x) /** * The offset applied to the Y axis according to the origin factor. diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index e13699c94..31d7f6f04 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -20,7 +20,7 @@ class ConstraintContainer : Container() { val target = constraints[child] ?: this val targetX = target.getDrawX() - val anchorOffsetX = target.getDrawWidth() * child.anchorX + val anchorOffsetX = target.getDrawWidth() * child.anchor.x var childX = child.x @@ -38,7 +38,7 @@ class ConstraintContainer : Container() { val target = constraints[child] ?: this val targetY = target.getDrawY() - val anchorOffsetY = target.getDrawHeight() * child.anchorY + val anchorOffsetY = target.getDrawHeight() * child.anchor.y var childY = child.y diff --git a/src/com/reco1l/osu/hitobjects/FollowPoints.kt b/src/com/reco1l/osu/hitobjects/FollowPoints.kt index 81d604db1..b604d6666 100644 --- a/src/com/reco1l/osu/hitobjects/FollowPoints.kt +++ b/src/com/reco1l/osu/hitobjects/FollowPoints.kt @@ -117,8 +117,8 @@ object FollowPointConnection { fp.clearEntityModifiers() fp.setPosition(pointStartX, pointStartY) - fp.setOrigin(Anchor.Center) fp.setScale(1.5f * scale) + fp.origin = Anchor.Center fp.rotation = rotation fp.alpha = 0f diff --git a/src/com/reco1l/osu/hitobjects/SliderTicks.kt b/src/com/reco1l/osu/hitobjects/SliderTicks.kt index 1b852a846..a87ac6d91 100644 --- a/src/com/reco1l/osu/hitobjects/SliderTicks.kt +++ b/src/com/reco1l/osu/hitobjects/SliderTicks.kt @@ -1,5 +1,6 @@ package com.reco1l.osu.hitobjects +import com.reco1l.andengine.Anchor import com.reco1l.andengine.container.* import com.reco1l.andengine.sprite.* import com.reco1l.framework.* @@ -43,8 +44,7 @@ class SliderTickSprite : ExtendedSprite() { init { textureRegion = ResourceManager.getInstance().getTexture("sliderscorepoint") - originX = 0.5f - originY = 0.5f + origin = Anchor.Center } override fun onDetached() { diff --git a/src/com/reco1l/osu/playfield/CirclePiece.kt b/src/com/reco1l/osu/playfield/CirclePiece.kt index b58a6d4c2..48c3d9afe 100644 --- a/src/com/reco1l/osu/playfield/CirclePiece.kt +++ b/src/com/reco1l/osu/playfield/CirclePiece.kt @@ -3,6 +3,7 @@ package com.reco1l.osu.playfield import com.reco1l.andengine.* import com.reco1l.andengine.container.* import com.reco1l.andengine.sprite.* +import com.rian.osu.math.Vector2 import ru.nsu.ccfit.zuev.osu.* import ru.nsu.ccfit.zuev.skins.* @@ -14,15 +15,13 @@ open class CirclePiece( ) : Container() { - override var originX = 0.5f - - override var originY = 0.5f + override var origin = Anchor.Center private val circle = ExtendedSprite().also { - it.setOrigin(Anchor.Center) - it.setAnchor(Anchor.Center) + it.origin = Anchor.Center + it.anchor = Anchor.Center it.textureRegion = ResourceManager.getInstance().getTexture(circleTexture) attachChild(it) @@ -30,8 +29,8 @@ open class CirclePiece( private val overlay = ExtendedSprite().also { - it.setOrigin(Anchor.Center) - it.setAnchor(Anchor.Center) + it.origin = Anchor.Center + it.anchor = Anchor.Center it.textureRegion = ResourceManager.getInstance().getTexture(overlayTexture) attachChild(it) @@ -48,8 +47,8 @@ class NumberedCirclePiece(circleTexture: String, overlayTexture: String) : Circl private val number = SpriteFont(OsuSkin.get().hitCirclePrefix).also { - it.setOrigin(Anchor.Center) - it.setAnchor(Anchor.Center) + it.origin = Anchor.Center + it.anchor = Anchor.Center it.spacing = -OsuSkin.get().hitCircleOverlap attachChild(it) diff --git a/src/com/reco1l/osu/playfield/CircularSongProgress.kt b/src/com/reco1l/osu/playfield/CircularSongProgress.kt index d955ab748..1da0373e3 100644 --- a/src/com/reco1l/osu/playfield/CircularSongProgress.kt +++ b/src/com/reco1l/osu/playfield/CircularSongProgress.kt @@ -21,8 +21,8 @@ class CircularSongProgress : Container() { Circle().also { clear -> clear.setSize(30f, 30f) - clear.setAnchor(Anchor.Center) - clear.setOrigin(Anchor.Center) + clear.anchor = Anchor.Center + clear.origin = Anchor.Center clear.color = ColorARGB.Transparent clear.depthInfo = DepthInfo.Clear @@ -32,8 +32,8 @@ class CircularSongProgress : Container() { Circle().also { background -> background.setSize(33f, 33f) - background.setAnchor(Anchor.Center) - background.setOrigin(Anchor.Center) + background.anchor = Anchor.Center + background.origin = Anchor.Center background.color = ColorARGB.White background.depthInfo = DepthInfo.Default @@ -43,8 +43,8 @@ class CircularSongProgress : Container() { circularProgress = Circle().also { progress -> progress.setSize(30f, 30f) - progress.setAnchor(Anchor.Center) - progress.setOrigin(Anchor.Center) + progress.anchor = Anchor.Center + progress.origin = Anchor.Center progress.alpha = 0.6f attachChild(progress) @@ -54,8 +54,8 @@ class CircularSongProgress : Container() { Circle().also { dot -> dot.setSize(4f, 4f) - dot.setAnchor(Anchor.Center) - dot.setOrigin(Anchor.Center) + dot.anchor = Anchor.Center + dot.origin = Anchor.Center dot.color = ColorARGB.White attachChild(dot) @@ -63,8 +63,8 @@ class CircularSongProgress : Container() { onMeasureContentSize() - setAnchor(Anchor.TopRight) - setOrigin(Anchor.CenterRight) + anchor = Anchor.TopRight + origin = Anchor.CenterRight } diff --git a/src/com/reco1l/osu/playfield/Counters.kt b/src/com/reco1l/osu/playfield/Counters.kt index 3d9e15cde..aa3aa380a 100644 --- a/src/com/reco1l/osu/playfield/Counters.kt +++ b/src/com/reco1l/osu/playfield/Counters.kt @@ -17,8 +17,8 @@ class ScoreCounter : SpriteFont(OsuSkin.get().scorePrefix) { init { - setAnchor(Anchor.TopRight) - setOrigin(Anchor.TopRight) + anchor = Anchor.TopRight + origin = Anchor.TopRight setScale(0.96f) x = -10f @@ -35,8 +35,8 @@ class ScoreCounter : SpriteFont(OsuSkin.get().scorePrefix) { class PPCounter(private val algorithm: DifficultyAlgorithm) : SpriteFont(OsuSkin.get().scorePrefix) { init { - setAnchor(Anchor.TopRight) - setOrigin(Anchor.TopRight) + anchor = Anchor.TopRight + origin = Anchor.TopRight setScale(0.6f * 0.96f) setValue(0.0) } @@ -55,8 +55,8 @@ class AccuracyCounter : SpriteFont(OsuSkin.get().scorePrefix) { init { - setAnchor(Anchor.TopRight) - setOrigin(Anchor.TopRight) + anchor = Anchor.TopRight + origin = Anchor.TopRight setScale(0.6f * 0.96f) setPosition(-17f, 9f) text = "100.00%" @@ -77,8 +77,8 @@ class ComboCounter : Container() { it.alpha = 0f it.text = "0x" - it.setAnchor(Anchor.BottomLeft) - it.setOrigin(Anchor.BottomLeft) + it.anchor = Anchor.BottomLeft + it.origin = Anchor.BottomLeft // In stable, the bigger pop out scales a bit to the left it.translationX = -3f @@ -94,8 +94,8 @@ class ComboCounter : Container() { private val displayedCountTextSprite = SpriteFont(OsuSkin.get().comboPrefix).also { it.text = "0x" - it.setAnchor(Anchor.BottomLeft) - it.setOrigin(Anchor.BottomLeft) + it.anchor = Anchor.BottomLeft + it.origin = Anchor.BottomLeft it.translationY = -(FONT_HEIGHT_RATIO * it.drawHeight + VERTICAL_OFFSET) @@ -114,8 +114,8 @@ class ComboCounter : Container() { init { - setAnchor(Anchor.BottomLeft) - setOrigin(Anchor.BottomLeft) + anchor = Anchor.BottomLeft + origin = Anchor.BottomLeft setPosition(10f, -10f) setScale(1.28f) } diff --git a/src/com/reco1l/osu/playfield/HealthBar.kt b/src/com/reco1l/osu/playfield/HealthBar.kt index 31849ed08..37f74bce9 100644 --- a/src/com/reco1l/osu/playfield/HealthBar.kt +++ b/src/com/reco1l/osu/playfield/HealthBar.kt @@ -49,7 +49,7 @@ class HealthBar(private val statistics: StatisticV2) : Container() { attachChild(ExtendedSprite().apply { textureRegion = backgroundTexture }) fillClear = Box() - fillClear.setOrigin(Anchor.TopRight) + fillClear.origin = Anchor.TopRight fillClear.depthInfo = DepthInfo.Clear fillClear.alpha = 0f attachChild(fillClear) @@ -60,11 +60,11 @@ class HealthBar(private val statistics: StatisticV2) : Container() { attachChild(fill) marker = ExtendedSprite() - marker.setOrigin(Anchor.Center) + marker.origin = Anchor.Center attachChild(marker) explode = ExtendedSprite() - explode.setOrigin(Anchor.Center) + explode.origin = Anchor.Center explode.blendingFunction = BlendingFunction.Additive explode.alpha = 0f attachChild(explode) From 964949e117a205c624f4119e76794ed07ca6ec3d Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 22:54:35 -0300 Subject: [PATCH 38/73] Always inherit colors --- src/com/reco1l/andengine/ExtendedEntity.kt | 44 +++++++++++++--------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 9c5216e6c..b721c9ff6 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -174,6 +174,21 @@ abstract class ExtendedEntity( */ open var depthInfo: DepthInfo? = null + /** + * The blending information of the entity. + */ + open var blendInfo: BlendInfo? = null + set(value) { + if (field != value) { + field = value + + if (value != null) { + mSourceBlendFunction = value.function.source + mDestinationBlendFunction = value.function.destination + } + } + } + /** * The color of the entity boxed in a [ColorARGB] object. */ @@ -186,10 +201,6 @@ abstract class ExtendedEntity( mAlpha = value.alpha } - /** - * Whether the color should be inherited from all the parents in the hierarchy. - */ - open var inheritColor = true /** * The color blending function. @@ -397,23 +408,20 @@ abstract class ExtendedEntity( var blue = mBlue var alpha = mAlpha - if (inheritColor) { + var parent = parent + while (parent != null) { - var parent = parent - while (parent is ExtendedEntity && parent.inheritColor) { + red *= parent.red + green *= parent.green + blue *= parent.blue + alpha *= parent.alpha - red *= parent.red - green *= parent.green - blue *= parent.blue - alpha *= parent.alpha - - // We'll assume at this point there's no need to keep multiplying. - if (red == 0f && green == 0f && blue == 0f && alpha == 0f) { - break - } - - parent = parent.parent + // We'll assume at this point there's no need to keep multiplying. + if (red == 0f && green == 0f && blue == 0f && alpha == 0f) { + break } + + parent = parent.parent } GLHelper.setColor(pGL, red, green, blue, alpha) From 12b2d4a1d372f356ecbd186464bcf62609e20f77 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 23:00:09 -0300 Subject: [PATCH 39/73] Introduce BlendInfo --- src/com/reco1l/andengine/BlendInfo.kt | 59 ++++++++++++++++++++++ src/com/reco1l/andengine/ExtendedEntity.kt | 37 +++----------- src/com/reco1l/osu/playfield/HealthBar.kt | 7 +-- 3 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 src/com/reco1l/andengine/BlendInfo.kt diff --git a/src/com/reco1l/andengine/BlendInfo.kt b/src/com/reco1l/andengine/BlendInfo.kt new file mode 100644 index 000000000..e3776b639 --- /dev/null +++ b/src/com/reco1l/andengine/BlendInfo.kt @@ -0,0 +1,59 @@ +package com.reco1l.andengine + +import javax.microedition.khronos.opengles.GL10 + +data class BlendInfo( + + /** + * The blending function to use. + */ + var function: BlendingFunction, + + /** + * Whether to mask the red channel. + */ + var redMask: Boolean = true, + + /** + * Whether to mask the green channel. + */ + var greenMask: Boolean = true, + + /** + * Whether to mask the blue channel. + */ + var blueMask: Boolean = true, + + /** + * Whether to mask the alpha channel. + */ + var alphaMask: Boolean = true, + + /** + * Whether to clear the color buffer. + */ + var clear: Boolean = false + +) { + + fun apply(gl: GL10) { + + gl.glColorMask(redMask, greenMask, blueMask, alphaMask) + + if (function != BlendingFunction.Inherit) { + gl.glBlendFunc(function.source, function.destination) + } + + if (clear) { + gl.glClear(GL10.GL_COLOR_BUFFER_BIT) + } + } + + + companion object { + + val Inherit = BlendInfo(BlendingFunction.Inherit) + + } + +} \ No newline at end of file diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index b721c9ff6..43bdb7531 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -201,22 +201,6 @@ abstract class ExtendedEntity( mAlpha = value.alpha } - - /** - * The color blending function. - */ - open var blendingFunction: BlendingFunction? = null - set(value) { - if (field != value) { - field = value - - if (value != null) { - mSourceBlendFunction = value.source - mDestinationBlendFunction = value.destination - } - } - } - /** * The width of the content inside the entity. */ @@ -429,22 +413,13 @@ abstract class ExtendedEntity( protected open fun applyBlending(pGL: GL10) { - // If there's a blending function set, apply it instead of the engine's method. - val blendingFunction = blendingFunction - - if (blendingFunction != null) { + blendInfo?.apply(pGL) ?: GLHelper.blendFunction(pGL, mSourceBlendFunction, mDestinationBlendFunction) - val parent = parent as? ExtendedEntity - - // If the blending function is set to inherit, apply the parent's blending function. - if (blendingFunction == BlendingFunction.Inherit && parent != null) { + if (blendInfo?.function == BlendingFunction.Inherit) { + val parent = parent + if (parent is ExtendedEntity) { GLHelper.blendFunction(pGL, parent.mSourceBlendFunction, parent.mDestinationBlendFunction) - } else { - GLHelper.blendFunction(pGL, blendingFunction.source, blendingFunction.destination) } - - } else { - GLHelper.blendFunction(pGL, mSourceBlendFunction, mDestinationBlendFunction) } } @@ -778,7 +753,9 @@ abstract class ExtendedEntity( // Transformation override fun setBlendFunction(pSourceBlendFunction: Int, pDestinationBlendFunction: Int) { - blendingFunction = null + if (blendInfo != null) { + Log.w("ExtendedEntity", "BlendInfo is set, use blendInfo property to change the blending function.") + } super.setBlendFunction(pSourceBlendFunction, pDestinationBlendFunction) } diff --git a/src/com/reco1l/osu/playfield/HealthBar.kt b/src/com/reco1l/osu/playfield/HealthBar.kt index 37f74bce9..a764d516d 100644 --- a/src/com/reco1l/osu/playfield/HealthBar.kt +++ b/src/com/reco1l/osu/playfield/HealthBar.kt @@ -61,11 +61,12 @@ class HealthBar(private val statistics: StatisticV2) : Container() { marker = ExtendedSprite() marker.origin = Anchor.Center + marker.blendInfo = BlendInfo(BlendingFunction.Additive) attachChild(marker) explode = ExtendedSprite() explode.origin = Anchor.Center - explode.blendingFunction = BlendingFunction.Additive + explode.blendInfo = BlendInfo(BlendingFunction.Additive) explode.alpha = 0f attachChild(explode) @@ -116,7 +117,7 @@ class HealthBar(private val statistics: StatisticV2) : Container() { fill.color = color marker.color = color - marker.blendingFunction = if (statistics.hp < EPIC_CUTOFF) BlendingFunction.Inherit else BlendingFunction.Additive + marker.blendInfo?.function = if (statistics.hp < EPIC_CUTOFF) BlendingFunction.Inherit else BlendingFunction.Additive } else { @@ -139,7 +140,7 @@ class HealthBar(private val statistics: StatisticV2) : Container() { bulge() explode.clearEntityModifiers() - explode.blendingFunction = if (isEpic) BlendingFunction.Additive else BlendingFunction.Inherit + explode.blendInfo?.function = if (isEpic) BlendingFunction.Additive else BlendingFunction.Inherit explode.alpha = 1f explode.setScale(1f) From 4f3f39f659146950529451f3fae8e07102cb5427 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 23:18:38 -0300 Subject: [PATCH 40/73] Allow to use custom rotation and scale center / Reverting back old behavior --- src/com/reco1l/andengine/ExtendedEntity.kt | 109 +++++++++++---------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 43bdb7531..6f2ce5d1d 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,7 +4,6 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* -import com.rian.osu.math.Vector2 import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.scene.CameraScene @@ -138,6 +137,12 @@ abstract class ExtendedEntity( set(value) { if (field != value) { field = value + + mRotationCenterX = origin.x + mRotationCenterY = origin.y + mScaleCenterX = origin.x + mScaleCenterY = origin.y + invalidateTransformations() } } @@ -365,22 +370,36 @@ abstract class ExtendedEntity( override fun applyRotation(pGL: GL10) { - // This will ensure getSceneCenterCoordinates() applies the correct transformation. - mRotationCenterX = -originOffsetX - mRotationCenterY = -originOffsetY + if (rotation == 0f) { + return + } + + val offsetX = drawWidth * mRotationCenterX + val offsetY = drawHeight * mRotationCenterY - if (rotation != 0f) { + if (offsetX > 0f || offsetY > 0f) { + pGL.glTranslatef(offsetX, offsetY, 0f) + pGL.glRotatef(rotation, 0f, 0f, 1f) + pGL.glTranslatef(-offsetX, -offsetY, 0f) + } else { pGL.glRotatef(rotation, 0f, 0f, 1f) } } override fun applyScale(pGL: GL10) { - // This will ensure getSceneCenterCoordinates() applies the correct transformation. - mScaleCenterX = -originOffsetX - mScaleCenterY = -originOffsetY + if (scaleX == 1f && scaleY == 1f) { + return + } + + val offsetX = drawWidth * mScaleCenterX + val offsetY = drawHeight * mScaleCenterY - if (scaleX != 1f || scaleY != 1f) { + if (offsetX > 0f || offsetY > 0f) { + pGL.glTranslatef(offsetX, offsetY, 0f) + pGL.glScalef(scaleX, scaleY, 1f) + pGL.glTranslatef(-offsetX, -offsetY, 0f) + } else { pGL.glScalef(scaleX, scaleY, 1f) } } @@ -425,14 +444,8 @@ abstract class ExtendedEntity( override fun onApplyTransformations(pGL: GL10, camera: Camera) { applyTranslation(pGL, camera) - - if (rotation != 0f || scaleX != 1f || scaleY != 1f) { - pGL.glTranslatef(-originOffsetX, -originOffsetY, 0f) - applyRotation(pGL) - applyScale(pGL) - pGL.glTranslatef(originOffsetX, originOffsetY, 0f) - } - + applyRotation(pGL) + applyScale(pGL) applyColor(pGL) applyBlending(pGL) } @@ -649,24 +662,6 @@ abstract class ExtendedEntity( @Deprecated("Base height is not preserved in ExtendedEntity, use getHeight() instead.") override fun getBaseHeight() = height - @Deprecated("Rotation center is determined by the entity's origin, use setOrigin() instead.") - final override fun setRotationCenter(pRotationCenterX: Float, pRotationCenterY: Float) {} - - @Deprecated("Rotation center is determined by the entity's origin, use setOrigin() instead.") - final override fun setRotationCenterX(pRotationCenterX: Float) {} - - @Deprecated("Rotation center is determined by the entity's origin, use setOrigin() instead.") - final override fun setRotationCenterY(pRotationCenterY: Float) {} - - @Deprecated("Scale center is determined by the entity's origin, use setOrigin() instead.") - final override fun setScaleCenter(pScaleCenterX: Float, pScaleCenterY: Float) {} - - @Deprecated("Scale center is determined by the entity's origin, use setOrigin() instead.") - final override fun setScaleCenterX(pScaleCenterX: Float) {} - - @Deprecated("Scale center is determined by the entity's origin, use setOrigin() instead.") - final override fun setScaleCenterY(pScaleCenterY: Float) {} - // Collision @@ -698,18 +693,22 @@ abstract class ExtendedEntity( if (mLocalToParentTransformationDirty) { mLocalToParentTransformation.setToIdentity() - if (scaleX != 1f || scaleY != 1f || rotation != 0f) { - mLocalToParentTransformation.postTranslate(originOffsetX, originOffsetY) + if (scaleX != 1f || scaleY != 1f) { + val offsetX = drawWidth * mScaleCenterX + val offsetY = drawHeight * mScaleCenterY - if (scaleX != 1f || scaleY != 1f) { - mLocalToParentTransformation.postScale(scaleX, scaleY) - } + mLocalToParentTransformation.postTranslate(-offsetX, -offsetY) + mLocalToParentTransformation.postScale(scaleX, scaleY) + mLocalToParentTransformation.postTranslate(offsetX, offsetY) + } - if (rotation != 0f) { - mLocalToParentTransformation.postRotate(rotation) - } + if (rotation != 0f) { + val offsetX = drawWidth * mRotationCenterX + val offsetY = drawHeight * mRotationCenterY - mLocalToParentTransformation.postTranslate(-originOffsetX, -originOffsetY) + mLocalToParentTransformation.postTranslate(-offsetX, -offsetY) + mLocalToParentTransformation.postRotate(rotation) + mLocalToParentTransformation.postTranslate(offsetX, offsetY) } mLocalToParentTransformation.postTranslate(drawX, drawY) @@ -729,18 +728,22 @@ abstract class ExtendedEntity( mParentToLocalTransformation.setToIdentity() mParentToLocalTransformation.postTranslate(-drawX, -drawY) - if (scaleX != 1f || scaleY != 1f || rotation != 0f) { - mParentToLocalTransformation.postTranslate(originOffsetX, originOffsetY) + if (scaleX != 1f || scaleY != 1f) { + val offsetX = drawWidth * mScaleCenterX + val offsetY = drawHeight * mScaleCenterY - if (rotation != 0f) { - mParentToLocalTransformation.postRotate(-rotation) - } + mParentToLocalTransformation.postTranslate(-offsetX, -offsetY) + mParentToLocalTransformation.postScale(1 / scaleX, 1 / scaleY) + mParentToLocalTransformation.postTranslate(offsetX, offsetY) + } - if (scaleX != 1f || scaleY != 1f) { - mParentToLocalTransformation.postScale(1 / scaleX, 1 / scaleY) - } + if (rotation != 0f) { + val offsetX = drawWidth * mRotationCenterX + val offsetY = drawHeight * mRotationCenterY - mParentToLocalTransformation.postTranslate(-originOffsetX, -originOffsetY) + mParentToLocalTransformation.postTranslate(-offsetX, -offsetY) + mParentToLocalTransformation.postRotate(-rotation) + mParentToLocalTransformation.postTranslate(offsetX, offsetY) } mParentToLocalTransformationDirty = false From 6821b776d1c93094a3f796792aac0cbee7f4b299 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 23:23:13 -0300 Subject: [PATCH 41/73] Revert "Register touch area to all `Scene` types" --- src/com/reco1l/andengine/ExtendedEntity.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 6f2ce5d1d..e3df2a714 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -304,9 +304,17 @@ abstract class ExtendedEntity( // Attachment override fun setParent(pEntity: IEntity?) { - (parent as? Scene)?.unregisterTouchArea(this) + + val parent = parent + if (parent is Scene) { + parent.unregisterTouchArea(this) + } + super.setParent(pEntity) - (pEntity as? Scene)?.registerTouchArea(this) + + if (pEntity is ExtendedScene) { + pEntity.registerTouchArea(this) + } } From e28c63081f4fb496cd6bf2bfed224cf63437c4d8 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Wed, 25 Dec 2024 23:29:57 -0300 Subject: [PATCH 42/73] Fix scale center not being applied properly in CirclePiece --- src/com/reco1l/osu/playfield/CirclePiece.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/osu/playfield/CirclePiece.kt b/src/com/reco1l/osu/playfield/CirclePiece.kt index 48c3d9afe..85a6a17d7 100644 --- a/src/com/reco1l/osu/playfield/CirclePiece.kt +++ b/src/com/reco1l/osu/playfield/CirclePiece.kt @@ -15,7 +15,9 @@ open class CirclePiece( ) : Container() { - override var origin = Anchor.Center + init { + origin = Anchor.Center + } private val circle = ExtendedSprite().also { From f5301c5085d21b297a954e77daf733152850e7ff Mon Sep 17 00:00:00 2001 From: Rian8337 <52914632+Rian8337@users.noreply.github.com> Date: Fri, 27 Dec 2024 00:35:27 +0800 Subject: [PATCH 43/73] Update some confusing and outdated comments --- src/com/reco1l/andengine/Axes.kt | 2 +- src/com/reco1l/andengine/ExtendedEntity.kt | 16 ++++++++-------- .../andengine/container/ConstraintContainer.kt | 4 ++-- .../andengine/container/ScrollableContainer.kt | 1 - src/com/reco1l/andengine/text/TextSprite.kt | 4 ++-- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/com/reco1l/andengine/Axes.kt b/src/com/reco1l/andengine/Axes.kt index 55f049a43..4b9b82bf4 100644 --- a/src/com/reco1l/andengine/Axes.kt +++ b/src/com/reco1l/andengine/Axes.kt @@ -27,7 +27,7 @@ enum class Axes { /** - * Whether this axis [Y] or [Both]. + * Whether this axis is [Y] or [Both]. */ val isVertical: Boolean get() = this == Y || this == Both diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index e3df2a714..ee747de86 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -68,11 +68,11 @@ abstract class ExtendedEntity( * * Example: * - * If relativeSizeAxes is set to [Axes.Both] and we set the size to 0.5, the entity's + * If [relativeSizeAxes] is set to [Axes.Both] and we set the size to 0.5, the entity's * size will be half the size of the parent. * - * Note: autoSizeAxes has priority over relativeSizeAxes. As for example if autoSizeAxes - * is set to [Axes.Both] and relativeSizeAxes is set to [Axes.Both], relativeSizeAxes + * Note: [autoSizeAxes] has priority over [relativeSizeAxes]. For example, if [autoSizeAxes] + * is set to [Axes.Both] and [relativeSizeAxes] is set to [Axes.Both], [relativeSizeAxes] * will be ignored. */ open var relativeSizeAxes = Axes.None @@ -108,7 +108,7 @@ abstract class ExtendedEntity( * * Example: * - * If relativePositionAxes is set to [Axes.Both] and we set the position to 0.5 for both axes, + * If [relativePositionAxes] is set to [Axes.Both] and we set the position to 0.5 for both axes, * the entity's position will be at the center of the parent. */ open var relativePositionAxes = Axes.None @@ -578,7 +578,7 @@ abstract class ExtendedEntity( /** * Sets a relative size for the entity. - * This will set the [relativeSizeAxes] property to [Axes.Both] automaticall. + * This will set the [relativeSizeAxes] property to [Axes.Both] automatically. */ fun setRelativeSize(width: Float, height: Float) { relativeSizeAxes = Axes.Both @@ -590,7 +590,7 @@ abstract class ExtendedEntity( * * Note: This will change the [autoSizeAxes] property to [Axes.None] automatically. * - * @return Whether the size of the entity was changed or not, this depends on the [autoSizeAxes] property. + * @return Whether the size of the entity was changed or not. */ open fun setSize(newWidth: Float, newHeight: Float): Boolean { @@ -692,6 +692,8 @@ abstract class ExtendedEntity( || drawY > pCamera.maxY || drawY + drawHeight < pCamera.minY } + // Transformation + override fun getLocalToParentTransformation(): Transformation { if (mLocalToParentTransformation == null) { @@ -761,8 +763,6 @@ abstract class ExtendedEntity( } - // Transformation - override fun setBlendFunction(pSourceBlendFunction: Int, pDestinationBlendFunction: Int) { if (blendInfo != null) { Log.w("ExtendedEntity", "BlendInfo is set, use blendInfo property to change the blending function.") diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index 31d7f6f04..40811844e 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -24,7 +24,7 @@ class ConstraintContainer : Container() { var childX = child.x - // Relative positions will be multiplied by the remaining space since the + // Relative positions will be multiplied by the remaining space from the // target's position to the edge of the container. if (child.relativePositionAxes.isHorizontal) { childX *= drawWidth - targetX @@ -42,7 +42,7 @@ class ConstraintContainer : Container() { var childY = child.y - // Relative positions will be multiplied by the remaining space since the + // Relative positions will be multiplied by the remaining space from the // target's position to the edge of the container. if (child.relativePositionAxes.isVertical) { childY *= drawHeight - targetY diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index 2db646dbf..28d2a77b3 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -294,7 +294,6 @@ open class ScrollableContainer : Container() { ACTION_MOVE -> { isDragging = true - // Coerce the delta values to the width and height of the container because the user can't scroll more than that. var deltaX = localX - initialX var deltaY = localY - initialY diff --git a/src/com/reco1l/andengine/text/TextSprite.kt b/src/com/reco1l/andengine/text/TextSprite.kt index d9a2ae2d9..29d2187e4 100644 --- a/src/com/reco1l/andengine/text/TextSprite.kt +++ b/src/com/reco1l/andengine/text/TextSprite.kt @@ -26,8 +26,8 @@ import kotlin.math.max /** * A sprite that displays text. * - * Differently from the original [Text] class, this is a sprite that pre-renders the entire text - * to a texture, it is not as efficient as the original [Text] class, but it is more flexible and + * Unlike [org.anddev.andengine.entity.text.Text], this is a sprite that pre-renders the entire text to a texture. + * It is not as efficient as [org.anddev.andengine.entity.text.Text], but it is more flexible and * allows for more customization. * * It is not recommended to use this on places where the text changes frequently, as it will From a8af4b73e3c78ce062682bf8708246628e557805 Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 26 Dec 2024 14:43:40 -0300 Subject: [PATCH 44/73] Make relativeSizeAxes compatible with autoSizeAxes --- src/com/reco1l/andengine/ExtendedEntity.kt | 60 +++------------------- 1 file changed, 6 insertions(+), 54 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index ee747de86..3b0f118cc 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -39,23 +39,6 @@ abstract class ExtendedEntity( set(value) { if (field != value) { field = value - - // Setting the opposite value for relativeSizeAxes to avoid conflicts. - if (relativeSizeAxes != Axes.None) { - - if (value == Axes.Both) { - relativeSizeAxes = Axes.None - } - - if (value == Axes.X && relativeSizeAxes == Axes.Y) { - relativeSizeAxes = Axes.Y - } - - if (value == Axes.Y && relativeSizeAxes == Axes.X) { - relativeSizeAxes = Axes.X - } - } - onContentSizeMeasured() } } @@ -79,23 +62,6 @@ abstract class ExtendedEntity( set(value) { if (field != value) { field = value - - // Setting the opposite value for autoSizeAxes to avoid conflicts. - if (autoSizeAxes != Axes.None) { - - if (value == Axes.Both) { - autoSizeAxes = Axes.None - } - - if (value == Axes.X && autoSizeAxes == Axes.Y) { - autoSizeAxes = Axes.Y - } - - if (value == Axes.Y && autoSizeAxes == Axes.X) { - autoSizeAxes = Axes.X - } - } - onContentSizeMeasured() } } @@ -320,11 +286,6 @@ abstract class ExtendedEntity( // Positions - fun setRelativePosition(x: Float, y: Float) { - relativePositionAxes = Axes.Both - setPosition(x, y) - } - override fun setPosition(x: Float, y: Float) { if (mX != x || mY != y) { mX = x @@ -576,15 +537,6 @@ abstract class ExtendedEntity( } - /** - * Sets a relative size for the entity. - * This will set the [relativeSizeAxes] property to [Axes.Both] automatically. - */ - fun setRelativeSize(width: Float, height: Float) { - relativeSizeAxes = Axes.Both - setSize(width, height) - } - /** * Sets the size of the entity. * @@ -595,8 +547,8 @@ abstract class ExtendedEntity( open fun setSize(newWidth: Float, newHeight: Float): Boolean { if (autoSizeAxes != Axes.None) { - Log.w("ExtendedEntity", "autoSizeAxes is set to ${autoSizeAxes.name} while changing the size manually.") - autoSizeAxes = Axes.None + Log.e("ExtendedEntity", "Cannot change the size manually while autoSizeAxes is set to ${autoSizeAxes.name}.") + return false } if (width != newWidth || height != newHeight) { @@ -618,8 +570,8 @@ abstract class ExtendedEntity( open fun setWidth(value: Float) { if (autoSizeAxes.isHorizontal) { - Log.w("ExtendedEntity", "autoSizeAxes is set to ${autoSizeAxes.name} while changing the width manually.") - autoSizeAxes = if (autoSizeAxes == Axes.Both) Axes.Y else Axes.None + Log.e("ExtendedEntity", "Cannot change the width manually while autoSizeAxes is set to ${autoSizeAxes.name}.") + return } if (width != value) { @@ -633,8 +585,8 @@ abstract class ExtendedEntity( open fun setHeight(value: Float) { if (autoSizeAxes.isVertical) { - Log.w("ExtendedEntity", "autoSizeAxes is set to ${autoSizeAxes.name} while changing the height manually.") - autoSizeAxes = if (autoSizeAxes == Axes.Both) Axes.X else Axes.None + Log.e("ExtendedEntity", "Cannot change the height manually while autoSizeAxes is set to ${autoSizeAxes.name}.") + return } if (height != value) { From c4fd6bfff7ca1353f75a379acf5eb93dbc4c826e Mon Sep 17 00:00:00 2001 From: Reco1l Date: Thu, 26 Dec 2024 14:44:18 -0300 Subject: [PATCH 45/73] Call value instead --- src/com/reco1l/andengine/ExtendedEntity.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 3b0f118cc..e32abb2cb 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -104,10 +104,10 @@ abstract class ExtendedEntity( if (field != value) { field = value - mRotationCenterX = origin.x - mRotationCenterY = origin.y - mScaleCenterX = origin.x - mScaleCenterY = origin.y + mRotationCenterX = value.x + mRotationCenterY = value.y + mScaleCenterX = value.x + mScaleCenterY = value.y invalidateTransformations() } From 3a9b59d8b04689650d6f6a7ab2ac94294bafa75d Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Thu, 26 Dec 2024 22:18:23 -0300 Subject: [PATCH 46/73] Introduce Padding for ExtendedEntity --- src/com/reco1l/andengine/Entities.kt | 105 ++++++++++++++ src/com/reco1l/andengine/ExtendedEntity.kt | 133 +++--------------- .../reco1l/andengine/container/Container.kt | 14 +- src/com/reco1l/framework/math/Vector4.kt | 89 ++++++++++++ 4 files changed, 222 insertions(+), 119 deletions(-) create mode 100644 src/com/reco1l/andengine/Entities.kt create mode 100644 src/com/reco1l/framework/math/Vector4.kt diff --git a/src/com/reco1l/andengine/Entities.kt b/src/com/reco1l/andengine/Entities.kt new file mode 100644 index 000000000..30ec3752b --- /dev/null +++ b/src/com/reco1l/andengine/Entities.kt @@ -0,0 +1,105 @@ +package com.reco1l.andengine + +import com.reco1l.framework.math.Vector4 +import org.anddev.andengine.entity.IEntity +import org.anddev.andengine.entity.shape.IShape + + +fun IEntity?.getPadding() = when (this) { + is ExtendedEntity -> padding + else -> Vector4.Zero +} + +fun IEntity?.getPaddedWidth() = when (this) { + is ExtendedEntity -> drawWidth - padding.horizontal + is IShape -> width + else -> 0f +} + +fun IEntity?.getPaddedHeight() = when (this) { + is ExtendedEntity -> drawHeight - padding.vertical + is IShape -> height + else -> 0f +} + + +/** + * The total offset applied to the X axis. + */ +val ExtendedEntity.totalOffsetX + get() = originOffsetX + anchorOffsetX + translationX + +/** + * The total offset applied to the Y axis. + */ +val ExtendedEntity.totalOffsetY + get() = originOffsetY + anchorOffsetY + translationY + +/** + * The offset applied to the X axis according to the anchor factor. + */ +val ExtendedEntity.anchorOffsetX: Float + get() = parent.getPaddedWidth() * anchor.x + +/** + * The offset applied to the Y axis according to the anchor factor. + */ +val ExtendedEntity.anchorOffsetY: Float + get() = parent.getPaddedHeight() * anchor.y + +/** + * The offset applied to the X axis according to the origin factor. + */ +val ExtendedEntity.originOffsetX: Float + get() = -(drawWidth * origin.x) + +/** + * The offset applied to the Y axis according to the origin factor. + */ +val ExtendedEntity.originOffsetY: Float + get() = -(drawHeight * origin.y) + + +/** + * Returns the draw width of the entity. + */ +fun IEntity?.getDrawWidth(): Float = when (this) { + is ExtendedEntity -> drawWidth + is IShape -> width + else -> 0f +} + +/** + * Returns the draw height of the entity. + */ +fun IEntity?.getDrawHeight(): Float = when (this) { + is ExtendedEntity -> drawHeight + is IShape -> height + else -> 0f +} + +/** + * Returns the draw X position of the entity. + */ +fun IEntity?.getDrawX(): Float = when (this) { + is ExtendedEntity -> drawX + is IShape -> x + else -> 0f +} + +/** + * Returns the draw Y position of the entity. + */ +fun IEntity?.getDrawY(): Float = when (this) { + is ExtendedEntity -> drawY + is IShape -> y + else -> 0f +} + +/** + * Attaches the entity to a parent. + */ +infix fun T.attachTo(parent: IEntity): T { + parent.attachChild(this) + return this +} \ No newline at end of file diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index e32abb2cb..34b84f5ce 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,9 +4,9 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* +import com.reco1l.framework.math.Vector4 import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* -import org.anddev.andengine.entity.scene.CameraScene import org.anddev.andengine.entity.scene.Scene import org.anddev.andengine.entity.scene.Scene.ITouchArea import org.anddev.andengine.entity.shape.* @@ -113,6 +113,17 @@ abstract class ExtendedEntity( } } + /** + * The padding of the entity. + */ + open var padding = Vector4.Zero + set(value) { + if (field != value) { + field = value + invalidateTransformations() + } + } + /** * The translation in the X axis. */ @@ -203,7 +214,7 @@ abstract class ExtendedEntity( open val drawWidth: Float get() { if (relativeSizeAxes.isHorizontal) { - return getParentWidth() * width + return parent.getPaddedWidth() * width } return width } @@ -217,7 +228,7 @@ abstract class ExtendedEntity( open val drawHeight: Float get() { if (relativeSizeAxes.isVertical) { - return getParentHeight() * height + return parent.getPaddedHeight() * height } return height } @@ -233,11 +244,12 @@ abstract class ExtendedEntity( return parent.getChildDrawX(this) } + var x = x if (relativePositionAxes.isHorizontal) { - return getParentWidth() * x + totalOffsetX + x *= parent.getPaddedWidth() } - return x + totalOffsetX + return parent.getPadding().left + x + totalOffsetX } @@ -252,11 +264,12 @@ abstract class ExtendedEntity( return parent.getChildDrawY(this) } + var y = y if (relativePositionAxes.isVertical) { - return getParentHeight() * y + totalOffsetY + y *= parent.getPaddedHeight() } - return y + totalOffsetY + return parent.getPadding().top + y + totalOffsetY } @@ -521,11 +534,11 @@ abstract class ExtendedEntity( if (contentWidth != width || contentHeight != height) { if (autoSizeAxes.isHorizontal) { - width = if (relativeSizeAxes.isHorizontal) contentWidth / getParentWidth() else contentWidth + width = if (relativeSizeAxes.isHorizontal) contentWidth / parent.getPaddedWidth() else contentWidth } if (autoSizeAxes.isVertical) { - height = if (relativeSizeAxes.isVertical) contentHeight / getParentHeight() else contentHeight + height = if (relativeSizeAxes.isVertical) contentHeight / parent.getPaddedHeight() else contentHeight } updateVertexBuffer() @@ -763,105 +776,3 @@ abstract class ExtendedEntity( } } - - -/** - * The total offset applied to the X axis. - */ -val ExtendedEntity.totalOffsetX - get() = originOffsetX + anchorOffsetX + translationX - -/** - * The total offset applied to the Y axis. - */ -val ExtendedEntity.totalOffsetY - get() = originOffsetY + anchorOffsetY + translationY - -/** - * The offset applied to the X axis according to the anchor factor. - */ -val ExtendedEntity.anchorOffsetX: Float - get() = getParentWidth() * anchor.x - -/** - * The offset applied to the Y axis according to the anchor factor. - */ -val ExtendedEntity.anchorOffsetY: Float - get() = getParentHeight() * anchor.y - -/** - * The offset applied to the X axis according to the origin factor. - */ -val ExtendedEntity.originOffsetX: Float - get() = -(drawWidth * origin.x) - -/** - * The offset applied to the Y axis according to the origin factor. - */ -val ExtendedEntity.originOffsetY: Float - get() = -(drawHeight * origin.y) - -/** - * Returns the width of the parent entity. - */ -fun ExtendedEntity.getParentWidth() = when (val parent = parent) { - is ExtendedEntity -> parent.drawWidth - is CameraScene -> parent.camera.widthRaw - is IShape -> parent.width - else -> 0f -} - -/** - * Returns the height of the parent entity. - */ -fun ExtendedEntity.getParentHeight() = when (val parent = parent) { - is ExtendedEntity -> parent.drawHeight - is CameraScene -> parent.camera.heightRaw - is IShape -> parent.height - else -> 0f -} - -/** - * Returns the draw width of the entity. - */ -fun IEntity.getDrawWidth(): Float = when (this) { - is ExtendedEntity -> drawWidth - is IShape -> width - else -> 0f -} - -/** - * Returns the draw height of the entity. - */ -fun IEntity.getDrawHeight(): Float = when (this) { - is ExtendedEntity -> drawHeight - is IShape -> height - else -> 0f -} - -/** - * Returns the draw X position of the entity. - */ -fun IEntity.getDrawX(): Float = when (this) { - is ExtendedEntity -> drawX - is IShape -> x - else -> 0f -} - -/** - * Returns the draw Y position of the entity. - */ -fun IEntity.getDrawY(): Float = when (this) { - is ExtendedEntity -> drawY - is IShape -> y - else -> 0f -} - -/** - * Attaches the entity to a parent. - */ -infix fun T.attachTo(parent: IEntity): T { - parent.attachChild(this) - return this -} - diff --git a/src/com/reco1l/andengine/container/Container.kt b/src/com/reco1l/andengine/container/Container.kt index 822f8452c..ec1ada9de 100644 --- a/src/com/reco1l/andengine/container/Container.kt +++ b/src/com/reco1l/andengine/container/Container.kt @@ -1,14 +1,10 @@ package com.reco1l.andengine.container -import android.util.* import com.reco1l.andengine.* import com.reco1l.toolkt.kotlin.* import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.IEntity.* -import org.anddev.andengine.entity.scene.Scene.ITouchArea -import org.anddev.andengine.entity.shape.IShape -import org.anddev.andengine.input.touch.* import org.anddev.andengine.util.* import javax.microedition.khronos.opengles.GL10 import kotlin.math.* @@ -63,20 +59,22 @@ open class Container : ExtendedEntity() { open fun getChildDrawX(child: ExtendedEntity): Float { + var x = child.x if (child.relativePositionAxes.isHorizontal) { - return child.x * drawWidth + child.totalOffsetX + x *= getPaddedWidth() } - return child.x + child.totalOffsetX + return getPadding().left + x + child.totalOffsetX } open fun getChildDrawY(child: ExtendedEntity): Float { + var y = child.y if (child.relativePositionAxes.isVertical) { - return child.y * drawHeight + child.totalOffsetY + y *= getPaddedHeight() } - return child.y + child.totalOffsetY + return getPadding().top + y + child.totalOffsetY } diff --git a/src/com/reco1l/framework/math/Vector4.kt b/src/com/reco1l/framework/math/Vector4.kt new file mode 100644 index 000000000..d8e25947b --- /dev/null +++ b/src/com/reco1l/framework/math/Vector4.kt @@ -0,0 +1,89 @@ +package com.reco1l.framework.math + +@JvmInline +value class Vector4(private val values: FloatArray = FloatArray(4)) { + + + constructor(x: Float, y: Float, z: Float, w: Float) : this(floatArrayOf(x, y, z, w)) + + + val x: Float + get() = values[0] + + val y: Float + get() = values[1] + + val z: Float + get() = values[2] + + val w: Float + get() = values[3] + + + val left: Float + get() = values[0] + + val top: Float + get() = values[1] + + val right: Float + get() = values[2] + + val bottom: Float + get() = values[3] + + + val total + get() = x + y + z + w + + val vertical + get() = y + w + + val horizontal + get() = x + z + + + operator fun plus(other: Vector4) = Vector4( + x + other.x, + y + other.y, + z + other.z, + w + other.w + ) + + operator fun minus(other: Vector4) = Vector4( + x - other.x, + y - other.y, + z - other.z, + w - other.w + ) + + operator fun times(scalar: Float) = Vector4( + x * scalar, + y * scalar, + z * scalar, + w * scalar + ) + + operator fun div(scalar: Float) = Vector4( + x / scalar, + y / scalar, + z / scalar, + w / scalar + ) + + operator fun unaryMinus() = Vector4( + -x, + -y, + -z, + -w + ) + + override fun toString() = "Vector4($x, $y, $z, $w)" + + + companion object { + val Zero = Vector4() + val One = Vector4(1f, 1f, 1f, 1f) + } + +} \ No newline at end of file From df8316d9b56cb383744a3f281c4bdddaa84c8471 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Thu, 26 Dec 2024 22:28:43 -0300 Subject: [PATCH 47/73] Make `Vec2` and `Vec4` immutable --- src/com/reco1l/andengine/Anchor.kt | 20 ++--- src/com/reco1l/andengine/Entities.kt | 4 +- src/com/reco1l/andengine/ExtendedEntity.kt | 4 +- src/com/reco1l/framework/math/Vec2.kt | 54 +++++++++++++ src/com/reco1l/framework/math/Vec4.kt | 78 +++++++++++++++++++ src/com/reco1l/framework/math/Vector4.kt | 89 ---------------------- 6 files changed, 146 insertions(+), 103 deletions(-) create mode 100644 src/com/reco1l/framework/math/Vec2.kt create mode 100644 src/com/reco1l/framework/math/Vec4.kt delete mode 100644 src/com/reco1l/framework/math/Vector4.kt diff --git a/src/com/reco1l/andengine/Anchor.kt b/src/com/reco1l/andengine/Anchor.kt index 448d33638..43c3e63e3 100644 --- a/src/com/reco1l/andengine/Anchor.kt +++ b/src/com/reco1l/andengine/Anchor.kt @@ -1,34 +1,34 @@ package com.reco1l.andengine -import com.rian.osu.math.Vector2 +import com.reco1l.framework.math.Vec2 object Anchor { @JvmField - val TopLeft = Vector2(0f, 0f) + val TopLeft = Vec2(0f, 0f) @JvmField - val TopCenter = Vector2(0.5f, 0f) + val TopCenter = Vec2(0.5f, 0f) @JvmField - val TopRight = Vector2(1f, 0f) + val TopRight = Vec2(1f, 0f) @JvmField - val CenterLeft = Vector2(0f, 0.5f) + val CenterLeft = Vec2(0f, 0.5f) @JvmField - val Center = Vector2(0.5f, 0.5f) + val Center = Vec2(0.5f, 0.5f) @JvmField - val CenterRight = Vector2(1f, 0.5f) + val CenterRight = Vec2(1f, 0.5f) @JvmField - val BottomLeft = Vector2(0f, 1f) + val BottomLeft = Vec2(0f, 1f) @JvmField - val BottomCenter = Vector2(0.5f, 1f) + val BottomCenter = Vec2(0.5f, 1f) @JvmField - val BottomRight = Vector2(1f, 1f) + val BottomRight = Vec2(1f, 1f) } \ No newline at end of file diff --git a/src/com/reco1l/andengine/Entities.kt b/src/com/reco1l/andengine/Entities.kt index 30ec3752b..f4e28e2f0 100644 --- a/src/com/reco1l/andengine/Entities.kt +++ b/src/com/reco1l/andengine/Entities.kt @@ -1,13 +1,13 @@ package com.reco1l.andengine -import com.reco1l.framework.math.Vector4 +import com.reco1l.framework.math.Vec4 import org.anddev.andengine.entity.IEntity import org.anddev.andengine.entity.shape.IShape fun IEntity?.getPadding() = when (this) { is ExtendedEntity -> padding - else -> Vector4.Zero + else -> Vec4.Zero } fun IEntity?.getPaddedWidth() = when (this) { diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 34b84f5ce..4bc548fc8 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,7 +4,7 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* -import com.reco1l.framework.math.Vector4 +import com.reco1l.framework.math.Vec4 import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.scene.Scene @@ -116,7 +116,7 @@ abstract class ExtendedEntity( /** * The padding of the entity. */ - open var padding = Vector4.Zero + open var padding = Vec4.Zero set(value) { if (field != value) { field = value diff --git a/src/com/reco1l/framework/math/Vec2.kt b/src/com/reco1l/framework/math/Vec2.kt new file mode 100644 index 000000000..fe303f071 --- /dev/null +++ b/src/com/reco1l/framework/math/Vec2.kt @@ -0,0 +1,54 @@ +package com.reco1l.framework.math + +data class Vec2( + + val x: Float = 0f, + + val y: Float = 0f, + +) { + + val total + get() = x + y + + val vertical + get() = y + + val horizontal + get() = x + + + operator fun plus(other: Vec2) = Vec2( + x + other.x, + y + other.y + ) + + operator fun minus(other: Vec2) = Vec2( + x - other.x, + y - other.y + ) + + operator fun times(scalar: Float) = Vec2( + x * scalar, + y * scalar, + ) + + operator fun div(scalar: Float) = Vec2( + x / scalar, + y / scalar + ) + + operator fun unaryMinus() = Vec2( + -x, + -y + ) + + override fun toString() = "Vector2($x, $y)" + + + companion object { + val Zero = Vec2() + val One = Vec2(1f, 1f) + } + +} \ No newline at end of file diff --git a/src/com/reco1l/framework/math/Vec4.kt b/src/com/reco1l/framework/math/Vec4.kt new file mode 100644 index 000000000..675c25b49 --- /dev/null +++ b/src/com/reco1l/framework/math/Vec4.kt @@ -0,0 +1,78 @@ +package com.reco1l.framework.math + +data class Vec4( + + val x: Float = 0f, + val y: Float = 0f, + val z: Float = 0f, + val w: Float = 0f, + +) { + + val left: Float + get() = x + + val top: Float + get() = y + + val right: Float + get() = z + + val bottom: Float + get() = w + + + val total + get() = x + y + z + w + + val vertical + get() = y + w + + val horizontal + get() = x + z + + + operator fun plus(other: Vec4) = Vec4( + x + other.x, + y + other.y, + z + other.z, + w + other.w + ) + + operator fun minus(other: Vec4) = Vec4( + x - other.x, + y - other.y, + z - other.z, + w - other.w + ) + + operator fun times(scalar: Float) = Vec4( + x * scalar, + y * scalar, + z * scalar, + w * scalar + ) + + operator fun div(scalar: Float) = Vec4( + x / scalar, + y / scalar, + z / scalar, + w / scalar + ) + + operator fun unaryMinus() = Vec4( + -x, + -y, + -z, + -w + ) + + override fun toString() = "Vector4($x, $y, $z, $w)" + + + companion object { + val Zero = Vec4() + val One = Vec4(1f, 1f, 1f, 1f) + } + +} \ No newline at end of file diff --git a/src/com/reco1l/framework/math/Vector4.kt b/src/com/reco1l/framework/math/Vector4.kt deleted file mode 100644 index d8e25947b..000000000 --- a/src/com/reco1l/framework/math/Vector4.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.reco1l.framework.math - -@JvmInline -value class Vector4(private val values: FloatArray = FloatArray(4)) { - - - constructor(x: Float, y: Float, z: Float, w: Float) : this(floatArrayOf(x, y, z, w)) - - - val x: Float - get() = values[0] - - val y: Float - get() = values[1] - - val z: Float - get() = values[2] - - val w: Float - get() = values[3] - - - val left: Float - get() = values[0] - - val top: Float - get() = values[1] - - val right: Float - get() = values[2] - - val bottom: Float - get() = values[3] - - - val total - get() = x + y + z + w - - val vertical - get() = y + w - - val horizontal - get() = x + z - - - operator fun plus(other: Vector4) = Vector4( - x + other.x, - y + other.y, - z + other.z, - w + other.w - ) - - operator fun minus(other: Vector4) = Vector4( - x - other.x, - y - other.y, - z - other.z, - w - other.w - ) - - operator fun times(scalar: Float) = Vector4( - x * scalar, - y * scalar, - z * scalar, - w * scalar - ) - - operator fun div(scalar: Float) = Vector4( - x / scalar, - y / scalar, - z / scalar, - w / scalar - ) - - operator fun unaryMinus() = Vector4( - -x, - -y, - -z, - -w - ) - - override fun toString() = "Vector4($x, $y, $z, $w)" - - - companion object { - val Zero = Vector4() - val One = Vector4(1f, 1f, 1f, 1f) - } - -} \ No newline at end of file From 92c006f3cba6a0521092daed26edebee6ca10a66 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Thu, 26 Dec 2024 22:38:09 -0300 Subject: [PATCH 48/73] Fix getPaddedWidth() and getPaddedHeight() missing cases --- src/com/reco1l/andengine/Entities.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/reco1l/andengine/Entities.kt b/src/com/reco1l/andengine/Entities.kt index f4e28e2f0..b90979023 100644 --- a/src/com/reco1l/andengine/Entities.kt +++ b/src/com/reco1l/andengine/Entities.kt @@ -2,6 +2,7 @@ package com.reco1l.andengine import com.reco1l.framework.math.Vec4 import org.anddev.andengine.entity.IEntity +import org.anddev.andengine.entity.scene.CameraScene import org.anddev.andengine.entity.shape.IShape @@ -12,12 +13,14 @@ fun IEntity?.getPadding() = when (this) { fun IEntity?.getPaddedWidth() = when (this) { is ExtendedEntity -> drawWidth - padding.horizontal + is CameraScene -> camera.widthRaw is IShape -> width else -> 0f } fun IEntity?.getPaddedHeight() = when (this) { is ExtendedEntity -> drawHeight - padding.vertical + is CameraScene -> camera.heightRaw is IShape -> height else -> 0f } From 14260c191e43bf8015956e7fce5038a2fafb499f Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Thu, 26 Dec 2024 23:08:20 -0300 Subject: [PATCH 49/73] Override autoSizeAxes when changing manually the dimensions --- src/com/reco1l/andengine/ExtendedEntity.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 4bc548fc8..87b3cc41f 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -560,8 +560,7 @@ abstract class ExtendedEntity( open fun setSize(newWidth: Float, newHeight: Float): Boolean { if (autoSizeAxes != Axes.None) { - Log.e("ExtendedEntity", "Cannot change the size manually while autoSizeAxes is set to ${autoSizeAxes.name}.") - return false + autoSizeAxes = Axes.None } if (width != newWidth || height != newHeight) { @@ -583,8 +582,7 @@ abstract class ExtendedEntity( open fun setWidth(value: Float) { if (autoSizeAxes.isHorizontal) { - Log.e("ExtendedEntity", "Cannot change the width manually while autoSizeAxes is set to ${autoSizeAxes.name}.") - return + autoSizeAxes = if (autoSizeAxes == Axes.Both) Axes.Y else Axes.None } if (width != value) { @@ -598,8 +596,7 @@ abstract class ExtendedEntity( open fun setHeight(value: Float) { if (autoSizeAxes.isVertical) { - Log.e("ExtendedEntity", "Cannot change the height manually while autoSizeAxes is set to ${autoSizeAxes.name}.") - return + autoSizeAxes = if (autoSizeAxes == Axes.Both) Axes.X else Axes.None } if (height != value) { From 933cb9da951a72b032ce3e066046cbfb894b0214 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Thu, 26 Dec 2024 23:49:51 -0300 Subject: [PATCH 50/73] Support padding in Container sub-classes --- src/com/reco1l/andengine/ExtendedEntity.kt | 5 +-- .../container/ConstraintContainer.kt | 17 ++++++---- .../reco1l/andengine/container/Container.kt | 4 +-- .../andengine/container/LinearContainer.kt | 34 +++++++------------ .../container/ScrollableContainer.kt | 10 +++--- 5 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 87b3cc41f..507131659 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -15,6 +15,7 @@ import org.anddev.andengine.opengl.util.* import org.anddev.andengine.opengl.vertex.* import org.anddev.andengine.util.Transformation import javax.microedition.khronos.opengles.* +import kotlin.math.max /** @@ -249,7 +250,7 @@ abstract class ExtendedEntity( x *= parent.getPaddedWidth() } - return parent.getPadding().left + x + totalOffsetX + return max(parent.getPadding().left, x) + totalOffsetX } @@ -269,7 +270,7 @@ abstract class ExtendedEntity( y *= parent.getPaddedHeight() } - return parent.getPadding().top + y + totalOffsetY + return max(parent.getPadding().top, y) + totalOffsetY } diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index 40811844e..850c491d0 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -3,6 +3,7 @@ package com.reco1l.andengine.container import com.reco1l.andengine.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.shape.* +import kotlin.math.max /** * Container that allows to constrain nested entities to other entities in the same container. @@ -19,10 +20,12 @@ class ConstraintContainer : Container() { val target = constraints[child] ?: this - val targetX = target.getDrawX() - val anchorOffsetX = target.getDrawWidth() * child.anchor.x + val targetX = if (target == this) 0f else target.getDrawX() + val targetWidth = if (target == this) getPaddedWidth() else target.getDrawWidth() - var childX = child.x + val anchorOffsetX = targetWidth * child.anchor.x + + var childX = max(getPadding().left, child.x) // Relative positions will be multiplied by the remaining space from the // target's position to the edge of the container. @@ -37,10 +40,12 @@ class ConstraintContainer : Container() { val target = constraints[child] ?: this - val targetY = target.getDrawY() - val anchorOffsetY = target.getDrawHeight() * child.anchor.y + val targetY = if (target == this) 0f else target.getDrawY() + val targetHeight = if (target == this) getPaddedHeight() else target.getDrawHeight() + + val anchorOffsetY = targetHeight * child.anchor.y - var childY = child.y + var childY = max(getPadding().top, child.y) // Relative positions will be multiplied by the remaining space from the // target's position to the edge of the container. diff --git a/src/com/reco1l/andengine/container/Container.kt b/src/com/reco1l/andengine/container/Container.kt index ec1ada9de..efd1263ac 100644 --- a/src/com/reco1l/andengine/container/Container.kt +++ b/src/com/reco1l/andengine/container/Container.kt @@ -64,7 +64,7 @@ open class Container : ExtendedEntity() { x *= getPaddedWidth() } - return getPadding().left + x + child.totalOffsetX + return max(getPadding().left, x) + child.totalOffsetX } open fun getChildDrawY(child: ExtendedEntity): Float { @@ -74,7 +74,7 @@ open class Container : ExtendedEntity() { y *= getPaddedHeight() } - return getPadding().top + y + child.totalOffsetY + return max(getPadding().top, y) + child.totalOffsetY } diff --git a/src/com/reco1l/andengine/container/LinearContainer.kt b/src/com/reco1l/andengine/container/LinearContainer.kt index f09a24afb..266c61caf 100644 --- a/src/com/reco1l/andengine/container/LinearContainer.kt +++ b/src/com/reco1l/andengine/container/LinearContainer.kt @@ -30,9 +30,6 @@ open class LinearContainer : Container() { } - private var lastDrawOffset = 0f - - override fun onMeasureContentSize() { shouldMeasureSize = false @@ -44,9 +41,7 @@ open class LinearContainer : Container() { for (i in mChildren.indices) { val child = mChildren.getOrNull(i) ?: continue - - // Non-shape children are ignored as they doesn't have a size there's nothing to do. - if (child !is IShape) { + if (child !is ExtendedEntity) { continue } @@ -55,11 +50,13 @@ open class LinearContainer : Container() { when (orientation) { Horizontal -> { + child.x = contentWidth contentWidth += child.getDrawWidth() + spacing contentHeight = max(contentHeight, child.getDrawHeight()) } Vertical -> { + child.y = contentHeight contentWidth = max(contentWidth, child.getDrawWidth()) contentHeight += child.getDrawHeight() + spacing } @@ -71,33 +68,28 @@ open class LinearContainer : Container() { } - override fun onManagedDrawChildren(pGL: GL10, pCamera: Camera) { - lastDrawOffset = 0f - super.onManagedDrawChildren(pGL, pCamera) - } - override fun getChildDrawX(child: ExtendedEntity): Float { + val drawX = super.getChildDrawX(child) + if (orientation == Vertical) { - return super.getChildDrawX(child) + return drawX } - val drawX = lastDrawOffset + super.getChildDrawX(child) - lastDrawOffset += child.drawWidth + spacing - - return drawX + // Subtract the anchor offset for the X axis because it should be ignored in this case. + return drawX - child.anchorOffsetX } override fun getChildDrawY(child: ExtendedEntity): Float { + val drawY = super.getChildDrawY(child) + if (orientation == Horizontal) { - return super.getChildDrawY(child) + return drawY } - val drawY = lastDrawOffset + super.getChildDrawY(child) - lastDrawOffset += child.drawHeight + spacing - - return drawY + // Subtract the anchor offset for the Y axis because it should be ignored in this case. + return drawY - child.anchorOffsetY } } diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index 28d2a77b3..b656cd2ca 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -338,20 +338,20 @@ open class ScrollableContainer : Container() { override fun getChildDrawX(child: ExtendedEntity): Float { - if (child == indicatorX || child == indicatorY) { + if (child == indicatorX || child == indicatorY || !scrollAxes.isHorizontal) { return super.getChildDrawX(child) } - return -scrollX + child.x - child.originOffsetX + child.translationX + return -scrollX + max(getPadding().left, child.x) - child.originOffsetX + child.translationX } override fun getChildDrawY(child: ExtendedEntity): Float { - if (child == indicatorX || child == indicatorY) { + if (child == indicatorX || child == indicatorY || !scrollAxes.isVertical) { return super.getChildDrawY(child) } - return -scrollY + child.y - child.originOffsetY + child.translationY + return -scrollY + max(getPadding().top, child.y) - child.originOffsetY + child.translationY } @@ -359,7 +359,5 @@ open class ScrollableContainer : Container() { const val DEFAULT_DECELERATION = 0.98f - const val INSIGNIFICANT_DISTANCE = 0.05f - } } \ No newline at end of file From 9ecb8c7030189c53fe6f96d22a27ff7a83a4b1ee Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 27 Dec 2024 00:09:46 -0300 Subject: [PATCH 51/73] Fix padding not being applied properly in LinearContainer --- .../andengine/container/LinearContainer.kt | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/com/reco1l/andengine/container/LinearContainer.kt b/src/com/reco1l/andengine/container/LinearContainer.kt index 266c61caf..9f2dd9080 100644 --- a/src/com/reco1l/andengine/container/LinearContainer.kt +++ b/src/com/reco1l/andengine/container/LinearContainer.kt @@ -36,29 +36,42 @@ open class LinearContainer : Container() { contentWidth = 0f contentHeight = 0f - if (mChildren != null) { + for (i in 0 until childCount) { - for (i in mChildren.indices) { + val child = getChild(i) ?: continue + if (child !is ExtendedEntity) { + continue + } + + when (orientation) { + + Horizontal -> { + child.x = contentWidth + + contentWidth += child.getDrawWidth() + contentHeight = max(contentHeight, child.getDrawHeight()) - val child = mChildren.getOrNull(i) ?: continue - if (child !is ExtendedEntity) { - continue + if (i == 0) { + contentWidth += getPadding().left + } + + if (i < childCount - 1) { + contentWidth += spacing + } } - val spacing = if (i == mChildren.size - 1) 0f else spacing + Vertical -> { + child.y = contentHeight - when (orientation) { + contentWidth = max(contentWidth, child.getDrawWidth()) + contentHeight += child.getDrawHeight() - Horizontal -> { - child.x = contentWidth - contentWidth += child.getDrawWidth() + spacing - contentHeight = max(contentHeight, child.getDrawHeight()) + if (i == 0) { + contentHeight += getPadding().top } - Vertical -> { - child.y = contentHeight - contentWidth = max(contentWidth, child.getDrawWidth()) - contentHeight += child.getDrawHeight() + spacing + if (i < childCount - 1) { + contentHeight += spacing } } } From 85561f506ad95c6f65b4381387573641b1062e45 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 27 Dec 2024 00:29:55 -0300 Subject: [PATCH 52/73] Don't pre-multiply fonts --- src/com/reco1l/andengine/text/ExtendedText.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/com/reco1l/andengine/text/ExtendedText.kt b/src/com/reco1l/andengine/text/ExtendedText.kt index 9951fdd6c..713feddfd 100644 --- a/src/com/reco1l/andengine/text/ExtendedText.kt +++ b/src/com/reco1l/andengine/text/ExtendedText.kt @@ -121,12 +121,6 @@ open class ExtendedText : ExtendedEntity() { shouldRebuildTextureBuffer = false textureBuffer = TextTextureBuffer(2 * VERTICES_PER_CHARACTER * maximumSize, GL_STATIC_DRAW, true) - - if (font!!.texture.textureOptions.mPreMultipyAlpha) { - setBlendFunction(BLENDFUNCTION_SOURCE_PREMULTIPLYALPHA_DEFAULT, BLENDFUNCTION_DESTINATION_PREMULTIPLYALPHA_DEFAULT) - } else { - setBlendFunction(BLENDFUNCTION_SOURCE_DEFAULT, BLENDFUNCTION_DESTINATION_DEFAULT) - } } val lines = text.split('\n').toTypedArray() From f991d58cd76d23f7ce504cfff4ddaedb93155156 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 27 Dec 2024 22:04:48 -0300 Subject: [PATCH 53/73] Optimize RoundedBox --- src/com/reco1l/andengine/shape/Box.kt | 35 +++++++++------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/com/reco1l/andengine/shape/Box.kt b/src/com/reco1l/andengine/shape/Box.kt index b8a30de39..d0593c221 100644 --- a/src/com/reco1l/andengine/shape/Box.kt +++ b/src/com/reco1l/andengine/shape/Box.kt @@ -124,7 +124,7 @@ open class RoundedBox : ExtendedEntity() { class RoundedBoxVertexBuffer(private val segmentsPerArc: Int) : VertexBuffer( - (5 /*Quads*/ * 4 + (segmentsPerArc + 2) /*Arcs*/ * 4) * 2, + (3 /*Quads*/ * 4 + (segmentsPerArc + 2) /*Arcs*/ * 4) * 2, GL11.GL_STATIC_DRAW, false ) { @@ -151,41 +151,28 @@ open class RoundedBox : ExtendedEntity() { } // Quads: - // [1] - // [4] [5] [2] - // [3] + // [ ] + // [1] [2] [3] + // [ ] // [1] addQuad( - fromX = cornerRadius, fromY = 0f, - toX = width - cornerRadius, toY = cornerRadius + fromX = 0f, fromY = cornerRadius, + toX = cornerRadius, toY = height - cornerRadius ) // [2] addQuad( - fromX = width - cornerRadius, fromY = cornerRadius, - toX = width, toY = height - cornerRadius - ) - - // [3] - addQuad( - fromX = cornerRadius, fromY = height - cornerRadius, + fromX = cornerRadius, fromY = 0f, toX = width - cornerRadius, toY = height ) - // [4] - addQuad( - fromX = 0f, fromY = cornerRadius, - toX = cornerRadius, toY = height - cornerRadius - ) - - // [5] + // [3] addQuad( - fromX = cornerRadius, fromY = cornerRadius, - toX = width - cornerRadius, toY = height - cornerRadius + fromX = width - cornerRadius, fromY = cornerRadius, + toX = width, toY = height - cornerRadius ) - // Arcs fun addArc(centerX: Float, centerY: Float, startAngle: Float, endAngle: Float) { @@ -234,7 +221,7 @@ open class RoundedBox : ExtendedEntity() { var offset = 0 // Quads - for (i in 0 until 5) { + for (i in 0 until 3) { gl.glDrawArrays(GL_TRIANGLE_STRIP, offset, 4) offset += 4 } From 6c1a2af831d26f7dd75c3de0b92d6957bc18ebc2 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 27 Dec 2024 22:15:13 -0300 Subject: [PATCH 54/73] Introduce size property --- src/com/reco1l/andengine/Entities.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/com/reco1l/andengine/Entities.kt b/src/com/reco1l/andengine/Entities.kt index b90979023..29cadc323 100644 --- a/src/com/reco1l/andengine/Entities.kt +++ b/src/com/reco1l/andengine/Entities.kt @@ -4,6 +4,7 @@ import com.reco1l.framework.math.Vec4 import org.anddev.andengine.entity.IEntity import org.anddev.andengine.entity.scene.CameraScene import org.anddev.andengine.entity.shape.IShape +import kotlin.math.max fun IEntity?.getPadding() = when (this) { @@ -26,6 +27,20 @@ fun IEntity?.getPaddedHeight() = when (this) { } +/** + * The size of the entity. + * + * When using the getter this will return the maximum value between the width and height or the same. + * When using the setter this will set the width and height to the same value. + */ +var ExtendedEntity.size + get() = max(width, height) + set(value) { + width = value + height = value + } + + /** * The total offset applied to the X axis. */ From ee7b195ef0d5b4c756399f9c87d71a0c1719ad6a Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Fri, 27 Dec 2024 22:23:59 -0300 Subject: [PATCH 55/73] Improve Vec2 and Vec4 constructors --- src/com/reco1l/framework/math/Vec2.kt | 7 +++++-- src/com/reco1l/framework/math/Vec4.kt | 13 +++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/com/reco1l/framework/math/Vec2.kt b/src/com/reco1l/framework/math/Vec2.kt index fe303f071..283e30167 100644 --- a/src/com/reco1l/framework/math/Vec2.kt +++ b/src/com/reco1l/framework/math/Vec2.kt @@ -2,12 +2,15 @@ package com.reco1l.framework.math data class Vec2( - val x: Float = 0f, + val x: Float, - val y: Float = 0f, + val y: Float, ) { + constructor(value: Float = 0f) : this(value, value) + + val total get() = x + y diff --git a/src/com/reco1l/framework/math/Vec4.kt b/src/com/reco1l/framework/math/Vec4.kt index 675c25b49..a4b11dade 100644 --- a/src/com/reco1l/framework/math/Vec4.kt +++ b/src/com/reco1l/framework/math/Vec4.kt @@ -2,13 +2,18 @@ package com.reco1l.framework.math data class Vec4( - val x: Float = 0f, - val y: Float = 0f, - val z: Float = 0f, - val w: Float = 0f, + val x: Float, + val y: Float, + val z: Float, + val w: Float, ) { + constructor(value: Float = 0f) : this(value, value, value, value) + + constructor(xz: Float, yw: Float) : this(xz, yw, xz, yw) + + val left: Float get() = x From 3e6ea8fda866cf3e3e83c5b33f477a6937ffaeac Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 17:14:00 -0300 Subject: [PATCH 56/73] Fix padding in ConstraintContainer --- src/com/reco1l/andengine/container/ConstraintContainer.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index 850c491d0..f92faaf94 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -23,9 +23,10 @@ class ConstraintContainer : Container() { val targetX = if (target == this) 0f else target.getDrawX() val targetWidth = if (target == this) getPaddedWidth() else target.getDrawWidth() + val paddingLeft = if (target == this) getPadding().left else 0f val anchorOffsetX = targetWidth * child.anchor.x - var childX = max(getPadding().left, child.x) + var childX = max(paddingLeft, child.x) // Relative positions will be multiplied by the remaining space from the // target's position to the edge of the container. @@ -43,9 +44,10 @@ class ConstraintContainer : Container() { val targetY = if (target == this) 0f else target.getDrawY() val targetHeight = if (target == this) getPaddedHeight() else target.getDrawHeight() + val paddingTop = if (target == this) getPadding().top else 0f val anchorOffsetY = targetHeight * child.anchor.y - var childY = max(getPadding().top, child.y) + var childY = max(paddingTop, child.y) // Relative positions will be multiplied by the remaining space from the // target's position to the edge of the container. From 443e0a8e173b8710b297d8f1232041faed9d453a Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 17:14:24 -0300 Subject: [PATCH 57/73] Use Vec2 for ExtendedEntity.size property --- src/com/reco1l/andengine/Entities.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/reco1l/andengine/Entities.kt b/src/com/reco1l/andengine/Entities.kt index 29cadc323..00a3f653e 100644 --- a/src/com/reco1l/andengine/Entities.kt +++ b/src/com/reco1l/andengine/Entities.kt @@ -1,10 +1,10 @@ package com.reco1l.andengine +import com.reco1l.framework.math.Vec2 import com.reco1l.framework.math.Vec4 import org.anddev.andengine.entity.IEntity import org.anddev.andengine.entity.scene.CameraScene import org.anddev.andengine.entity.shape.IShape -import kotlin.math.max fun IEntity?.getPadding() = when (this) { @@ -34,10 +34,10 @@ fun IEntity?.getPaddedHeight() = when (this) { * When using the setter this will set the width and height to the same value. */ var ExtendedEntity.size - get() = max(width, height) + get() = Vec2(width, height) set(value) { - width = value - height = value + width = value.x + height = value.y } From 5279392de77bf4d291b222e30332b111e578e758 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 18:18:18 -0300 Subject: [PATCH 58/73] Fix potential crash due to corner radius being 0 --- src/com/reco1l/andengine/shape/Box.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/shape/Box.kt b/src/com/reco1l/andengine/shape/Box.kt index d0593c221..041ef7d79 100644 --- a/src/com/reco1l/andengine/shape/Box.kt +++ b/src/com/reco1l/andengine/shape/Box.kt @@ -103,7 +103,8 @@ open class RoundedBox : ExtendedEntity() { override fun onUpdateVertexBuffer() { - val cornerRadius = cornerRadius.coerceIn(0f, min(drawWidth, drawHeight) / 2f) + val smallerSide = min(drawWidth, drawHeight) + val cornerRadius = cornerRadius.coerceAtMost(smallerSide / 2f).coerceAtLeast(0f) if (shouldRebuildVertexBuffer) { shouldRebuildVertexBuffer = false From 3e87067b1f839790e13806c6f4fa70b9758712a8 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 18:18:33 -0300 Subject: [PATCH 59/73] Introduce foreground and background --- src/com/reco1l/andengine/ExtendedEntity.kt | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 507131659..8a85f7b40 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,6 +4,7 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* +import com.reco1l.framework.math.Vec2 import com.reco1l.framework.math.Vec4 import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* @@ -147,6 +148,39 @@ abstract class ExtendedEntity( } } + /** + * The background entity. This entity will be drawn before the entity children and will not be + * affected by padding. + */ + open var background: ExtendedEntity? = null + set(value) { + if (field != value) { + if (value?.parent != null) { + Log.e("ExtendedEntity", "The background entity is already attached to another entity.") + return + } + + field = value + } + } + + /** + * The foreground entity. This entity will be drawn after the entity children and will not be + * affected by padding. + */ + open var foreground: ExtendedEntity? = null + set(value) { + if (field != value) { + if (value?.parent != null) { + Log.e("ExtendedEntity", "The foreground entity is already attached to another entity.") + return + } + + field = value + } + } + + /** * Whether the entity should clip its children. */ @@ -433,6 +467,21 @@ abstract class ExtendedEntity( applyBlending(pGL) } + override fun doDraw(gl: GL10, camera: Camera) { + + background?.setSize(drawWidth, drawHeight) + background?.onDraw(gl, camera) + + super.doDraw(gl, camera) + } + + override fun onDrawChildren(gl: GL10, camera: Camera) { + super.onDrawChildren(gl, camera) + + foreground?.setSize(drawWidth, drawHeight) + foreground?.onDraw(gl, camera) + } + override fun onManagedDraw(gl: GL10, camera: Camera) { if (isVertexBufferDirty) { From 32305dcfbaf2152ab8fabbc3d3cc974d4007f5cd Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 18:44:57 -0300 Subject: [PATCH 60/73] Improve Padding compatibility --- src/com/reco1l/andengine/ExtendedEntity.kt | 54 ++++++++++++------- .../container/ConstraintContainer.kt | 40 ++++++++------ .../reco1l/andengine/container/Container.kt | 4 +- .../andengine/container/LinearContainer.kt | 8 --- .../container/ScrollableContainer.kt | 4 +- 5 files changed, 64 insertions(+), 46 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 8a85f7b40..452803847 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -16,7 +16,6 @@ import org.anddev.andengine.opengl.util.* import org.anddev.andengine.opengl.vertex.* import org.anddev.andengine.util.Transformation import javax.microedition.khronos.opengles.* -import kotlin.math.max /** @@ -284,7 +283,7 @@ abstract class ExtendedEntity( x *= parent.getPaddedWidth() } - return max(parent.getPadding().left, x) + totalOffsetX + return x + totalOffsetX } @@ -304,7 +303,7 @@ abstract class ExtendedEntity( y *= parent.getPaddedHeight() } - return max(parent.getPadding().top, y) + totalOffsetY + return y + totalOffsetY } @@ -476,26 +475,20 @@ abstract class ExtendedEntity( } override fun onDrawChildren(gl: GL10, camera: Camera) { - super.onDrawChildren(gl, camera) - - foreground?.setSize(drawWidth, drawHeight) - foreground?.onDraw(gl, camera) - } - override fun onManagedDraw(gl: GL10, camera: Camera) { + val hasPaddingApplicable = padding.left > 0f || padding.top > 0f - if (isVertexBufferDirty) { - isVertexBufferDirty = false - onUpdateVertexBuffer() + if (hasPaddingApplicable) { + gl.glTranslatef(padding.left, padding.top, 0f) } if (clipChildren) { GLHelper.enableScissorTest(gl) var (bottomLeftX, bottomLeftY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(0f, 0f)) - var (topLeftX, topLeftY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(0f, drawHeight)) - var (topRightX, topRightY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(drawWidth, drawHeight)) - var (bottomRightX, bottomRightY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(drawWidth, 0f)) + var (topLeftX, topLeftY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(0f, getPaddedHeight())) + var (topRightX, topRightY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(getPaddedWidth(), getPaddedHeight())) + var (bottomRightX, bottomRightY) = camera.getScreenSpaceCoordinates(convertLocalToSceneCoordinates(getPaddedWidth(), 0f)) // Flip the Y axis to match the OpenGL coordinate system. bottomLeftY = camera.surfaceHeight - bottomLeftY @@ -517,11 +510,28 @@ abstract class ExtendedEntity( ) } - super.onManagedDraw(gl, camera) + super.onDrawChildren(gl, camera) if (clipChildren) { GLHelper.disableScissorTest(gl) } + + if (hasPaddingApplicable) { + gl.glTranslatef(-padding.right, -padding.top, 0f) + } + + foreground?.setSize(drawWidth, drawHeight) + foreground?.onDraw(gl, camera) + } + + override fun onManagedDraw(gl: GL10, camera: Camera) { + + if (isVertexBufferDirty) { + isVertexBufferDirty = false + onUpdateVertexBuffer() + } + + super.onManagedDraw(gl, camera) } override fun onInitDraw(pGL: GL10) { @@ -584,11 +594,19 @@ abstract class ExtendedEntity( if (contentWidth != width || contentHeight != height) { if (autoSizeAxes.isHorizontal) { - width = if (relativeSizeAxes.isHorizontal) contentWidth / parent.getPaddedWidth() else contentWidth + width = contentWidth + padding.horizontal + + if (relativeSizeAxes.isHorizontal) { + width /= parent.getPaddedWidth() + } } if (autoSizeAxes.isVertical) { - height = if (relativeSizeAxes.isVertical) contentHeight / parent.getPaddedHeight() else contentHeight + height = contentHeight + padding.vertical + + if (relativeSizeAxes.isVertical) { + height /= parent.getPaddedHeight() + } } updateVertexBuffer() diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index f92faaf94..7e1e7a71a 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -20,18 +20,22 @@ class ConstraintContainer : Container() { val target = constraints[child] ?: this - val targetX = if (target == this) 0f else target.getDrawX() - val targetWidth = if (target == this) getPaddedWidth() else target.getDrawWidth() + var targetX = target.getDrawX() + var targetWidth = target.getDrawWidth() - val paddingLeft = if (target == this) getPadding().left else 0f - val anchorOffsetX = targetWidth * child.anchor.x + if (target == this) { + targetX = 0f + targetWidth = getPaddedWidth() + } - var childX = max(paddingLeft, child.x) + val anchorOffsetX = targetWidth * child.anchor.x - // Relative positions will be multiplied by the remaining space from the - // target's position to the edge of the container. + var childX = child.x if (child.relativePositionAxes.isHorizontal) { - childX *= drawWidth - targetX + + // Relative positions will be multiplied by the remaining space from the + // target's position to the edge of the container. + childX *= getPaddedWidth() - targetX } return targetX + childX + child.originOffsetX + anchorOffsetX + child.translationX @@ -41,18 +45,22 @@ class ConstraintContainer : Container() { val target = constraints[child] ?: this - val targetY = if (target == this) 0f else target.getDrawY() - val targetHeight = if (target == this) getPaddedHeight() else target.getDrawHeight() + var targetY = target.getDrawY() + var targetHeight = target.getDrawHeight() - val paddingTop = if (target == this) getPadding().top else 0f - val anchorOffsetY = targetHeight * child.anchor.y + if (target == this) { + targetY = 0f + targetHeight = getPaddedHeight() + } - var childY = max(paddingTop, child.y) + val anchorOffsetY = targetHeight * child.anchor.y - // Relative positions will be multiplied by the remaining space from the - // target's position to the edge of the container. + var childY = child.y if (child.relativePositionAxes.isVertical) { - childY *= drawHeight - targetY + + // Relative positions will be multiplied by the remaining space from the + // target's position to the edge of the container. + childY *= getPaddedHeight() - targetY } return targetY + childY + child.originOffsetY + anchorOffsetY + child.translationY diff --git a/src/com/reco1l/andengine/container/Container.kt b/src/com/reco1l/andengine/container/Container.kt index efd1263ac..2364427d5 100644 --- a/src/com/reco1l/andengine/container/Container.kt +++ b/src/com/reco1l/andengine/container/Container.kt @@ -64,7 +64,7 @@ open class Container : ExtendedEntity() { x *= getPaddedWidth() } - return max(getPadding().left, x) + child.totalOffsetX + return x + child.totalOffsetX } open fun getChildDrawY(child: ExtendedEntity): Float { @@ -74,7 +74,7 @@ open class Container : ExtendedEntity() { y *= getPaddedHeight() } - return max(getPadding().top, y) + child.totalOffsetY + return y + child.totalOffsetY } diff --git a/src/com/reco1l/andengine/container/LinearContainer.kt b/src/com/reco1l/andengine/container/LinearContainer.kt index 9f2dd9080..3c4e4abc1 100644 --- a/src/com/reco1l/andengine/container/LinearContainer.kt +++ b/src/com/reco1l/andengine/container/LinearContainer.kt @@ -51,10 +51,6 @@ open class LinearContainer : Container() { contentWidth += child.getDrawWidth() contentHeight = max(contentHeight, child.getDrawHeight()) - if (i == 0) { - contentWidth += getPadding().left - } - if (i < childCount - 1) { contentWidth += spacing } @@ -66,10 +62,6 @@ open class LinearContainer : Container() { contentWidth = max(contentWidth, child.getDrawWidth()) contentHeight += child.getDrawHeight() - if (i == 0) { - contentHeight += getPadding().top - } - if (i < childCount - 1) { contentHeight += spacing } diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index b656cd2ca..ab6752f0d 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -342,7 +342,7 @@ open class ScrollableContainer : Container() { return super.getChildDrawX(child) } - return -scrollX + max(getPadding().left, child.x) - child.originOffsetX + child.translationX + return -scrollX + child.x - child.originOffsetX + child.translationX } override fun getChildDrawY(child: ExtendedEntity): Float { @@ -351,7 +351,7 @@ open class ScrollableContainer : Container() { return super.getChildDrawY(child) } - return -scrollY + max(getPadding().top, child.y) - child.originOffsetY + child.translationY + return -scrollY + child.y - child.originOffsetY + child.translationY } From a6f7722d58dc1ecc623fee4a81a044ec0a24ee58 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 20:31:27 -0300 Subject: [PATCH 61/73] Introduce touch area binding --- src/com/reco1l/andengine/ExtendedEntity.kt | 27 ++++++++++++++--- .../container/ScrollableContainer.kt | 30 +++++++++---------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 452803847..9b0adb3d2 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -4,7 +4,6 @@ import android.util.* import com.reco1l.andengine.container.* import com.reco1l.andengine.modifier.* import com.reco1l.framework.* -import com.reco1l.framework.math.Vec2 import com.reco1l.framework.math.Vec4 import org.anddev.andengine.engine.camera.* import org.anddev.andengine.entity.* @@ -313,6 +312,8 @@ abstract class ExtendedEntity( private var isVertexBufferDirty = true + private var currentBoundEntity: ITouchArea? = null + // Attachment @@ -819,16 +820,34 @@ abstract class ExtendedEntity( localY: Float ): Boolean { + val boundEntity = currentBoundEntity + if (boundEntity != null) { + boundEntity as IEntity + + val transformedX = localX - boundEntity.getDrawX() + val transformedY = localY - boundEntity.getDrawY() + + boundEntity.onAreaTouched(event, transformedX, transformedY) + + if (event.isActionUp || event.isActionOutside || event.isActionCancel) { + currentBoundEntity = null + } + return true + } + try { for (i in childCount - 1 downTo 0) { val child = getChild(i) - val transformedX = localX - child.getDrawX() - val transformedY = localY - child.getDrawY() + if (child is ITouchArea && child.contains(localX, localY)) { - if (child is ITouchArea && child.contains(transformedX, transformedY)) { + val transformedX = localX - child.getDrawX() + val transformedY = localY - child.getDrawY() if (child.onAreaTouched(event, transformedX, transformedY)) { + if (event.isActionDown) { + currentBoundEntity = child + } return true } } diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index ab6752f0d..fe796b4b9 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -280,31 +280,33 @@ open class ScrollableContainer : Container() { when (event.action) { ACTION_DOWN -> { - isDragging = true - initialX = localX initialY = localY velocityX = 0f velocityY = 0f - - lastDragTimeSec = elapsedTimeSec } ACTION_MOVE -> { - isDragging = true - var deltaX = localX - initialX - var deltaY = localY - initialY + var deltaX = if (scrollAxes.isHorizontal) localX - initialX else 0f + var deltaY = if (scrollAxes.isVertical) localY - initialY else 0f + + if (!isDragging) { + isDragging = abs(deltaX) > 1f || abs(deltaY) > 1f + + if (!isDragging) { + return super.onAreaTouched(event, localX, localY) + } + } val length = hypot(deltaX, deltaY) - // Slow down the scroll when reaching the bounds. - if (scrollX + deltaX < 0 || scrollX + deltaX > maxScrollX) { + if (scrollX - deltaX < 0 || scrollX - deltaX > maxScrollX) { deltaX *= if (length <= 0) 0f else length.pow(0.7f) / length } - if (scrollY + deltaY < 0 || scrollY + deltaY > maxScrollY) { + if (scrollY - deltaY < 0 || scrollY - deltaY > maxScrollY) { deltaY *= if (length <= 0) 0f else length.pow(0.7f) / length } @@ -313,18 +315,16 @@ open class ScrollableContainer : Container() { if (abs(deltaX) > 0.1f) { scrollX -= deltaX velocityX = abs(deltaX / dragTimeSec) * sign(deltaX) - initialX = localX - lastDragTimeSec = elapsedTimeSec } if (abs(deltaY) > 0.1f) { scrollY -= deltaY velocityY = abs(deltaY / dragTimeSec) * sign(deltaY) - initialY = localY - lastDragTimeSec = elapsedTimeSec } + + lastDragTimeSec = elapsedTimeSec } else -> { @@ -332,7 +332,7 @@ open class ScrollableContainer : Container() { } } - return super.onAreaTouched(event, localX, localY) + return isDragging || super.onAreaTouched(event, localX, localY) } From f2cb224b4a3debfe3cea16a1f921b146f51f8332 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sat, 28 Dec 2024 20:48:42 -0300 Subject: [PATCH 62/73] Make ConstraintContainer open --- src/com/reco1l/andengine/container/ConstraintContainer.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/reco1l/andengine/container/ConstraintContainer.kt b/src/com/reco1l/andengine/container/ConstraintContainer.kt index 7e1e7a71a..159257aca 100644 --- a/src/com/reco1l/andengine/container/ConstraintContainer.kt +++ b/src/com/reco1l/andengine/container/ConstraintContainer.kt @@ -3,14 +3,13 @@ package com.reco1l.andengine.container import com.reco1l.andengine.* import org.anddev.andengine.entity.* import org.anddev.andengine.entity.shape.* -import kotlin.math.max /** * Container that allows to constrain nested entities to other entities in the same container. * * This is useful for creating complex layouts. */ -class ConstraintContainer : Container() { +open class ConstraintContainer : Container() { private val constraints = mutableMapOf() From 35a631feaba254375164c25da91ad5b5c3f0e96b Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 02:44:58 -0300 Subject: [PATCH 63/73] Change transform order --- src/com/reco1l/andengine/ExtendedEntity.kt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 9b0adb3d2..9ec9f1514 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -769,21 +769,21 @@ abstract class ExtendedEntity( mParentToLocalTransformation.setToIdentity() mParentToLocalTransformation.postTranslate(-drawX, -drawY) - if (scaleX != 1f || scaleY != 1f) { - val offsetX = drawWidth * mScaleCenterX - val offsetY = drawHeight * mScaleCenterY + if (rotation != 0f) { + val offsetX = drawWidth * mRotationCenterX + val offsetY = drawHeight * mRotationCenterY mParentToLocalTransformation.postTranslate(-offsetX, -offsetY) - mParentToLocalTransformation.postScale(1 / scaleX, 1 / scaleY) + mParentToLocalTransformation.postRotate(-rotation) mParentToLocalTransformation.postTranslate(offsetX, offsetY) } - if (rotation != 0f) { - val offsetX = drawWidth * mRotationCenterX - val offsetY = drawHeight * mRotationCenterY + if (scaleX != 1f || scaleY != 1f) { + val offsetX = drawWidth * mScaleCenterX + val offsetY = drawHeight * mScaleCenterY mParentToLocalTransformation.postTranslate(-offsetX, -offsetY) - mParentToLocalTransformation.postRotate(-rotation) + mParentToLocalTransformation.postScale(1 / scaleX, 1 / scaleY) mParentToLocalTransformation.postTranslate(offsetX, offsetY) } @@ -855,7 +855,6 @@ abstract class ExtendedEntity( } catch (e: IndexOutOfBoundsException) { Log.e("ExtendedEntity", "A child entity was removed during touch event propagation.", e) } - return false } From 06ac2c806886158526cc60c400557c3e6f1d71a2 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 02:45:32 -0300 Subject: [PATCH 64/73] Use drawWidth and drawHeight to check whether a point it's on a Entity --- src/com/reco1l/andengine/ExtendedEntity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 9ec9f1514..6eb649fd2 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -711,7 +711,7 @@ abstract class ExtendedEntity( override fun contains(x: Float, y: Float): Boolean { - if (width == 0f || height == 0f) { + if (drawWidth == 0f || drawHeight == 0f) { return false } From 17e1741fbc49191d0234a5b7c8f51e75d866ca9f Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 02:46:24 -0300 Subject: [PATCH 65/73] Prevent event propagation if ScrollableContainer is scrolling --- src/com/reco1l/andengine/container/ScrollableContainer.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index fe796b4b9..d84d41190 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -332,7 +332,11 @@ open class ScrollableContainer : Container() { } } - return isDragging || super.onAreaTouched(event, localX, localY) + if (!isDragging) { + return super.onAreaTouched(event, localX, localY) + } + + return true } From 88fbc3bc32c5041e8a76a03f3c9006085128fd82 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 03:17:44 -0300 Subject: [PATCH 66/73] Update background and foreground --- src/com/reco1l/andengine/ExtendedEntity.kt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index 6eb649fd2..c7ea26f96 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -551,6 +551,17 @@ abstract class ExtendedEntity( } + // Update + + override fun onManagedUpdate(pSecondsElapsed: Float) { + + background?.onManagedUpdate(pSecondsElapsed) + foreground?.onManagedUpdate(pSecondsElapsed) + + super.onManagedUpdate(pSecondsElapsed) + } + + // Vertex buffer override fun updateVertexBuffer() { @@ -611,6 +622,7 @@ abstract class ExtendedEntity( } updateVertexBuffer() + invalidateTransformations() (parent as? Container)?.onChildSizeChanged(this) return true @@ -637,6 +649,7 @@ abstract class ExtendedEntity( height = newHeight updateVertexBuffer() + invalidateTransformations() val parent = parent if (parent is Container) { @@ -658,6 +671,7 @@ abstract class ExtendedEntity( width = value updateVertexBuffer() + invalidateTransformations() (parent as? Container)?.onChildSizeChanged(this) } } @@ -672,6 +686,7 @@ abstract class ExtendedEntity( height = value updateVertexBuffer() + invalidateTransformations() (parent as? Container)?.onChildSizeChanged(this) } } @@ -715,7 +730,7 @@ abstract class ExtendedEntity( return false } - return EntityCollision.contains(this, x, y) + return EntityCollision.contains(this, x, y, parent is Scene) } override fun isCulled(pCamera: Camera): Boolean { From c0ccd9a345239131b0cc4060e9a9042e70a29f33 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 03:18:04 -0300 Subject: [PATCH 67/73] Set traversal front to back by default for ExtendedScene --- src/com/reco1l/andengine/ExtendedScene.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/reco1l/andengine/ExtendedScene.kt b/src/com/reco1l/andengine/ExtendedScene.kt index f61155e20..5111da013 100644 --- a/src/com/reco1l/andengine/ExtendedScene.kt +++ b/src/com/reco1l/andengine/ExtendedScene.kt @@ -28,6 +28,7 @@ open class ExtendedScene : Scene(), IShape { init { super.setTouchAreaBindingEnabled(true) + super.setOnAreaTouchTraversalFrontToBack() } From 3fdc324843b14abdb6a2c715b80557419d5d3fd0 Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 03:18:28 -0300 Subject: [PATCH 68/73] Difference whether to apply transformation from scene or from parent entity --- src/com/reco1l/andengine/EntityCollision.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/com/reco1l/andengine/EntityCollision.kt b/src/com/reco1l/andengine/EntityCollision.kt index a6432d368..d96959fb3 100644 --- a/src/com/reco1l/andengine/EntityCollision.kt +++ b/src/com/reco1l/andengine/EntityCollision.kt @@ -10,7 +10,7 @@ object EntityCollision { private val vertices = FloatArray(8) - fun contains(entity: ExtendedEntity, x: Float, y: Float): Boolean { + fun contains(entity: ExtendedEntity, x: Float, y: Float, fromScene: Boolean): Boolean { val left = 0f val top = 0f @@ -29,7 +29,11 @@ object EntityCollision { vertices[6 + VERTEX_INDEX_X] = left vertices[6 + VERTEX_INDEX_Y] = bottom - entity.getLocalToSceneTransformation().transform(vertices) + if (fromScene) { + entity.localToSceneTransformation.transform(vertices) + } else { + entity.localToParentTransformation.transform(vertices) + } return ShapeCollisionChecker.checkContains(vertices, vertices.size, x, y) } From f4f7659a1a92378465caeb29a58adfadc1569a3c Mon Sep 17 00:00:00 2001 From: Geronimo Ferruccio Date: Sun, 29 Dec 2024 03:21:39 -0300 Subject: [PATCH 69/73] Draw indicators on top --- src/com/reco1l/andengine/container/ScrollableContainer.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/container/ScrollableContainer.kt b/src/com/reco1l/andengine/container/ScrollableContainer.kt index d84d41190..c6cf72417 100644 --- a/src/com/reco1l/andengine/container/ScrollableContainer.kt +++ b/src/com/reco1l/andengine/container/ScrollableContainer.kt @@ -270,9 +270,10 @@ open class ScrollableContainer : Container() { } override fun onManagedDrawChildren(pGL: GL10, pCamera: Camera) { + super.onManagedDrawChildren(pGL, pCamera) + indicatorX?.onDraw(pGL, pCamera) indicatorY?.onDraw(pGL, pCamera) - super.onManagedDrawChildren(pGL, pCamera) } override fun onAreaTouched(event: TouchEvent, localX: Float, localY: Float): Boolean { From b5bc690140c4607f7723b8cd489e7b8d9a28052e Mon Sep 17 00:00:00 2001 From: Rian8337 <52914632+Rian8337@users.noreply.github.com> Date: Sat, 25 Jan 2025 18:27:59 +0800 Subject: [PATCH 70/73] Resolve... weird "syntax" error? See https://github.com/osudroid/osu-droid/actions/runs/12964055528/job/36162349793?pr=475. --- src/com/reco1l/andengine/text/ExtendedText.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/reco1l/andengine/text/ExtendedText.kt b/src/com/reco1l/andengine/text/ExtendedText.kt index 713feddfd..e899652a3 100644 --- a/src/com/reco1l/andengine/text/ExtendedText.kt +++ b/src/com/reco1l/andengine/text/ExtendedText.kt @@ -30,10 +30,12 @@ open class ExtendedText : ExtendedEntity() { set(value) { if (field != value) { field = value + if (value.length > maximumSize) { shouldRebuildVertexBuffer = true shouldRebuildTextureBuffer = true } + updateVertexBuffer() } } From e2e3605fadf4fae9cf1f119fb7f4c0ba4e573d06 Mon Sep 17 00:00:00 2001 From: Rian8337 <52914632+Rian8337@users.noreply.github.com> Date: Sat, 25 Jan 2025 18:35:17 +0800 Subject: [PATCH 71/73] Reformat line to fix weird indentation issue --- src/com/reco1l/andengine/text/ExtendedText.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/com/reco1l/andengine/text/ExtendedText.kt b/src/com/reco1l/andengine/text/ExtendedText.kt index e899652a3..7c42670cf 100644 --- a/src/com/reco1l/andengine/text/ExtendedText.kt +++ b/src/com/reco1l/andengine/text/ExtendedText.kt @@ -29,7 +29,7 @@ open class ExtendedText : ExtendedEntity() { var text: String = "" set(value) { if (field != value) { - field = value + field = value if (value.length > maximumSize) { shouldRebuildVertexBuffer = true @@ -37,7 +37,7 @@ open class ExtendedText : ExtendedEntity() { } updateVertexBuffer() - } + } } /** @@ -47,17 +47,17 @@ open class ExtendedText : ExtendedEntity() { var font: Font? = null set(value) { if (field != value) { - field = value + field = value shouldRebuildTextureBuffer = true updateVertexBuffer() - } + } } /** * The horizontal alignment of the text. */ var horizontalAlign = HorizontalAlign.LEFT - set(value) { + set(value) { if (field != value) { field = value updateVertexBuffer() @@ -108,8 +108,8 @@ open class ExtendedText : ExtendedEntity() { currentSize = text.length if (text.length > maximumSize) { - shouldRebuildVertexBuffer = true - shouldRebuildTextureBuffer = true + shouldRebuildVertexBuffer = true + shouldRebuildTextureBuffer = true maximumSize = text.length } From 3ce2c138c901215c6720099a0660ea049746d65e Mon Sep 17 00:00:00 2001 From: Rian8337 <52914632+Rian8337@users.noreply.github.com> Date: Sat, 25 Jan 2025 19:19:03 +0800 Subject: [PATCH 72/73] Make `invalidateTransformations` `protected` --- src/com/reco1l/andengine/ExtendedEntity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/ExtendedEntity.kt b/src/com/reco1l/andengine/ExtendedEntity.kt index c7ea26f96..1575dac2d 100644 --- a/src/com/reco1l/andengine/ExtendedEntity.kt +++ b/src/com/reco1l/andengine/ExtendedEntity.kt @@ -367,7 +367,7 @@ abstract class ExtendedEntity( } } - open fun invalidateTransformations() { + protected open fun invalidateTransformations() { mLocalToParentTransformationDirty = true mParentToLocalTransformationDirty = true } From 7c1e3cf6a90ed70d4ebcc1e9fedd7cf95065b395 Mon Sep 17 00:00:00 2001 From: Rian8337 <52914632+Rian8337@users.noreply.github.com> Date: Sat, 25 Jan 2025 19:43:23 +0800 Subject: [PATCH 73/73] Update `GradientCircle` KDoc --- src/com/reco1l/andengine/shape/GradientCircle.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/reco1l/andengine/shape/GradientCircle.kt b/src/com/reco1l/andengine/shape/GradientCircle.kt index 2a8c66f82..388651741 100644 --- a/src/com/reco1l/andengine/shape/GradientCircle.kt +++ b/src/com/reco1l/andengine/shape/GradientCircle.kt @@ -10,7 +10,9 @@ import javax.microedition.khronos.opengles.* /** - * A circle shape. + * A circle that supports gradients. + * + * The gradient is applied from [startAngle] to [endAngle]. * * @author Reco1l */