333 lines
11 KiB
Java
333 lines
11 KiB
Java
package me.topchetoeu.animatedchunks.gui;
|
|
|
|
import org.lwjgl.glfw.GLFW;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
|
|
import me.topchetoeu.animatedchunks.AnimatedChunks;
|
|
import net.minecraft.client.MinecraftClient;
|
|
import net.minecraft.client.gui.Drawable;
|
|
import net.minecraft.client.gui.DrawableHelper;
|
|
import net.minecraft.client.gui.Element;
|
|
import net.minecraft.client.gui.Selectable;
|
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
|
import net.minecraft.client.gui.screen.narration.NarrationPart;
|
|
import net.minecraft.client.render.BufferBuilder;
|
|
import net.minecraft.client.render.BufferRenderer;
|
|
import net.minecraft.client.render.GameRenderer;
|
|
import net.minecraft.client.render.Tessellator;
|
|
import net.minecraft.client.render.VertexFormat;
|
|
import net.minecraft.client.render.VertexFormats;
|
|
import net.minecraft.client.util.math.MatrixStack;
|
|
import net.minecraft.util.math.Matrix4f;
|
|
import net.minecraft.util.math.Quaternion;
|
|
import net.minecraft.util.math.Vec3f;
|
|
import net.minecraft.util.math.Vector4f;
|
|
import net.minecraft.util.math.ColorHelper.Argb;
|
|
|
|
public class ChunkPreview extends DrawableHelper implements Drawable, Element, Selectable, BoundboxProvider {
|
|
public static interface ClickAction {
|
|
void onClick();
|
|
}
|
|
|
|
public ClickAction clickAction;
|
|
public final MinecraftClient client;
|
|
private boolean clicked = false;
|
|
private boolean rotating = false;
|
|
private boolean focused = false;
|
|
private boolean hovered = false;
|
|
private float globalProgress = 0;
|
|
private float duration = 0;
|
|
private float mouseStartX, mouseStartY;
|
|
private float rotX, rotY, scale = 1;
|
|
|
|
public float x, y;
|
|
public float padding = 5;
|
|
public float width = 100, height = 100;
|
|
|
|
public float getX() {
|
|
return x;
|
|
}
|
|
public float getY() {
|
|
return y;
|
|
}
|
|
|
|
public float getWidth() {
|
|
return width;
|
|
}
|
|
public float getHeight() {
|
|
return height;
|
|
}
|
|
|
|
public void click() {
|
|
refresh();
|
|
}
|
|
|
|
@Override
|
|
public void appendNarrations(NarrationMessageBuilder msgBuilder) {
|
|
msgBuilder.put(NarrationPart.HINT, "Chunk preview");
|
|
}
|
|
|
|
@Override
|
|
public SelectionType getType() {
|
|
if (focused) return SelectionType.FOCUSED;
|
|
if (hovered || clicked || rotating) return SelectionType.HOVERED;
|
|
return SelectionType.NONE;
|
|
}
|
|
@Override
|
|
public boolean changeFocus(boolean lookForwards) {
|
|
focused = !focused;
|
|
return focused;
|
|
}
|
|
|
|
private void refresh() {
|
|
globalProgress = 0;
|
|
}
|
|
|
|
private static boolean checkZ(float z) {
|
|
return z < 3;
|
|
}
|
|
|
|
private static void myFill(MatrixStack matrices, float x1, float y1, float x2, float y2, float a, float r, float g, float b) {
|
|
if (x1 < x2) {
|
|
float tmp = x1;
|
|
x1 = x2;
|
|
x2 = tmp;
|
|
}
|
|
if (y1 < y2) {
|
|
float tmp = y1;
|
|
y1 = y2;
|
|
y2 = tmp;
|
|
}
|
|
|
|
Vector4f p1 = new Vector4f(x1, y1, 0, 1);
|
|
Vector4f p2 = new Vector4f(x1, y2, 0, 1);
|
|
Vector4f p3 = new Vector4f(x2, y2, 0, 1);
|
|
Vector4f p4 = new Vector4f(x2, y1, 0, 1);
|
|
|
|
p1.transform(matrices.peek().getPositionMatrix());
|
|
p2.transform(matrices.peek().getPositionMatrix());
|
|
p3.transform(matrices.peek().getPositionMatrix());
|
|
p4.transform(matrices.peek().getPositionMatrix());
|
|
|
|
p1.multiply(1 / p1.getW());
|
|
p2.multiply(1 / p2.getW());
|
|
p3.multiply(1 / p3.getW());
|
|
p4.multiply(1 / p4.getW());
|
|
|
|
if (checkZ(p1.getZ()) && checkZ(p2.getZ()) && checkZ(p3.getZ()) && checkZ(p4.getZ())) {
|
|
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
|
RenderSystem.enableBlend();
|
|
RenderSystem.disableCull();
|
|
RenderSystem.disableTexture();
|
|
RenderSystem.defaultBlendFunc();
|
|
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
|
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
|
|
bufferBuilder.vertex(p1.getX(), p1.getY(), p1.getZ()).color(r, g, b, a).next();
|
|
bufferBuilder.vertex(p2.getX(), p2.getY(), p2.getZ()).color(r, g, b, a).next();
|
|
bufferBuilder.vertex(p3.getX(), p3.getY(), p3.getZ()).color(r, g, b, a).next();
|
|
bufferBuilder.vertex(p4.getX(), p4.getY(), p4.getZ()).color(r, g, b, a).next();
|
|
BufferRenderer.drawWithShader(bufferBuilder.end());
|
|
RenderSystem.enableTexture();
|
|
RenderSystem.disableBlend();
|
|
}
|
|
|
|
}
|
|
|
|
private final Quaternion rotation = Quaternion.fromEulerXyzDegrees(new Vec3f(-90, 0, 0));
|
|
|
|
private void setupDepth(MatrixStack matrices) {
|
|
RenderSystem.enableDepthTest();
|
|
RenderSystem.disableBlend();
|
|
RenderSystem.clearDepth(-1);
|
|
RenderSystem.clear(GL11.GL_DEPTH_BUFFER_BIT, true);
|
|
RenderSystem.depthFunc(GL11.GL_ALWAYS);
|
|
RenderSystem.depthMask(true);
|
|
matrices.push();
|
|
matrices.scale(.5f, .5f, 1);
|
|
matrices.translate(0, 0, .1f);
|
|
if (hovered) {
|
|
myFill(matrices, -1, -1, 1, 1, 0.1f, 1, 1, 1);
|
|
}
|
|
else {
|
|
myFill(matrices, -1, -1, 1, 1, 0.004f, 0, 0, 0);
|
|
}
|
|
matrices.pop();
|
|
RenderSystem.depthMask(false);
|
|
RenderSystem.depthFunc(GL11.GL_LESS);
|
|
RenderSystem.enableBlend();
|
|
}
|
|
private void renderChunk(MatrixStack matrices, int x, int y, int n, float delta) {
|
|
matrices.push();
|
|
matrices.translate(x * 16 - 8, 0, y * 16 - 8);
|
|
|
|
// x += n;
|
|
// y += n;
|
|
|
|
float progress = globalProgress / duration - (float)Math.sqrt(x * x + y * y) / (float)n / 2;
|
|
if (progress < 0) progress = 0;
|
|
if (progress > 1) progress = 1;
|
|
if (progress < 0.999) {
|
|
float _progress = AnimatedChunks.getInstance().getEaseManager().getValue().ease(progress);
|
|
AnimatedChunks.getInstance().getAnimationManager().getValue().animate(
|
|
_progress, matrices,
|
|
x * 16, 0, y * 16, 0, 0, 0
|
|
);
|
|
// matrices.translate(0, 0, 16);
|
|
}
|
|
matrices.translate(0, 0, 16);
|
|
matrices.multiply(rotation);
|
|
myFill(matrices, 2, 1, 14, 2, progress, 1, 1, 1);
|
|
myFill(matrices, 2, 14, 14, 15, progress, 1, 1, 1);
|
|
myFill(matrices, 1, 1, 2, 15, progress, 1, 1, 1);
|
|
myFill(matrices, 14, 1, 15, 15, progress, 1, 1, 1);
|
|
|
|
matrices.pop();
|
|
}
|
|
private void renderChunks(MatrixStack matrices, float delta, int n) {
|
|
duration = AnimatedChunks.getInstance().getProgressManager().getDuration();
|
|
// globalProgress += (lastTime - (lastTime = System.nanoTime())) / -1000000000f;
|
|
globalProgress += delta * 0.05f;
|
|
matrices.push();
|
|
|
|
matrices.scale(width, width, 1);
|
|
matrices.translate(.5f, .5f, 0);
|
|
setupDepth(matrices);
|
|
|
|
matrices.multiplyPositionMatrix(Matrix4f.viewboxMatrix(75, 1, .00001f, 100));
|
|
matrices.translate(0, 0, -2);
|
|
matrices.scale(0.0625f, 0.0625f, 0.0625f);
|
|
matrices.scale(1f / (n * 2 + 1), 1f / (n * 2 + 1), 1f / (n * 2 + 1));
|
|
// matrices.multiply(Quaternion.fromEulerXyzDegrees(new Vec3f(150, -45, 0)));
|
|
matrices.scale(scale, scale, scale);
|
|
|
|
matrices.multiply(Quaternion.fromEulerXyzDegrees(new Vec3f(rotY + 150, 0, 0)));
|
|
matrices.multiply(Quaternion.fromEulerXyzDegrees(new Vec3f(0, rotX - 45, 0)));
|
|
|
|
// matrices.translate(-8, 0, 8);
|
|
|
|
for (int x = -n; x <= n; x++) {
|
|
for (int y = -n; y <= n; y++) {
|
|
renderChunk(matrices, x, y, n, delta);
|
|
}
|
|
}
|
|
|
|
RenderSystem.depthMask(true);
|
|
RenderSystem.disableDepthTest();
|
|
RenderSystem.clearDepth(1);
|
|
RenderSystem.clear(GL11.GL_DEPTH_BUFFER_BIT, true);
|
|
matrices.pop();
|
|
}
|
|
|
|
@Override
|
|
public void render(MatrixStack matrices, int x, int y, float delta) {
|
|
int white = Argb.getArgb(255, 255, 255, 255);
|
|
matrices.push();
|
|
matrices.translate(this.x, this.y, getZOffset());
|
|
|
|
hovered = isMouseOver(x, y);
|
|
|
|
renderChunks(matrices, delta, 5);
|
|
|
|
drawHorizontalLine(matrices, 0, (int)getWidth() - 1, (int)getHeight() - 1, white);
|
|
|
|
if (focused) {
|
|
drawHorizontalLine(matrices, 0, (int)getWidth() - 1, 0, white);
|
|
drawVerticalLine(matrices, 0, 0, (int)getHeight() - 1, white);
|
|
drawVerticalLine(matrices, (int)getWidth() - 1, 0, (int)getHeight() - 1, white);
|
|
}
|
|
|
|
|
|
matrices.pop();
|
|
}
|
|
|
|
@Override
|
|
public boolean isMouseOver(double x, double y) {
|
|
if (clicked) return true;
|
|
|
|
return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
|
|
}
|
|
|
|
@Override
|
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
|
if (keyCode == GLFW.GLFW_KEY_ENTER) {
|
|
click();
|
|
clicked = true;
|
|
hovered = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
@Override
|
|
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
|
|
if (keyCode == GLFW.GLFW_KEY_ENTER) {
|
|
clicked = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
|
if (isMouseOver(mouseX, mouseY)) {
|
|
scale /= Math.pow(2, -amount / 3);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
@Override
|
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
|
if (isMouseOver(mouseX, mouseY)) {
|
|
if (button == 0) {
|
|
click();
|
|
clicked = true;
|
|
hovered = true;
|
|
return true;
|
|
}
|
|
else if (button == 2) {
|
|
rotating = true;
|
|
hovered = true;
|
|
mouseStartX = (float)mouseX;
|
|
mouseStartY = (float)mouseY;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
@Override
|
|
public void mouseMoved(double mouseX, double mouseY) {
|
|
if (rotating) {
|
|
rotX += mouseStartX - (float)mouseX;
|
|
rotY += mouseStartY - (float)mouseY;
|
|
mouseStartX = (float)mouseX;
|
|
mouseStartY = (float)mouseY;
|
|
}
|
|
}
|
|
@Override
|
|
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
|
if (button == 0 && clicked) {
|
|
clicked = false;
|
|
return true;
|
|
}
|
|
if (button == 2 && rotating) {
|
|
rotating = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public ChunkPreview(int x, int y) {
|
|
this.client = MinecraftClient.getInstance();
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
public ChunkPreview(int x, int y, int w, int h) {
|
|
this.client = MinecraftClient.getInstance();
|
|
this.x = x;
|
|
this.y = y;
|
|
this.width = w;
|
|
this.height = h;
|
|
}
|
|
}
|