diff --git a/src/main/java/de/johni0702/minecraft/gui/GuiRenderer.java b/src/main/java/de/johni0702/minecraft/gui/GuiRenderer.java index af77bbc2..e69b9e7e 100644 --- a/src/main/java/de/johni0702/minecraft/gui/GuiRenderer.java +++ b/src/main/java/de/johni0702/minecraft/gui/GuiRenderer.java @@ -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); diff --git a/src/main/java/de/johni0702/minecraft/gui/MinecraftGuiRenderer.java b/src/main/java/de/johni0702/minecraft/gui/MinecraftGuiRenderer.java index 73399366..de20509d 100644 --- a/src/main/java/de/johni0702/minecraft/gui/MinecraftGuiRenderer.java +++ b/src/main/java/de/johni0702/minecraft/gui/MinecraftGuiRenderer.java @@ -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); + } } diff --git a/src/main/java/de/johni0702/minecraft/gui/OffsetGuiRenderer.java b/src/main/java/de/johni0702/minecraft/gui/OffsetGuiRenderer.java index ffda23fe..90f835c4 100644 --- a/src/main/java/de/johni0702/minecraft/gui/OffsetGuiRenderer.java +++ b/src/main/java/de/johni0702/minecraft/gui/OffsetGuiRenderer.java @@ -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(); diff --git a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java index e1d3ebe3..704c357a 100644 --- a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java +++ b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java @@ -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> extends AbstractGuiContainer { @@ -70,6 +76,59 @@ public abstract class AbstractGuiScreen> 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 diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractComposedGuiElement.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractComposedGuiElement.java index c12b2ded..02de7b89 100644 --- a/src/main/java/de/johni0702/minecraft/gui/element/AbstractComposedGuiElement.java +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractComposedGuiElement.java @@ -47,6 +47,7 @@ public abstract class AbstractComposedGuiElement> implements GuiElement { @@ -35,6 +37,8 @@ public abstract class AbstractGuiElement> implem @Getter private GuiContainer container; + private GuiElement tooltip; + @Getter private boolean enabled = true; @@ -65,6 +69,30 @@ public abstract class AbstractGuiElement> 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; diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiTooltip.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiTooltip.java new file mode 100644 index 00000000..954bb358 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiTooltip.java @@ -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> extends AbstractGuiElement { + 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(); + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/GuiElement.java b/src/main/java/de/johni0702/minecraft/gui/element/GuiElement.java index a9fdb9a5..108b7e50 100644 --- a/src/main/java/de/johni0702/minecraft/gui/element/GuiElement.java +++ b/src/main/java/de/johni0702/minecraft/gui/element/GuiElement.java @@ -49,4 +49,7 @@ public interface GuiElement> { T setEnabled(); T setDisabled(); + GuiElement getTooltip(RenderInfo renderInfo); + T setTooltip(GuiElement tooltip); + } diff --git a/src/main/java/de/johni0702/minecraft/gui/element/GuiTooltip.java b/src/main/java/de/johni0702/minecraft/gui/element/GuiTooltip.java new file mode 100644 index 00000000..39d4b55b --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/GuiTooltip.java @@ -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 { + @Override + protected GuiTooltip getThis() { + return this; + } +}