Scissor and draggable canvas panel for android research window

This commit is contained in:
DBotThePony 2021-08-24 21:08:26 +07:00
parent e7b810f1a8
commit e79bdb4326
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 185 additions and 20 deletions

View File

@ -115,7 +115,27 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
autoAttachToFrame(frame);
var grid = new GridPanel(this, frame, 0, 0, GRID_WIDTH * 22, 0, GRID_WIDTH, GRID_HEIGHT);
var canvas = new DraggableCanvasPanel(this, frame, 0, 0, GRID_WIDTH * 22, 0);
var grid = new GridPanel(this, canvas, 0, 0, 0, 0, GRID_WIDTH, GRID_HEIGHT) {
@Override
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) {
// pass event to canvas
return false;
}
@Override
protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) {
// pass event to canvas
return false;
}
@Override
protected boolean mouseDraggedInner(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) {
// pass event to canvas
return false;
}
};
minecraft.player.getCapability(MatteryCapability.ANDROID).ifPresent(_cap -> {
if (_cap instanceof AndroidCapabilityPlayer cap) {
@ -129,7 +149,8 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
}
});
grid.setDock(Dock.RIGHT);
canvas.setDock(Dock.RIGHT);
grid.setDock(Dock.FILL);
return frame;
}

View File

@ -3,10 +3,13 @@ package ru.dbotthepony.mc.otm.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Matrix4f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import java.util.Stack;
import static org.lwjgl.opengl.GL11.GL_ALWAYS;
import static org.lwjgl.opengl.GL11.GL_LESS;
@ -553,4 +556,49 @@ public class RenderHelper {
) {
drawRect(stack.last().pose(), x, y, width, height);
}
record ScissorRect(int x, int y, int width, int height) {}
private static final Stack<ScissorRect> SCISSOR = new Stack<>();
public static void ensureScissorStackEmpty() {
if (!SCISSOR.empty()) {
throw new IllegalStateException("Unbalanced scissor rects: Popping less than pushing");
}
}
public static void pushScissorRect(int x, int y, int width, int height) {
if (!SCISSOR.empty()) {
final var peek = SCISSOR.peek();
x = Math.max(x, peek.x);
y = Math.max(y, peek.y);
width = Math.min(width, peek.width);
height = Math.min(height, peek.height);
}
SCISSOR.push(new ScissorRect(x, y, width, height));
final var window = Minecraft.getInstance().getWindow();
y = window.getHeight() - y - height;
RenderSystem.enableScissor(x, y, width, height);
}
public static void popScissorRect() {
if (SCISSOR.empty()) {
throw new IllegalStateException("Unbalanced scissor rects: Popping more than pushing");
}
SCISSOR.pop();
if (SCISSOR.empty()) {
RenderSystem.disableScissor();
return;
}
final var value = SCISSOR.peek();
final var window = Minecraft.getInstance().getWindow();
final var y = window.getHeight() - value.y - value.height;
RenderSystem.enableScissor(value.x, y, value.width, value.height);
}
}

View File

@ -0,0 +1,51 @@
package ru.dbotthepony.mc.otm.screen.panels;
import ru.dbotthepony.mc.otm.screen.MatteryScreen;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class DraggableCanvasPanel extends EditablePanel {
public DraggableCanvasPanel(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, float x, float y, float width, float height) {
super(screen, parent, x, y, width, height);
scissor = true;
}
public DraggableCanvasPanel(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent) {
super(screen, parent);
scissor = true;
}
protected boolean dragging = false;
protected double last_mouse_x;
protected double last_mouse_y;
@Override
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) {
dragging = true;
last_mouse_x = mouse_x;
last_mouse_y = mouse_y;
setIgnoreMouseEventBoundaries(true);
return true;
}
@Override
protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) {
dragging = false;
setIgnoreMouseEventBoundaries(false);
return true;
}
@Override
protected boolean mouseDraggedInner(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) {
if (dragging) {
x_offset -= last_mouse_x - mouse_x;
y_offset -= last_mouse_y - mouse_y;
last_mouse_x = mouse_x;
last_mouse_y = mouse_y;
}
return true;
}
}

View File

