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