All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mini2Dx.libgdx.LibgdxGraphics Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright 2019 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 org.mini2Dx.libgdx;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.LibgdxSpriteBatchWrapper;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Align;
import org.mini2Dx.core.Graphics;
import org.mini2Dx.core.GraphicsDriver;
import org.mini2Dx.core.Mdx;
import org.mini2Dx.core.font.GameFont;
import org.mini2Dx.core.font.GameFontCache;
import org.mini2Dx.core.geom.Rectangle;
import org.mini2Dx.core.geom.Shape;
import org.mini2Dx.core.graphics.*;
import org.mini2Dx.gdx.math.EarClippingTriangulator;
import org.mini2Dx.gdx.math.MathUtils;
import org.mini2Dx.gdx.math.Matrix4;
import org.mini2Dx.libgdx.game.GameWrapper;
import org.mini2Dx.libgdx.graphics.*;

public class LibgdxGraphics implements Graphics {
	enum RenderState {
		NOT_RENDERING,
		SHAPES,
		POLYGONS,
		SPRITEBATCH
	}

	private static final String LOGGING_TAG = LibgdxGraphics.class.getSimpleName();

	public final LibgdxSpriteBatchWrapper spriteBatch;

	private final static Vector3 cameraRotationPoint = new Vector3(0, 0, 0), cameraRotationAxis = new Vector3(0, 0, 1);
	private final GameWrapper gameWrapper;
	private final ShapeTextureCache colorTextureCache;
	private final ShapeRenderer shapeRenderer;
	private final PolygonSpriteBatch polygonSpriteBatch;
	private final EarClippingTriangulator triangulator = new EarClippingTriangulator();

	private LibgdxColor color, defaultColor, backgroundColor;
	private LibgdxColor tint, defaultTint;
	private OrthographicCamera camera;
	private GameFont font;
	private LibgdxShader defaultShader, currentShader;

	private float translationX, translationY;
	private float scaleX, scaleY;
	private float rotation, rotationX, rotationY;
	private int windowWidth, windowHeight;

	private int defaultBlendSrcFunc = GL20.GL_SRC_ALPHA, defaultBlendDstFunc = GL20.GL_ONE_MINUS_SRC_ALPHA;
	private int lineHeight;
	private RenderState rendering;
	private boolean transformationsApplied;
	private Rectangle clip;

	private float [] triangleVertices = new float[6];
	//3 edge polygon by default, expanded as needed during rendering
	private float [] polygonRenderData = new float[15];

	public LibgdxGraphics(GameWrapper gameWrapper, LibgdxSpriteBatchWrapper spriteBatch, PolygonSpriteBatch polygonSpriteBatch, ShapeRenderer shapeRenderer) {
		this.gameWrapper = gameWrapper;
		this.spriteBatch = spriteBatch;
		this.shapeRenderer = shapeRenderer;
		this.shapeRenderer.setAutoShapeType(true);
		this.polygonSpriteBatch = polygonSpriteBatch;

		this.windowWidth = Gdx.graphics.getWidth();
		this.windowHeight = Gdx.graphics.getHeight();

		defaultTint = new LibgdxReadOnlyColor(spriteBatch.getColor().cpy());
		font = Mdx.fonts.defaultFont();
		tint = defaultTint;

		lineHeight = 1;
		color = new LibgdxColor(1f, 1f, 1f, 1f);
		defaultColor = new LibgdxReadOnlyColor(1f, 1f, 1f, 1f);
		backgroundColor = new LibgdxColor(0f, 0f, 0f, 1f);
		colorTextureCache = new ShapeTextureCache();

		translationX = 0;
		translationY = 0;
		scaleX = 1f;
		scaleY = 1f;
		rotation = 0f;
		rotationX = 0f;
		rotationY = 0f;

		/* Create Ortho camera so that 0,0 is in top-left */
		camera = new OrthographicCamera();
	}

	@Override
	public void preRender(int gameWidth, int gameHeight) {
		this.windowWidth = gameWidth;
		this.windowHeight = gameHeight;

		tint = defaultTint;
		color = defaultColor;
		spriteBatch.setColor(tint.rf(), tint.gf(), tint.bf(), tint.af());

		Gdx.gl.glClearColor(backgroundColor.rf(), backgroundColor.gf(), backgroundColor.bf(), 1f);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_STENCIL_BUFFER_BIT);

		rendering = RenderState.NOT_RENDERING;

