package net.minecraft.client.renderer.texture;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.minecraft.client.renderer.StitcherException;
@SideOnly(Side.CLIENT)
public class Stitcher
{
private final Set setStitchHolders;
private final List stitchSlots;
private int currentWidth;
private int currentHeight;
private final int maxWidth;
private final int maxHeight;
private final boolean forcePowerOf2;
/** Max size (width or height) of a single tile */
private final int maxTileDimension;
private Texture atlasTexture;
private final String textureName;
public Stitcher(String par1Str, int par2, int par3, boolean par4)
{
this(par1Str, par2, par3, par4, 0);
}
public Stitcher(String par1, int par2, int par3, boolean par4, int par5)
{
this.setStitchHolders = new HashSet(256);
this.stitchSlots = new ArrayList(256);
this.currentWidth = 0;
this.currentHeight = 0;
this.textureName = par1;
this.maxWidth = par2;
this.maxHeight = par3;
this.forcePowerOf2 = par4;
this.maxTileDimension = par5;
}
public void addStitchHolder(StitchHolder par1StitchHolder)
{
if (this.maxTileDimension > 0)
{
par1StitchHolder.setNewDimension(this.maxTileDimension);
}
this.setStitchHolders.add(par1StitchHolder);
}
public Texture getTexture()
{
if (this.forcePowerOf2)
{
this.currentWidth = this.getCeilPowerOf2(this.currentWidth);
this.currentHeight = this.getCeilPowerOf2(this.currentHeight);
}
this.atlasTexture = TextureManager.instance().createEmptyTexture(this.textureName, 1, this.currentWidth, this.currentHeight, 6408);
this.atlasTexture.fillRect(this.atlasTexture.getTextureRect(), -65536);
List list = this.getStichSlots();
for (int i = 0; i < list.size(); ++i)
{
StitchSlot stitchslot = (StitchSlot)list.get(i);
StitchHolder stitchholder = stitchslot.getStitchHolder();
this.atlasTexture.copyFrom(stitchslot.getOriginX(), stitchslot.getOriginY(), stitchholder.func_98150_a(), stitchholder.isRotated());
}
TextureManager.instance().registerTexture(this.textureName, this.atlasTexture);
return this.atlasTexture;
}
public void doStitch()
{
StitchHolder[] astitchholder = (StitchHolder[])this.setStitchHolders.toArray(new StitchHolder[this.setStitchHolders.size()]);
Arrays.sort(astitchholder);
this.atlasTexture = null;
for (int i = 0; i < astitchholder.length; ++i)
{
StitchHolder stitchholder = astitchholder[i];
if (!this.allocateSlot(stitchholder))
{
throw new StitcherException(stitchholder);
}
}
}
public List getStichSlots()
{
ArrayList arraylist = new ArrayList();
Iterator iterator = this.stitchSlots.iterator();
while (iterator.hasNext())
{
StitchSlot stitchslot = (StitchSlot)iterator.next();
stitchslot.getAllStitchSlots(arraylist);
}
return arraylist;
}
/**
* Returns power of 2 >= the specified value
*/
private int getCeilPowerOf2(int par1)
{
int j = par1 - 1;
j |= j >> 1;
j |= j >> 2;
j |= j >> 4;
j |= j >> 8;
j |= j >> 16;
return j + 1;
}
/**
* Attempts to find space for specified tile
*/
private boolean allocateSlot(StitchHolder par1StitchHolder)
{
for (int i = 0; i < this.stitchSlots.size(); ++i)
{
if (((StitchSlot)this.stitchSlots.get(i)).func_94182_a(par1StitchHolder))
{
return true;
}
par1StitchHolder.rotate();
if (((StitchSlot)this.stitchSlots.get(i)).func_94182_a(par1StitchHolder))
{
return true;
}
par1StitchHolder.rotate();
}
return this.expandAndAllocateSlot(par1StitchHolder);
}
/**
* Expand stitched texture in order to make space for specified tile
*/
private boolean expandAndAllocateSlot(StitchHolder par1StitchHolder)
{
int i = Math.min(par1StitchHolder.getHeight(), par1StitchHolder.getWidth());
boolean flag = this.currentWidth == 0 && this.currentHeight == 0;
boolean flag1;
if (this.forcePowerOf2)
{
int j = this.getCeilPowerOf2(this.currentWidth);
int k = this.getCeilPowerOf2(this.currentHeight);
int l = this.getCeilPowerOf2(this.currentWidth + i);
int i1 = this.getCeilPowerOf2(this.currentHeight + i);
boolean flag2 = l <= this.maxWidth;
boolean flag3 = i1 <= this.maxHeight;
if (!flag2 && !flag3)
{
return false;
}
int j1 = Math.max(par1StitchHolder.getHeight(), par1StitchHolder.getWidth());
if (flag && !flag2 && this.getCeilPowerOf2(this.currentHeight + j1) > this.maxHeight)
{
return false;
}
boolean flag4 = j != l;
boolean flag5 = k != i1;
if (flag4 ^ flag5)
{
flag1 = flag5 && flag3; //Forge: Bug fix: Attempt to fill all downward space before expanding width
}
else
{
flag1 = flag2 && j <= k;
}
}
else
{
boolean flag6 = this.currentWidth + i <= this.maxWidth;
boolean flag7 = this.currentHeight + i <= this.maxHeight;
if (!flag6 && !flag7)
{
return false;
}
flag1 = (flag || this.currentWidth <= this.currentHeight) && flag6;
}
StitchSlot stitchslot;
if (flag1)
{
if (par1StitchHolder.getWidth() > par1StitchHolder.getHeight())
{
par1StitchHolder.rotate();
}
if (this.currentHeight == 0)
{
this.currentHeight = par1StitchHolder.getHeight();
}
stitchslot = new StitchSlot(this.currentWidth, 0, par1StitchHolder.getWidth(), this.currentHeight);
this.currentWidth += par1StitchHolder.getWidth();
}
else
{
stitchslot = new StitchSlot(0, this.currentHeight, this.currentWidth, par1StitchHolder.getHeight());
this.currentHeight += par1StitchHolder.getHeight();
}
stitchslot.func_94182_a(par1StitchHolder);
this.stitchSlots.add(stitchslot);
return true;
}
}