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;
006
007import java.awt.image.BufferedImage;
008import java.io.BufferedReader;
009import java.util.ArrayList;
010import java.util.List;
011
012import net.minecraft.client.texturepacks.ITexturePack;
013import net.minecraft.util.Icon;
014import net.minecraft.util.Tuple;
015
016@SideOnly(Side.CLIENT)
017public class TextureStitched implements Icon
018{
019    private final String textureName;
020
021    /** texture sheet containing this texture */
022    protected Texture textureSheet;
023    protected List textureList;
024    private List listAnimationTuples;
025    protected boolean rotated;
026
027    /** x position of this icon on the texture sheet in pixels */
028    protected int originX;
029
030    /** y position of this icon on the texture sheet in pixels */
031    protected int originY;
032
033    /** width of this icon in pixels */
034    private int width;
035
036    /** height of this icon in pixels */
037    private int height;
038    private float minU;
039    private float maxU;
040    private float minV;
041    private float maxV;
042    private float widthNorm;
043    private float heightNorm;
044    protected int frameCounter = 0;
045    protected int tickCounter = 0;
046
047    public static TextureStitched makeTextureStitched(String par0Str)
048    {
049        return (TextureStitched)("clock".equals(par0Str) ? new TextureClock() : ("compass".equals(par0Str) ? new TextureCompass() : new TextureStitched(par0Str)));
050    }
051
052    protected TextureStitched(String par1)
053    {
054        this.textureName = par1;
055    }
056
057    public void init(Texture par1Texture, List par2List, int par3, int par4, int par5, int par6, boolean par7)
058    {
059        this.textureSheet = par1Texture;
060        this.textureList = par2List;
061        this.originX = par3;
062        this.originY = par4;
063        this.width = par5;
064        this.height = par6;
065        this.rotated = par7;
066        float f = 0.01F / (float)par1Texture.getWidth();
067        float f1 = 0.01F / (float)par1Texture.getHeight();
068        this.minU = (float)par3 / (float)par1Texture.getWidth() + f;
069        this.maxU = (float)(par3 + par5) / (float)par1Texture.getWidth() - f;
070        this.minV = (float)par4 / (float)par1Texture.getHeight() + f1;
071        this.maxV = (float)(par4 + par6) / (float)par1Texture.getHeight() - f1;
072        this.widthNorm = (float)par5 / 16.0F;
073        this.heightNorm = (float)par6 / 16.0F;
074        TextureFXManager.instance().getHelper().doTextureUpload(this);
075        if (this.rotated)
076        {
077            TextureFXManager.instance().getHelper().rotateTexture(this.textureSheet, this.textureSheet.getTextureData());
078        }
079    }
080
081    public void copyFrom(TextureStitched par1TextureStitched)
082    {
083        this.init(par1TextureStitched.textureSheet, par1TextureStitched.textureList, par1TextureStitched.originX, par1TextureStitched.originY, par1TextureStitched.width, par1TextureStitched.height, par1TextureStitched.rotated);
084    }
085
086    /**
087     * Returns the X position of this icon on its texture sheet, in pixels.
088     */
089    public int getOriginX()
090    {
091        return this.originX;
092    }
093
094    /**
095     * Returns the Y position of this icon on its texture sheet, in pixels.
096     */
097    public int getOriginY()
098    {
099        return this.originY;
100    }
101
102    /**
103     * Returns the minimum U coordinate to use when rendering with this icon.
104     */
105    public float getMinU()
106    {
107        return this.minU;
108    }
109
110    /**
111     * Returns the maximum U coordinate to use when rendering with this icon.
112     */
113    public float getMaxU()
114    {
115        return this.maxU;
116    }
117
118    /**
119     * Gets a U coordinate on the icon. 0 returns uMin and 16 returns uMax. Other arguments return in-between values.
120     */
121    public float getInterpolatedU(double par1)
122    {
123        float f = this.maxU - this.minU;
124        return this.minU + f * ((float)par1 / 16.0F);
125    }
126
127    /**
128     * Returns the minimum V coordinate to use when rendering with this icon.
129     */
130    public float getMinV()
131    {
132        return this.minV;
133    }
134
135    /**
136     * Returns the maximum V coordinate to use when rendering with this icon.
137     */
138    public float getMaxV()
139    {
140        return this.maxV;
141    }
142
143    /**
144     * Gets a V coordinate on the icon. 0 returns vMin and 16 returns vMax. Other arguments return in-between values.
145     */
146    public float getInterpolatedV(double par1)
147    {
148        float f = this.maxV - this.minV;
149        return this.minV + f * ((float)par1 / 16.0F);
150    }
151
152    public String getIconName()
153    {
154        return this.textureName;
155    }
156
157    /**
158     * Returns the width of the texture sheet this icon is on, in pixels.
159     */
160    public int getSheetWidth()
161    {
162        return this.textureSheet.getWidth();
163    }
164
165    /**
166     * Returns the height of the texture sheet this icon is on, in pixels.
167     */
168    public int getSheetHeight()
169    {
170        return this.textureSheet.getHeight();
171    }
172
173    public void updateAnimation()
174    {
175        if (this.listAnimationTuples != null)
176        {
177            Tuple tuple = (Tuple)this.listAnimationTuples.get(this.frameCounter);
178            ++this.tickCounter;
179
180            if (this.tickCounter >= ((Integer)tuple.getSecond()).intValue())
181            {
182                int i = ((Integer)tuple.getFirst()).intValue();
183                this.frameCounter = (this.frameCounter + 1) % this.listAnimationTuples.size();
184                this.tickCounter = 0;
185                tuple = (Tuple)this.listAnimationTuples.get(this.frameCounter);
186                int j = ((Integer)tuple.getFirst()).intValue();
187
188                if (i != j && j >= 0 && j < this.textureList.size())
189                {
190                    this.textureSheet.copyFrom(this.originX, this.originY, (Texture)this.textureList.get(j), false); //FML: We rotate the textures in init.
191                }
192            }
193        }
194        else
195        {
196            int k = this.frameCounter;
197            this.frameCounter = (this.frameCounter + 1) % this.textureList.size();
198
199            if (k != this.frameCounter)
200            {
201                this.textureSheet.copyFrom(this.originX, this.originY, (Texture)this.textureList.get(this.frameCounter), false); //FML: We rotate the textures in init.
202            }
203        }
204    }
205
206    public void readAnimationInfo(BufferedReader par1BufferedReader)
207    {
208        ArrayList arraylist = new ArrayList();
209
210        try
211        {
212            for (String s = par1BufferedReader.readLine(); s != null; s = par1BufferedReader.readLine())
213            {
214                s = s.trim();
215
216                if (s.length() > 0)
217                {
218                    String[] astring = s.split(",");
219                    String[] astring1 = astring;
220                    int i = astring.length;
221
222                    for (int j = 0; j < i; ++j)
223                    {
224                        String s1 = astring1[j];
225                        int k = s1.indexOf(42);
226
227                        if (k > 0)
228                        {
229                            Integer integer = new Integer(s1.substring(0, k));
230                            Integer integer1 = new Integer(s1.substring(k + 1));
231                            arraylist.add(new Tuple(integer, integer1));
232                        }
233                        else
234                        {
235                            arraylist.add(new Tuple(new Integer(s1), Integer.valueOf(1)));
236                        }
237                    }
238                }
239            }
240        }
241        catch (Exception exception)
242        {
243            System.err.println("Failed to read animation info for " + this.textureName + ": " + exception.getMessage());
244        }
245
246        if (!arraylist.isEmpty() && arraylist.size() < 600)
247        {
248            this.listAnimationTuples = arraylist;
249        }
250    }
251
252    public void createAndUploadTextures()
253    {
254        for (Texture t : ((List<Texture>)textureList))
255        {
256            t.createAndUploadTexture();
257        }
258    }
259
260    //===================================================================================================
261    //                                           Forge Start
262    //===================================================================================================
263    /**
264     * Called when texture packs are refreshed, from TextureManager.createNewTexture,
265     * allows for finer control over loading the animation lists and verification of the image.
266     * If the return value from this is true, no further loading will be done by vanilla code.
267     * 
268     * You need to add all Texture's to the textures argument. At the end of this function at least one
269     * entry should be in that argument, or a error should of been thrown.
270     * 
271     * @param manager The invoking manager
272     * @param texturepack Current texture pack
273     * @param name The name of the texture
274     * @param fileName Resource path for this texture
275     * @param image Buffered image of the loaded resource
276     * @param textures ArrayList of element type Texture, split textures should be added to this list for the stitcher to handle.  
277     * @return Return true to skip further vanilla texture loading for this texture
278     */
279    public boolean loadTexture(TextureManager manager, ITexturePack texturepack, String name, String fileName, BufferedImage image, ArrayList textures)
280    {
281        return false;
282    }
283}