282 lines
8.1 KiB
Java
282 lines
8.1 KiB
Java
|
package mods.tinker.tconstruct.client;
|
||
|
|
||
|
import java.awt.Color;
|
||
|
import java.awt.Font;
|
||
|
import java.awt.FontMetrics;
|
||
|
import java.awt.Graphics;
|
||
|
import java.awt.Rectangle;
|
||
|
import java.awt.geom.Rectangle2D;
|
||
|
import java.awt.image.BufferedImage;
|
||
|
import java.io.File;
|
||
|
import java.io.InputStream;
|
||
|
|
||
|
import net.minecraft.client.Minecraft;
|
||
|
import net.minecraft.client.gui.Gui;
|
||
|
import net.minecraft.client.renderer.Tessellator;
|
||
|
|
||
|
import org.lwjgl.opengl.GL11;
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @author TheObliterator
|
||
|
*
|
||
|
* A class to create and draw true type
|
||
|
* fonts onto the Minecraft game engine.
|
||
|
*/
|
||
|
public class CustomFont
|
||
|
{
|
||
|
private int texID;
|
||
|
private int[] xPos;
|
||
|
private int[] yPos;
|
||
|
private int startChar;
|
||
|
private int endChar;
|
||
|
private FontMetrics metrics;
|
||
|
|
||
|
/**
|
||
|
* Instantiates the font, filling in default start
|
||
|
* and end character parameters.
|
||
|
*
|
||
|
* 'new CustomFont(ModLoader.getMinecraftInstance(),
|
||
|
* "Arial", 12);
|
||
|
*
|
||
|
* @param mc The Minecraft instance for the font to be bound to.
|
||
|
* @param fontName The name of the font to be drawn.
|
||
|
* @param size The size of the font to be drawn.
|
||
|
*/
|
||
|
public CustomFont(Minecraft mc, Object font, int size)
|
||
|
{
|
||
|
this(mc, font, size, 0, 4000);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Instantiates the font, pre-rendering a sprite
|
||
|
* font image by using a true type font on a
|
||
|
* bitmap. Then allocating that bitmap to the
|
||
|
* Minecraft rendering engine for later use.
|
||
|
*
|
||
|
* 'new CustomFont(ModLoader.getMinecraftInstance(),
|
||
|
* "Arial", 12, 32, 126);'
|
||
|
*
|
||
|
* @param mc The Minecraft instance for the font to be bound to.
|
||
|
* @param fontName The name of the font to be drawn.
|
||
|
* @param size The size of the font to be drawn.
|
||
|
* @param startChar The starting ASCII character id to be drawable. (Default 32)
|
||
|
* @param endChar The ending ASCII character id to be drawable. (Default 126)
|
||
|
*/
|
||
|
public CustomFont(Minecraft mc, Object font, int size, int startChar, int endChar)
|
||
|
{
|
||
|
this.startChar = startChar;
|
||
|
this.endChar = endChar;
|
||
|
xPos = new int[endChar - startChar];
|
||
|
yPos = new int[endChar - startChar];
|
||
|
|
||
|
// Create a bitmap and fill it with a transparent color as well
|
||
|
// as obtain a Graphics instance which can be drawn on.
|
||
|
// NOTE: It is CRUICIAL that the size of the image is 256x256, if
|
||
|
// it is not the Minecraft engine will not draw it properly.
|
||
|
BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
|
||
|
Graphics g = img.getGraphics();
|
||
|
try
|
||
|
{
|
||
|
if (font instanceof String)
|
||
|
{
|
||
|
String fontName = (String) font;
|
||
|
if (fontName.contains("/"))
|
||
|
g.setFont(Font.createFont(Font.TRUETYPE_FONT, new File(fontName)).deriveFont((float) size));
|
||
|
else
|
||
|
g.setFont(new Font(fontName, 0, size));
|
||
|
}
|
||
|
else if (font instanceof InputStream)
|
||
|
{
|
||
|
g.setFont(Font.createFont(Font.TRUETYPE_FONT, (InputStream) font).deriveFont((float) size));
|
||
|
}
|
||
|
else if (font instanceof File)
|
||
|
{
|
||
|
g.setFont(Font.createFont(Font.TRUETYPE_FONT, (File) font).deriveFont((float) size));
|
||
|
}
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
|
||
|
g.setColor(new Color(255, 255, 255, 0));
|
||
|
g.fillRect(0, 0, 256, 256);
|
||
|
g.setColor(Color.white);
|
||
|
metrics = g.getFontMetrics();
|
||
|
|
||
|
// Draw the specified range of characters onto
|
||
|
// the new bitmap, spacing according to the font
|
||
|
// widths. Also allocating positions of characters
|
||
|
// on the bitmap to two arrays which will be used
|
||
|
// later when drawing.
|
||
|
int x = 2;
|
||
|
int y = 2;
|
||
|
for (int i = startChar; i < endChar; i++)
|
||
|
{
|
||
|
g.drawString("" + ((char) i), x, y + g.getFontMetrics().getAscent());
|
||
|
xPos[i - startChar] = x;
|
||
|
yPos[i - startChar] = y - metrics.getMaxDescent();
|
||
|
x += metrics.stringWidth("" + (char) i) + 2;
|
||
|
if (x >= 250 - metrics.getMaxAdvance())
|
||
|
{
|
||
|
x = 2;
|
||
|
y += metrics.getMaxAscent() + metrics.getMaxDescent() + size / 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Render the finished bitmap into the Minecraft
|
||
|
// graphics engine.
|
||
|
texID = mc.renderEngine.allocateAndSetupTexture(img);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Draws a given string with an automatically
|
||
|
* calculated shadow below it.
|
||
|
* @param gui The gui/subclass to be drawn on
|
||
|
* @param text The string to be drawn
|
||
|
* @param x The x position to start drawing
|
||
|
* @param y The y position to start drawing
|
||
|
* @param color The color of the non-shadowed text (Hex)
|
||
|
*/
|
||
|
public void drawStringS (Gui gui, String text, int x, int y, int color)
|
||
|
{
|
||
|
int l = color & 0xff000000;
|
||
|
int shade = (color & 0xfcfcfc) >> 2;
|
||
|
shade += l;
|
||
|
drawString(gui, text, x + 1, y + 1, shade);
|
||
|
drawString(gui, text, x, y, color);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Draws a given string onto a gui/subclass.
|
||
|
* @param gui The gui/subclass to be drawn on
|
||
|
* @param text The string to be drawn
|
||
|
* @param x The x position to start drawing
|
||
|
* @param y The y position to start drawing
|
||
|
* @param color The color of the non-shadowed text (Hex)
|
||
|
*/
|
||
|
public void drawString (Gui gui, String text, int x, int y, int color)
|
||
|
{
|
||
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||
|
GL11.glEnable(3553 /*GL_TEXTURE_2D*/);
|
||
|
GL11.glBindTexture(3553 /*GL_TEXTURE_2D*/, texID);
|
||
|
float red = (float) (color >> 16 & 0xff) / 255F;
|
||
|
float green = (float) (color >> 8 & 0xff) / 255F;
|
||
|
float blue = (float) (color & 0xff) / 255F;
|
||
|
float alpha = (float) (color >> 24 & 0xff) / 255F;
|
||
|
GL11.glColor4f(red, green, blue, alpha);
|
||
|
int startX = x;
|
||
|
for (int i = 0; i < text.length(); i++)
|
||
|
{
|
||
|
char c = text.charAt(i);
|
||
|
if (c == '\\')
|
||
|
{
|
||
|
char type = text.charAt(i + 1);
|
||
|
if (type == 'n')
|
||
|
{
|
||
|
y += metrics.getAscent() + 2;
|
||
|
x = startX;
|
||
|
}
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
drawChar(gui, c, x, y);
|
||
|
x += metrics.getStringBounds("" + c, null).getWidth();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the created FontMetrics
|
||
|
* which is used to retrive various
|
||
|
* information about the True Type Font
|
||
|
* @return FontMetrics of the created font.
|
||
|
*/
|
||
|
public FontMetrics getMetrics ()
|
||
|
{
|
||
|
return metrics;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the drawing width of a given
|
||
|
* string of string.
|
||
|
* @param text The string to be measured
|
||
|
* @return The width of the given string.
|
||
|
*/
|
||
|
public int getStringWidth (String text)
|
||
|
{
|
||
|
return (int) getBounds(text).getWidth();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the drawing height of a given
|
||
|
* string of string.
|
||
|
* @param text The string to be measured
|
||
|
* @return The height of the given string.
|
||
|
*/
|
||
|
public int getStringHeight (String text)
|
||
|
{
|
||
|
return (int) getBounds(text).getHeight();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A method that returns a Rectangle that
|
||
|
* contains the width and height demensions
|
||
|
* of the given string.
|
||
|
* @param text The string to be measured
|
||
|
* @return Rectangle containing width and height that
|
||
|
* the text will consume when drawn.
|
||
|
*/
|
||
|
private Rectangle getBounds (String text)
|
||
|
{
|
||
|
int w = 0;
|
||
|
int h = 0;
|
||
|
int tw = 0;
|
||
|
for (int i = 0; i < text.length(); i++)
|
||
|
{
|
||
|
char c = text.charAt(i);
|
||
|
if (c == '\\')
|
||
|
{
|
||
|
char type = text.charAt(i + 1);
|
||
|
|
||
|
if (type == 'n')
|
||
|
{
|
||
|
h += metrics.getAscent() + 2;
|
||
|
if (tw > w)
|
||
|
w = tw;
|
||
|
tw = 0;
|
||
|
}
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
tw += metrics.stringWidth("" + c);
|
||
|
}
|
||
|
if (tw > w)
|
||
|
w = tw;
|
||
|
h += metrics.getAscent();
|
||
|
return new Rectangle(0, 0, w, h);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Private drawing method used within other
|
||
|
* drawing methods.
|
||
|
*/
|
||
|
private void drawChar (Gui gui, char c, int x, int y)
|
||
|
{
|
||
|
Rectangle2D bounds = metrics.getStringBounds("" + c, null);
|
||
|
drawTexturedModalRect(x, y, xPos[(byte) c - startChar], yPos[(byte) c - startChar], (int) bounds.getWidth(), (int) bounds.getHeight() + metrics.getMaxDescent());
|
||
|
}
|
||
|
|
||
|
public void drawTexturedModalRect(int x, int y, int u, int v, int width, int height)
|
||
|
{
|
||
|
float offsetWidth = 0.00390625F;
|
||
|
float offsetHeight = 0.00390625F;
|
||
|
Tessellator tessellator = Tessellator.instance;
|
||
|
tessellator.startDrawingQuads();
|
||
|
tessellator.addVertexWithUV((x + 0), (y + height), 0, ((u + 0) * offsetWidth), ((v + height) * offsetHeight));
|
||
|
tessellator.addVertexWithUV((x + width), (y + height), 0, ((u + width) * offsetWidth), ((v + height) * offsetHeight));
|
||
|
tessellator.addVertexWithUV((x + width), (y + 0), 0, ((u + width) * offsetWidth), ((v + 0) * offsetHeight));
|
||
|
tessellator.addVertexWithUV((x + 0), (y + 0), 0, ((u + 0) * offsetWidth), ((v + 0) * offsetHeight));
|
||
|
tessellator.draw();
|
||
|
}
|
||
|
}
|