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

com.blastedstudios.gdxworld.ui.GDXRenderer Maven / Gradle / Ivy

The newest version!
package com.blastedstudios.gdxworld.ui;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.blastedstudios.gdxworld.ui.drawable.BackgroundDrawable;
import com.blastedstudios.gdxworld.ui.drawable.Drawable;
import com.blastedstudios.gdxworld.ui.drawable.ShapeDrawable;
import com.blastedstudios.gdxworld.util.BlurUtil;
import com.blastedstudios.gdxworld.util.FileUtil;
import com.blastedstudios.gdxworld.util.Log;
import com.blastedstudios.gdxworld.util.Properties;
import com.blastedstudios.gdxworld.world.GDXBackground;
import com.blastedstudios.gdxworld.world.GDXLevel;
import com.blastedstudios.gdxworld.world.GDXTile;
import com.blastedstudios.gdxworld.world.shape.GDXShape;

public class GDXRenderer {
	private static final Format PREFERRED_FORMAT = Format.valueOf(Properties.get("texture.format", "RGBA8888"));
	private static final boolean USE_MIP_MAPS = Properties.getBool("texture.useMipMaps", true);
	private static final boolean USE_DEPTH_BLUR = Properties.getBool("texture.useDepthBlur", true);
	private static final TextureWrap TEXTURE_WRAP = TextureWrap.valueOf(Properties.get("texture.wrap", "Repeat"));
	private static final float SHAPE_SCALE = Properties.getFloat("renderer.shape.scale", .02f);
	private boolean drawBackground, drawShapes;
	private Map textureMap = new HashMap<>();
	private Map> textureBlurMap = new HashMap<>();
	
	public GDXRenderer(boolean drawBackground, boolean drawShapes){
		this.drawBackground = drawBackground;
		this.drawShapes = drawShapes;
	}
	
	public void render(AssetManager assetManager, Batch batch, GDXLevel level, OrthographicCamera camera, 
			Iterable> bodies){
		if(drawBackground)
			for(GDXBackground background : level.getBackgrounds())
				drawBackground(assetManager, camera, background, batch);
		if(drawShapes)
			for(Entry entry : bodies)
				drawShape(assetManager, camera, entry.getKey(), entry.getValue(), batch);
	}
	
	public LinkedList generateDrawables(AssetManager assetManager, Batch batch,
			GDXLevel level, Camera camera, Iterable> bodies){
		LinkedList drawables = new LinkedList<>();
		for(GDXBackground background : level.getBackgrounds())
			drawables.add(new BackgroundDrawable(background));
		for(Entry entry : bodies)
			drawables.add(new ShapeDrawable(entry.getKey(), entry.getValue()));
		return drawables;
	}
	
	public void drawTile(OrthographicCamera camera, GDXTile tile, Batch batch) {
		Texture texture = getTexture(tile.getResource());
		if(texture != null) {
			Sprite sprite = new Sprite(new TextureRegion(texture, tile.getX(), tile.getY(), tile.getTilesize(), tile.getTilesize()));
			sprite.setPosition(tile.getPosition().x, tile.getPosition().y);
			sprite.draw(batch);
		}
	}
	
	public void drawShape(AssetManager assetManager, Camera camera, GDXShape shape, Body body, Batch batch){
		drawShape(assetManager, camera, shape, body, batch, 1f);
	}
	
	public void drawShape(AssetManager assetManager, Camera camera, GDXShape shape, Body body, Batch batch, float alpha){
		if(shape.getResource().isEmpty()){
			Log.debug("GDXRenderer.drawShape", "Resource empty string, not drawing");
			return;
		}
		Texture texture = null;
		try{
			texture = assetManager.get(shape.getResource());
		}catch(GdxRuntimeException e){
			Log.error("GDXRenderer.drawShape", e.getMessage() + ", loading " + shape.getResource() + " manually");
			texture = getTexture(shape.getResource());
		}
		if(!shape.isRepeatable() && texture != null && body != null){
			Sprite sprite = new Sprite(texture);
			sprite.setScale(SHAPE_SCALE);
			sprite.setRotation((float)Math.toDegrees(body.getAngle()));
			sprite.setPosition(body.getPosition().x - texture.getWidth()/2f, body.getPosition().y - texture.getHeight()/2f);
			if(alpha != 1f)
				sprite.setAlpha(alpha);
			sprite.draw(batch);
		}
	}
	