@ -2,8 +2,12 @@ package ru.dbotthepony.mc.otm.screen.panels;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.GuiEventListener;
import ru.dbotthepony.mc.otm.screen.MatteryScreen;
import ru.dbotthepony.mc.otm.screen.RenderHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -56,6 +60,37 @@ public class EditablePanel implements GuiEventListener {
protected float parent_x;
protected float parent_y;
// allows to offset children by given amount of pixels
protected float x_offset;
protected float y_offset;
// whenever is to scissor render bounds
protected boolean scissor = false;
public float getXOffset() {
return x_offset;
}
public void setXOffset(float x_offset) {
this.x_offset = x_offset;
}
public float getYOffset() {
return y_offset;
}
public void setYOffset(float y_offset) {
this.y_offset = y_offset;
}
public boolean getEnableScissor() {
return scissor;
}
public void setEnableScissor(boolean scissor) {
this.scissor = scissor;
}
protected float accumulated_depth = 0;
public float getMost3DHeight() {
@ -151,8 +186,16 @@ public class EditablePanel implements GuiEventListener {
is_hovered = parent.is_hovered && mouse_x >= parent_x && mouse_x < parent_x + width && mouse_y >= parent_y && mouse_y < parent_y + height;
}
var scissor = this.scissor;
if (scissor) {
var window = Minecraft.getInstance().getWindow();
var scale = window.getGuiScale();
RenderHelper.pushScissorRect((int) (parent_x * scale), (int) (parent_y * scale), (int) (width * scale), (int) (height * scale));
}
stack.pushPose();
stack.translate(parent_x, parent_y, accumulated_depth);
stack.translate(parent_x + getXOffset(), parent_y + getYOffset(), accumulated_depth);
innerRender(stack, mouse_x, mouse_y, flag);
stack.popPose();
@ -161,14 +204,18 @@ public class EditablePanel implements GuiEventListener {
for (var child : children) {
if (child.getVisible()) {
child.accumulated_depth = accumulated_depth + 1;
child.parent_x = parent_x + child.x;
child.parent_y = parent_y + child.y;
child.parent_x = parent_x + child.x + getXOffset();
child.parent_y = parent_y + child.y + getYOffset();
RenderSystem.setShaderColor(1F, 1F, 1F, 1F);
most_depth = Math.max(most_depth, child.render(stack, mouse_x, mouse_y, flag));
}
}
if (scissor) {
RenderHelper.popScissorRect();
}
return most_depth;
}
@ -278,8 +325,8 @@ public class EditablePanel implements GuiEventListener {
var get_parent = getParent();
while (get_parent != null) {
x += get_parent.getX();
y += get_parent.getY();
x += get_parent.getX() + get_parent.getXOffset();
y += get_parent.getY() + get_parent.getYOffset();
get_parent = get_parent.getParent();
}
@ -741,7 +788,7 @@ public class EditablePanel implements GuiEventListener {
}
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) {
return false;
return true;
}
public boolean withinBounds(double mouse_x, double mouse_y) {
@ -781,8 +828,7 @@ public class EditablePanel implements GuiEventListener {
if (getMouseInputEnabled() && parent == null)
screen.popup(this);
mouseClicked(mouse_x, mouse_y, flag);
return true;
return mouseClicked(mouse_x, mouse_y, flag);
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (var child : children) {
if (child.mouseClickedChecked(mouse_x, mouse_y, flag)) {
@ -802,7 +848,7 @@ public class EditablePanel implements GuiEventListener {
}
protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) {
return false;
return true;
}
@Override
@ -827,8 +873,7 @@ public class EditablePanel implements GuiEventListener {
return false;
if (getIgnoreMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
mouseReleased(mouse_x, mouse_y, flag);
return true;
return mouseReleased(mouse_x, mouse_y, flag);
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (var child : children) {
if (child.mouseReleasedChecked(mouse_x, mouse_y, flag)) {
@ -841,7 +886,7 @@ public class EditablePanel implements GuiEventListener {
}
protected boolean mouseDraggedInner(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) {
return false;
return true;
}
@Override
@ -866,8 +911,7 @@ public class EditablePanel implements GuiEventListener {
return false;
if (getIgnoreMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
mouseDragged(mouse_x, mouse_y, flag, drag_x, drag_y);
return true;
return mouseDragged(mouse_x, mouse_y, flag, drag_x, drag_y);
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (var child : children) {
if (child.mouseDraggedChecked(mouse_x, mouse_y, flag, drag_x, drag_y)) {
@ -880,7 +924,7 @@ public class EditablePanel implements GuiEventListener {
}
protected boolean mouseScrolledInner(double mouse_x, double mouse_y, double scroll) {
return false;
return true;
}
@Override
@ -905,8 +949,7 @@ public class EditablePanel implements GuiEventListener {
return false;
if (getIgnoreMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
mouseScrolled(mouse_x, mouse_y, scroll);
return true;
return mouseScrolled(mouse_x, mouse_y, scroll);
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (var child : children) {
if (child.mouseScrolledChecked(mouse_x, mouse_y, scroll)) {
@ -1011,7 +1054,9 @@ public class EditablePanel implements GuiEventListener {
}
public void tick() {
for (var child : children) {
child.tick();
}
}
private boolean is_removed = false;