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.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; import net.minecraft.util.MathHelper; @SideOnly(Side.CLIENT) public class Stitcher { private final int mipmapLevelStitcher; private final Set setStitchHolders = new HashSet(256); private final List stitchSlots = new ArrayList(256); 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 static final String __OBFID = "CL_00001054"; public Stitcher(int p_i45095_1_, int p_i45095_2_, boolean p_i45095_3_, int p_i45095_4_, int p_i45095_5_) { this.mipmapLevelStitcher = p_i45095_5_; this.maxWidth = p_i45095_1_; this.maxHeight = p_i45095_2_; this.forcePowerOf2 = p_i45095_3_; this.maxTileDimension = p_i45095_4_; } public int getCurrentWidth() { return this.currentWidth; } public int getCurrentHeight() { return this.currentHeight; } public void addSprite(TextureAtlasSprite p_110934_1_) { Stitcher.Holder holder = new Stitcher.Holder(p_110934_1_, this.mipmapLevelStitcher); if (this.maxTileDimension > 0) { holder.setNewDimension(this.maxTileDimension); } this.setStitchHolders.add(holder); } public void doStitch() { Stitcher.Holder[] aholder = (Stitcher.Holder[])this.setStitchHolders.toArray(new Stitcher.Holder[this.setStitchHolders.size()]); cpw.mods.fml.common.ProgressManager.ProgressBar bar = cpw.mods.fml.common.ProgressManager.push("Texture stitching", aholder.length); Arrays.sort(aholder); Stitcher.Holder[] aholder1 = aholder; int i = aholder.length; for (int j = 0; j < i; ++j) { Stitcher.Holder holder = aholder1[j]; bar.step(holder.getAtlasSprite().getIconName()); if (!this.allocateSlot(holder)) { String s = String.format("Unable to fit: %s - size: %dx%d - Maybe try a lowerresolution resourcepack?", new Object[] {holder.getAtlasSprite().getIconName(), Integer.valueOf(holder.getAtlasSprite().getIconWidth()), Integer.valueOf(holder.getAtlasSprite().getIconHeight())}); throw new StitcherException(holder, s); } } if (this.forcePowerOf2) { this.currentWidth = MathHelper.roundUpToPowerOfTwo(this.currentWidth); this.currentHeight = MathHelper.roundUpToPowerOfTwo(this.currentHeight); } cpw.mods.fml.common.ProgressManager.pop(bar); } public List getStichSlots() { ArrayList arraylist = Lists.newArrayList(); Iterator iterator = this.stitchSlots.iterator(); while (iterator.hasNext()) { Stitcher.Slot slot = (Stitcher.Slot)iterator.next(); slot.getAllStitchSlots(arraylist); } ArrayList arraylist1 = Lists.newArrayList(); Iterator iterator1 = arraylist.iterator(); while (iterator1.hasNext()) { Stitcher.Slot slot1 = (Stitcher.Slot)iterator1.next(); Stitcher.Holder holder = slot1.getStitchHolder(); TextureAtlasSprite textureatlassprite = holder.getAtlasSprite(); textureatlassprite.initSprite(this.currentWidth, this.currentHeight, slot1.getOriginX(), slot1.getOriginY(), holder.isRotated()); arraylist1.add(textureatlassprite); } return arraylist1; } private static int getMipmapDimension(int p_147969_0_, int p_147969_1_) { return (p_147969_0_ >> p_147969_1_) + ((p_147969_0_ & (1 << p_147969_1_) - 1) == 0 ? 0 : 1) << p_147969_1_; } /** * Attempts to find space for specified tile */ private boolean allocateSlot(Stitcher.Holder p_94310_1_) { for (int i = 0; i < this.stitchSlots.size(); ++i) { if (((Stitcher.Slot)this.stitchSlots.get(i)).addSlot(p_94310_1_)) { return true; } p_94310_1_.rotate(); if (((Stitcher.Slot)this.stitchSlots.get(i)).addSlot(p_94310_1_)) { return true; } p_94310_1_.rotate(); } return this.expandAndAllocateSlot(p_94310_1_); } /** * Expand stitched texture in order to make space for specified tile */ private boolean expandAndAllocateSlot(Stitcher.Holder p_94311_1_) { int i = Math.min(p_94311_1_.getWidth(), p_94311_1_.getHeight()); boolean flag = this.currentWidth == 0 && this.currentHeight == 0; boolean flag1; int j; if (this.forcePowerOf2) { j = MathHelper.roundUpToPowerOfTwo(this.currentWidth); int k = MathHelper.roundUpToPowerOfTwo(this.currentHeight); int l = MathHelper.roundUpToPowerOfTwo(this.currentWidth + i); int i1 = MathHelper.roundUpToPowerOfTwo(this.currentHeight + i); boolean flag2 = l <= this.maxWidth; boolean flag3 = i1 <= this.maxHeight; if (!flag2 && !flag3) { return false; } boolean flag4 = j != l; boolean flag5 = k != i1; if (flag4 ^ flag5) { flag1 = !flag4; } 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 = flag6 && (flag || this.currentWidth <= this.currentHeight); } j = Math.max(p_94311_1_.getWidth(), p_94311_1_.getHeight()); if (MathHelper.roundUpToPowerOfTwo((flag1 ? this.currentHeight : this.currentWidth) + j) > (flag1 ? this.maxHeight : this.maxWidth)) { return false; } else { Stitcher.Slot slot; if (flag1) { if (p_94311_1_.getWidth() > p_94311_1_.getHeight()) { p_94311_1_.rotate(); } if (this.currentHeight == 0) { this.currentHeight = p_94311_1_.getHeight(); } slot = new Stitcher.Slot(this.currentWidth, 0, p_94311_1_.getWidth(), this.currentHeight); this.currentWidth += p_94311_1_.getWidth(); } else { slot = new Stitcher.Slot(0, this.currentHeight, this.currentWidth, p_94311_1_.getHeight()); this.currentHeight += p_94311_1_.getHeight(); } slot.addSlot(p_94311_1_); this.stitchSlots.add(slot); return true; } } @SideOnly(Side.CLIENT) public static class Holder implements Comparable { private final TextureAtlasSprite theTexture; private final int width; private final int height; private final int mipmapLevelHolder; private boolean rotated; private float scaleFactor = 1.0F; private static final String __OBFID = "CL_00001055"; public Holder(TextureAtlasSprite p_i45094_1_, int p_i45094_2_) { this.theTexture = p_i45094_1_; this.width = p_i45094_1_.getIconWidth(); this.height = p_i45094_1_.getIconHeight(); this.mipmapLevelHolder = p_i45094_2_; this.rotated = Stitcher.getMipmapDimension(this.height, p_i45094_2_) > Stitcher.getMipmapDimension(this.width, p_i45094_2_); } public TextureAtlasSprite getAtlasSprite() { return this.theTexture; } public int getWidth() { return this.rotated ? Stitcher.getMipmapDimension((int)((float)this.height * this.scaleFactor), this.mipmapLevelHolder) : Stitcher.getMipmapDimension((int)((float)this.width * this.scaleFactor), this.mipmapLevelHolder); } public int getHeight() { return this.rotated ? Stitcher.getMipmapDimension((int)((float)this.width * this.scaleFactor), this.mipmapLevelHolder) : Stitcher.getMipmapDimension((int)((float)this.height * this.scaleFactor), this.mipmapLevelHolder); } public void rotate() { this.rotated = !this.rotated; } public boolean isRotated() { return this.rotated; } public void setNewDimension(int p_94196_1_) { if (this.width > p_94196_1_ && this.height > p_94196_1_) { this.scaleFactor = (float)p_94196_1_ / (float)Math.min(this.width, this.height); } } public String toString() { return "Holder{width=" + this.width + ", height=" + this.height + '}'; } public int compareTo(Stitcher.Holder p_compareTo_1_) { int i; if (this.getHeight() == p_compareTo_1_.getHeight()) { if (this.getWidth() == p_compareTo_1_.getWidth()) { if (this.theTexture.getIconName() == null) { return p_compareTo_1_.theTexture.getIconName() == null ? 0 : -1; } return this.theTexture.getIconName().compareTo(p_compareTo_1_.theTexture.getIconName()); } i = this.getWidth() < p_compareTo_1_.getWidth() ? 1 : -1; } else { i = this.getHeight() < p_compareTo_1_.getHeight() ? 1 : -1; } return i; } public int compareTo(Object p_compareTo_1_) { return this.compareTo((Stitcher.Holder)p_compareTo_1_); } } @SideOnly(Side.CLIENT) public static class Slot { private final int originX; private final int originY; private final int width; private final int height; private List subSlots; private Stitcher.Holder holder; private static final String __OBFID = "CL_00001056"; public Slot(int p_i1277_1_, int p_i1277_2_, int p_i1277_3_, int p_i1277_4_) { this.originX = p_i1277_1_; this.originY = p_i1277_2_; this.width = p_i1277_3_; this.height = p_i1277_4_; } public Stitcher.Holder getStitchHolder() { return this.holder; } public int getOriginX() { return this.originX; } public int getOriginY() { return this.originY; } public boolean addSlot(Stitcher.Holder p_94182_1_) { if (this.holder != null) { return false; } else { int i = p_94182_1_.getWidth(); int j = p_94182_1_.getHeight(); if (i <= this.width && j <= this.height) { if (i == this.width && j == this.height) { this.holder = p_94182_1_; return true; } else { if (this.subSlots == null) { this.subSlots = new ArrayList(1); this.subSlots.add(new Stitcher.Slot(this.originX, this.originY, i, j)); int k = this.width - i; int l = this.height - j; if (l > 0 && k > 0) { int i1 = Math.max(this.height, k); int j1 = Math.max(this.width, l); if (i1 >= j1) { this.subSlots.add(new Stitcher.Slot(this.originX, this.originY + j, i, l)); this.subSlots.add(new Stitcher.Slot(this.originX + i, this.originY, k, this.height)); } else { this.subSlots.add(new Stitcher.Slot(this.originX + i, this.originY, k, j)); this.subSlots.add(new Stitcher.Slot(this.originX, this.originY + j, this.width, l)); } } else if (k == 0) { this.subSlots.add(new Stitcher.Slot(this.originX, this.originY + j, i, l)); } else if (l == 0) { this.subSlots.add(new Stitcher.Slot(this.originX + i, this.originY, k, j)); } } Iterator iterator = this.subSlots.iterator(); Stitcher.Slot slot; do { if (!iterator.hasNext()) { return false; } slot = (Stitcher.Slot)iterator.next(); } while (!slot.addSlot(p_94182_1_)); return true; } } else { return false; } } } /** * Gets the slot and all its subslots */ public void getAllStitchSlots(List p_94184_1_) { if (this.holder != null) { p_94184_1_.add(this); } else if (this.subSlots != null) { Iterator iterator = this.subSlots.iterator(); while (iterator.hasNext()) { Stitcher.Slot slot = (Stitcher.Slot)iterator.next(); slot.getAllStitchSlots(p_94184_1_); } } } public String toString() { return "Slot{originX=" + this.originX + ", originY=" + this.originY + ", width=" + this.width + ", height=" + this.height + ", texture=" + this.holder + ", subSlots=" + this.subSlots + '}'; } } }