	public void drawBackground(AssetManager assetManager, Camera camera, GDXBackground background, Batch batch){
		if(background.getTexture().isEmpty()){
			Log.debug("GDXRenderer.drawBackground", "Background texture name empty, skipping");
			return;
		}
		
		Texture texture = null;
		if(background.getDepth() == 1f || !USE_DEPTH_BLUR)
			try{
				texture = assetManager.get(background.getTexture());
			}catch(GdxRuntimeException e){
				Gdx.app.error("GDXRenderer.drawBackground", "Texture not available: " + background.getTexture());
				texture = getTexture(background.getTexture());
			}
		else
			texture = getBlurTexture(background.getTexture(), background.getDepth());
		if(texture != null){
			float depth = Math.max(background.getDepth(), .001f);
			Vector2 offset = new Vector2(texture.getWidth(),texture.getHeight()).scl(.5f * background.getScale());
			Vector2 xy = toParallax(depth, background.getCoordinates(), camera).sub(offset);
			//Need the following boolean in case of failed pushScissors. This may
			//happen if we zoom far out to the point where the scissord area is 0
			boolean scissorCheck = background.isScissor();
			if(scissorCheck){
				Rectangle scissors = new Rectangle();
				Vector2 dimensions = new Vector2(background.getScissorUpperRight().x - background.getScissorLowerLeft().x,
						background.getScissorUpperRight().y - background.getScissorLowerLeft().y);
				Rectangle clipBounds = new Rectangle(background.getScissorLowerLeft().x, background.getScissorLowerLeft().y,
						dimensions.x, dimensions.y);
				Matrix4 batchTransform = new Matrix4();
				batchTransform.translate(camera.position.x/background.getDepth(), camera.position.y/background.getDepth(), 0);
				ScissorStack.calculateScissors(camera, batchTransform, clipBounds, scissors);
				scissorCheck = ScissorStack.pushScissors(scissors);
			}
			batch.draw(texture, xy.x, xy.y, texture.getWidth()*background.getScale(), 
					texture.getHeight()*background.getScale());
			if(scissorCheck){
				batch.flush();
				ScissorStack.popScissors();
			}
		}
	}
	
	/**
	 * Convert from world coordinates to parallax screen coordinates
	 */
	public static Vector2 toParallax(float depth, Vector2 world, Camera camera){
		return toParallax(depth, world, camera.position.x, camera.position.y);
	}
	
	public static Vector2 toParallax(float depth, Vector2 world, float camx, float camy){
		return world.cpy().add(new Vector2(camx, camy).scl(1f-(1f/depth)));
	}
	
	public static Vector2 fromParallax(float depth, Vector2 parallax, Camera camera){
		return fromParallax(depth, parallax, camera.position.x, camera.position.y);
	}
	
	public static Vector2 fromParallax(float depth, Vector2 parallax, float camx, float camy){
		return new Vector2(-camx, -camy).scl(1f-(1f/depth)).add(parallax);
	}

	public boolean isDrawBackground() {
		return drawBackground;
	}

	public void setDrawBackground(boolean drawBackground) {
		this.drawBackground = drawBackground;
	}

	public boolean isDrawShapes() {
		return drawShapes;
	}

	public void setDrawShapes(boolean drawShapes) {
		this.drawShapes = drawShapes;
	}
	
	public Texture getBlurTexture(String name, float depth){
		Map texMap = textureBlurMap.get(name);
		if(texMap == null)
			textureBlurMap.put(name, texMap = new HashMap<>());
		Texture texture = texMap.get(depth);
		if(texture == null){
			int blurRadius = (int) Math.ceil(Math.sqrt(depth));
			texMap.put(depth, texture = new Texture(BlurUtil.blur(new Pixmap(getTextureFile(name)), blurRadius, 2, true)));
		}
		return texture;
	}
	
	public Texture getTexture(String name){
		if(!textureMap.containsKey(name)){
			final Texture EMPTY = new Texture(1,1,Format.RGBA4444);
			FileHandle file = getTextureFile(name);
			if(file != null){
				try{
					Texture texture = new Texture(file, PREFERRED_FORMAT, USE_MIP_MAPS);
					texture.setWrap(TEXTURE_WRAP, TEXTURE_WRAP);
					textureMap.put(name, texture);
					Log.log("GDXRenderer.render", "Added texture " + name);
				}catch(Exception e){
					Log.error("GDXRenderer.render", "Texture found but error loading " + 
							name + ", using empty. Exception: " + e.getMessage());
					e.printStackTrace();
					textureMap.put(name, EMPTY);
				}
			}else{
				Log.error("GDXRenderer.render", "Texture " + name + " not found, using empty");
				textureMap.put(name, EMPTY);
			}
		}
		return textureMap.get(name);
	}
	
	private static FileHandle getTextureFile(String name){
		return FileUtil.find(name);
	}
	
	public static Vector2 toWorldCoordinates(Camera cam, Vector2 screen){
		Vector3 coords = new Vector3(screen.x, screen.y, 0);
		cam.unproject(coords);
		return new Vector2(coords.x, coords.y);
	}

	public static Vector2 toScreenCoordinates(Camera cam, Vector2 world){
		Vector3 coords = new Vector3(world.x, world.y, 0);
		cam.project(coords);
		return new Vector2(coords.x, coords.y);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy