package com.fdangelo.circleworld.universeview.tilemap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.fdangelo.circleworld.GameLogic;
import com.fdangelo.circleworld.universeengine.tilemap.ITilemapCircleListener;
import com.fdangelo.circleworld.universeengine.tilemap.TilemapCircle;
public class TilemapCircleView extends Actor implements ITilemapCircleListener {
private int lastHeight;
private int lastWidth;
private TilemapCircleViewBackgroundRenderer backgroundRenderer;
private TilemapCircleViewRenderer[] renderers;
private TilemapCircle tilemapCircle;
private Texture tilesetTexture;
public final Texture getTilesetTexture() {
return tilesetTexture;
}
public final TilemapCircle getTilemapCircle() {
return tilemapCircle;
}
public TilemapCircleView() {
}
public final void init(final TilemapCircle tilemapCircle) {
this.tilemapCircle = tilemapCircle;
tilemapCircle.setListener(this);
// Use the first texture in the atlas as the tileset texture
final TextureAtlas atlas = GameLogic.getInstace().assetManager.get("atlas/tilemap.atlas", TextureAtlas.class);
tilesetTexture = atlas.getTextures().iterator().next();
updatePosition();
initRenderers();
updateMesh();
}
private final void updateMesh() {
for (int i = 0; i < renderers.length; i++) {
renderers[i].updateMesh();
}
}
private final void initRenderers() {
final int renderersAmount = MathUtils.clamp(MathUtils.ceil((tilemapCircle.getWidth() * tilemapCircle.getHeight()) / (32 * 32)), 1, 256);
if (renderers == null || renderers.length != renderersAmount || lastWidth != tilemapCircle.getWidth() || lastHeight != tilemapCircle.getHeight()) {
// Destroy existing renderers
if (renderers != null) {
for (int i = 0; i < renderers.length; i++) {
renderers[i].dispose();
}
}
if (backgroundRenderer != null) {
backgroundRenderer.dispose();
}
// Add tile map circle renderers
renderers = new TilemapCircleViewRenderer[renderersAmount];
lastWidth = tilemapCircle.getWidth();
lastHeight = tilemapCircle.getHeight();
final int sizeX = MathUtils.ceil((float) tilemapCircle.getWidth() / (float) renderers.length);
int fromX = 0;
int toX = sizeX;
for (int i = 0; i < renderers.length; i++) {
renderers[i] = new TilemapCircleViewRenderer();
renderers[i].init(this, fromX, toX);
fromX += sizeX;
toX += sizeX;
if (toX >= tilemapCircle.getWidth()) {
toX = tilemapCircle.getWidth();
}
if (fromX > toX) {
fromX = toX;
}
}
// Add background renderer
backgroundRenderer = new TilemapCircleViewBackgroundRenderer();
}
backgroundRenderer.init(this);
for (int i = 0; i < renderers.length; i++) {
renderers[i].setDirty();
}
}
private final TilemapCircleViewRenderer getRenderer(final int tileX, final int tileY) {
if (renderers != null && renderers.length > 0) {
final int sizeX = MathUtils.ceil((float) tilemapCircle.getWidth() / (float) renderers.length);
final int rendererIndex = tileX / sizeX;
return renderers[rendererIndex];
}
return null;
}
@Override
public void onTilemapTileChanged(final int tileX, final int tileY) {
getRenderer(tileX, tileY).setDirty();
}
@Override
public void onTilemapParentChanged(final float deltaTime) {
updatePosition();
updateMesh();
}
static private Matrix4 tmpMatrix4 = new Matrix4();
@Override
public void draw(final Batch batch, final float parentAlpha) {
batch.end();
tmpMatrix4.set(batch.getProjectionMatrix());
tmpMatrix4.mul(batch.getTransformMatrix());
tmpMatrix4.translate(getX(), getY(), 0);
backgroundRenderer.draw(tmpMatrix4);
TilemapCircleViewRenderer.beginDraw(tmpMatrix4, tilesetTexture);
for (int i = 0; i < renderers.length; i++) {
renderers[i].draw();
}
TilemapCircleViewRenderer.endDraw();
batch.begin();
}
private final void updatePosition() {
setPosition(tilemapCircle.getPositionX(), tilemapCircle.getPositionY());
setRotation(tilemapCircle.getRotation() * MathUtils.radiansToDegrees);
}
public void recycle() {
tilemapCircle = null;
}
}