• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.graphics.g2d;
18 
19 import com.badlogic.gdx.graphics.Texture;
20 
21 /** Defines a rectangular area of a texture. The coordinate system used has its origin in the upper left corner with the x-axis
22  * pointing to the right and the y axis pointing downwards.
23  * @author mzechner
24  * @author Nathan Sweet */
25 public class TextureRegion {
26 	Texture texture;
27 	float u, v;
28 	float u2, v2;
29 	int regionWidth, regionHeight;
30 
31 	/** Constructs a region with no texture and no coordinates defined. */
TextureRegion()32 	public TextureRegion () {
33 	}
34 
35 	/** Constructs a region the size of the specified texture. */
TextureRegion(Texture texture)36 	public TextureRegion (Texture texture) {
37 		if (texture == null) throw new IllegalArgumentException("texture cannot be null.");
38 		this.texture = texture;
39 		setRegion(0, 0, texture.getWidth(), texture.getHeight());
40 	}
41 
42 	/** @param width The width of the texture region. May be negative to flip the sprite when drawn.
43 	 * @param height The height of the texture region. May be negative to flip the sprite when drawn. */
TextureRegion(Texture texture, int width, int height)44 	public TextureRegion (Texture texture, int width, int height) {
45 		this.texture = texture;
46 		setRegion(0, 0, width, height);
47 	}
48 
49 	/** @param width The width of the texture region. May be negative to flip the sprite when drawn.
50 	 * @param height The height of the texture region. May be negative to flip the sprite when drawn. */
TextureRegion(Texture texture, int x, int y, int width, int height)51 	public TextureRegion (Texture texture, int x, int y, int width, int height) {
52 		this.texture = texture;
53 		setRegion(x, y, width, height);
54 	}
55 
TextureRegion(Texture texture, float u, float v, float u2, float v2)56 	public TextureRegion (Texture texture, float u, float v, float u2, float v2) {
57 		this.texture = texture;
58 		setRegion(u, v, u2, v2);
59 	}
60 
61 	/** Constructs a region with the same texture and coordinates of the specified region. */
TextureRegion(TextureRegion region)62 	public TextureRegion (TextureRegion region) {
63 		setRegion(region);
64 	}
65 
66 	/** Constructs a region with the same texture as the specified region and sets the coordinates relative to the specified region.
67 	 * @param width The width of the texture region. May be negative to flip the sprite when drawn.
68 	 * @param height The height of the texture region. May be negative to flip the sprite when drawn. */
TextureRegion(TextureRegion region, int x, int y, int width, int height)69 	public TextureRegion (TextureRegion region, int x, int y, int width, int height) {
70 		setRegion(region, x, y, width, height);
71 	}
72 
73 	/** Sets the texture and sets the coordinates to the size of the specified texture. */
setRegion(Texture texture)74 	public void setRegion (Texture texture) {
75 		this.texture = texture;
76 		setRegion(0, 0, texture.getWidth(), texture.getHeight());
77 	}
78 
79 	/** @param width The width of the texture region. May be negative to flip the sprite when drawn.
80 	 * @param height The height of the texture region. May be negative to flip the sprite when drawn. */
setRegion(int x, int y, int width, int height)81 	public void setRegion (int x, int y, int width, int height) {
82 		float invTexWidth = 1f / texture.getWidth();
83 		float invTexHeight = 1f / texture.getHeight();
84 		setRegion(x * invTexWidth, y * invTexHeight, (x + width) * invTexWidth, (y + height) * invTexHeight);
85 		regionWidth = Math.abs(width);
86 		regionHeight = Math.abs(height);
87 	}
88 
setRegion(float u, float v, float u2, float v2)89 	public void setRegion (float u, float v, float u2, float v2) {
90 		int texWidth = texture.getWidth(), texHeight = texture.getHeight();
91 		regionWidth = Math.round(Math.abs(u2 - u) * texWidth);
92 		regionHeight = Math.round(Math.abs(v2 - v) * texHeight);
93 
94 		// For a 1x1 region, adjust UVs toward pixel center to avoid filtering artifacts on AMD GPUs when drawing very stretched.
95 		if (regionWidth == 1 && regionHeight == 1) {
96 			float adjustX = 0.25f / texWidth;
97 			u += adjustX;
98 			u2 -= adjustX;
99 			float adjustY = 0.25f / texHeight;
100 			v += adjustY;
101 			v2 -= adjustY;
102 		}
103 
104 		this.u = u;
105 		this.v = v;
106 		this.u2 = u2;
107 		this.v2 = v2;
108 	}
109 
110 	/** Sets the texture and coordinates to the specified region. */
setRegion(TextureRegion region)111 	public void setRegion (TextureRegion region) {
112 		texture = region.texture;
113 		setRegion(region.u, region.v, region.u2, region.v2);
114 	}
115 
116 	/** Sets the texture to that of the specified region and sets the coordinates relative to the specified region. */
setRegion(TextureRegion region, int x, int y, int width, int height)117 	public void setRegion (TextureRegion region, int x, int y, int width, int height) {
118 		texture = region.texture;
119 		setRegion(region.getRegionX() + x, region.getRegionY() + y, width, height);
120 	}
121 
getTexture()122 	public Texture getTexture () {
123 		return texture;
124 	}
125 
setTexture(Texture texture)126 	public void setTexture (Texture texture) {
127 		this.texture = texture;
128 	}
129 
getU()130 	public float getU () {
131 		return u;
132 	}
133 
setU(float u)134 	public void setU (float u) {
135 		this.u = u;
136 		regionWidth = Math.round(Math.abs(u2 - u) * texture.getWidth());
137 	}
138 
getV()139 	public float getV () {
140 		return v;
141 	}
142 
setV(float v)143 	public void setV (float v) {
144 		this.v = v;
145 		regionHeight = Math.round(Math.abs(v2 - v) * texture.getHeight());
146 	}
147 
getU2()148 	public float getU2 () {
149 		return u2;
150 	}
151 
setU2(float u2)152 	public void setU2 (float u2) {
153 		this.u2 = u2;
154 		regionWidth = Math.round(Math.abs(u2 - u) * texture.getWidth());
155 	}
156 
getV2()157 	public float getV2 () {
158 		return v2;
159 	}
160 
setV2(float v2)161 	public void setV2 (float v2) {
162 		this.v2 = v2;
163 		regionHeight = Math.round(Math.abs(v2 - v) * texture.getHeight());
164 	}
165 
getRegionX()166 	public int getRegionX () {
167 		return Math.round(u * texture.getWidth());
168 	}
169 
setRegionX(int x)170 	public void setRegionX (int x) {
171 		setU(x / (float)texture.getWidth());
172 	}
173 
getRegionY()174 	public int getRegionY () {
175 		return Math.round(v * texture.getHeight());
176 	}
177 
setRegionY(int y)178 	public void setRegionY (int y) {
179 		setV(y / (float)texture.getHeight());
180 	}
181 
182 	/** Returns the region's width. */
getRegionWidth()183 	public int getRegionWidth () {
184 		return regionWidth;
185 	}
186 
setRegionWidth(int width)187 	public void setRegionWidth (int width) {
188 		if (isFlipX()) {
189 			setU(u2 + width / (float)texture.getWidth());
190 		} else {
191 			setU2(u + width / (float)texture.getWidth());
192 		}
193 	}
194 
195 	/** Returns the region's height. */
getRegionHeight()196 	public int getRegionHeight () {
197 		return regionHeight;
198 	}
199 
setRegionHeight(int height)200 	public void setRegionHeight (int height) {
201 		if (isFlipY()) {
202 			setV(v2 + height / (float)texture.getHeight());
203 		} else {
204 			setV2(v + height / (float)texture.getHeight());
205 		}
206 	}
207 
flip(boolean x, boolean y)208 	public void flip (boolean x, boolean y) {
209 		if (x) {
210 			float temp = u;
211 			u = u2;
212 			u2 = temp;
213 		}
214 		if (y) {
215 			float temp = v;
216 			v = v2;
217 			v2 = temp;
218 		}
219 	}
220 
isFlipX()221 	public boolean isFlipX () {
222 		return u > u2;
223 	}
224 
isFlipY()225 	public boolean isFlipY () {
226 		return v > v2;
227 	}
228 
229 	/** Offsets the region relative to the current region. Generally the region's size should be the entire size of the texture in
230 	 * the direction(s) it is scrolled.
231 	 * @param xAmount The percentage to offset horizontally.
232 	 * @param yAmount The percentage to offset vertically. This is done in texture space, so up is negative. */
scroll(float xAmount, float yAmount)233 	public void scroll (float xAmount, float yAmount) {
234 		if (xAmount != 0) {
235 			float width = (u2 - u) * texture.getWidth();
236 			u = (u + xAmount) % 1;
237 			u2 = u + width / texture.getWidth();
238 		}
239 		if (yAmount != 0) {
240 			float height = (v2 - v) * texture.getHeight();
241 			v = (v + yAmount) % 1;
242 			v2 = v + height / texture.getHeight();
243 		}
244 	}
245 
246 	/** Helper function to create tiles out of this TextureRegion starting from the top left corner going to the right and ending at
247 	 * the bottom right corner. Only complete tiles will be returned so if the region's width or height are not a multiple of the
248 	 * tile width and height not all of the region will be used. This will not work on texture regions returned form a TextureAtlas
249 	 * that either have whitespace removed or where flipped before the region is split.
250 	 *
251 	 * @param tileWidth a tile's width in pixels
252 	 * @param tileHeight a tile's height in pixels
253 	 * @return a 2D array of TextureRegions indexed by [row][column]. */
split(int tileWidth, int tileHeight)254 	public TextureRegion[][] split (int tileWidth, int tileHeight) {
255 		int x = getRegionX();
256 		int y = getRegionY();
257 		int width = regionWidth;
258 		int height = regionHeight;
259 
260 		int rows = height / tileHeight;
261 		int cols = width / tileWidth;
262 
263 		int startX = x;
264 		TextureRegion[][] tiles = new TextureRegion[rows][cols];
265 		for (int row = 0; row < rows; row++, y += tileHeight) {
266 			x = startX;
267 			for (int col = 0; col < cols; col++, x += tileWidth) {
268 				tiles[row][col] = new TextureRegion(texture, x, y, tileWidth, tileHeight);
269 			}
270 		}
271 
272 		return tiles;
273 	}
274 
275 	/** Helper function to create tiles out of the given {@link Texture} starting from the top left corner going to the right and
276 	 * ending at the bottom right corner. Only complete tiles will be returned so if the texture's width or height are not a
277 	 * multiple of the tile width and height not all of the texture will be used.
278 	 *
279 	 * @param texture the Texture
280 	 * @param tileWidth a tile's width in pixels
281 	 * @param tileHeight a tile's height in pixels
282 	 * @return a 2D array of TextureRegions indexed by [row][column]. */
split(Texture texture, int tileWidth, int tileHeight)283 	public static TextureRegion[][] split (Texture texture, int tileWidth, int tileHeight) {
284 		TextureRegion region = new TextureRegion(texture);
285 		return region.split(tileWidth, tileHeight);
286 	}
287 }
288