Skip to content

Commit

Permalink
Fix #1471 Remove texture pack sizing restrictions
Browse files Browse the repository at this point in the history
  • Loading branch information
mezz committed Jan 22, 2019
1 parent 43f5f19 commit fe4ee85
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 303 deletions.
50 changes: 16 additions & 34 deletions src/main/java/mezz/jei/gui/GuiHelper.java
@@ -1,6 +1,5 @@
package mezz.jei.gui;

import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;

import mezz.jei.api.IGuiHelper;
Expand All @@ -17,7 +16,7 @@
import mezz.jei.gui.elements.DrawableBuilder;
import mezz.jei.gui.elements.DrawableIngredient;
import mezz.jei.gui.elements.DrawableNineSliceTexture;
import mezz.jei.gui.textures.JeiTextureMap;
import mezz.jei.gui.elements.DrawableSprite;
import mezz.jei.gui.textures.TextureInfo;
import mezz.jei.gui.textures.Textures;
import mezz.jei.util.ErrorUtil;
Expand Down Expand Up @@ -49,28 +48,22 @@ public class GuiHelper implements IGuiHelper {
public GuiHelper(IIngredientRegistry ingredientRegistry, Textures textures) {
this.ingredientRegistry = ingredientRegistry;
this.slotDrawable = createDrawable(textures.slot);
this.nineSliceSlot = createNineSliceDrawable(textures.slot, 4, 4, 4, 4);
this.nineSliceSlot = createNineSliceDrawable(textures.slot);

this.tabSelected = createDrawable(textures.tabSelected);
this.tabUnselected = createDrawable(textures.tabUnselected);

this.buttonDisabled = createNineSliceDrawable(textures.buttonDisabled, 2, 2, 2, 2);
this.buttonEnabled = createNineSliceDrawable(textures.buttonEnabled, 2, 2, 2, 2);
this.buttonHighlight = createNineSliceDrawable(textures.buttonHighlight, 2, 2, 2, 2);
this.guiBackground = createNineSliceDrawable(textures.guiBackground, 16, 16, 16, 16);
this.recipeBackground = createNineSliceDrawable(textures.recipeBackground, 16, 16, 16, 16);
this.searchBackground = createNineSliceDrawable(textures.searchBackground, 4, 4, 4, 4);
this.catalystTab = createNineSliceDrawable(textures.catalystTab, 8, 9, 8, 8);

this.shapelessIcon = drawableBuilder(textures.shapelessIcon)
.trim(1, 2, 1, 1)
.build();
this.arrowPrevious = drawableBuilder(textures.arrowPrevious)
.trim(0, 0, 1, 1)
.build();
this.arrowNext = drawableBuilder(textures.arrowNext)
.trim(0, 0, 1, 1)
.build();
this.buttonDisabled = createNineSliceDrawable(textures.buttonDisabled);
this.buttonEnabled = createNineSliceDrawable(textures.buttonEnabled);
this.buttonHighlight = createNineSliceDrawable(textures.buttonHighlight);
this.guiBackground = createNineSliceDrawable(textures.guiBackground);
this.recipeBackground = createNineSliceDrawable(textures.recipeBackground);
this.searchBackground = createNineSliceDrawable(textures.searchBackground);
this.catalystTab = createNineSliceDrawable(textures.catalystTab);

this.shapelessIcon = createDrawable(textures.shapelessIcon);
this.arrowPrevious = createDrawable(textures.arrowPrevious);
this.arrowNext = createDrawable(textures.arrowNext);
this.recipeTransfer = createDrawable(textures.recipeTransfer);

this.configButtonIcon = createDrawable(textures.configButtonIcon);
Expand Down Expand Up @@ -121,22 +114,11 @@ public ITickTimer createTickTimer(int ticksPerCycle, int maxValue, boolean count
}

private IDrawableStatic createDrawable(TextureInfo textureInfo) {
return drawableBuilder(textureInfo).build();
return new DrawableSprite(textureInfo);
}

private DrawableNineSliceTexture createNineSliceDrawable(TextureInfo textureInfo, int leftWidth, int rightWidth, int topHeight, int bottomHeight) {
JeiTextureMap textureMap = textureInfo.getTextureMap();
TextureAtlasSprite sprite = textureInfo.getSprite();
int scale = textureInfo.getScale();
return new DrawableNineSliceTexture(textureMap.getLocation(), sprite.getOriginX() / scale, sprite.getOriginY() / scale, sprite.getIconWidth() / scale, sprite.getIconHeight() / scale, leftWidth, rightWidth, topHeight, bottomHeight, textureMap.getWidth() / scale, textureMap.getHeight() / scale);
}

private IDrawableBuilder drawableBuilder(TextureInfo textureInfo) {
JeiTextureMap textureMap = textureInfo.getTextureMap();
TextureAtlasSprite sprite = textureInfo.getSprite();
int scale = textureInfo.getScale();
return drawableBuilder(textureMap.getLocation(), sprite.getOriginX() / scale, sprite.getOriginY() / scale, sprite.getIconWidth() / scale, sprite.getIconHeight() / scale)
.setTextureSize(textureMap.getWidth() / scale, textureMap.getHeight() / scale);
private DrawableNineSliceTexture createNineSliceDrawable(TextureInfo textureInfo) {
return new DrawableNineSliceTexture(textureInfo);
}

public IDrawableStatic getTabSelected() {
Expand Down
140 changes: 69 additions & 71 deletions src/main/java/mezz/jei/gui/elements/DrawableNineSliceTexture.java
Expand Up @@ -3,116 +3,96 @@
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;

import mezz.jei.gui.textures.TextureInfo;

/**
* Breaks a texture into 9 pieces so that it can be scaled to any size.
* Draws the corners and then repeats any middle textures to fill the remaining area.
*/
public class DrawableNineSliceTexture {
private final ResourceLocation resourceLocation;
private final int u;
private final int v;
private final int width;
private final int height;
private final int leftWidth;
private final int rightWidth;
private final int topHeight;
private final int bottomHeight;
private final int textureWidth;
private final int textureHeight;

public DrawableNineSliceTexture(ResourceLocation resourceLocation, int u, int v, int width, int height, int leftWidth, int rightWidth, int topHeight, int bottomHeight, int textureWidth, int textureHeight) {
this.resourceLocation = resourceLocation;
this.u = u;
this.v = v;
this.width = width;
this.height = height;
this.leftWidth = leftWidth;
this.rightWidth = rightWidth;
this.topHeight = topHeight;
this.bottomHeight = bottomHeight;
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
private final TextureInfo info;

public DrawableNineSliceTexture(TextureInfo info) {
this.info = info;
}

public void draw(Minecraft minecraft, int xOffset, int yOffset, int width, int height) {
ResourceLocation location = info.getLocation();
TextureAtlasSprite sprite = info.getSprite();
int leftWidth = info.getSliceLeft();
int rightWidth = info.getSliceRight();
int topHeight = info.getSliceTop();
int bottomHeight = info.getSliceBottom();
int textureWidth = info.getWidth();
int textureHeight = info.getHeight();

TextureManager textureManager = minecraft.getTextureManager();
textureManager.bindTexture(resourceLocation);
textureManager.bindTexture(location);

float uMin = sprite.getMinU();
float uMax = sprite.getMaxU();
float vMin = sprite.getMinV();
float vMax = sprite.getMaxV();
float uSize = uMax - uMin;
float vSize = vMax - vMin;

final int uMiddle = u + leftWidth;
final int uRight = u + this.width - rightWidth;
final int vMiddle = v + topHeight;
final int vBottom = v + this.height - bottomHeight;
final int middleWidth = uRight - uMiddle;
final int middleHeight = vBottom - vMiddle;
float uLeft = uMin + uSize * (leftWidth / (float) textureWidth);
float uRight = uMax - uSize * (rightWidth / (float) textureWidth);
float vTop = vMin + vSize * (topHeight / (float) textureHeight);
float vBottom = vMax - vSize * (bottomHeight / (float) textureHeight);

Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
bufferBuilder.begin(7, DefaultVertexFormats.POSITION_TEX);

// left top
draw(bufferBuilder, u, v, leftWidth, topHeight, xOffset, yOffset);
draw(bufferBuilder, uMin, vMin, uLeft, vTop, xOffset, yOffset, leftWidth, topHeight);
// left bottom
draw(bufferBuilder, u, vBottom, leftWidth, bottomHeight, xOffset, yOffset + height - bottomHeight);
draw(bufferBuilder, uMin, vBottom, uLeft, vMax, xOffset, yOffset + height - bottomHeight, leftWidth, bottomHeight);
// right top
draw(bufferBuilder, uRight, v, rightWidth, topHeight, xOffset + width - rightWidth, yOffset);
draw(bufferBuilder, uRight, vMin, uMax, vTop, xOffset + width - rightWidth, yOffset, rightWidth, topHeight);
// right bottom
draw(bufferBuilder, uRight, vBottom, rightWidth, bottomHeight, xOffset + width - rightWidth, yOffset + height - bottomHeight);
draw(bufferBuilder, uRight, vBottom, uMax, vMax, xOffset + width - rightWidth, yOffset + height - bottomHeight, rightWidth, bottomHeight);

final int tiledMiddleWidth = width - leftWidth - rightWidth;
final int tiledMiddleHeight = height - topHeight - bottomHeight;
int middleWidth = textureWidth - leftWidth - rightWidth;
int middleHeight = textureWidth - topHeight - bottomHeight;
int tiledMiddleWidth = width - leftWidth - rightWidth;
int tiledMiddleHeight = height - topHeight - bottomHeight;
if (tiledMiddleWidth > 0) {
// top edge
drawTiled(bufferBuilder, uMiddle, v, middleWidth, topHeight, xOffset + leftWidth, yOffset, tiledMiddleWidth, topHeight);
drawTiled(bufferBuilder, uLeft, vMin, uRight, vTop, xOffset + leftWidth, yOffset, tiledMiddleWidth, topHeight, middleWidth, topHeight);
// bottom edge
drawTiled(bufferBuilder, uMiddle, vBottom, middleWidth, bottomHeight, xOffset + leftWidth, yOffset + height - bottomHeight, tiledMiddleWidth, bottomHeight);
drawTiled(bufferBuilder, uLeft, vBottom, uRight, vMax, xOffset + leftWidth, yOffset + height - bottomHeight, tiledMiddleWidth, bottomHeight, middleWidth, bottomHeight);
}
if (tiledMiddleHeight > 0) {
// left side
drawTiled(bufferBuilder, u, vMiddle, leftWidth, middleHeight, xOffset, yOffset + topHeight, leftWidth, tiledMiddleHeight);
drawTiled(bufferBuilder, uMin, vTop, uLeft, vBottom, xOffset, yOffset + topHeight, leftWidth, tiledMiddleHeight, leftWidth, middleHeight);
// right side
drawTiled(bufferBuilder, uRight, vMiddle, rightWidth, middleHeight, xOffset + width - rightWidth, yOffset + topHeight, rightWidth, tiledMiddleHeight);
drawTiled(bufferBuilder, uRight, vTop, uMax, vBottom, xOffset + width - rightWidth, yOffset + topHeight, rightWidth, tiledMiddleHeight, rightWidth, middleHeight);
}
if (tiledMiddleHeight > 0 && tiledMiddleWidth > 0) {
// middle area
drawTiled(bufferBuilder, uMiddle, vMiddle, middleWidth, middleHeight, xOffset + leftWidth, yOffset + topHeight, tiledMiddleWidth, tiledMiddleHeight);
drawTiled(bufferBuilder, uLeft, vTop, uRight, vBottom, xOffset + leftWidth, yOffset + topHeight, tiledMiddleWidth, tiledMiddleHeight, middleWidth, middleHeight);
}

tessellator.draw();
}

private void draw(BufferBuilder bufferBuilder, int u, int v, int width, int height, int xOffset, int yOffset) {
double widthScale = 1.0 / textureWidth;
double heightScale = 1.0 / textureHeight;
double u1 = u * widthScale;
double v1 = (v + height) * heightScale;
double u2 = (u + width) * widthScale;
double v2 = v * heightScale;

bufferBuilder.pos(xOffset, yOffset + height, 0)
.tex(u1, v1)
.endVertex();
bufferBuilder.pos(xOffset + width, yOffset + height, 0)
.tex(u2, v1)
.endVertex();
bufferBuilder.pos(xOffset + width, yOffset, 0)
.tex(u2, v2)
.endVertex();
bufferBuilder.pos(xOffset, yOffset, 0)
.tex(u1, v2)
.endVertex();
}
private void drawTiled(BufferBuilder bufferBuilder, float uMin, float vMin, float uMax, float vMax, int xOffset, int yOffset, int tiledWidth, int tiledHeight, int width, int height) {
int xTileCount = tiledWidth / width;
int xRemainder = tiledWidth - (xTileCount * width);
int yTileCount = tiledHeight / height;
int yRemainder = tiledHeight - (yTileCount * height);

private void drawTiled(BufferBuilder bufferBuilder, int u, int v, int width, int height, int xOffset, int yOffset, int tiledWidth, int tiledHeight) {
final int xTileCount = tiledWidth / width;
final int xRemainder = tiledWidth - (xTileCount * width);
final int yTileCount = tiledHeight / height;
final int yRemainder = tiledHeight - (yTileCount * height);
int yStart = yOffset + tiledHeight;

final int yStart = yOffset + tiledHeight;
float uSize = uMax - uMin;
float vSize = vMax - vMin;

for (int xTile = 0; xTile <= xTileCount; xTile++) {
for (int yTile = 0; yTile <= yTileCount; yTile++) {
Expand All @@ -121,11 +101,29 @@ private void drawTiled(BufferBuilder bufferBuilder, int u, int v, int width, int
int x = xOffset + (xTile * width);
int y = yStart - ((yTile + 1) * height);
if (tileWidth > 0 && tileHeight > 0) {
int maskTop = height - tileHeight;
int maskRight = width - tileWidth;
draw(bufferBuilder, u, v + maskTop, width - maskRight, height - maskTop, x, y + maskTop);
int maskTop = height - tileHeight;
float uOffset = (maskRight / (float) width) * uSize;
float vOffset = (maskTop / (float) height) * vSize;

draw(bufferBuilder, uMin, vMin + vOffset, uMax - uOffset, vMax, x, y + maskTop, tileWidth, tileHeight);
}
}
}
}

private static void draw(BufferBuilder bufferBuilder, float minU, double minV, float maxU, float maxV, int xOffset, int yOffset, int width, int height) {
bufferBuilder.pos(xOffset, yOffset + height, 0)
.tex(minU, maxV)
.endVertex();
bufferBuilder.pos(xOffset + width, yOffset + height, 0)
.tex(maxU, maxV)
.endVertex();
bufferBuilder.pos(xOffset + width, yOffset, 0)
.tex(maxU, minV)
.endVertex();
bufferBuilder.pos(xOffset, yOffset, 0)
.tex(minU, minV)
.endVertex();
}
}
80 changes: 80 additions & 0 deletions src/main/java/mezz/jei/gui/elements/DrawableSprite.java
@@ -0,0 +1,80 @@
package mezz.jei.gui.elements;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;

import mezz.jei.api.gui.IDrawableStatic;
import mezz.jei.gui.textures.TextureInfo;

public class DrawableSprite implements IDrawableStatic {
private final TextureInfo info;

public DrawableSprite(TextureInfo info) {
this.info = info;
}

@Override
public int getWidth() {
return info.getWidth();
}

@Override
public int getHeight() {
return info.getHeight();
}

@Override
public void draw(Minecraft minecraft, int xOffset, int yOffset) {
draw(minecraft, xOffset, yOffset, 0, 0, 0, 0);
}

@Override
public void draw(Minecraft minecraft, int xOffset, int yOffset, int maskTop, int maskBottom, int maskLeft, int maskRight) {
ResourceLocation location = info.getLocation();
TextureAtlasSprite sprite = info.getSprite();
int textureWidth = info.getWidth();
int textureHeight = info.getHeight();

TextureManager textureManager = minecraft.getTextureManager();
textureManager.bindTexture(location);

maskTop += info.getTrimTop();
maskBottom += info.getTrimBottom();
maskLeft += info.getTrimLeft();
maskRight += info.getTrimRight();

int x = xOffset + maskLeft;
int y = yOffset + maskTop;
int width = textureWidth - maskRight - maskLeft;
int height = textureHeight - maskBottom - maskTop;
float uSize = sprite.getMaxU() - sprite.getMinU();
float vSize = sprite.getMaxV() - sprite.getMinV();

float minU = sprite.getMinU() + uSize * (maskLeft / (float) textureWidth);
float minV = sprite.getMinV() + vSize * (maskTop / (float) textureHeight);
float maxU = sprite.getMaxU() - uSize * (maskRight / (float) textureWidth);
float maxV = sprite.getMaxV() - vSize * (maskBottom / (float) textureHeight);

Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
bufferBuilder.begin(7, DefaultVertexFormats.POSITION_TEX);
bufferBuilder.pos(x, y + height, 0)
.tex(minU, maxV)
.endVertex();
bufferBuilder.pos(x + width, y + height, 0)
.tex(maxU, maxV)
.endVertex();
bufferBuilder.pos(x + width, y, 0)
.tex(maxU, minV)
.endVertex();
bufferBuilder.pos(x, y, 0)
.tex(minU, minV)
.endVertex();
tessellator.draw();
}
}

0 comments on commit fe4ee85

Please sign in to comment.