001package net.minecraft.client.renderer.texture; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.awt.image.BufferedImage; 006import java.io.File; 007import java.io.IOException; 008import java.nio.ByteBuffer; 009import javax.imageio.ImageIO; 010import net.minecraft.client.Minecraft; 011import net.minecraft.client.renderer.OpenGlHelper; 012import org.lwjgl.opengl.GL11; 013import org.lwjgl.opengl.GL12; 014 015@SideOnly(Side.CLIENT) 016public class Texture 017{ 018 private int glTextureId; 019 private int textureId; 020 private int textureType; 021 022 /** Width of this texture in pixels. */ 023 private final int width; 024 025 /** Height of this texture in pixels. */ 026 private final int height; 027 private final int textureDepth; 028 private final int textureFormat; 029 private final int textureTarget; 030 private final int textureMinFilter; 031 private final int textureMagFilter; 032 private final int textureWrap; 033 private final boolean mipmapActive; 034 private final String textureName; 035 private Rect2i textureRect; 036 private boolean transferred; 037 private boolean autoCreate; 038 private boolean textureCreated; 039 private ByteBuffer textureData; 040 041 private Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, int par9) 042 { 043 this.textureName = par1Str; 044 this.textureType = par2; 045 this.width = par3; 046 this.height = par4; 047 this.textureDepth = par5; 048 this.textureFormat = par7; 049 this.textureMinFilter = par8; 050 this.textureMagFilter = par9; 051 this.textureWrap = par6; 052 this.textureRect = new Rect2i(0, 0, par3, par4); 053 054 if (par4 == 1 && par5 == 1) 055 { 056 this.textureTarget = 3552; 057 } 058 else if (par5 == 1) 059 { 060 this.textureTarget = 3553; 061 } 062 else 063 { 064 this.textureTarget = 32879; 065 } 066 067 this.mipmapActive = par8 != 9728 && par8 != 9729 || par9 != 9728 && par9 != 9729; 068 069 if (par2 != 2) 070 { 071 this.glTextureId = GL11.glGenTextures(); 072 GL11.glBindTexture(this.textureTarget, this.glTextureId); 073 GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_MIN_FILTER, par8); 074 GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_MAG_FILTER, par9); 075 GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_WRAP_S, par6); 076 GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_WRAP_T, par6); 077 } 078 else 079 { 080 this.glTextureId = -1; 081 } 082 083 this.textureId = TextureManager.instance().getNextTextureId(); 084 } 085 086 public Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, BufferedImage par9BufferedImage) 087 { 088 this(par1Str, par2, par3, par4, 1, par5, par6, par7, par8, par9BufferedImage); 089 } 090 091 public Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, int par9, BufferedImage par10BufferedImage) 092 { 093 this(par1Str, par2, par3, par4, par5, par6, par7, par8, par9); 094 095 if (par10BufferedImage == null) 096 { 097 if (par3 != -1 && par4 != -1) 098 { 099 byte[] abyte = new byte[par3 * par4 * par5 * 4]; 100 101 for (int i2 = 0; i2 < abyte.length; ++i2) 102 { 103 abyte[i2] = 0; 104 } 105 106 this.textureData = ByteBuffer.allocateDirect(abyte.length); 107 this.textureData.clear(); 108 this.textureData.put(abyte); 109 this.textureData.position(0).limit(abyte.length); 110 111 if (this.autoCreate) 112 { 113 this.createTexture(); 114 } 115 else 116 { 117 this.textureCreated = false; 118 } 119 } 120 else 121 { 122 this.transferred = false; 123 } 124 } 125 else 126 { 127 this.transferred = true; 128 this.transferFromImage(par10BufferedImage); 129 130 if (par2 != 2) 131 { 132 this.createTexture(); 133 this.autoCreate = false; 134 } 135 } 136 } 137 138 public final Rect2i getTextureRect() 139 { 140 return this.textureRect; 141 } 142 143 public void fillRect(Rect2i par1Rect2i, int par2) 144 { 145 if (this.textureTarget != 32879) 146 { 147 Rect2i rect2i1 = new Rect2i(0, 0, this.width, this.height); 148 rect2i1.intersection(par1Rect2i); 149 this.textureData.position(0); 150 151 for (int j = rect2i1.getRectY(); j < rect2i1.getRectY() + rect2i1.getRectHeight(); ++j) 152 { 153 int k = j * this.width * 4; 154 155 for (int l = rect2i1.getRectX(); l < rect2i1.getRectX() + rect2i1.getRectWidth(); ++l) 156 { 157 this.textureData.put(k + l * 4 + 0, (byte)(par2 >> 24 & 255)); 158 this.textureData.put(k + l * 4 + 1, (byte)(par2 >> 16 & 255)); 159 this.textureData.put(k + l * 4 + 2, (byte)(par2 >> 8 & 255)); 160 this.textureData.put(k + l * 4 + 3, (byte)(par2 >> 0 & 255)); 161 } 162 } 163 164 if (this.autoCreate) 165 { 166 this.createTexture(); 167 } 168 else 169 { 170 this.textureCreated = false; 171 } 172 } 173 } 174 175 public void writeImage(String par1Str) 176 { 177 BufferedImage bufferedimage = new BufferedImage(this.width, this.height, 2); 178 ByteBuffer bytebuffer = this.getTextureData(); 179 byte[] abyte = new byte[this.width * this.height * 4]; 180 bytebuffer.position(0); 181 bytebuffer.get(abyte); 182 183 for (int i = 0; i < this.width; ++i) 184 { 185 for (int j = 0; j < this.height; ++j) 186 { 187 int k = j * this.width * 4 + i * 4; 188 byte b0 = 0; 189 int l = b0 | (abyte[k + 2] & 255) << 0; 190 l |= (abyte[k + 1] & 255) << 8; 191 l |= (abyte[k + 0] & 255) << 16; 192 l |= (abyte[k + 3] & 255) << 24; 193 bufferedimage.setRGB(i, j, l); 194 } 195 } 196 197 this.textureData.position(this.width * this.height * 4); 198 199 try 200 { 201 ImageIO.write(bufferedimage, "png", new File(Minecraft.getMinecraftDir(), par1Str)); 202 } 203 catch (IOException ioexception) 204 { 205 ioexception.printStackTrace(); 206 } 207 } 208 209 public void copyFrom(int par1, int par2, Texture par3Texture, boolean par4) 210 { 211 if (this.textureTarget != 32879) 212 { 213 ByteBuffer bytebuffer = par3Texture.getTextureData(); 214 this.textureData.position(0); 215 bytebuffer.position(0); 216 217 for (int k = 0; k < par3Texture.getHeight(); ++k) 218 { 219 int l = par2 + k; 220 int i1 = k * par3Texture.getWidth() * 4; 221 int j1 = l * this.width * 4; 222 223 if (par4) 224 { 225 l = par2 + (par3Texture.getHeight() - k); 226 } 227 228 for (int k1 = 0; k1 < par3Texture.getWidth(); ++k1) 229 { 230 int l1 = j1 + (k1 + par1) * 4; 231 int i2 = i1 + k1 * 4; 232 233 if (par4) 234 { 235 l1 = par1 + k1 * this.width * 4 + l * 4; 236 } 237 238 this.textureData.put(l1 + 0, bytebuffer.get(i2 + 0)); 239 this.textureData.put(l1 + 1, bytebuffer.get(i2 + 1)); 240 this.textureData.put(l1 + 2, bytebuffer.get(i2 + 2)); 241 this.textureData.put(l1 + 3, bytebuffer.get(i2 + 3)); 242 } 243 } 244 245 this.textureData.position(this.width * this.height * 4); 246 247 if (this.autoCreate) 248 { 249 this.createTexture(); 250 } 251 else 252 { 253 this.textureCreated = false; 254 } 255 } 256 } 257 258 public void transferFromImage(BufferedImage par1BufferedImage) 259 { 260 if (this.textureTarget != 32879) 261 { 262 int i = par1BufferedImage.getWidth(); 263 int j = par1BufferedImage.getHeight(); 264 265 if (i <= this.width && j <= this.height) 266 { 267 int[] aint = new int[] {3, 0, 1, 2}; 268 int[] aint1 = new int[] {3, 2, 1, 0}; 269 int[] aint2 = this.textureFormat == 32993 ? aint1 : aint; 270 int[] aint3 = new int[this.width * this.height]; 271 int k = par1BufferedImage.getTransparency(); 272 par1BufferedImage.getRGB(0, 0, this.width, this.height, aint3, 0, i); 273 byte[] abyte = new byte[this.width * this.height * 4]; 274 275 for (int l = 0; l < this.height; ++l) 276 { 277 for (int i1 = 0; i1 < this.width; ++i1) 278 { 279 int j1 = l * this.width + i1; 280 int k1 = j1 * 4; 281 abyte[k1 + aint2[0]] = (byte)(aint3[j1] >> 24 & 255); 282 abyte[k1 + aint2[1]] = (byte)(aint3[j1] >> 16 & 255); 283 abyte[k1 + aint2[2]] = (byte)(aint3[j1] >> 8 & 255); 284 abyte[k1 + aint2[3]] = (byte)(aint3[j1] >> 0 & 255); 285 } 286 } 287 288 this.textureData = ByteBuffer.allocateDirect(abyte.length); 289 this.textureData.clear(); 290 this.textureData.put(abyte); 291 this.textureData.limit(abyte.length); 292 293 if (this.autoCreate) 294 { 295 this.createTexture(); 296 } 297 else 298 { 299 this.textureCreated = false; 300 } 301 } 302 else 303 { 304 Minecraft.getMinecraft().getLogAgent().logWarning("transferFromImage called with a BufferedImage with dimensions (" + i + ", " + j + ") larger than the Texture dimensions (" + this.width + ", " + this.height + "). Ignoring."); 305 } 306 } 307 } 308 309 public int getTextureId() 310 { 311 return this.textureId; 312 } 313 314 public int getGlTextureId() 315 { 316 return this.glTextureId; 317 } 318 319 public int getWidth() 320 { 321 return this.width; 322 } 323 324 public int getHeight() 325 { 326 return this.height; 327 } 328 329 public String getTextureName() 330 { 331 return this.textureName; 332 } 333 334 public void bindTexture(int par1) 335 { 336 if (this.textureDepth == 1) 337 { 338 GL11.glEnable(GL11.GL_TEXTURE_2D); 339 } 340 else 341 { 342 GL11.glEnable(GL12.GL_TEXTURE_3D); 343 } 344 345 OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit + par1); 346 GL11.glBindTexture(this.textureTarget, this.glTextureId); 347 348 if (!this.textureCreated) 349 { 350 this.createTexture(); 351 } 352 } 353 354 public void createTexture() 355 { 356 this.textureData.flip(); 357 358 if (this.height != 1 && this.textureDepth != 1) 359 { 360 GL12.glTexImage3D(this.textureTarget, 0, this.textureFormat, this.width, this.height, this.textureDepth, 0, this.textureFormat, GL11.GL_UNSIGNED_BYTE, this.textureData); 361 } 362 else if (this.height != 1) 363 { 364 GL11.glTexImage2D(this.textureTarget, 0, this.textureFormat, this.width, this.height, 0, this.textureFormat, GL11.GL_UNSIGNED_BYTE, this.textureData); 365 } 366 else 367 { 368 GL11.glTexImage1D(this.textureTarget, 0, this.textureFormat, this.width, 0, this.textureFormat, GL11.GL_UNSIGNED_BYTE, this.textureData); 369 } 370 371 this.textureCreated = true; 372 } 373 374 public ByteBuffer getTextureData() 375 { 376 return this.textureData; 377 } 378}