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 = par1 + (par3Texture.getHeight() - k); //BUGFIX: targetY -> targetX
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 = (par2 + k1) * this.width * 4 + l * 4; //BUGFIX: targetX -> targetY and parens
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}