mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
438 lines
10 KiB
Java
438 lines
10 KiB
Java
package com.hbm.module;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.util.Arrays;
|
|
|
|
import javax.annotation.Nonnegative;
|
|
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import com.google.common.annotations.Beta;
|
|
import com.hbm.inventory.gui.GuiInfoContainer;
|
|
import com.hbm.util.BobMathUtil;
|
|
|
|
import net.minecraft.client.renderer.Tessellator;
|
|
import net.minecraft.util.EnumChatFormatting;
|
|
import net.minecraft.util.MathHelper;
|
|
|
|
|
|
/**
|
|
* Seven segment style displays for GUIs, tried to be as adaptable as possible. Still has some bugs that need to be ironed out but it works for the most part.
|
|
* @author UFFR
|
|
*
|
|
*/
|
|
public class NumberDisplay {
|
|
|
|
/*
|
|
* Moved the entire class into its own file to keep GuiInfoContainer tidy.
|
|
* This new class needs a reference to the GUI because of this so it can render things using the GUI's utils.
|
|
*/
|
|
protected GuiInfoContainer gui;
|
|
|
|
/** The display's X coordinate **/
|
|
private int displayX;
|
|
/** The display's Y coordinate **/
|
|
private int displayY;
|
|
/** The display's color, in hexadecimal **/
|
|
private int color;
|
|
/** The amount of padding between digits, default 3 **/
|
|
@Nonnegative
|
|
private byte padding = 3;
|
|
/** Does it blink or not, default false, not yet used **/
|
|
private boolean blink = false;
|
|
/** Max number the display can handle **/
|
|
private float maxNum;
|
|
/** Min number the display can handle **/
|
|
private float minNum;
|
|
private boolean customBounds = false;
|
|
// Should it be a decimal number?
|
|
private boolean isFloat = false;
|
|
// How many trailing zeros?
|
|
private byte floatPad = 1;
|
|
/** Does it pad out with zeros **/
|
|
private boolean pads = false;
|
|
/** Max number of digits the display has, default 3 **/
|
|
@Nonnegative
|
|
private byte digitLength = 3;
|
|
private Number numIn = 0;
|
|
private char[] toDisp = {'0', '0', '0'};
|
|
@Nonnegative
|
|
private short dispOffset = 0;
|
|
/** Length and thickness of segments. **/
|
|
private int verticalLength = 5;
|
|
private int horizontalLength = 4;
|
|
private int thickness = 1;
|
|
/**
|
|
* Construct a new number display
|
|
* @param dX X coordinate of the display
|
|
* @param dY Y coordinate of the display
|
|
* @param c Enum Color to use, invalid enums will default to yellow
|
|
*/
|
|
public NumberDisplay(GuiInfoContainer gui, int x, int y, EnumChatFormatting c)
|
|
{
|
|
this(gui, x, y);
|
|
setColor(enumToColor(c));
|
|
}
|
|
/**
|
|
* Construct a new number display
|
|
* @param x X coordinate of the display
|
|
* @param y Y coordinate of the display
|
|
* @param color Color to use, valid hexadecimal value required
|
|
*/
|
|
public NumberDisplay(GuiInfoContainer gui, int x, int y, int color)
|
|
{
|
|
this(gui, x, y);
|
|
setColor(color);
|
|
}
|
|
/**
|
|
* Construct a new number display, color is yellow
|
|
* @param x X coordinate of the display
|
|
* @param y Y coordinate of the display
|
|
*/
|
|
public NumberDisplay(GuiInfoContainer gui, int x, int y)
|
|
{
|
|
displayX = x;
|
|
displayY = y;
|
|
setColor(0xFFFF55);
|
|
this.gui = gui;
|
|
}
|
|
|
|
/**
|
|
* Returns a hexadecimal from EnumChatFormatting
|
|
* @param c Color to use
|
|
* @return
|
|
*/
|
|
private int enumToColor(EnumChatFormatting c) {
|
|
if(c.isColor()) {
|
|
switch(c) {
|
|
case AQUA:
|
|
return 0x55FFFF;
|
|
case BLACK:
|
|
return 0x000000;
|
|
case BLUE:
|
|
return 0x5555FF;
|
|
case DARK_AQUA:
|
|
return 0x00AAAA;
|
|
case DARK_BLUE:
|
|
return 0x0000AA;
|
|
case DARK_GRAY:
|
|
return 0x555555;
|
|
case DARK_GREEN:
|
|
return 0x00AA00;
|
|
case DARK_PURPLE:
|
|
return 0xAA00AA;
|
|
case DARK_RED:
|
|
return 0xAA0000;
|
|
case GOLD:
|
|
return 0xFFAA00;
|
|
case GRAY:
|
|
return 0xAAAAAA;
|
|
case GREEN:
|
|
return 0x55FF55;
|
|
case LIGHT_PURPLE:
|
|
return 0xFF55FF;
|
|
case RED:
|
|
return 0xFF5555;
|
|
case WHITE:
|
|
return 0xFFFFFF;
|
|
case YELLOW:
|
|
return 0xFFFF55;
|
|
default:
|
|
}
|
|
}
|
|
|
|
return 0xFFFF55;
|
|
}
|
|
/**
|
|
* Sets color
|
|
* @param color - The color in hexadecimal
|
|
**/
|
|
public void setColor(int color) {
|
|
this.color = color;
|
|
}
|
|
/**
|
|
* Draw custom number
|
|
* @param num - The char array that has the number
|
|
*/
|
|
public void drawNumber(char[] num)
|
|
{
|
|
if (blink && !BobMathUtil.getBlink())
|
|
return;
|
|
|
|
short gap = (short) (digitLength - num.length);
|
|
for (int i = 0; i < num.length; i++)
|
|
{
|
|
if (num[i] == '.')
|
|
gap--;
|
|
dispOffset = (short) ((padding + horizontalLength + 2 * thickness) * (i + gap));
|
|
drawChar(num[i]);
|
|
}
|
|
if (pads)
|
|
padOut(gap);
|
|
}
|
|
/** Draw the previously provided number **/
|
|
public void drawNumber()
|
|
{
|
|
if (isFloat)
|
|
formatForFloat();
|
|
drawNumber(toDisp);
|
|
}
|
|
public void drawNumber(Number num)
|
|
{
|
|
setNumber(num);
|
|
drawNumber();
|
|
}
|
|
private void padOut(short gap)
|
|
{
|
|
if (gap == 0)
|
|
return;
|
|
for (int i = 0; i < gap; i++)
|
|
{
|
|
dispOffset = (short) ((padding + horizontalLength + 2 * thickness) * i);
|
|
drawChar('0');
|
|
}
|
|
}
|
|
|
|
/** Draw a single character (requires dispOffset to be set) **/
|
|
public void drawChar(char num)
|
|
{
|
|
switch (num)
|
|
{
|
|
case '1':
|
|
drawVertical(1, 0);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '2':
|
|
drawHorizontal(0);
|
|
drawVertical(1, 0);
|
|
drawHorizontal(1);
|
|
drawVertical(0, 1);
|
|
drawHorizontal(2);
|
|
break;
|
|
case '3':
|
|
drawHorizontal(0);
|
|
drawHorizontal(1);
|
|
drawHorizontal(2);
|
|
drawVertical(1, 0);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '4':
|
|
drawVertical(0, 0);
|
|
drawVertical(1, 0);
|
|
drawVertical(1, 1);
|
|
drawHorizontal(1);
|
|
break;
|
|
case '5':
|
|
drawHorizontal(0);
|
|
drawHorizontal(1);
|
|
drawHorizontal(2);
|
|
drawVertical(0, 0);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '6':
|
|
drawHorizontal(0);
|
|
drawHorizontal(1);
|
|
drawHorizontal(2);
|
|
drawVertical(0, 0);
|
|
drawVertical(0, 1);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '7':
|
|
drawHorizontal(0);
|
|
drawVertical(1, 0);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '8':
|
|
drawHorizontal(0);
|
|
drawHorizontal(1);
|
|
drawHorizontal(2);
|
|
drawVertical(0, 0);
|
|
drawVertical(1, 0);
|
|
drawVertical(0, 1);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '9':
|
|
drawHorizontal(0);
|
|
drawHorizontal(1);
|
|
drawHorizontal(2);
|
|
drawVertical(0, 0);
|
|
drawVertical(1, 0);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '0':
|
|
drawHorizontal(0);
|
|
drawHorizontal(2);
|
|
drawVertical(0, 0);
|
|
drawVertical(0, 1);
|
|
drawVertical(1, 0);
|
|
drawVertical(1, 1);
|
|
break;
|
|
case '-':
|
|
drawHorizontal(1);
|
|
break;
|
|
case '.':
|
|
drawPeriod();
|
|
break;
|
|
case 'E':
|
|
default:
|
|
drawHorizontal(0);
|
|
drawHorizontal(1);
|
|
drawHorizontal(2);
|
|
drawVertical(0, 0);
|
|
drawVertical(0, 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void drawHorizontal(int pos)
|
|
{
|
|
byte offset = (byte) (pos * (verticalLength + thickness));
|
|
renderSegment(gui.getGuiLeft() + displayX + dispOffset + thickness, gui.getGuiTop() + displayY + offset, horizontalLength, thickness);
|
|
}
|
|
|
|
private void drawPeriod()
|
|
{
|
|
renderSegment(gui.getGuiLeft() + displayX + dispOffset + padding - (int) Math.ceil(padding / 2) + (horizontalLength + thickness),
|
|
gui.getGuiLeft() + displayY + 2 * (verticalLength + thickness), thickness, thickness);
|
|
}
|
|
|
|
private void drawVertical(int posX, int posY)
|
|
{
|
|
byte offsetX = (byte) (posX * (horizontalLength + thickness));
|
|
byte offsetY = (byte) (posY * (verticalLength + thickness));
|
|
renderSegment(gui.getGuiLeft() + displayX + offsetX + dispOffset, gui.getGuiTop() + displayY + offsetY + thickness, thickness, verticalLength);
|
|
}
|
|
/**
|
|
* drawTexturedModalRect() for cool kids
|
|
* @param renX X coordinate to render the part
|
|
* @param renY Y coordinate to render the part
|
|
* @param width Relevant for horizontals
|
|
* @param height Relevant for verticals
|
|
*/
|
|
private void renderSegment(int renX, int renY, int width, int height)
|
|
{
|
|
final Tessellator tess = Tessellator.instance;
|
|
final float z = gui.getZLevel();
|
|
|
|
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
|
tess.startDrawingQuads();
|
|
tess.setColorOpaque_I(color);
|
|
tess.addVertex(renX, renY + height, z);
|
|
tess.addVertex(renX + width, renY + height, z);
|
|
tess.addVertex(renX + width, renY + 0, z);
|
|
tess.addVertex(renX, renY, z);
|
|
tess.draw();
|
|
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
|
}
|
|
|
|
public void setNumber(Number num)
|
|
{
|
|
numIn = num;
|
|
if (customBounds)
|
|
numIn = MathHelper.clamp_double(num.doubleValue(), minNum, maxNum);
|
|
if (isFloat)
|
|
formatForFloat();
|
|
else
|
|
{
|
|
toDisp = new Long(Math.round(numIn.doubleValue())).toString().toCharArray();
|
|
toDisp = truncOrExpand();
|
|
}
|
|
}
|
|
/** Get the set number **/
|
|
public Number getNumber()
|
|
{
|
|
return numIn;
|
|
}
|
|
/** Get the char array for display **/
|
|
public char[] getDispNumber()
|
|
{
|
|
return toDisp.clone();
|
|
}
|
|
/** Make the display blink **/
|
|
public NumberDisplay setBlinks(boolean doesBlink)
|
|
{
|
|
blink = doesBlink;
|
|
return this;
|
|
}
|
|
/** Padding between digits, default 3 **/
|
|
public NumberDisplay setPadding(@Nonnegative int p)
|
|
{
|
|
padding = (byte) p;
|
|
return this;
|
|
}
|
|
/** Max number of digits **/
|
|
public NumberDisplay setDigitLength(@Nonnegative int l)
|
|
{
|
|
digitLength = (byte) l;
|
|
toDisp = truncOrExpand();
|
|
return this;
|
|
}
|
|
/** Set sizes and thickness of horizontal and vertical segments. **/
|
|
public NumberDisplay setSegmentSize(int vertical, int horizontal, int thickness)
|
|
{
|
|
this.verticalLength = vertical;
|
|
this.horizontalLength = horizontal;
|
|
this.thickness = thickness;
|
|
return this;
|
|
}
|
|
/** Set custom number bounds **/
|
|
public NumberDisplay setMaxMin(float max, float min)
|
|
{
|
|
if (min > max)
|
|
throw new IllegalArgumentException("Minimum value is larger than maximum value!");
|
|
maxNum = max;
|
|
minNum = min;
|
|
customBounds = true;
|
|
return this;
|
|
}
|
|
/** Pad out the left side of the number with zeros **/
|
|
public NumberDisplay setPadNumber()
|
|
{
|
|
pads = true;
|
|
return this;
|
|
}
|
|
/** Set the number to be a decimal, default zero trailing is 1 **/
|
|
public NumberDisplay setFloat()
|
|
{
|
|
return setFloat(1);
|
|
}
|
|
/** Set the number to be a decimal with specified zero trailing **/
|
|
public NumberDisplay setFloat(@Nonnegative int pad)
|
|
{
|
|
floatPad = (byte) pad;
|
|
isFloat = true;
|
|
|
|
formatForFloat();
|
|
|
|
return this;
|
|
}
|
|
private void formatForFloat()
|
|
{
|
|
BigDecimal bd = new BigDecimal(numIn.toString());
|
|
bd = bd.setScale(floatPad, RoundingMode.HALF_UP);
|
|
|
|
// char[] proc = new Double(bd.doubleValue()).toString().toCharArray();
|
|
char[] proc = bd.toString().toCharArray();
|
|
proc = Double.valueOf(BobMathUtil.roundDecimal(numIn.doubleValue(), floatPad)).toString().toCharArray();
|
|
|
|
if (proc.length == digitLength)
|
|
toDisp = proc;
|
|
else
|
|
toDisp = truncOrExpand();
|
|
}
|
|
@Beta
|
|
private char[] truncOrExpand()
|
|
{
|
|
if (isFloat)
|
|
{
|
|
char[] out = Arrays.copyOf(toDisp, digitLength);
|
|
for (int i = 0; i < digitLength; i++)
|
|
if (out[i] == '\u0000')
|
|
out[i] = '0';
|
|
return out.clone();
|
|
}
|
|
return toDisp;
|
|
}
|
|
}
|