Scrollable GridScreen
This commit is contained in:
parent
f3bdaaac8e
commit
9d7fa9f925
5 changed files with 353 additions and 31 deletions
|
@ -5,6 +5,7 @@ import net.fabricmc.api.EnvType;
|
|||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import ru.bclib.gui.gridlayout.GridLayout.GridValueType;
|
||||
import ru.bclib.util.Pair;
|
||||
import ru.bclib.util.TriConsumer;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
@ -63,7 +64,7 @@ class GridElement extends GridTransform{
|
|||
}
|
||||
|
||||
GridTransform transformWithPadding(int leftPadding, int topPadding){
|
||||
return new GridTransform(left + leftPadding, top +topPadding, width, height);
|
||||
return new GridTransform(left + leftPadding, top + topPadding, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,8 +85,10 @@ abstract class GridContainer extends GridCellDefinition{
|
|||
@Environment(EnvType.CLIENT)
|
||||
public class GridLayout extends GridColumn {
|
||||
public static final int COLOR_WHITE = 0xFFFFFFFF;
|
||||
public static final int COLOR_RED = 0xFFFF0000;
|
||||
public static final int COLOR_RED = 0xFFDB1F48;
|
||||
public static final int COLOR_CYAN = 0xFF01949A;
|
||||
public static final int COLOR_GREEN = 0xFF00FF00;
|
||||
public static final int COLOR_YELLOW = 0xFFFAD02C;
|
||||
public static final int COLOR_BLUE = 0xFF0000FF;
|
||||
public static final int COLOR_GRAY = 0xFF7F7F7F;
|
||||
|
||||
|
@ -130,14 +133,15 @@ public class GridLayout extends GridColumn {
|
|||
elements = new LinkedList<>();
|
||||
GridElement el = this.buildElement((int)this.width, 0, 1, 0,0, elements);
|
||||
this.height = el.height;
|
||||
if (centerVertically) {
|
||||
if (centerVertically && el.height + initialTopPadding < screenHeight) {
|
||||
topPadding = (screenHeight - el.height - initialTopPadding) >> 1;
|
||||
} else {
|
||||
topPadding = initialTopPadding;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public List<Pair<AbstractWidget, Integer>> movableWidgets = new LinkedList<>();
|
||||
public void finalizeLayout(){
|
||||
buildLayout();
|
||||
|
||||
|
@ -145,11 +149,14 @@ public class GridLayout extends GridColumn {
|
|||
.stream()
|
||||
.filter(element -> element.componentPlacer!=null)
|
||||
.forEach(element -> {
|
||||
Object context = element.componentPlacer.apply(element.transformWithPadding(sidePadding, topPadding));
|
||||
final GridTransform transform = element.transformWithPadding(sidePadding, topPadding);
|
||||
final Object context = element.componentPlacer.apply(transform);
|
||||
if (element.customRender != null){
|
||||
element.renderContext = context;
|
||||
} else if (context instanceof AbstractWidget) {
|
||||
screen.addRenderableWidget((AbstractWidget) context);
|
||||
final AbstractWidget widget = (AbstractWidget)context;
|
||||
movableWidgets.add(new Pair(widget, widget.y));
|
||||
screen.addRenderableWidget(widget);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ public class GridRow extends GridContainer {
|
|||
|
||||
public GridStringCell addString(Component text, int color, GridScreen parent) {
|
||||
final int width = parent.getWidth(text);
|
||||
return this.addString(text, width, GridValueType.CONSTANT, GridLayout.COLOR_WHITE, Alignment.CENTER, parent);
|
||||
return this.addString(text, width, GridValueType.CONSTANT, color, Alignment.CENTER, parent);
|
||||
}
|
||||
|
||||
public GridStringCell addString(Component text, Alignment contentAlignment, GridScreen parent) {
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
package ru.bclib.gui.gridlayout;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import net.minecraft.client.gui.components.OptionsList;
|
||||
import net.minecraft.client.gui.components.Widget;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.bclib.gui.gridlayout.GridLayout.Alignment;
|
||||
|
||||
|
@ -21,6 +30,8 @@ public abstract class GridScreen extends Screen {
|
|||
public final boolean centerVertically;
|
||||
@Nullable
|
||||
public final Screen parent;
|
||||
|
||||
protected int scrollPos = 0;
|
||||
|
||||
public GridScreen(Component title) {
|
||||
this(null, title);
|
||||
|
@ -65,8 +76,6 @@ public abstract class GridScreen extends Screen {
|
|||
return super.addRenderableWidget(guiEventListener);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void addTitle(){
|
||||
grid.addRow().addString(this.title, Alignment.CENTER, this);
|
||||
grid.addSpacerRow(15);
|
||||
|
@ -87,16 +96,32 @@ public abstract class GridScreen extends Screen {
|
|||
protected void renderScreen(PoseStack poseStack, int i, int j, float f) {
|
||||
super.render(poseStack, i, j, f);
|
||||
}
|
||||
|
||||
|
||||
public void render(PoseStack poseStack, int i, int j, float f) {
|
||||
//this.renderBackground(poseStack);
|
||||
this.renderDirtBackground(i);
|
||||
//drawCenteredString(poseStack, this.font, this.title, grid.width / 2, grid.getTopStart(), 16777215);
|
||||
if (grid!=null) grid.render(poseStack);
|
||||
|
||||
renderGrid(poseStack);
|
||||
super.render(poseStack, i, j, f);
|
||||
}
|
||||
|
||||
|
||||
protected void renderGrid(PoseStack poseStack) {
|
||||
if (grid!=null) {
|
||||
if (isScrollable()) {
|
||||
for (var item : grid.movableWidgets) {
|
||||
item.first.y = item.second + scrollPos;
|
||||
}
|
||||
|
||||
renderScroll(poseStack);
|
||||
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(0, scrollPos, 0);
|
||||
grid.render(poseStack);
|
||||
poseStack.popPose();
|
||||
} else {
|
||||
grid.render(poseStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getWidth(Component text, Font font) {
|
||||
return font.width(text.getVisualOrderText());
|
||||
}
|
||||
|
@ -104,4 +129,127 @@ public abstract class GridScreen extends Screen {
|
|||
public int getWidth(Component text) {
|
||||
return getWidth(text, getFont());
|
||||
}
|
||||
|
||||
public void setScrollPos(int sp) {
|
||||
scrollPos = Math.max(getMaxScrollPos(), Math.min(0, sp));
|
||||
}
|
||||
|
||||
public int getScrollPos() {
|
||||
return scrollPos;
|
||||
}
|
||||
|
||||
public int getScrollHeight() {
|
||||
if (grid!=null) return grid.getHeight() + topPadding;
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getMaxScrollPos() {
|
||||
return height-getScrollHeight();
|
||||
}
|
||||
|
||||
public boolean isScrollable() {
|
||||
if (grid==null) return false;
|
||||
return height<grid.getHeight();
|
||||
}
|
||||
|
||||
public boolean isMouseOverScroller(double x, double y) {
|
||||
return y >= 0 && y <= height && x >= width-SCROLLER_WIDTH && x <= width;
|
||||
}
|
||||
|
||||
private boolean scrolling = false;
|
||||
protected void updateScrollingState(double x, double y, int i) {
|
||||
this.scrolling = i == 0 && x >= width-SCROLLER_WIDTH && x < width;
|
||||
}
|
||||
|
||||
private static final int SCROLLER_WIDTH = 6;
|
||||
private void renderScroll(PoseStack poseStack){
|
||||
final int y1 = height;
|
||||
final int y0 = 0;
|
||||
final int yd = y1 - y0;
|
||||
final int maxPosition = getScrollHeight();
|
||||
|
||||
final int x0 = width-SCROLLER_WIDTH;
|
||||
final int x1 = width;
|
||||
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
BufferBuilder bufferBuilder = tesselator.getBuilder();
|
||||
RenderSystem.disableTexture();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
int widgetHeight = (int)((float)(yd*yd) / (float)maxPosition);
|
||||
widgetHeight = Mth.clamp(widgetHeight, 32, yd - 8);
|
||||
float relPos = (float)this.getScrollPos() / this.getMaxScrollPos();
|
||||
int top = (int)(relPos * (yd - widgetHeight)) + y0;
|
||||
if (top < y0) {
|
||||
top = y0;
|
||||
}
|
||||
|
||||
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
//scroller background
|
||||
bufferBuilder.vertex((double)x0, (double)y1, 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x1, (double)y1, 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x1, (double)y0, 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x0, (double)y0, 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
|
||||
//scroll widget shadow
|
||||
bufferBuilder.vertex((double)x0, (double)(top + widgetHeight), 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x1, (double)(top + widgetHeight), 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x1, (double)top, 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x0, (double)top, 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
|
||||
//scroll widget
|
||||
bufferBuilder.vertex((double)x0, (double)(top + widgetHeight - 1), 0.0D).color(192, 192, 192, 255).endVertex();
|
||||
bufferBuilder.vertex((double)(x1 - 1), (double)(top + widgetHeight - 1), 0.0D).color(192, 192, 192, 255).endVertex();
|
||||
bufferBuilder.vertex((double)(x1 - 1), (double)top, 0.0D).color(192, 192, 192, 255).endVertex();
|
||||
bufferBuilder.vertex((double)x0, (double)top, 0.0D).color(192, 192, 192, 255).endVertex();
|
||||
tesselator.end();
|
||||
}
|
||||
|
||||
public boolean mouseClicked(double x, double y, int i) {
|
||||
this.updateScrollingState(x, y, i);
|
||||
if (this.scrolling) {
|
||||
return true;
|
||||
} else {
|
||||
return super.mouseClicked(x, y, i);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mouseDragged(double xAbs, double yAbs, int i, double dX, double dY) {
|
||||
if (super.mouseDragged(xAbs, yAbs, i, dX, dY)) {
|
||||
return true;
|
||||
} else if (i == 0 && this.scrolling) {
|
||||
if (yAbs < 0) {
|
||||
this.setScrollPos(0);
|
||||
} else if (yAbs > height) {
|
||||
this.setScrollPos(this.getMaxScrollPos());
|
||||
} else {
|
||||
this.setScrollPos((int)(this.getScrollPos() - dY * 2));
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mouseScrolled(double d, double e, double f) {
|
||||
if (isScrollable()) {
|
||||
setScrollPos((int) (scrollPos + f * 10));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean keyPressed(int keyCode, int j, int k) {
|
||||
if (super.keyPressed(keyCode, j, k)) {
|
||||
return true;
|
||||
} else if (keyCode == 264) {
|
||||
this.mouseScrolled(0, -1.0f, 0);
|
||||
return true;
|
||||
} else if (keyCode == 265) {
|
||||
this.mouseScrolled(0, 1.0, 0);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue