/*
* Copyright (C) 2022-2023 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
* NotEnoughUpdates is free software: you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* NotEnoughUpdates is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with NotEnoughUpdates. If not, see .
*/
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.vector.Vector2f;
import java.awt.*;
import java.util.List;
import java.util.function.Supplier;
public abstract class TextOverlay {
private final Position position;
protected Supplier styleSupplier;
public int overlayWidth = -1;
public int overlayHeight = -1;
public List overlayStrings = null;
private final Supplier> dummyStrings;
public boolean shouldUpdateFrequent = false;
private static final int PADDING_X = 5;
private static final int PADDING_Y = 5;
public TextOverlay(Position position, Supplier> dummyStrings, Supplier styleSupplier) {
this.position = position;
this.styleSupplier = styleSupplier;
if (dummyStrings == null) {
this.dummyStrings = () -> null;
} else {
this.dummyStrings = dummyStrings;
}
}
public Vector2f getDummySize() {
List dummyStrings = this.dummyStrings.get();
if (dummyStrings != null) {
return getSize(dummyStrings);
}
return new Vector2f(100, 50);
}
public boolean isEnabled() {
return true;
}
public void tick() {
update();
}
public void updateFrequent() {
}
public abstract void update();
public void renderDummy() {
List dummyStrings = this.dummyStrings.get();
render(dummyStrings, true);
}
public void render() {
if (shouldUpdateFrequent) {
updateFrequent();
shouldUpdateFrequent = false;
}
render(overlayStrings, false);
}
protected Vector2f getSize(List strings) {
int overlayHeight = 0;
int overlayWidth = 0;
for (String s : strings) {
if (s == null) {
overlayHeight += 3;
continue;
}
if (s.startsWith("CUSTOM")) {
s = s.substring(s.indexOf(':') + 1);
}
for (String s2 : s.split("\n")) {
int sWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(s2);
if (sWidth > overlayWidth) {
overlayWidth = sWidth;
}
overlayHeight += 10;
}
}
overlayHeight -= 2;
int paddingX = 0;
int paddingY = 0;
if (styleSupplier.get() == TextOverlayStyle.BACKGROUND) {
paddingX = PADDING_X;
paddingY = PADDING_Y;
}
return new Vector2f(overlayWidth + paddingX * 2, overlayHeight + paddingY * 2);
}
protected Vector2f getTextOffset() {
return new Vector2f();
}
protected Vector2f getPosition(int overlayWidth, int overlayHeight, boolean scaled) {
GlStateManager.pushMatrix();
ScaledResolution scaledResolution;
if (!scaled) scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
else scaledResolution = Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.locationedit.guiScale);
int x = position.getAbsX(scaledResolution, overlayWidth);
int y = position.getAbsY(scaledResolution, overlayHeight);
GlStateManager.popMatrix();
return new Vector2f(x, y);
}
public Position getPosition() {
return position;
}
protected void renderLine(String line, Vector2f position, boolean dummy) {
}
private void render(List strings, boolean dummy) {
if (strings == null) return;
Vector2f size = getSize(strings);
overlayHeight = (int) size.y;
overlayWidth = (int) size.x;
Vector2f position = getPosition(overlayWidth, overlayHeight, !dummy);
int x = (int) position.x;
int y = (int) position.y;
TextOverlayStyle style = styleSupplier.get();
if (style == TextOverlayStyle.BACKGROUND) Gui.drawRect(x, y, x + overlayWidth, y + overlayHeight, 0x80000000);
GlStateManager.enableBlend();
GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.tryBlendFuncSeparate(
GL11.GL_SRC_ALPHA,
GL11.GL_ONE_MINUS_SRC_ALPHA,
GL11.GL_ONE,
GL11.GL_ONE_MINUS_SRC_ALPHA
);
int paddingX = 0;
int paddingY = 0;
if (styleSupplier.get() == TextOverlayStyle.BACKGROUND) {
paddingX = PADDING_X;
paddingY = PADDING_Y;
}
Vector2f textOffset = getTextOffset();
paddingX += (int) textOffset.x;
paddingY += (int) textOffset.y;
int yOff = 0;
for (String s : strings) {
if (s == null) {
yOff += 3;
} else {
for (String s2 : s.split("\n")) {
Vector2f pos = new Vector2f(x + paddingX, y + paddingY + yOff);
renderLine(s2, pos, dummy);
if (s2.startsWith("CUSTOM")) {
s2 = s2.split(":", 2)[1];
}
int xPad = (int) pos.x;
int yPad = (int) pos.y;
if (style == TextOverlayStyle.FULL_SHADOW) {
String clean = Utils.cleanColourNotModifiers(s2);
for (int xO = -2; xO <= 2; xO++) {
for (int yO = -2; yO <= 2; yO++) {
if (Math.abs(xO) != Math.abs(yO)) {
Minecraft.getMinecraft().fontRendererObj.drawString(clean,
xPad + xO / 2f, yPad + yO / 2f,
new Color(0, 0, 0, 200 / Math.max(Math.abs(xO), Math.abs(yO))).getRGB(), false
);
}
}
}
}
Minecraft.getMinecraft().fontRendererObj.drawString(s2,
xPad, yPad, 0xffffff, style == TextOverlayStyle.MC_SHADOW
);
yOff += 10;
}
}
}
}
}