Advanced Modding - Drawing a GUI with Miner's Basic

Goal

I want to show you how you can draw a GUI with methods provided by Miner's Basic.

Difficulty

3/10 - Relatively Easy

Prerequisites

Forge Version

This Tutorial was created with Forge 11.14.3.1450 for Minecraft 1.8. If anything doesn't work with other versions, please contact me!

Version

This tutorial requires at least version 1.0-b.325 of Miner's Basic.


A few words at the beginning

In this tutorial I'll show you how to use the methods provided by Miner's Basic to draw content on a GUI.

It is very useful if you know how to draw a GUI with vanilla methods before you start creating one using Miner's Basic. Also, I've explained some GUI basics in the tutorial about vanilla GUIs, so please read it too. I also refer to it quite often and don't explain stuff in detail if I've explained it there already.


Again, I won't show you exactly how to make a GUI, that's your own job, but I'll show you how you can use the methods by Miner's Basic.

Integrating the Miner's Basic GuiRenderer

The Miner's Basic GuiRenderer is a collection of static methods that can be used to render GUIs.

Every method can be called using this syntax:

GuiRenderer.whateverMethodYouWantToCall();

It can be useful, however, to store an instance of the GuiRenderer in a static variable to reduce code length:

GuiRenderer r = GuiRenderer.instance;

...

r.whateverMethodYouWantToCall();


The methods can be used in every GUI class, you only need to remember the different properties of the different classes as explained in the vanilla GUI tutorial.

Useful variables and objects of the GuiRenderer

  • zLevel
    Similar to the vanilla GUI object, the GuiRenderer has a zLevel variable. It works exactly the same as the vanilla one, however every method respects it (unlike the vanilla methods where the string is always drawn at level 0).
  • mc
    Contains the instance of Minecraft. Shortcut for Minecraft.getMinecraft() or ClientUtils.mc().
  • font
    Contains the FontRenderer instance. Shortcut for mc.fontRendererObj.
  • scale
    Instance of ScaledResolution. Can be used to calculate the size of GUI components on the screen. Updated using updateScaledResolution().
  • some others, use Code Completion to get those.

Methods for rendering

The following methods can be called inside the rendering methods to render something onto the screen.

Note that the GuiRenderer extends the class ObjectRenderer which can be used to render 3D objects. Methods starting with render... are used for 3D objects and are normally not suitable for GUIs.

Method
GuiRenderer.bindTexture(ResourceLocation location);

This method loads the image at the given resource location and binds it to the renderer. Resource locations are explained in detail in the vanilla GUI tutorial.


Method
GuiRenderer.setColor(Color color);

Sets the rendering color.

The class Color provides several constant color values, but can also be instantiated on the fly using

new Color(double r, double g, double b)

or

new Color(double r, double g, double b, double alpha)

Note that alpha 1.0 is opaque and alpha 0.0 transparent.


Method
GuiRenderer.drawLine(int x1, int y1, int x2, int y2);

Draws a line between the two points.

The width of the line can be set using setLineWidth(float width);

Before a line is drawn, the texture should be disabled, otherwise it would draw a textured line which looks relatively weird or wouldn't be visible at all. The methods to use here are:

disableTexture(); and enableTexture();


Method
GuiRenderer.drawRect(int x1, int y1, int x2, int y2, Color color);

Draws a filled rectangle at the given coordinates with the given color.

 

Method
GuiRenderer.drawVerticalGradient(int x1, int y1, int x2, int y2, Color c1, Color c2);

Draws a rectangle with a vertical gradient at the given coordinates.

Color c1 is the upper color, c2 the lower one.


Method
GuiRenderer.drawHorizontalGradient(int x1, int y1, int x2, int y2, Color c1, Color c2);

Same as above, however the gradient goes from left to right.

 

Method
GuiRenderer.drawTexturedRect(int x, int y, int u, int v, int width, int height);

This method draws a textured rectangle at the given position with the given size.

The image used is the currently bound image. The position of the texture is determined by the u and v value, the texture's size is assumed to be 256*256. See the vanilla GUI tutorial for examples.

 

Method
GuiRenderer.drawTexturedRect(int x, int y, int imgwidth, int imgheight, int u, int v, int width, int height);

Same as above, however the texture can have any size. The size is set by the imgwidth and -height parameter.


Method
GuiRenderer.drawTexturedRect(int x, int y, TexPos icon, int width, int height);

Same as above, but uses a TexPos to determine the position of the texture on the image. TexPos is explained in the section about classes below.


Method
GuiRenderer.drawString(String text, int x, int y, Color color, boolean shadow);

Draws a String at the given position with the given color. If shadow is true, the text has a shadow.


Method
GuiRenderer.drawString(String text, int x, int y, Align align, Color color, boolean shadow);

Same as above, however the text has a specific align to the position.

Align is an enum containing nine different align possibilities.

