animated-chunks/src/main/java/me/topchetoeu/animatedchunks/gui/Section.java

243 lines
7.8 KiB
Java

package me.topchetoeu.animatedchunks.gui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.AbstractParentElement;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import net.minecraft.util.math.ColorHelper.Argb;
public abstract class Section extends AbstractParentElement implements Drawable, Selectable, BoundboxProvider {
protected class Offset {
public float x, y;
public Offset(float x, float y) {
this.x = x;
this.y = y;
}
}
public class ChildList {
protected final Map<Element, Offset> offsets = new Hashtable<>();
protected final Map<Element, BoundboxProvider> boundboxes = new Hashtable<>();
protected final List<Element> children = new ArrayList<>();
protected final List<Selectable> selectables = new ArrayList<>();
protected final List<Drawable> drawables = new ArrayList<>();
protected Offset getOffsetAndPos(Object element) {
Offset of = new Offset(offsets.get(element).x, offsets.get(element).y);
of.x += boundboxes.get(element).getX();
of.y += boundboxes.get(element).getY();
return of;
}
protected Offset getOffset(Object element) {
return offsets.get(element);
}
public BoundboxProvider getBoundbox(Object element) {
return boundboxes.get(element);
}
public <T extends Element & Drawable & Selectable & BoundboxProvider> T addSelectableChild(T element) {
return addSelectableChild(element, element);
}
public <T extends Element & Drawable & BoundboxProvider> T addChild(T element) {
return addChild(element, element);
}
public <T extends Element & Drawable & Selectable> T addSelectableChild(T element, BoundboxProvider boundbox) {
this.boundboxes.put(element, boundbox);
this.offsets.put(element, new Offset(0, 0));
this.drawables.add(element);
this.selectables.add(element);
this.children.add(element);
recalculate();
return element;
}
public <T extends Element & Drawable> T addChild(T element, BoundboxProvider boundbox) {
this.boundboxes.put(element, boundbox);
this.offsets.put(element, new Offset(0, 0));
this.drawables.add(element);
this.children.add(element);
recalculate();
return element;
}
public List<? extends Element> get() {
return Collections.unmodifiableList(children);
}
public void clear() {
focusedIndex = -1;
offsets.clear();
boundboxes.clear();
children.clear();
selectables.clear();
drawables.clear();
}
private ChildList() {}
}
public enum OrderType {
Start,
Middle,
End,
Justified,
}
public final ChildList children = new ChildList();
public OrderType order = OrderType.Start;
protected int focusedIndex = 0;
protected float width, height;
protected MinecraftClient mc = MinecraftClient.getInstance();
public Text title;
public float x, y;
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
@Override
public List<? extends Element> children() {
return children.get();
}
@Override
public Element getFocused() {
if (focusedIndex < 0) return null;
else return children().get(focusedIndex);
}
@Override
public void setFocused(Element element) {
focusedIndex = children().indexOf(element);
}
@Override
public void appendNarrations(NarrationMessageBuilder var1) {
}
protected abstract void recalculate();
@Override
public SelectionType getType() {
if (this.children.selectables.stream().anyMatch(v -> v.getType() == SelectionType.HOVERED)) {
return SelectionType.HOVERED;
}
return SelectionType.NONE;
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
recalculate();
matrices.push();
matrices.translate(x, y, getZOffset());
if (title != null) {
mc.textRenderer.draw(matrices, title, 5, 0, Argb.getArgb(255, 255, 255, 255));
drawHorizontalLine(matrices, 0, (int)width, mc.textRenderer.fontHeight, Argb.getArgb(255, 255, 255, 255));
}
for (Drawable d : children.drawables) {
Offset o = children.getOffset(d);
matrices.push();
matrices.translate(o.x, o.y, 0);
d.render(matrices, mouseX - (int)o.x - (int)x, mouseY - (int)o.y - (int)y, delta);
matrices.pop();
}
matrices.pop();
}
@Override
public boolean isMouseOver(double mouseX, double mouseY) {
return getType() == SelectionType.HOVERED || (mouseX >= x && mouseX <= width && mouseY >= y && mouseY <= height);
}
@Override
public Optional<Element> hoveredElement(double mouseX, double mouseY) {
for (Selectable element : this.children.selectables) {
var offset = children.getOffset(element);
if (element.getType() != SelectionType.HOVERED || !((Element)element).isMouseOver(mouseX - offset.x, mouseY - offset.y)) continue;
return Optional.of((Element)element);
}
return Optional.empty();
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
for (Element element : this.children()) {
var offset = children.getOffset(element);
if (!element.mouseScrolled(mouseX - offset.x - x, mouseY - offset.y - y, delta)) continue;
return true;
}
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
for (Element element : this.children()) {
var offset = children.getOffset(element);
if (!element.mouseClicked(mouseX - offset.x - x, mouseY - offset.y - y, button)) continue;
this.setFocused(element);
if (button == 0) {
this.setDragging(true);
}
return true;
}
return false;
}
@Override
public void mouseMoved(double mouseX, double mouseY) {
for (Element element : this.children()) {
var offset = children.getOffset(element);
element.mouseMoved(mouseX - offset.x - x, mouseY - offset.y - y);
}
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
this.setDragging(false);
for (Element element : children.get()) {
var offset = children.getOffset(element);
if (element.mouseReleased(mouseX - (int)offset.x - x, mouseY - (int)offset.y - y, button)) return true;
}
return false;
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (this.getFocused() != null && this.isDragging() && button == 0) {
var offset = children.getOffset(getFocused());
return this.getFocused().mouseDragged(mouseX - offset.x - x, mouseY - offset.y - y, button, deltaX, deltaY);
}
return false;
}
}