content: /*
   * This is a modified copy of OrthogonalTiledMapRenderer from libgdx. Original copyright follows:
   *
   * Copyright 2013 See AUTHORS file.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.agateau.pixelwheels.racescreen;
  
  import static com.badlogic.gdx.graphics.g2d.Batch.C1;
  import static com.badlogic.gdx.graphics.g2d.Batch.C2;
  import static com.badlogic.gdx.graphics.g2d.Batch.C3;
  import static com.badlogic.gdx.graphics.g2d.Batch.C4;
  import static com.badlogic.gdx.graphics.g2d.Batch.U1;
  import static com.badlogic.gdx.graphics.g2d.Batch.U2;
  import static com.badlogic.gdx.graphics.g2d.Batch.U3;
  import static com.badlogic.gdx.graphics.g2d.Batch.U4;
  import static com.badlogic.gdx.graphics.g2d.Batch.V1;
  import static com.badlogic.gdx.graphics.g2d.Batch.V2;
  import static com.badlogic.gdx.graphics.g2d.Batch.V3;
  import static com.badlogic.gdx.graphics.g2d.Batch.V4;
  import static com.badlogic.gdx.graphics.g2d.Batch.X1;
  import static com.badlogic.gdx.graphics.g2d.Batch.X2;
  import static com.badlogic.gdx.graphics.g2d.Batch.X3;
  import static com.badlogic.gdx.graphics.g2d.Batch.X4;
  import static com.badlogic.gdx.graphics.g2d.Batch.Y1;
  import static com.badlogic.gdx.graphics.g2d.Batch.Y2;
  import static com.badlogic.gdx.graphics.g2d.Batch.Y3;
  import static com.badlogic.gdx.graphics.g2d.Batch.Y4;
  
  import com.agateau.pixelwheels.map.MapUtils;
  import com.agateau.utils.Assert;
  import com.badlogic.gdx.graphics.Color;
  import com.badlogic.gdx.graphics.g2d.Batch;
  import com.badlogic.gdx.graphics.g2d.TextureRegion;
  import com.badlogic.gdx.maps.MapProperties;
  import com.badlogic.gdx.maps.tiled.TiledMap;
  import com.badlogic.gdx.maps.tiled.TiledMapTile;
  import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
  import com.badlogic.gdx.maps.tiled.renderers.BatchTiledMapRenderer;
  
  /** A copy of OrthogonalTiledMapRenderer, modified to repeat borders */
  public class PwTiledMapRenderer extends BatchTiledMapRenderer {
      private final int mPaddingLeft;
      private final int mPaddingTop;
      private final int mPaddingRight;
      private final int mPaddingBottom;
  
      private static int readPadding(TiledMap map, String name) {
          MapProperties properties = map.getProperties();
          int value = MapUtils.getIntProperty(properties, name, 1);
          Assert.check(value >= 1, "map padding should be >= 1");
          return value;
      }
  
      public PwTiledMapRenderer(TiledMap map, float unitScale, Batch batch) {
          super(map, unitScale, batch);
          mPaddingLeft = readPadding(map, "paddingLeft");
          mPaddingTop = readPadding(map, "paddingTop");
          mPaddingRight = readPadding(map, "paddingRight");
          mPaddingBottom = readPadding(map, "paddingBottom");
      }
  
      @Override
      public void renderTileLayer(TiledMapTileLayer layer) {
          final Color batchColor = batch.getColor();
          final float color =
                  Color.toFloatBits(
                          batchColor.r,
                          batchColor.g,
                          batchColor.b,
                          batchColor.a * layer.getOpacity());
  
          final int layerWidth = layer.getWidth();
          final int layerHeight = layer.getHeight();
  
          final float layerTileWidth = layer.getTileWidth() * unitScale;
          final float layerTileHeight = layer.getTileHeight() * unitScale;
  
          final float layerOffsetX = layer.getRenderOffsetX() * unitScale;
          // offset in tiled is y down, so we flip it
          final float layerOffsetY = -layer.getRenderOffsetY() * unitScale;
  
          final int col1 = (int) ((viewBounds.x - layerOffsetX) / layerTileWidth) - 1;
          final int col2 =
                  (int)
                          ((viewBounds.x + viewBounds.width + layerTileWidth - layerOffsetX)
                                  / layerTileWidth);
  
          final int row1 = (int) ((viewBounds.y - layerOffsetY) / layerTileHeight) - 1;
          final int row2 =
                  (int)
                          ((viewBounds.y + viewBounds.height + layerTileHeight - layerOffsetY)
                                  / layerTileHeight);
  
          float y = row2 * layerTileHeight + layerOffsetY;
          float xStart = col1 * layerTileWidth + layerOffsetX;
          final float[] vertices = this.vertices;
  
          for (int row = row2; row >= row1; row--) {
              float x = xStart;
              for (int col = col1; col < col2; col++) {
                  int cellCol = wrapClamp(col, 0, layerWidth - 1, mPaddingLeft, mPaddingRight);
                  int cellRow = wrapClamp(row, 0, layerHeight - 1, mPaddingBottom, mPaddingTop);
                  final TiledMapTileLayer.Cell cell = layer.getCell(cellCol, cellRow);
                  if (cell == null) {
                      x += layerTileWidth;
                      continue;
                  }
                  final TiledMapTile tile = cell.getTile();
  
                  if (tile != null) {
                      final boolean flipX = cell.getFlipHorizontally();
                      final boolean flipY = cell.getFlipVertically();
                      final int rotations = cell.getRotation();
  
                      TextureRegion region = tile.getTextureRegion();
  
                      float x1 = x + tile.getOffsetX() * unitScale;
                      float y1 = y + tile.getOffsetY() * unitScale;
                      float x2 = x1 + region.getRegionWidth() * unitScale;
                      float y2 = y1 + region.getRegionHeight() * unitScale;
  
                      float u1 = region.getU();
                      float v1 = region.getV2();
                      float u2 = region.getU2();
                      float v2 = region.getV();
  
                      vertices[X1] = x1;
                      vertices[Y1] = y1;
                      vertices[C1] = color;
                      vertices[U1] = u1;
                      vertices[V1] = v1;
  
                      vertices[X2] = x1;
                      vertices[Y2] = y2;
                      vertices[C2] = color;
                      vertices[U2] = u1;
                      vertices[V2] = v2;
  
                      vertices[X3] = x2;
                      vertices[Y3] = y2;
                      vertices[C3] = color;
                      vertices[U3] = u2;
                      vertices[V3] = v2;
  
                      vertices[X4] = x2;
                      vertices[Y4] = y1;
                      vertices[C4] = color;
                      vertices[U4] = u2;
                      vertices[V4] = v1;
  
                      if (flipX) {
                          float temp = vertices[U1];
                          vertices[U1] = vertices[U3];
                          vertices[U3] = temp;
                          temp = vertices[U2];
                          vertices[U2] = vertices[U4];
                          vertices[U4] = temp;
                      }
                      if (flipY) {
                          float temp = vertices[V1];
                          vertices[V1] = vertices[V3];
                          vertices[V3] = temp;
                          temp = vertices[V2];
                          vertices[V2] = vertices[V4];
                          vertices[V4] = temp;
                      }
                      if (rotations != 0) {
                          switch (rotations) {
                              case TiledMapTileLayer.Cell.ROTATE_90:
                                  {
                                      float tempV = vertices[V1];
                                      vertices[V1] = vertices[V2];
                                      vertices[V2] = vertices[V3];
                                      vertices[V3] = vertices[V4];
                                      vertices[V4] = tempV;
  
                                      float tempU = vertices[U1];
                                      vertices[U1] = vertices[U2];
                                      vertices[U2] = vertices[U3];
                                      vertices[U3] = vertices[U4];
                                      vertices[U4] = tempU;
                                      break;
                                  }
                              case TiledMapTileLayer.Cell.ROTATE_180:
                                  {
                                      float tempU = vertices[U1];
                                      vertices[U1] = vertices[U3];
                                      vertices[U3] = tempU;
                                      tempU = vertices[U2];
                                      vertices[U2] = vertices[U4];
                                      vertices[U4] = tempU;
                                      float tempV = vertices[V1];
                                      vertices[V1] = vertices[V3];
                                      vertices[V3] = tempV;
                                      tempV = vertices[V2];
                                      vertices[V2] = vertices[V4];
                                      vertices[V4] = tempV;
                                      break;
                                  }
                              case TiledMapTileLayer.Cell.ROTATE_270:
                                  {
                                      float tempV = vertices[V1];
                                      vertices[V1] = vertices[V4];
                                      vertices[V4] = vertices[V3];
                                      vertices[V3] = vertices[V2];
                                      vertices[V2] = tempV;
  
                                      float tempU = vertices[U1];
                                      vertices[U1] = vertices[U4];
                                      vertices[U4] = vertices[U3];
                                      vertices[U3] = vertices[U2];
                                      vertices[U2] = tempU;
                                      break;
                                  }
                          }
                      }
                      batch.draw(region.getTexture(), vertices, 0, NUM_VERTICES);
                  }
                  x += layerTileWidth;
              }
              y -= layerTileHeight;
          }
      }
  
      @SuppressWarnings("SameParameterValue")
      private static int wrapClamp(int value, int min, int max, int paddingMin, int paddingMax) {
          while (value < min) {
              value += paddingMin;
          }
          while (value > max) {
              value -= paddingMax;
          }
          return value;
      }
  }
  