For instance, if Align.TL (Top Left) is used, the coordinates define the upper left corner of the text.

If Align.CC (Center Center) is used, the coordinates define the exact center of the text.

 

Method
GuiRenderer.drawSplitString(String text, int x, int y, int width, Color color);

Draws a String with automatic word-wrap when the given width is exceeded.


Method
GuiRenderer.drawItemStack(ItemStack stack, int x, int y);

Draws the given ItemStack.


Method
GuiRenderer.drawTooltip(ItemStack stack, int x, int y);

Draws the tooltip for the given ItemStack. Can be used if the mouse is over a custom drawn ItemStack.


Method
GuiRenderer.drawHoveringText(List<String> text, int x, int y, boolean offset);

Draws the list of Strings as lines in a hovering box like an item tooltip. If offset is true, the box is moved a bit to the side. This is used when x/y are mouse coordinates.

This method can be used to create tooltips for custom GUI components.


Method
GuiRenderer.renderCurve(GuiRenderer.controlpoints(new Vector2d[]{new Vector2d(x1, y1), ...}));

This method renders a bezier curve from given controlpoints.

This relies on the renderLine method, so the texture needs to be disabled as well.

The controlpoints are packed into a buffer by the controlpoints method. Four controlpoints are needed. They are passed as Vector2d objects (javax.vecmath.Vector2d).

The first and last controlpoint are the endpoints of the curve, the other ones are used to modify the curve's shape.


There are also a few other methods, but those can be found easily using code completion.


Miner's Basic classes used during rendering

I've created a lot of utility classes, that can be used during rendering.

Here, I'll explain some of them:

Color

(minersbasic.api.client.render.Color)

The color class is used to define a color for rendering.

It provides several constant colors, but can also be instantiated directly using new Color(r, g, b).

The available constants are:

WHITE (#FFFFFF)
BLACK (#000000)
RED (#FF0000)
GREEN (#00FF00)
BLUE (#0000FF)
YELLOW (#FFFF00)

CYAN (#00FFFF)

MAGENTA (#FF00FF)
GRAY (#777777)
DARK_RED (#770000)
DARK_GREEN (#007700)
DARK_BLUE (#000077)

DARK_CYAN (#007777)

DARK_MAGENTA (#770077)

DARK_GRAY (#555555)
GOLD (#FFAA00)
LIGHT_GRAY (#AAAAAA)
LIGHT_RED (#FF7777)

LIGHT_GREEN (#77FF77)
LIGHT_BLUE (#7777FF)
LIGHT_MAGENTA (#FF77FF)

LIGHT_CYAN (#77FFFF)
LIGHT_YELLOW (#FFFFAA)
INVENTORY_TITLE (#3F3F3F)
NEARLY_WHITE (#E1E1E1)


TexPos

A TexPos object stores the position of a texture on an image. This can be used in the drawTexturedRect method.

A TexPos can be created using

new TexPos(double u, double v, double U, double V);

where the capital letters are the maximum values (u = minU, U = maxU)

The point (u|v) is the upper left corner, (U|V) is the lower right corner.

 

A TexPos can be interpolated to get an extract of it. For instance, you need to call this method to get the upper half of a TexPos:

interpolate(double u, double v, double U, double V);

texpos.interpolate(0.0, 0.0, 1.0, 0.5);

You can also interpolate a TexPos with another.

Image

(minersbasic.api.client.gui.widgets.Image)

The class image is probably the most useful class in Miner's Basic. It contains a resource location for the specific image file and additionally a TexPos for that image.

To create an image, just use one of these constructors:

new Image(ResourceLocation location);

new Image(String path);

new Image(ResourceLocation location, TexPos texpos);

new Image(String path, TexPos texpos);

 

Images have the method bind() to bind the resource location to the renderer.

To render an image into the gui, just call:

image.bind();

GuiRenderer.drawTexturedRect(x, y, image.getTexPos(), width, height);

 

The best thing about images: They support animations!

When the image is loaded, the object automatically searches for an associated .mcmeta file that contains animation information.

If one is found, it is loaded and stored in the image. The syntax of the animation .mcmeta files can be found on the Minecraft Wiki.

Animations normally run automatically using the system time. If you want the animation not to run automatically, you can call setAutomaticAnimation(false); and activate the frame you want to see using setFrame(int frame); or nextFrame();

 

However, Images that are created dynamically need to be manually released, otherwise they fill up the RAM relatively fast.

To release an image object when it's not needed anymore, just call release();.

To avoid allocating and releasing space for images, make them static in your classes. Then you don't need to call release() anymore.


Recommended tutorials to continue with

Take a look at the tutorial overview and decide what you want to do next.


Comments and Questions:

If you want to report modding problems, please make sure to include the code in a pastebin link or something else! Don't just write "It doesn't work", otherwise your post will be deleted. For more complicated problems, please use the troubleshooter form.