Home | History | Annotate | Download | only in viewport
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.utils.viewport;
     18 
     19 import com.badlogic.gdx.ApplicationListener;
     20 import com.badlogic.gdx.Gdx;
     21 import com.badlogic.gdx.Screen;
     22 import com.badlogic.gdx.graphics.Camera;
     23 import com.badlogic.gdx.graphics.glutils.HdpiUtils;
     24 import com.badlogic.gdx.math.Matrix4;
     25 import com.badlogic.gdx.math.Rectangle;
     26 import com.badlogic.gdx.math.Vector2;
     27 import com.badlogic.gdx.math.Vector3;
     28 import com.badlogic.gdx.math.collision.Ray;
     29 import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
     30 
     31 /** Manages a {@link Camera} and determines how world coordinates are mapped to and from the screen.
     32  * @author Daniel Holderbaum
     33  * @author Nathan Sweet */
     34 public abstract class Viewport {
     35 	private Camera camera;
     36 	private float worldWidth, worldHeight;
     37 	private int screenX, screenY, screenWidth, screenHeight;
     38 
     39 	private final Vector3 tmp = new Vector3();
     40 
     41 	/** Calls {@link #apply(boolean)} with false. */
     42 	public void apply () {
     43 		apply(false);
     44 	}
     45 
     46 	/** Applies the viewport to the camera and sets the glViewport.
     47 	 * @param centerCamera If true, the camera position is set to the center of the world. */
     48 	public void apply (boolean centerCamera) {
     49 		HdpiUtils.glViewport(screenX, screenY, screenWidth, screenHeight);
     50 		camera.viewportWidth = worldWidth;
     51 		camera.viewportHeight = worldHeight;
     52 		if (centerCamera) camera.position.set(worldWidth / 2, worldHeight / 2, 0);
     53 		camera.update();
     54 	}
     55 
     56 	/** Calls {@link #update(int, int, boolean)} with false. */
     57 	public final void update (int screenWidth, int screenHeight) {
     58 		update(screenWidth, screenHeight, false);
     59 	}
     60 
     61 	/** Configures this viewport's screen bounds using the specified screen size and calls {@link #apply(boolean)}. Typically called
     62 	 * from {@link ApplicationListener#resize(int, int)} or {@link Screen#resize(int, int)}.
     63 	 * <p>
     64 	 * The default implementation only calls {@link #apply(boolean)}. */
     65 	public void update (int screenWidth, int screenHeight, boolean centerCamera) {
     66 		apply(centerCamera);
     67 	}
     68 
     69 	/** Transforms the specified screen coordinate to world coordinates.
     70 	 * @return The vector that was passed in, transformed to world coordinates.
     71 	 * @see Camera#unproject(Vector3) */
     72 	public Vector2 unproject (Vector2 screenCoords) {
     73 		tmp.set(screenCoords.x, screenCoords.y, 1);
     74 		camera.unproject(tmp, screenX, screenY, screenWidth, screenHeight);
     75 		screenCoords.set(tmp.x, tmp.y);
     76 		return screenCoords;
     77 	}
     78 
     79 	/** Transforms the specified world coordinate to screen coordinates.
     80 	 * @return The vector that was passed in, transformed to screen coordinates.
     81 	 * @see Camera#project(Vector3) */
     82 	public Vector2 project (Vector2 worldCoords) {
     83 		tmp.set(worldCoords.x, worldCoords.y, 1);
     84 		camera.project(tmp, screenX, screenY, screenWidth, screenHeight);
     85 		worldCoords.set(tmp.x, tmp.y);
     86 		return worldCoords;
     87 	}
     88 
     89 	/** Transforms the specified screen coordinate to world coordinates.
     90 	 * @return The vector that was passed in, transformed to world coordinates.
     91 	 * @see Camera#unproject(Vector3) */
     92 	public Vector3 unproject (Vector3 screenCoords) {
     93 		camera.unproject(screenCoords, screenX, screenY, screenWidth, screenHeight);
     94 		return screenCoords;
     95 	}
     96 
     97 	/** Transforms the specified world coordinate to screen coordinates.
     98 	 * @return The vector that was passed in, transformed to screen coordinates.
     99 	 * @see Camera#project(Vector3) */
    100 	public Vector3 project (Vector3 worldCoords) {
    101 		camera.project(worldCoords, screenX, screenY, screenWidth, screenHeight);
    102 		return worldCoords;
    103 	}
    104 
    105 	/** @see Camera#getPickRay(float, float, float, float, float, float) */
    106 	public Ray getPickRay (float screenX, float screenY) {
    107 		return camera.getPickRay(screenX, screenY, this.screenX, this.screenY, screenWidth, screenHeight);
    108 	}
    109 
    110 	/** @see ScissorStack#calculateScissors(Camera, float, float, float, float, Matrix4, Rectangle, Rectangle) */
    111 	public void calculateScissors (Matrix4 batchTransform, Rectangle area, Rectangle scissor) {
    112 		ScissorStack.calculateScissors(camera, screenX, screenY, screenWidth, screenHeight, batchTransform, area, scissor);
    113 	}
    114 
    115 	/** Transforms a point to real screen coordinates (as opposed to OpenGL ES window coordinates), where the origin is in the top
    116 	 * left and the the y-axis is pointing downwards. */
    117 	public Vector2 toScreenCoordinates (Vector2 worldCoords, Matrix4 transformMatrix) {
    118 		tmp.set(worldCoords.x, worldCoords.y, 0);
    119 		tmp.mul(transformMatrix);
    120 		camera.project(tmp);
    121 		tmp.y = Gdx.graphics.getHeight() - tmp.y;
    122 		worldCoords.x = tmp.x;
    123 		worldCoords.y = tmp.y;
    124 		return worldCoords;
    125 	}
    126 
    127 	public Camera getCamera () {
    128 		return camera;
    129 	}
    130 
    131 	public void setCamera (Camera camera) {
    132 		this.camera = camera;
    133 	}
    134 
    135 	public float getWorldWidth () {
    136 		return worldWidth;
    137 	}
    138 
    139 	/** The virtual width of this viewport in world coordinates. This width is scaled to the viewport's screen width. */
    140 	public void setWorldWidth (float worldWidth) {
    141 		this.worldWidth = worldWidth;
    142 	}
    143 
    144 	public float getWorldHeight () {
    145 		return worldHeight;
    146 	}
    147 
    148 	/** The virtual height of this viewport in world coordinates. This height is scaled to the viewport's screen height. */
    149 	public void setWorldHeight (float worldHeight) {
    150 		this.worldHeight = worldHeight;
    151 	}
    152 
    153 	public void setWorldSize (float worldWidth, float worldHeight) {
    154 		this.worldWidth = worldWidth;
    155 		this.worldHeight = worldHeight;
    156 	}
    157 
    158 	public int getScreenX () {
    159 		return screenX;
    160 	}
    161 
    162 	/** Sets the viewport's offset from the left edge of the screen. This is typically set by {@link #update(int, int, boolean)}. */
    163 	public void setScreenX (int screenX) {
    164 		this.screenX = screenX;
    165 	}
    166 
    167 	public int getScreenY () {
    168 		return screenY;
    169 	}
    170 
    171 	/** Sets the viewport's offset from the bottom edge of the screen. This is typically set by {@link #update(int, int, boolean)}. */
    172 	public void setScreenY (int screenY) {
    173 		this.screenY = screenY;
    174 	}
    175 
    176 	public int getScreenWidth () {
    177 		return screenWidth;
    178 	}
    179 
    180 	/** Sets the viewport's width in screen coordinates. This is typically set by {@link #update(int, int, boolean)}. */
    181 	public void setScreenWidth (int screenWidth) {
    182 		this.screenWidth = screenWidth;
    183 	}
    184 
    185 	public int getScreenHeight () {
    186 		return screenHeight;
    187 	}
    188 
    189 	/** Sets the viewport's height in screen coordinates. This is typically set by {@link #update(int, int, boolean)}. */
    190 	public void setScreenHeight (int screenHeight) {
    191 		this.screenHeight = screenHeight;
    192 	}
    193 
    194 	/** Sets the viewport's position in screen coordinates. This is typically set by {@link #update(int, int, boolean)}. */
    195 	public void setScreenPosition (int screenX, int screenY) {
    196 		this.screenX = screenX;
    197 		this.screenY = screenY;
    198 	}
    199 
    200 	/** Sets the viewport's size in screen coordinates. This is typically set by {@link #update(int, int, boolean)}. */
    201 	public void setScreenSize (int screenWidth, int screenHeight) {
    202 		this.screenWidth = screenWidth;
    203 		this.screenHeight = screenHeight;
    204 	}
    205 
    206 	/** Sets the viewport's bounds in screen coordinates. This is typically set by {@link #update(int, int, boolean)}. */
    207 	public void setScreenBounds (int screenX, int screenY, int screenWidth, int screenHeight) {
    208 		this.screenX = screenX;
    209 		this.screenY = screenY;
    210 		this.screenWidth = screenWidth;
    211 		this.screenHeight = screenHeight;
    212 	}
    213 
    214 	/** Returns the left gutter (black bar) width in screen coordinates. */
    215 	public int getLeftGutterWidth () {
    216 		return screenX;
    217 	}
    218 
    219 	/** Returns the right gutter (black bar) x in screen coordinates. */
    220 	public int getRightGutterX () {
    221 		return screenX + screenWidth;
    222 	}
    223 
    224 	/** Returns the right gutter (black bar) width in screen coordinates. */
    225 	public int getRightGutterWidth () {
    226 		return Gdx.graphics.getWidth() - (screenX + screenWidth);
    227 	}
    228 
    229 	/** Returns the bottom gutter (black bar) height in screen coordinates. */
    230 	public int getBottomGutterHeight () {
    231 		return screenY;
    232 	}
    233 
    234 	/** Returns the top gutter (black bar) y in screen coordinates. */
    235 	public int getTopGutterY () {
    236 		return screenY + screenHeight;
    237 	}
    238 
    239 	/** Returns the top gutter (black bar) height in screen coordinates. */
    240 	public int getTopGutterHeight () {
    241 		return Gdx.graphics.getHeight() - (screenY + screenHeight);
    242 	}
    243 }
    244