Skip to content

Commit

Permalink
align for TiledDrawable (libgdx#7207)
Browse files Browse the repository at this point in the history
* TiledDrawable align

* Removed obsolete ShapeRenderer from test

* Apply formatter

* Removed redundant loops
  • Loading branch information
TCreutzenberg authored Oct 6, 2023
1 parent 99c1090 commit f23b840
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[1.12.1]
- LWJGL3 Improvement: Audio device is automatically switched if it was changed in the operating system.
- Tiled Fix: TiledLayer parallax default values fix
- API Addition: TiledDrawable: Align can be set to manipulate the alignment of the rendering (TiledDrawable#setAlign, TiledDrawable#getAlign)
- API Addition: TiledDrawable#draw: Also available as a static function (with align) if you don't want to create an extra instance per texture region
- Android: Removed mouse catching added on 1.12.0 due to unintended effects (see #7187).
- iOS: Update to MobiVM 2.3.20
- API Addition: Using "object" property in Tiled object now fetches MapObject being pointed to, and BaseTmxMapLoader includes method for fetching map where key is id and value is MapObject instance.
Expand Down
253 changes: 216 additions & 37 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/utils/TiledDrawable.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Align;

/** Draws a {@link TextureRegion} repeatedly to fill the area, instead of stretching it.
* @author Nathan Sweet */
* @author Nathan Sweet
* @author Thomas Creutzenberg */
public class TiledDrawable extends TextureRegionDrawable {
private final Color color = new Color(1, 1, 1, 1);
private float scale = 1;
private int align = Align.bottomLeft;

public TiledDrawable () {
super();
Expand All @@ -43,50 +46,218 @@ public void draw (Batch batch, float x, float y, float width, float height) {
float oldColor = batch.getPackedColor();
batch.setColor(batch.getColor().mul(color));

TextureRegion region = getRegion();
float regionWidth = region.getRegionWidth() * scale, regionHeight = region.getRegionHeight() * scale;
int fullX = (int)(width / regionWidth), fullY = (int)(height / regionHeight);
float remainingX = width - regionWidth * fullX, remainingY = height - regionHeight * fullY;
float startX = x, startY = y;
float endX = x + width - remainingX, endY = y + height - remainingY;
for (int i = 0; i < fullX; i++) {
y = startY;
for (int ii = 0; ii < fullY; ii++) {
batch.draw(region, x, y, regionWidth, regionHeight);
y += regionHeight;
draw(batch, getRegion(), x, y, width, height, scale, align);

batch.setPackedColor(oldColor);
}

public static void draw (Batch batch, TextureRegion textureRegion, float x, float y, float width, float height, float scale,
int align) {
final float regionWidth = textureRegion.getRegionWidth() * scale;
final float regionHeight = textureRegion.getRegionHeight() * scale;

final Texture texture = textureRegion.getTexture();
final float textureWidth = texture.getWidth() * scale;
final float textureHeight = texture.getHeight() * scale;
final float u = textureRegion.getU();
final float v = textureRegion.getV();
final float u2 = textureRegion.getU2();
final float v2 = textureRegion.getV2();

int fullX = (int)(width / regionWidth);
final float leftPartialWidth;
final float rightPartialWidth;
if (Align.isLeft(align)) {
leftPartialWidth = 0f;
rightPartialWidth = width - (regionWidth * fullX);
} else if (Align.isRight(align)) {
leftPartialWidth = width - (regionWidth * fullX);
rightPartialWidth = 0f;
} else {
if (fullX != 0) {
fullX = fullX % 2 == 1 ? fullX : fullX - 1;
final float leftRight = 0.5f * (width - (regionWidth * fullX));
leftPartialWidth = leftRight;
rightPartialWidth = leftRight;
} else {
leftPartialWidth = 0f;
rightPartialWidth = 0f;
}
}
int fullY = (int)(height / regionHeight);
final float topPartialHeight;
final float bottomPartialHeight;
if (Align.isTop(align)) {
topPartialHeight = 0f;
bottomPartialHeight = height - (regionHeight * fullY);
} else if (Align.isBottom(align)) {
topPartialHeight = height - (regionHeight * fullY);
bottomPartialHeight = 0f;
} else {
if (fullY != 0) {
fullY = fullY % 2 == 1 ? fullY : fullY - 1;
final float topBottom = 0.5f * (height - (regionHeight * fullY));
topPartialHeight = topBottom;
bottomPartialHeight = topBottom;
} else {
topPartialHeight = 0f;
bottomPartialHeight = 0f;
}
x += regionWidth;
}
Texture texture = region.getTexture();
float u = region.getU();
float v2 = region.getV2();
if (remainingX > 0) {
// Right edge.
float u2 = u + remainingX / (texture.getWidth() * scale);
float v = region.getV();
y = startY;
for (int ii = 0; ii < fullY; ii++) {
batch.draw(texture, x, y, remainingX, regionHeight, u, v2, u2, v);
y += regionHeight;

float drawX = x;
float drawY = y;

// Left edge
if (leftPartialWidth > 0f) {
final float leftEdgeU = u2 - (leftPartialWidth / textureWidth);

// Left bottom partial
if (bottomPartialHeight > 0f) {
final float leftBottomV = v + (bottomPartialHeight / textureHeight);
batch.draw(texture, drawX, drawY, leftPartialWidth, bottomPartialHeight, leftEdgeU, leftBottomV, u2, v);
drawY += bottomPartialHeight;
}
// Upper right corner.
if (remainingY > 0) {
v = v2 - remainingY / (texture.getHeight() * scale);
batch.draw(texture, x, y, remainingX, remainingY, u, v2, u2, v);

// Left center partials
if (fullY == 0 && Align.isCenterVertical(align)) {
final float vOffset = 0.5f * (v2 - v) * (1f - (height / regionHeight));
final float leftCenterV = v2 - vOffset;
final float leftCenterV2 = v + vOffset;
batch.draw(texture, drawX, drawY, leftPartialWidth, height, leftEdgeU, leftCenterV, u2, leftCenterV2);
drawY += height;
} else {
for (int i = 0; i < fullY; i++) {
batch.draw(texture, drawX, drawY, leftPartialWidth, regionHeight, leftEdgeU, v2, u2, v);
drawY += regionHeight;
}
}

// Left top partial
if (topPartialHeight > 0f) {
final float leftTopV = v2 - (topPartialHeight / textureHeight);
batch.draw(texture, drawX, drawY, leftPartialWidth, topPartialHeight, leftEdgeU, v2, u2, leftTopV);
}
}
if (remainingY > 0) {
// Top edge.
float u2 = region.getU2();
float v = v2 - remainingY / (texture.getHeight() * scale);
x = startX;
for (int i = 0; i < fullX; i++) {
batch.draw(texture, x, y, regionWidth, remainingY, u, v2, u2, v);
x += regionWidth;

// Center full texture regions
{
// Center bottom partials
if (bottomPartialHeight > 0f) {
drawX = x + leftPartialWidth;
drawY = y;

final float centerBottomV = v + (bottomPartialHeight / textureHeight);

if (fullX == 0 && Align.isCenterHorizontal(align)) {
final float uOffset = 0.5f * (u2 - u) * (1f - (width / regionWidth));
final float centerBottomU = u + uOffset;
final float centerBottomU2 = u2 - uOffset;
batch.draw(texture, drawX, drawY, width, bottomPartialHeight, centerBottomU, centerBottomV, centerBottomU2, v);
drawX += width;
} else {
for (int i = 0; i < fullX; i++) {
batch.draw(texture, drawX, drawY, regionWidth, bottomPartialHeight, u, centerBottomV, u2, v);
drawX += regionWidth;
}
}
}

// Center full texture regions
{
drawX = x + leftPartialWidth;

final int originalFullX = fullX;
final int originalFullY = fullY;

float centerCenterDrawWidth = regionWidth;
float centerCenterDrawHeight = regionHeight;
float centerCenterU = u;
float centerCenterU2 = u2;
float centerCenterV = v2;
float centerCenterV2 = v;
if (fullX == 0 && Align.isCenterHorizontal(align)) {
fullX = 1;
centerCenterDrawWidth = width;
final float uOffset = 0.5f * (u2 - u) * (1f - (width / regionWidth));
centerCenterU = u + uOffset;
centerCenterU2 = u2 - uOffset;
}
if (fullY == 0 && Align.isCenterVertical(align)) {
fullY = 1;
centerCenterDrawHeight = height;
final float vOffset = 0.5f * (v2 - v) * (1f - (height / regionHeight));
centerCenterV = v2 - vOffset;
centerCenterV2 = v + vOffset;
}
for (int i = 0; i < fullX; i++) {
drawY = y + bottomPartialHeight;
for (int ii = 0; ii < fullY; ii++) {
batch.draw(texture, drawX, drawY, centerCenterDrawWidth, centerCenterDrawHeight, centerCenterU, centerCenterV,
centerCenterU2, centerCenterV2);
drawY += centerCenterDrawHeight;
}
drawX += centerCenterDrawWidth;
}

fullX = originalFullX;
fullY = originalFullY;
}

// Center top partials
if (topPartialHeight > 0f) {
drawX = x + leftPartialWidth;

final float centerTopV = v2 - (topPartialHeight / textureHeight);

if (fullX == 0 && Align.isCenterHorizontal(align)) {
final float uOffset = 0.5f * (u2 - u) * (1f - (width / regionWidth));
final float centerTopU = u + uOffset;
final float centerTopU2 = u2 - uOffset;
batch.draw(texture, drawX, drawY, width, topPartialHeight, centerTopU, v2, centerTopU2, centerTopV);
drawX += width;
} else {
for (int i = 0; i < fullX; i++) {
batch.draw(texture, drawX, drawY, regionWidth, topPartialHeight, u, v2, u2, centerTopV);
drawX += regionWidth;
}
}
}
}

batch.setPackedColor(oldColor);
// Right edge
if (rightPartialWidth > 0f) {
drawY = y;

final float rightEdgeU2 = u + (rightPartialWidth / textureWidth);

// Right bottom partial
if (bottomPartialHeight > 0f) {
final float rightBottomV = v + (bottomPartialHeight / textureHeight);
batch.draw(texture, drawX, drawY, rightPartialWidth, bottomPartialHeight, u, rightBottomV, rightEdgeU2, v);
drawY += bottomPartialHeight;
}

// Right center partials
if (fullY == 0 && Align.isCenterVertical(align)) {
final float vOffset = 0.5f * (v2 - v) * (1f - (height / regionHeight));
final float rightCenterV = v2 - vOffset;
final float rightCenterV2 = v + vOffset;
batch.draw(texture, drawX, drawY, rightPartialWidth, height, u, rightCenterV, rightEdgeU2, rightCenterV2);
drawY += height;
} else {
for (int i = 0; i < fullY; i++) {
batch.draw(texture, drawX, drawY, rightPartialWidth, regionHeight, u, v2, rightEdgeU2, v);
drawY += regionHeight;
}
}

// Right top partial
if (topPartialHeight > 0f) {
final float rightTopV = v2 - (topPartialHeight / textureHeight);
batch.draw(texture, drawX, drawY, rightPartialWidth, topPartialHeight, u, v2, rightEdgeU2, rightTopV);
}
}
}

public void draw (Batch batch, float x, float y, float originX, float originY, float width, float height, float scaleX,
Expand All @@ -106,6 +277,14 @@ public float getScale () {
return scale;
}

public int getAlign () {
return align;
}

public void setAlign (int align) {
this.align = align;
}

public TiledDrawable tint (Color tint) {
TiledDrawable drawable = new TiledDrawable(this);
drawable.color.set(tint);
Expand Down
27 changes: 27 additions & 0 deletions tests/gdx-tests-android/assets/data/testAtlas.atlas
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
testAtlas.png
size: 256, 64
filter: Linear, Linear
black
bounds: 126, 16, 4, 8
darkBlue
bounds: 2, 33, 26, 26
darkBlue2
bounds: 2, 2, 26, 26
darkGray
bounds: 33, 33, 26, 26
darkGray2
bounds: 33, 2, 26, 26
darkGreen
bounds: 64, 33, 26, 26
darkGreen2
bounds: 64, 2, 26, 26
grey
bounds: 126, 29, 22, 30
pink
bounds: 95, 33, 26, 26
purple
bounds: 153, 17, 16, 42
tileTester
bounds: 95, 2, 26, 26
white
bounds: 174, 57, 4, 2
Binary file added tests/gdx-tests-android/assets/data/testAtlas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit f23b840

Please sign in to comment.