		if (defaultShader == null) {
			defaultShader = new LibgdxShader(SpriteBatch.createDefaultShader());
			currentShader = defaultShader;
		}
	}

	@Override
	public void postRender() {
		endRendering();
		resetTransformations();
		clearShader();
		clearBlendFunction();
	}

	@Override
	public void clearContext() {
		clearContext(backgroundColor, true, true);
	}

	@Override
	public void clearContext(Color color) {
		clearContext(color, true, true);
	}

	@Override
	public void clearContext(Color color, boolean depthBufferBit, boolean colorBufferBit) {
		int mask;
		if(depthBufferBit && colorBufferBit) {
			mask = GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT;
		} else if(depthBufferBit) {
			mask = GL20.GL_DEPTH_BUFFER_BIT;
		} else if(colorBufferBit) {
			mask = GL20.GL_COLOR_BUFFER_BIT;
		} else {
			mask = 0;
		}

		Gdx.gl.glClearColor(color.rf(), color.gf(), color.bf(), color.af());
		Gdx.gl.glClear(mask);
	}

	private void setupDepthBuffer() {
		if (clip != null) {
			Gdx.gl.glDepthFunc(GL20.GL_LESS);
			Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);

			Gdx.gl.glDepthMask(true);
			Gdx.gl.glColorMask(false, false, false, false);

			shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);

			shapeRenderer.setColor(0f, 1f, 0f, 0.5f);
			shapeRenderer.rect(clip.getX(), clip.getY(), clip.getWidth(), clip.getHeight());

			shapeRenderer.end();

			Gdx.gl.glColorMask(true, true, true, true);
			Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
			Gdx.gl.glDepthFunc(GL20.GL_EQUAL);
		}
	}

	private void beginRendering(RenderState newState) {
		if (newState == rendering){
			return;
		}
		switch (rendering){
			case NOT_RENDERING:
				applyTransformations();
				Gdx.gl.glClearDepthf(1f);
				Gdx.gl.glClear(GL20.GL_DEPTH_BUFFER_BIT);
				setupDepthBuffer();
				break;
			case SHAPES:
				shapeRenderer.end();
				break;
			case POLYGONS:
				polygonSpriteBatch.end();
				break;
			case SPRITEBATCH:
				spriteBatch.end();
				break;
		}
		switch (newState){
			case SHAPES:
				shapeRenderer.begin();
				break;
			case POLYGONS:
				polygonSpriteBatch.begin();
				break;
			case SPRITEBATCH:
				spriteBatch.begin();
				break;
		}
		rendering = newState;
	}

	/**
	 * Ends rendering
	 */
	private void endRendering() {
		switch (rendering){
			case NOT_RENDERING:
				return;
			case SHAPES:
				shapeRenderer.end();
				break;
			case POLYGONS:
				polygonSpriteBatch.end();
				break;
			case SPRITEBATCH:
				spriteBatch.end();
				break;
		}
		undoTransformations();
		if (clip != null) {
			Gdx.gl.glClearDepthf(1f);
			Gdx.gl.glClear(GL20.GL_DEPTH_BUFFER_BIT);
			Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
		}
		rendering = RenderState.NOT_RENDERING;
	}

	/**
	 * Applies all translation, scaling and rotation to the {@link SpriteBatch}
	 */
	private void applyTransformations() {
		if (!transformationsApplied) {
			transformationsApplied = true;
			float viewportWidth = MathUtils.round(windowWidth / scaleX);
			float viewportHeight = MathUtils.round(windowHeight / scaleY);

			camera.setToOrtho(true, viewportWidth, viewportHeight);

			if (translationX != 0f || translationY != 0f) {
				camera.translate(translationX, translationY);
			}
			camera.update();

			if (rotation != 0f) {
				cameraRotationPoint.x = rotationX;
				cameraRotationPoint.y = rotationY;
				camera.rotateAround(cameraRotationPoint, cameraRotationAxis, -rotation);
			}
			camera.update();

			spriteBatch.setProjectionMatrix(camera.combined);
			shapeRenderer.setProjectionMatrix(camera.combined);
			polygonSpriteBatch.setProjectionMatrix(camera.combined);
		}
	}

	/**
	 * Cleans up all translations, scaling and rotation
	 */
	private void undoTransformations() {
		if (transformationsApplied) {
			transformationsApplied = false;
			if (rotation != 0f) {
				camera.rotateAround(cameraRotationPoint, cameraRotationAxis, rotation);
			}
			camera.update();

			if (translationX != 0f || translationY != 0f) {
				camera.translate(-translationX, -translationY);
			}
			camera.update();
		}
	}

	/**
	 * Resets transformation values
	 */
	private void resetTransformations() {
		this.translationX = 0;
		this.translationY = 0;
		this.scaleX = 1f;
		this.scaleY = 1f;
		this.rotation = 0f;
		this.rotationX = 0f;
		this.rotationY = 0f;
	}


	@Override
	public void drawLineSegment(float x1, float y1, float x2, float y2) {
		beginShapeRendering(ShapeRenderer.ShapeType.Filled);

		shapeRenderer.rectLine(x1, y1, x2, y2, lineHeight);
	}

	@Override
	public void drawRect(float x, float y, float width, float height) {
		int roundWidth = MathUtils.round(width);
		int roundHeight = MathUtils.round(height);

		beginShapeRendering(ShapeRenderer.ShapeType.Filled);
		shapeRenderer.rectLine(x, y, x + roundWidth, y, lineHeight);
		shapeRenderer.rectLine(x, y, x , y + roundHeight, lineHeight);
		shapeRenderer.rectLine(x + roundWidth, y, x + roundWidth, y + roundHeight, lineHeight);
		shapeRenderer.rectLine(x, y + roundHeight, x + roundWidth, y + roundHeight, lineHeight);
	}

	private void beginShapeRendering(ShapeRenderer.ShapeType shapeType) {
		beginRendering(RenderState.SHAPES);

		shapeRenderer.set(shapeType);
		shapeRenderer.setColor(color.rf(), color.gf(), color.bf(), color.af());
	}

	@Override
	public void fillRect(float x, float y, float width, float height) {
		beginRendering(RenderState.SPRITEBATCH);

		spriteBatch.draw(colorTextureCache.getFilledRectangleTexture(color), x, y, 0, 0, width, height, 1f, 1f, 0, 0, 0,
				1, 1, false, false);
	}

	@Override
	public void drawCircle(float centerX, float centerY, int radius) {
		beginShapeRendering(ShapeRenderer.ShapeType.Line);
		shapeRenderer.circle(centerX, centerY, radius);
	}

	@Override
	public void drawCircle(float centerX, float centerY, float radius) {
		drawCircle(centerX, centerY, MathUtils.round(radius));
	}

	@Override
	public void fillCircle(float centerX, float centerY, int radius) {
		beginShapeRendering(ShapeRenderer.ShapeType.Filled);
		shapeRenderer.circle(centerX, centerY, radius);
	}

	@Override
	public void fillCircle(float centerX, float centerY, float radius) {
		fillCircle(centerX, centerY, MathUtils.round(radius));
	}

	@Override
	public void drawTriangle(float x1, float y1, float x2, float y2, float x3, float y3) {
		triangleVertices[0] = x1;
		triangleVertices[1] = y1;
		triangleVertices[2] = x2;
		triangleVertices[3] = y2;
		triangleVertices[4] = x3;
		triangleVertices[5] = y3;
		drawPolygon(triangleVertices);
	}

	@Override
	public void fillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) {
		triangleVertices[0] = x1;
		triangleVertices[1] = y1;
		triangleVertices[2] = x2;
		triangleVertices[3] = y2;
		triangleVertices[4] = x3;
		triangleVertices[5] = y3;
		fillPolygon(triangleVertices, triangulator.computeTriangles(triangleVertices).items);
	}

	@Override
	public void drawPolygon(float[] vertices) {
		beginShapeRendering(ShapeRenderer.ShapeType.Line);
		shapeRenderer.polygon(vertices);
	}

	@Override
	public void fillPolygon(float[] vertices, short[] triangles) {
		beginRendering(RenderState.POLYGONS);
		if(vertices.length * 5 > polygonRenderData.length) {
			polygonRenderData = new float[vertices.length * 5];
		}

		int totalPoints = vertices.length / 2;
		for(int i = 0; i < totalPoints; i++) {
			int verticesIndex = i * 2;
			int renderIndex = i * 5;
			polygonRenderData[renderIndex] = vertices[verticesIndex];
			polygonRenderData[renderIndex + 1] = vertices[verticesIndex + 1];
			polygonRenderData[renderIndex + 2] = color.color.toFloatBits();
			polygonRenderData[renderIndex + 3] = vertices[verticesIndex];
			polygonRenderData[renderIndex + 4] = vertices[verticesIndex + 1];
		}
		polygonSpriteBatch.draw(colorTextureCache.getFilledRectangleTexture(color), polygonRenderData, 0, vertices.length * 5, triangles, 0, triangles.length);
	}

	@Override
	public void drawString(String text, float x, float y) {
		if (font == null) {
			return;
		}
		beginRendering(RenderState.SPRITEBATCH);
		font.setColor(color);
		font.draw(this, text, x, y);
	}

	@Override
	public void drawString(String text, float x, float y, float targetWidth) {
		drawString(text, x, y, targetWidth, Align.left);
	}

	@Override
	public void drawString(String text, float x, float y, float targetWidth, int horizontalAlign) {
		if (font == null) {
			return;
		}
		beginRendering(RenderState.SPRITEBATCH);
		font.setColor(color);
		font.draw(this, text, x, y, targetWidth, horizontalAlign, true);
	}

	@Override
	public void drawTexture(Texture texture, float x, float y) {
		drawTexture(texture, x, y, texture.getWidth(), texture.getHeight());
	}

	@Override
	public void drawTexture(Texture texture, float x, float y, boolean flipY) {
		drawTexture(texture, x, y, texture.getWidth(), texture.getHeight(), flipY);
	}

	@Override
	public void drawTexture(Texture texture, float x, float y, float width, float height) {
		drawTexture(texture, x, y, width, height, true);
	}

	@Override
	public void drawTexture(Texture texture, float x, float y, float width, float height, boolean flipY) {
		beginRendering(RenderState.SPRITEBATCH);
		final LibgdxTexture gdxTexture = (LibgdxTexture) texture;
		spriteBatch.draw(gdxTexture, x, y, 0, 0, width, height, 1f, 1f, 0, 0, 0, texture.getWidth(), texture.getHeight(),
				false, flipY);
	}

	@Override
	public void drawTextureRegion(TextureRegion textureRegion, float x, float y) {
		drawTextureRegion(textureRegion, x, y, textureRegion.getRegionWidth(), textureRegion.getRegionHeight());
	}

	@Override
	public void drawTextureRegion(TextureRegion textureRegion, float x, float y, float width, float height) {
		drawTextureRegion(textureRegion, x, y, width, height, 0f);
	}

	@Override
	public void drawTextureRegion(TextureRegion textureRegion, float x, float y, float width, float height,
	                              float rotation) {
		beginRendering(RenderState.SPRITEBATCH);
		final GdxTextureRegion gdxTextureRegion = (GdxTextureRegion) textureRegion;
		spriteBatch.draw(gdxTextureRegion.asGdxTextureRegion(), x, y, 0f, 0f, width, height, 1f, 1f, rotation);
	}

	@Override
	public void drawShape(Shape shape) {
		shape.draw(this);
	}

	@Override
	public void fillShape(Shape shape) {
		shape.fill(this);
	}

	@Override
	public void drawSprite(Sprite sprite) {
		final LibgdxSprite gdxSprite = (LibgdxSprite) sprite;
		beginRendering(RenderState.SPRITEBATCH);
		gdxSprite.sprite.draw(spriteBatch);
	}

	@Override
	public void drawSprite(Sprite sprite, float x, float y) {
		final LibgdxSprite gdxSprite = (LibgdxSprite) sprite;

		beginRendering(RenderState.SPRITEBATCH);
		float oldX = sprite.getX();
		float oldY = sprite.getY();
		Color oldTint = sprite.getTint();

		if (tint != null) {
			sprite.setTint(tint);
		}
		sprite.setPosition(x, y);
		gdxSprite.sprite.draw(spriteBatch);
		sprite.setPosition(oldX, oldY);
		sprite.setTint(oldTint);
	}

	@Override
	public void drawSpriteCache(SpriteCache spriteCache, int cacheId) {
		spriteCache.draw(this, cacheId);
	}

	@Override
	public void drawParticleEffect(ParticleEffect effect) {

	}

	@Override
	public void drawNinePatch(NinePatch ninePatch, float x, float y, float width, float height) {
		beginRendering(RenderState.SPRITEBATCH);

		ninePatch.render(this, x, y, width, height);
	}

	@Override
	public void drawTilingDrawable(TilingDrawable tilingDrawable, float x, float y, float width, float height) {
		tilingDrawable.draw(this, x, y, width, height);
	}

	@Override
	public void drawFontCache(GameFontCache fontCache) {
		beginRendering(RenderState.SPRITEBATCH);
		fontCache.draw(this);
	}

	@Override
	public void setClip(float x, float y, float width, float height) {
		endRendering();

		if(MathUtils.isEqual(0f, x) && MathUtils.isEqual(0f, y) &&
				MathUtils.isEqual(getViewportWidth(), width) &&
				MathUtils.isEqual(getViewportHeight(), height)) {
			clip = null;
		} else if(clip == null) {
			clip = new Rectangle(x, y, width, height);
		} else {
			clip.set(x, y, width, height);
		}
	}

	@Override
	public void setClip(Rectangle clip) {
		setClip(clip.getX(), clip.getY(), clip.getWidth(), clip.getHeight());
	}

	@Override
	public Rectangle removeClip() {
		if (clip == null) {
			return null;
		}
		endRendering();

		Rectangle result = clip;
		clip = null;
		return result;
	}

	@Override
	public Rectangle peekClip() {
		Rectangle result = new Rectangle();
		peekClip(result);
		return result;
	}

	@Override
	public void peekClip(Rectangle rectangle) {
		if(clip == null) {
			rectangle.set(0f, 0f, getViewportWidth(), getViewportHeight());
		} else {
			rectangle.set(clip);
		}
	}

	@Override
	public void setTint(Color tint) {
		this.tint = (LibgdxColor) tint;
		spriteBatch.setColor(tint.rf(), tint.gf(), tint.bf(), tint.af());
	}

	@Override
	public void removeTint() {
		setTint(defaultTint);
	}

	@Override
	public void enableBlending() {
		spriteBatch.enableBlending();
	}

	@Override
	public void disableBlending() {
		spriteBatch.disableBlending();
	}

	@Override
	public void setShader(Shader shader) {
		this.currentShader = (LibgdxShader) shader;
		spriteBatch.setShader(currentShader.shaderProgram);
	}

	@Override
	public Shader getShader() {
		return currentShader;
	}

	@Override
	public void clearShader() {
		currentShader = defaultShader;
		setShader(currentShader);
	}

	@Override
	public void setBlendFunction(Mini2DxBlendFunction srcFunc, Mini2DxBlendFunction dstFunc) {
		final int srcF, dstF;

		srcF = convertBlendFunction(srcFunc);
		dstF = convertBlendFunction(dstFunc);
		spriteBatch.setBlendFunction(srcF, dstF);
	}

	private int convertBlendFunction(Mini2DxBlendFunction func) {
		switch(func) {
			default:
			case ZERO:
				return GL20.GL_ZERO;
			case ONE:
				return GL20.GL_ONE;
			case SRC_COLOR:
				return GL20.GL_SRC_COLOR;
			case ONE_MINUS_SRC_COLOR:
				return GL20.GL_ONE_MINUS_SRC_COLOR;
			case DST_COLOR:
				return GL20.GL_DST_COLOR;
			case ONE_MINUS_DST_COLOR:
				return GL20.GL_ONE_MINUS_DST_COLOR;
			case SRC_ALPHA:
				return GL20.GL_SRC_ALPHA;
			case ONE_MINUS_SRC_ALPHA:
				return GL20.GL_ONE_MINUS_SRC_ALPHA;
			case DST_ALPHA:
				return GL20.GL_DST_ALPHA;
			case ONE_MINUS_DST_ALPHA:
				return GL20.GL_ONE_MINUS_DST_ALPHA;
			case SRC_ALPHA_SATURATE:
				return GL20.GL_SRC_ALPHA_SATURATE;
		}
	}

	@Override
	public void clearBlendFunction() {
		spriteBatch.setBlendFunction(defaultBlendSrcFunc, defaultBlendDstFunc);
	}

	@Override
	public void flush() {
		spriteBatch.flush();
	}

	@Override
	public void setFont(GameFont font) {
		if (font == null) {
			return;
		}
		this.font = font;
	}

	@Override
	public void setLineHeight(int lineHeight) {
		if (lineHeight > 0) {
			this.lineHeight = lineHeight;
		}
	}

	@Override
	public void setColor(Color color) {
		if (color == null) {
			return;
		}
		this.color = (LibgdxColor) color;
	}

	@Override
	public void setBackgroundColor(Color backgroundColor) {
		if (backgroundColor != null) {
			this.backgroundColor = (LibgdxColor) backgroundColor;
		}
	}

	@Override
	public void scale(float scaleX, float scaleY) {
		if (MathUtils.isEqual(1f, scaleX) && MathUtils.isEqual(1f, scaleY)) {
			return;
		}
		endRendering();

		this.scaleX *= scaleX;
		this.scaleY *= scaleY;
	}

	@Override
	public void setScale(float scaleX, float scaleY) {
		if (MathUtils.isEqual(this.scaleX, scaleX) && MathUtils.isEqual(this.scaleY, scaleY)) {
			return;
		}
		endRendering();

		this.scaleX = scaleX;
		this.scaleY = scaleY;
	}

	@Override
	public void clearScaling() {
		if (MathUtils.isEqual(this.scaleX, 1f) && MathUtils.isEqual(this.scaleY, 1f)) {
			return;
		}
		endRendering();

		scaleX = 1f;
		scaleY = 1f;
	}

	@Override
	public void translate(float translateX, float translateY) {
		if (MathUtils.isZero(translateX) && MathUtils.isZero(translateY)) {
			return;
		}
		endRendering();

		this.translationX += translateX;
		this.translationY += translateY;
	}

	@Override
	public void setTranslation(float translateX, float translateY) {
		if (MathUtils.isEqual(this.translationX, translateX) && MathUtils.isEqual(this.translationY, translateY)) {
			return;
		}
		endRendering();

		this.translationX = translateX;
		this.translationY = translateY;
	}

	@Override
	public void rotate(float degrees, float x, float y) {
		if (MathUtils.isZero(degrees) &&
				MathUtils.isEqual(x, rotationX) &&
				MathUtils.isEqual(y, rotationY)) {
			return;
		}
		endRendering();

		this.rotation += degrees;
		this.rotation = this.rotation % 360f;
		this.rotationX = x;
		this.rotationY = y;
	}

	@Override
	public void setRotation(float degrees, float x, float y) {
		if(MathUtils.isEqual(this.rotation, degrees) &&
				MathUtils.isEqual(this.rotationX, x) &&
				MathUtils.isEqual(this.rotationY, y)) {
			return;
		}

		endRendering();

		this.rotation = degrees;
		this.rotation = this.rotation % 360f;
		this.rotationX = x;
		this.rotationY = y;
	}

	@Override
	public Matrix4 getProjectionMatrix() {
		return new Matrix4(camera.combined.val);
	}

	@Override
	public boolean isWindowReady() {
		return gameWrapper.isGameWindowReady();
	}

	@Override
	public int getWindowWidth() {
		return windowWidth;
	}

	@Override
	public int getWindowHeight() {
		return windowHeight;
	}

	@Override
	public float getViewportWidth() {
		return camera.viewportWidth;
	}

	@Override
	public float getViewportHeight() {
		return camera.viewportHeight;
	}

	@Override
	public int getWindowSafeX() {
		return 0;
	}

	@Override
	public int getWindowSafeY() {
		return 0;
	}

	@Override
	public int getWindowSafeWidth() {
		return windowWidth;
	}

	@Override
	public int getWindowSafeHeight() {
		return windowHeight;
	}

	@Override
	public long getFrameId() {
		return Gdx.graphics.getFrameId();
	}

	@Override
	public TextureFilter getMinFilter() {
		return spriteBatch.getMinFilter();
	}

	@Override
	public void setMinFilter(TextureFilter filter) {
		spriteBatch.setMinFilter(filter);
	}

	@Override
	public TextureFilter getMagFilter() {
		return spriteBatch.getMagFilter();
	}

	@Override
	public void setMagFilter(TextureFilter filter) {
		spriteBatch.setMagFilter(filter);
	}

	@Override
	public GraphicsDriver getDriver() {
		return GraphicsDriver.OPENGL;
	}

	@Override
	public float getRotation() {
		return rotation;
	}

	@Override
	public float getRotationX() {
		return rotationX;
	}

	@Override
	public float getRotationY() {
		return rotationY;
	}

	@Override
	public float getTranslationX() {
		return translationX;
	}

	@Override
	public float getTranslationY() {
		return translationY;
	}

	@Override
	public float getScaleX() {
		return scaleX;
	}

	@Override
	public float getScaleY() {
		return scaleY;
	}

	@Override
	public Color getTint() {
		return tint;
	}

	@Override
	public Color getBackgroundColor() {
		return backgroundColor;
	}

	@Override
	public Color getColor() {
		return color;
	}

	@Override
	public int getLineHeight() {
		return lineHeight;
	}

	@Override
	public GameFont getFont() {
		return font;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy