package net.minecraft.client.renderer.texture;
import com.google.common.collect.Lists;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.data.AnimationFrame;
import net.minecraft.client.resources.data.AnimationMetadataSection;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.IIcon;
import net.minecraft.util.ReportedException;
import net.minecraft.util.ResourceLocation;
@SideOnly(Side.CLIENT)
public class TextureAtlasSprite implements IIcon
{
private final String iconName;
protected List framesTextureData = Lists.newArrayList();
private AnimationMetadataSection animationMetadata;
protected boolean rotated;
private boolean useAnisotropicFiltering;
protected int originX;
protected int originY;
protected int width;
protected int height;
private float minU;
private float maxU;
private float minV;
private float maxV;
protected int frameCounter;
protected int tickCounter;
private static final String __OBFID = "CL_00001062";
protected TextureAtlasSprite(String p_i1282_1_)
{
this.iconName = p_i1282_1_;
}
public void initSprite(int p_110971_1_, int p_110971_2_, int p_110971_3_, int p_110971_4_, boolean p_110971_5_)
{
this.originX = p_110971_3_;
this.originY = p_110971_4_;
this.rotated = p_110971_5_;
float f = (float)(0.009999999776482582D / (double)p_110971_1_);
float f1 = (float)(0.009999999776482582D / (double)p_110971_2_);
this.minU = (float)p_110971_3_ / (float)((double)p_110971_1_) + f;
this.maxU = (float)(p_110971_3_ + this.width) / (float)((double)p_110971_1_) - f;
this.minV = (float)p_110971_4_ / (float)p_110971_2_ + f1;
this.maxV = (float)(p_110971_4_ + this.height) / (float)p_110971_2_ - f1;
if (this.useAnisotropicFiltering)
{
float f2 = 8.0F / (float)p_110971_1_;
float f3 = 8.0F / (float)p_110971_2_;
this.minU += f2;
this.maxU -= f2;
this.minV += f3;
this.maxV -= f3;
}
}
public void copyFrom(TextureAtlasSprite p_94217_1_)
{
this.originX = p_94217_1_.originX;
this.originY = p_94217_1_.originY;
this.width = p_94217_1_.width;
this.height = p_94217_1_.height;
this.rotated = p_94217_1_.rotated;
this.minU = p_94217_1_.minU;
this.maxU = p_94217_1_.maxU;
this.minV = p_94217_1_.minV;
this.maxV = p_94217_1_.maxV;
}
/**
* Returns the X position of this icon on its texture sheet, in pixels.
*/
public int getOriginX()
{
return this.originX;
}
/**
* Returns the Y position of this icon on its texture sheet, in pixels.
*/
public int getOriginY()
{
return this.originY;
}
/**
* Returns the width of the icon, in pixels.
*/
public int getIconWidth()
{
return this.width;
}
/**
* Returns the height of the icon, in pixels.
*/
public int getIconHeight()
{
return this.height;
}
/**
* Returns the minimum U coordinate to use when rendering with this icon.
*/
public float getMinU()
{
return this.minU;
}
/**
* Returns the maximum U coordinate to use when rendering with this icon.
*/
public float getMaxU()
{
return this.maxU;
}
/**
* Gets a U coordinate on the icon. 0 returns uMin and 16 returns uMax. Other arguments return in-between values.
*/
public float getInterpolatedU(double p_94214_1_)
{
float f = this.maxU - this.minU;
return this.minU + f * (float)p_94214_1_ / 16.0F;
}
/**
* Returns the minimum V coordinate to use when rendering with this icon.
*/
public float getMinV()
{
return this.minV;
}
/**
* Returns the maximum V coordinate to use when rendering with this icon.
*/
public float getMaxV()
{
return this.maxV;
}
/**
* Gets a V coordinate on the icon. 0 returns vMin and 16 returns vMax. Other arguments return in-between values.
*/
public float getInterpolatedV(double p_94207_1_)
{
float f = this.maxV - this.minV;
return this.minV + f * ((float)p_94207_1_ / 16.0F);
}
public String getIconName()
{
return this.iconName;
}
public void updateAnimation()
{
++this.tickCounter;
if (this.tickCounter >= this.animationMetadata.getFrameTimeSingle(this.frameCounter))
{
int i = this.animationMetadata.getFrameIndex(this.frameCounter);
int j = this.animationMetadata.getFrameCount() == 0 ? this.framesTextureData.size() : this.animationMetadata.getFrameCount();
this.frameCounter = (this.frameCounter + 1) % j;
this.tickCounter = 0;
int k = this.animationMetadata.getFrameIndex(this.frameCounter);
if (i != k && k >= 0 && k < this.framesTextureData.size())
{
TextureUtil.uploadTextureMipmap((int[][])this.framesTextureData.get(k), this.width, this.height, this.originX, this.originY, false, false);
}
}
}
public int[][] getFrameTextureData(int p_147965_1_)
{
return (int[][])this.framesTextureData.get(p_147965_1_);
}
public int getFrameCount()
{
return this.framesTextureData.size();
}
public void setIconWidth(int p_110966_1_)
{
this.width = p_110966_1_;
}
public void setIconHeight(int p_110969_1_)
{
this.height = p_110969_1_;
}
public void loadSprite(BufferedImage[] p_147964_1_, AnimationMetadataSection p_147964_2_, boolean p_147964_3_)
{
this.resetSprite();
this.useAnisotropicFiltering = p_147964_3_;
int i = p_147964_1_[0].getWidth();
int j = p_147964_1_[0].getHeight();
this.width = i;
this.height = j;
if (p_147964_3_)
{
this.width += 16;
this.height += 16;
}
int[][] aint = new int[p_147964_1_.length][];
int k;
for (k = 0; k < p_147964_1_.length; ++k)
{
BufferedImage bufferedimage = p_147964_1_[k];
if (bufferedimage != null)
{
if (k > 0 && (bufferedimage.getWidth() != i >> k || bufferedimage.getHeight() != j >> k))
{
throw new RuntimeException(String.format("Unable to load miplevel: %d, image is size: %dx%d, expected %dx%d", new Object[] {Integer.valueOf(k), Integer.valueOf(bufferedimage.getWidth()), Integer.valueOf(bufferedimage.getHeight()), Integer.valueOf(i >> k), Integer.valueOf(j >> k)}));
}
aint[k] = new int[bufferedimage.getWidth() * bufferedimage.getHeight()];
bufferedimage.getRGB(0, 0, bufferedimage.getWidth(), bufferedimage.getHeight(), aint[k], 0, bufferedimage.getWidth());
}
}
if (p_147964_2_ == null)
{
if (j != i)
{
throw new RuntimeException("broken aspect ratio and not an animation");
}
this.fixTransparentPixels(aint);
this.framesTextureData.add(this.prepareAnisotropicFiltering(aint, i, j));
}
else
{
k = j / i;
int j1 = i;
int l = i;
this.height = this.width;
int i1;
if (p_147964_2_.getFrameCount() > 0)
{
Iterator iterator = p_147964_2_.getFrameIndexSet().iterator();
while (iterator.hasNext())
{
i1 = ((Integer)iterator.next()).intValue();
if (i1 >= k)
{
throw new RuntimeException("invalid frameindex " + i1);
}
this.allocateFrameTextureData(i1);
this.framesTextureData.set(i1, this.prepareAnisotropicFiltering(getFrameTextureData(aint, j1, l, i1), j1, l));
}
this.animationMetadata = p_147964_2_;
}
else
{
ArrayList arraylist = Lists.newArrayList();
for (i1 = 0; i1 < k; ++i1)
{
this.framesTextureData.add(this.prepareAnisotropicFiltering(getFrameTextureData(aint, j1, l, i1), j1, l));
arraylist.add(new AnimationFrame(i1, -1));
}
this.animationMetadata = new AnimationMetadataSection(arraylist, this.width, this.height, p_147964_2_.getFrameTime());
}
}
}
public void generateMipmaps(int p_147963_1_)
{
ArrayList arraylist = Lists.newArrayList();
for (int j = 0; j < this.framesTextureData.size(); ++j)
{
final int[][] aint = (int[][])this.framesTextureData.get(j);
if (aint != null)
{
try
{
arraylist.add(TextureUtil.generateMipmapData(p_147963_1_, this.width, aint));
}
catch (Throwable throwable)
{
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Generating mipmaps for frame");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Frame being iterated");
crashreportcategory.addCrashSection("Frame index", Integer.valueOf(j));
crashreportcategory.addCrashSectionCallable("Frame sizes", new Callable()
{
private static final String __OBFID = "CL_00001063";
public String call()
{
StringBuilder stringbuilder = new StringBuilder();
int[][] aint1 = aint;
int k = aint1.length;
for (int l = 0; l < k; ++l)
{
int[] aint2 = aint1[l];
if (stringbuilder.length() > 0)
{
stringbuilder.append(", ");
}
stringbuilder.append(aint2 == null ? "null" : Integer.valueOf(aint2.length));
}
return stringbuilder.toString();
}
});
throw new ReportedException(crashreport);
}
}
}
this.setFramesTextureData(arraylist);
}
private void fixTransparentPixels(int[][] p_147961_1_)
{
int[] aint1 = p_147961_1_[0];
int i = 0;
int j = 0;
int k = 0;
int l = 0;
int i1;
for (i1 = 0; i1 < aint1.length; ++i1)
{
if ((aint1[i1] & -16777216) != 0)
{
j += aint1[i1] >> 16 & 255;
k += aint1[i1] >> 8 & 255;
l += aint1[i1] >> 0 & 255;
++i;
}
}
if (i != 0)
{
j /= i;
k /= i;
l /= i;
for (i1 = 0; i1 < aint1.length; ++i1)
{
if ((aint1[i1] & -16777216) == 0)
{
aint1[i1] = j << 16 | k << 8 | l;
}
}
}
}
private int[][] prepareAnisotropicFiltering(int[][] p_147960_1_, int p_147960_2_, int p_147960_3_)
{
if (!this.useAnisotropicFiltering)
{
return p_147960_1_;
}
else
{
int[][] aint1 = new int[p_147960_1_.length][];
for (int k = 0; k < p_147960_1_.length; ++k)
{
int[] aint2 = p_147960_1_[k];
if (aint2 != null)
{
int[] aint3 = new int[(p_147960_2_ + 16 >> k) * (p_147960_3_ + 16 >> k)];
System.arraycopy(aint2, 0, aint3, 0, aint2.length);
aint1[k] = TextureUtil.prepareAnisotropicData(aint3, p_147960_2_ >> k, p_147960_3_ >> k, 8 >> k);
}
}
return aint1;
}
}
private void allocateFrameTextureData(int p_130099_1_)
{
if (this.framesTextureData.size() <= p_130099_1_)
{
for (int j = this.framesTextureData.size(); j <= p_130099_1_; ++j)
{
this.framesTextureData.add((Object)null);
}
}
}
private static int[][] getFrameTextureData(int[][] p_147962_0_, int p_147962_1_, int p_147962_2_, int p_147962_3_)
{
int[][] aint1 = new int[p_147962_0_.length][];
for (int l = 0; l < p_147962_0_.length; ++l)
{
int[] aint2 = p_147962_0_[l];
if (aint2 != null)
{
aint1[l] = new int[(p_147962_1_ >> l) * (p_147962_2_ >> l)];
System.arraycopy(aint2, p_147962_3_ * aint1[l].length, aint1[l], 0, aint1[l].length);
}
}
return aint1;
}
public void clearFramesTextureData()
{
this.framesTextureData.clear();
}
public boolean hasAnimationMetadata()
{
return this.animationMetadata != null;
}
public void setFramesTextureData(List p_110968_1_)
{
this.framesTextureData = p_110968_1_;
}
private void resetSprite()
{
this.animationMetadata = null;
this.setFramesTextureData(Lists.newArrayList());
this.frameCounter = 0;
this.tickCounter = 0;
}
public String toString()
{
return "TextureAtlasSprite{name=\'" + this.iconName + '\'' + ", frameCount=" + this.framesTextureData.size() + ", rotated=" + this.rotated + ", x=" + this.originX + ", y=" + this.originY + ", height=" + this.height + ", width=" + this.width + ", u0=" + this.minU + ", u1=" + this.maxU + ", v0=" + this.minV + ", v1=" + this.maxV + '}';
}
/**
* The result of this function determines is the below 'load' function is called, and the
* default vanilla loading code is bypassed completely.
* @param manager
* @param location
* @return True to use your own custom load code and bypass vanilla loading.
*/
public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location)
{
return false;
}
/**
* Load the specified resource as this sprite's data.
* Returning false from this function will prevent this icon from being stitched onto the master texture.
* @param manager Main resource manager
* @param location File resource location
* @return False to prevent this Icon from being stitched
*/
public boolean load(IResourceManager manager, ResourceLocation location)
{
return true;
}
}