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}