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