Add tooltips to gui elements

This commit is contained in:
johni0702
2015-07-09 16:19:06 +02:00
parent d4e04feaeb
commit 9e886b6171
9 changed files with 311 additions and 2 deletions

View File

@@ -37,6 +37,14 @@ public interface GuiRenderer {
void drawTexturedRect(int x, int y, int u, int v, int width, int height);
void drawRect(int x, int y, int width, int height, int color);
void drawRect(int x, int y, int width, int height, ReadableColor color);
void drawRect(int x, int y, int width, int height, int topLeftColor, int topRightColor, int bottomLeftColor, int bottomRightColor);
void drawRect(int x, int y, int width, int height, ReadableColor topLeftColor, ReadableColor topRightColor, ReadableColor bottomLeftColor, ReadableColor bottomRightColor);
int drawString(int x, int y, int color, String text);
int drawString(int x, int y, ReadableColor color, String text);

View File

@@ -26,9 +26,15 @@ import lombok.NonNull;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Color;
import org.lwjgl.util.*;
import static net.minecraft.client.renderer.GlStateManager.*;
import static org.lwjgl.opengl.GL11.*;
public class MinecraftGuiRenderer implements GuiRenderer {
private final Gui gui = new Gui();
@@ -60,6 +66,46 @@ public class MinecraftGuiRenderer implements GuiRenderer {
gui.drawTexturedModalRect(x, y, u, v, width, height);
}
@Override
public void drawRect(int x, int y, int width, int height, int color) {
Gui.drawRect(x, y, x + width, y + height, color);
}
@Override
public void drawRect(int x, int y, int width, int height, ReadableColor color) {
drawRect(x, y, width, height, color(color));
}
@Override
public void drawRect(int x, int y, int width, int height, int topLeftColor, int topRightColor, int bottomLeftColor, int bottomRightColor) {
drawRect(x, y, width, height, color(topLeftColor), color(topRightColor), color(bottomLeftColor), color(bottomRightColor));
}
@Override
public void drawRect(int x, int y, int width, int height, ReadableColor tl, ReadableColor tr, ReadableColor bl, ReadableColor br) {
disableTexture2D();
enableBlend();
disableAlpha();
tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0);
shadeModel(GL_SMOOTH);
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer renderer = tessellator.getWorldRenderer();
renderer.startDrawingQuads();
renderer.setColorRGBA(bl.getRed(), bl.getGreen(), bl.getBlue(), bl.getAlpha());
renderer.addVertex(x, y + height, 0);
renderer.setColorRGBA(br.getRed(), br.getGreen(), br.getBlue(), br.getAlpha());
renderer.addVertex(x + width, y + height, 0);
renderer.setColorRGBA(tr.getRed(), tr.getGreen(), tr.getBlue(), tr.getAlpha());
renderer.addVertex(x + width, y, 0);
renderer.setColorRGBA(tl.getRed(), tl.getGreen(), tl.getBlue(), tl.getAlpha());
renderer.addVertex(x, y, 0);
tessellator.draw();
shadeModel(GL_FLAT);
disableBlend();
enableAlpha();
enableTexture2D();
}
@Override
public int drawString(int x, int y, int color, String text) {
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
@@ -88,4 +134,8 @@ public class MinecraftGuiRenderer implements GuiRenderer {
| color.getGreen() << 8
| color.getBlue();
}
private ReadableColor color(int color) {
return new Color((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, (color >> 24) & 0xff);
}
}

View File

@@ -71,6 +71,26 @@ public class OffsetGuiRenderer implements GuiRenderer {
renderer.drawTexturedRect(x + position.getX(), y + position.getY(), u, v, width, height);
}
@Override
public void drawRect(int x, int y, int width, int height, int color) {
renderer.drawRect(x + position.getX(), y + position.getY(), width, height, color);
}
@Override
public void drawRect(int x, int y, int width, int height, ReadableColor color) {
renderer.drawRect(x + position.getX(), y + position.getY(), width, height, color);
}
@Override
public void drawRect(int x, int y, int width, int height, int topLeftColor, int topRightColor, int bottomLeftColor, int bottomRightColor) {
renderer.drawRect(x + position.getX(), y + position.getY(), width, height, topLeftColor, topRightColor, bottomLeftColor, bottomRightColor);
}
@Override
public void drawRect(int x, int y, int width, int height, ReadableColor topLeftColor, ReadableColor topRightColor, ReadableColor bottomLeftColor, ReadableColor bottomRightColor) {
renderer.drawRect(x + position.getX(), y + position.getY(), width, height, topLeftColor, topRightColor, bottomLeftColor, bottomRightColor);
}
@Override
public int drawString(int x, int y, int color, String text) {
return renderer.drawString(x + position.getX(), y + position.getY(), color, text) - position.getX();

View File

@@ -26,17 +26,23 @@ import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.MinecraftGuiRenderer;
import de.johni0702.minecraft.gui.OffsetGuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.element.GuiElement;
import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.function.*;
import eu.crushedpixel.replaymod.utils.MouseUtils;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.ReportedException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.Dimension;
import org.lwjgl.util.Point;
import org.lwjgl.util.ReadableDimension;
import org.lwjgl.util.ReadablePoint;
import java.io.IOException;
import java.util.concurrent.Callable;
public abstract class AbstractGuiScreen<T extends AbstractGuiScreen<T>> extends AbstractGuiContainer<T> {
@@ -70,6 +76,59 @@ public abstract class AbstractGuiScreen<T extends AbstractGuiScreen<T>> extends
title.draw(eRenderer, null, null);
}
super.draw(renderer, size, renderInfo);
final GuiElement tooltip = forEach(GuiElement.class).getTooltip(renderInfo);
if (tooltip != null) {
final ReadableDimension tooltipSize = tooltip.getMinSize();
int dx, dy;
if (renderInfo.mouseX + 8 + tooltipSize.getWidth() < screenSize.getWidth()) {
dx = 8;
} else {
dx = -8;
}
if (renderInfo.mouseY + 8 + tooltipSize.getHeight() < screenSize.getHeight()) {
dy = 8;
} else {
dy = -8;
}
final ReadablePoint position = new Point(renderInfo.mouseX + dx, renderInfo.mouseY + dy);
try {
OffsetGuiRenderer eRenderer = new OffsetGuiRenderer(renderer, position, tooltipSize);
tooltip.draw(eRenderer, tooltipSize, renderInfo.offsetMouse(position.getX(), position.getY()));
} catch (Exception ex) {
CrashReport crashReport = CrashReport.makeCrashReport(ex, "Rendering Gui Tooltip");
renderInfo.addTo(crashReport);
CrashReportCategory category = crashReport.makeCategory("Gui container details");
category.addCrashSectionCallable("Container", new Callable() {
@Override
public Object call() throws Exception {
return this;
}
});
category.addCrashSection("Width", size.getWidth());
category.addCrashSection("Height", size.getHeight());
category = crashReport.makeCategory("Tooltip details");
category.addCrashSectionCallable("Element", new Callable() {
@Override
public Object call() throws Exception {
return tooltip;
}
});
category.addCrashSectionCallable("Position", new Callable() {
@Override
public Object call() throws Exception {
return position;
}
});
category.addCrashSectionCallable("Size", new Callable() {
@Override
public Object call() throws Exception {
return tooltipSize;
}
});
throw new ReportedException(crashReport);
}
}
}
@Override

View File

@@ -47,6 +47,7 @@ public abstract class AbstractComposedGuiElement<T extends AbstractComposedGuiEl
return (C) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{ofType}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean isGetter = method.getName().startsWith("get");
Object handled = null;
for (final GuiElement element : getChildren()) {
try {
@@ -55,8 +56,14 @@ public abstract class AbstractComposedGuiElement<T extends AbstractComposedGuiEl
} else if (ofType.isInstance(element)) {
handled = method.invoke(element, args);
}
if (Boolean.TRUE.equals(handled)) {
break;
if (handled != null) {
if (handled instanceof Boolean) {
if (Boolean.TRUE.equals(handled)) {
break;
}
} else if (isGetter) {
return handled;
}
}
} catch (Exception e) {
CrashReport crash = CrashReport.makeCrashReport(e, "Calling Gui method");

View File

@@ -22,10 +22,12 @@
package de.johni0702.minecraft.gui.element;
import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.container.GuiContainer;
import lombok.Getter;
import net.minecraft.client.Minecraft;
import org.lwjgl.util.Dimension;
import org.lwjgl.util.Point;
import org.lwjgl.util.ReadableDimension;
public abstract class AbstractGuiElement<T extends AbstractGuiElement<T>> implements GuiElement<T> {
@@ -35,6 +37,8 @@ public abstract class AbstractGuiElement<T extends AbstractGuiElement<T>> implem
@Getter
private GuiContainer container;
private GuiElement tooltip;
@Getter
private boolean enabled = true;
@@ -65,6 +69,30 @@ public abstract class AbstractGuiElement<T extends AbstractGuiElement<T>> implem
return setEnabled(false);
}
@Override
public GuiElement getTooltip(RenderInfo renderInfo) {
if (tooltip != null) {
Point mouse = new Point(renderInfo.mouseX, renderInfo.mouseY);
if (container != null) {
container.convertFor(this, mouse);
}
ReadableDimension size = getMinSize();
if (mouse.getX() > 0
&& mouse.getY() > 0
&& mouse.getX() < size.getWidth()
&& mouse.getY() < size.getHeight()) {
return tooltip;
}
}
return null;
}
@Override
public T setTooltip(GuiElement tooltip) {
this.tooltip = tooltip;
return getThis();
}
@Override
public T setContainer(GuiContainer container) {
this.container = container;

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2015 johni0702
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.johni0702.minecraft.gui.element;
import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo;
import eu.crushedpixel.replaymod.utils.StringUtils;
import lombok.Getter;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.resources.I18n;
import org.lwjgl.util.Color;
import org.lwjgl.util.Dimension;
import org.lwjgl.util.ReadableColor;
import org.lwjgl.util.ReadableDimension;
public abstract class AbstractGuiTooltip<T extends AbstractGuiTooltip<T>> extends AbstractGuiElement<T> {
private static final int LINE_SPACING = 3;
private static final ReadableColor BACKGROUND_COLOR = new Color(16, 0, 16, 240);
private static final ReadableColor BORDER_LIGHT = new Color(80, 0, 255, 80);
private static final ReadableColor BORDER_DARK = new Color(40, 0, 127, 80);
@Getter
private String[] text = {};
@Getter
private ReadableColor color = ReadableColor.WHITE;
@Override
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
int width = size.getWidth();
int height = size.getHeight();
// Draw background
renderer.drawRect(1, 0, width - 2, height, BACKGROUND_COLOR); // Top to bottom
renderer.drawRect(0, 1, 1, height - 2, BACKGROUND_COLOR); // Left pixel row
renderer.drawRect(width - 1, 1, 1, height - 2, BACKGROUND_COLOR); // Right pixel row
// Draw the border, it gets darker from top to bottom
renderer.drawRect(1, 1, width - 2, 1, BORDER_LIGHT); // Top border
renderer.drawRect(1, height - 2, width - 2, 1, BORDER_DARK); // Bottom border
renderer.drawRect(1, 2, 1, height - 4, BORDER_LIGHT, BORDER_LIGHT, BORDER_DARK, BORDER_DARK); // Left border
renderer.drawRect(width - 2, 2, 1, height - 4, BORDER_LIGHT, BORDER_LIGHT, BORDER_DARK, BORDER_DARK); // Right border
FontRenderer fontRenderer = getMinecraft().fontRendererObj;
int y = LINE_SPACING + 1;
for (String line : text) {
renderer.drawString(LINE_SPACING + 1, y, color, line);
y += fontRenderer.FONT_HEIGHT + LINE_SPACING;
}
}
@Override
public ReadableDimension getMinSize() {
FontRenderer fontRenderer = getMinecraft().fontRendererObj;
int height = 1 + LINE_SPACING + text.length * (fontRenderer.FONT_HEIGHT + LINE_SPACING);
int width = 0;
for (String line : text) {
int w = fontRenderer.getStringWidth(line);
if (w > width) {
width = w;
}
}
width+=4 * 2;
return new Dimension(width, height);
}
public T setText(String[]text) {
this.text = text;
return getThis();
}
public T setText(String text) {
return setText(StringUtils.splitStringInMultipleRows(text, 250));
}
public T setI18nText(String text, Object... args) {
return setText(I18n.format(text, args));
}
public T setColor(ReadableColor color) {
this.color = color;
return getThis();
}
}

View File

@@ -49,4 +49,7 @@ public interface GuiElement<T extends GuiElement<T>> {
T setEnabled();
T setDisabled();
GuiElement getTooltip(RenderInfo renderInfo);
T setTooltip(GuiElement tooltip);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2015 johni0702
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.johni0702.minecraft.gui.element;
public class GuiTooltip extends AbstractGuiTooltip<GuiTooltip> {
@Override
protected GuiTooltip getThis() {
return this;
}
}