Skip to content

Commit

Permalink
Rework scrollbars to be variable width and render the track themselves
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte committed Mar 19, 2024
1 parent 01813c0 commit 74e3b86
Show file tree
Hide file tree
Showing 19 changed files with 127 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ private boolean shouldCraftOnClick(GridInventoryEntry entry) {
}

private void updateScrollbar() {
scrollbar.setHeight(this.rows * style.getRow().getSrcHeight() - 2);
scrollbar.setHeight(this.rows * style.getRow().getSrcHeight());
int totalRows = (this.repo.size() + getSlotsPerRow() - 1) / getSlotsPerRow();
if (repo.hasPinnedRow()) {
totalRows++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public ProcessingEncodingPanel(PatternEncodingTermScreen<?> screen, WidgetContai
this.cycleOutputBtn.setHalfSize(true);
widgets.add("processingCycleOutput", this.cycleOutputBtn);

this.scrollbar = widgets.addScrollBar("processingPatternModeScrollbar", Scrollbar.SMALL);
this.scrollbar = widgets.addScrollBar("processingPatternModeScrollbar", Scrollbar.DEFAULT);
// The scrollbar ranges from 0 to the number of rows not visible
this.scrollbar.setRange(0, menu.getProcessingInputSlots().length / 3 - 3, 3);
this.scrollbar.setCaptureMouseWheel(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public final class StonecuttingEncodingPanel extends EncodingModePanel {

public StonecuttingEncodingPanel(PatternEncodingTermScreen<?> screen, WidgetContainer widgets) {
super(screen, widgets);
this.scrollbar = widgets.addScrollBar("stonecuttingPatternModeScrollbar", Scrollbar.SMALL);
this.scrollbar = widgets.addScrollBar("stonecuttingPatternModeScrollbar", Scrollbar.DEFAULT);
this.scrollbar.setRange(0, 0, COLS);
this.scrollbar.setCaptureMouseWheel(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ private void refreshList() {
*/
private void resetScrollbar() {
// Needs to take the border into account, so offset for 1 px on the top and bottom.
scrollbar.setHeight(this.visibleRows * ROW_HEIGHT - 2);
scrollbar.setHeight(this.visibleRows * ROW_HEIGHT);
scrollbar.setRange(0, this.rows.size() - this.visibleRows, 2);
}

Expand Down
88 changes: 53 additions & 35 deletions src/main/java/appeng/client/gui/widgets/Scrollbar.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,41 @@

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.client.resources.metadata.gui.GuiSpriteScaling;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;

import appeng.client.Point;
import appeng.client.gui.ICompositeWidget;
import appeng.client.gui.style.Blitter;
import appeng.core.AppEng;

/**
* Implements a vertical scrollbar using Vanilla's scrollbar handle texture from the creative tab.
* <p>
* It is expected that the background of the UI contains a pre-baked scrollbar track border, and that the exact
* rectangle of that track is set on this object via {@link #displayX}, {@link #displayY} and {@link #setHeight(int)}.
* While the width of the track can also be set, the drawn handle will use vanilla's sprite width (see
* {@link Style#handleWidth()}.
*/
public class Scrollbar implements IScrollSource, ICompositeWidget {

private boolean visible = true;

/**
* The screen x-coordinate of the scrollbar's inner track.
* The screen x-coordinate of the scrollbar.
*/
private int displayX = 0;

/**
* The screen y-coordinate of the scrollbar's inner track.
* The screen y-coordinate of the scrollbar.
*/
private int displayY = 0;

private final Style style;

/**
* The inner height of the scrollbar track.
*/
private int height = 16;
private int width = 14;
private int height = 18;

private int pageSize = 1;

private int maxScroll = 0;
Expand Down Expand Up @@ -94,7 +92,7 @@ public Scrollbar() {

@Override
public Rect2i getBounds() {
return new Rect2i(displayX, displayY, style.handleWidth(), height);
return new Rect2i(displayX, displayY, width, height);
}

/**
Expand All @@ -108,17 +106,27 @@ public void drawForegroundLayer(GuiGraphics guiGraphics, Rect2i bounds, Point mo
// guiGraphics.fill( displayX, displayY, this.displayX + width, this.displayY +
// height, 0xffff0000);

guiGraphics.blitSprite(style.trackSprite(), displayX, displayY, width, height);

// Blit the handle
var innerTrack = getInnerTrackRect();

int yOffset;
Blitter image;
ResourceLocation image;
if (this.getRange() == 0) {
yOffset = 0;
image = Blitter.guiSprite(style.disabledSprite());
image = style.disabledSprite();
} else {
yOffset = getHandleYOffset();
image = Blitter.guiSprite(style.enabledSprite());
image = style.enabledSprite();
}

image.dest(this.displayX, this.displayY + yOffset).blit(guiGraphics);
guiGraphics.blitSprite(
image,
displayX + innerTrack.left(),
displayY + innerTrack.top() + yOffset,
innerTrack.width(),
style.handleHeight());
}

/**
Expand All @@ -128,7 +136,7 @@ private int getHandleYOffset() {
if (getRange() == 0) {
return 0;
}
int availableHeight = this.height - style.handleHeight();
int availableHeight = getInnerTrackRect().height() - style.handleHeight();
return (this.currentScroll - this.minScroll) * availableHeight / this.getRange();
}

Expand All @@ -152,6 +160,9 @@ public void setSize(int width, int height) {
if (height != 0) {
this.height = height;
}
if (width != 0) {
this.width = width;
}
}

public void setRange(int min, int max, int pageSize) {
Expand Down Expand Up @@ -241,7 +252,7 @@ public boolean onMouseDrag(Point mousePos, int button) {
// the upper edge of it) within the scrollable area of the track (minus the
// handle height).
double handleUpperEdgeY = mousePos.getY() - this.displayY - this.dragYOffset;
double availableHeight = this.height - style.handleHeight();
double availableHeight = getInnerTrackRect().height() - style.handleHeight();
double position = Mth.clamp(handleUpperEdgeY / availableHeight, 0.0, 1.0);

this.currentScroll = this.minScroll + (int) Math.round(position * this.getRange());
Expand Down Expand Up @@ -285,6 +296,21 @@ public void tick() {
this.eventRepeater.tick();
}

private ScreenRectangle getInnerTrackRect() {
var minecraft = Minecraft.getInstance();
var resolvedTrackSprite = minecraft.getGuiSprites().getSprite(style.trackSprite());
var scaling = minecraft.getGuiSprites().getSpriteScaling(resolvedTrackSprite);
if (scaling instanceof GuiSpriteScaling.NineSlice nineSlice) {
return new ScreenRectangle(
nineSlice.border().left(),
nineSlice.border().top(),
width - nineSlice.border().left() - nineSlice.border().right(),
height - nineSlice.border().top() - nineSlice.border().bottom());
} else {
return new ScreenRectangle(0, 0, width, height);
}
}

private void pageUp() {
this.currentScroll -= this.pageSize;
this.applyRange();
Expand All @@ -296,30 +322,22 @@ private void pageDown() {
}

public static final Style DEFAULT = Style.create(
new ResourceLocation("minecraft", "container/creative_inventory/scroller"),
new ResourceLocation("minecraft", "container/creative_inventory/scroller_disabled"));

public static final Style SMALL = Style.create(
AppEng.makeId("small_scroller"),
AppEng.makeId("small_scroller_disabled"));
AppEng.makeId("sunken_panel_dark"),
AppEng.makeId("scroll_handle"),
AppEng.makeId("scroll_handle_disabled"),
15);

public record Style(
ResourceLocation trackSprite,
ResourceLocation enabledSprite,
ResourceLocation disabledSprite) {
ResourceLocation disabledSprite,
int handleHeight) {
public static Style create(
ResourceLocation trackSprite,
ResourceLocation enabledSprite,
ResourceLocation disabledSprite) {
return new Style(enabledSprite, disabledSprite);
}

public int handleWidth() {
var minecraft = Minecraft.getInstance();
return minecraft.getGuiSprites().getSprite(enabledSprite).contents().width();
}

public int handleHeight() {
var minecraft = Minecraft.getInstance();
return minecraft.getGuiSprites().getSprite(enabledSprite).contents().height();
ResourceLocation disabledSprite,
int handleHeight) {
return new Style(trackSprite, enabledSprite, disabledSprite, handleHeight);
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/assets/ae2/screens/craft_confirm.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
},
"widgets": {
"scrollbar": {
"left": 218,
"top": 19,
"height": 114
"left": 217,
"top": 18,
"width": 14,
"height": 116
},
"selectCpu": {
"left": 19,
Expand Down
8 changes: 4 additions & 4 deletions src/main/resources/assets/ae2/screens/crafting_cpu.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
"height": 20
},
"scrollbar": {
"left": 218,
"top": 19,
"width": 12,
"height": 137
"left": 217,
"top": 18,
"width": 14,
"height": 139
}
}
}
8 changes: 4 additions & 4 deletions src/main/resources/assets/ae2/screens/crafting_status.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"height": 164
},
"selectCpuScrollbar": {
"left": -16,
"top": 23,
"width": 12,
"height": 137
"left": -17,
"top": 22,
"width": 14,
"height": 139
}
},
"text": {
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/assets/ae2/screens/network_status.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@
},
"widgets": {
"scrollbar": {
"left": 175,
"top": 39,
"height": 78
"left": 174,
"top": 38,
"width": 14,
"height": 80
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
},
"widgets": {
"scrollbar": {
"left": 175,
"top": 18
"left": 174,
"top": 17,
"width": 14
},
"craftingStatus": {
"left": 170,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@
},
"widgets": {
"processingPatternModeScrollbar": {
"left": 17,
"bottom": 156,
"height": 52
"left": 16,
"bottom": 157,
"height": 54,
"width": 9
},
"processingCycleOutput": {
"left": 127,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
},
"widgets": {
"stonecuttingPatternModeScrollbar": {
"left": 119,
"bottom": 157,
"height": 54
"left": 118,
"bottom": 158,
"width": 9,
"height": 56
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
},
"widgets": {
"scrollbar": {
"left": 175,
"top": 18
"left": 174,
"top": 17,
"width": 14
},
"search": {
"left": 104,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"gui": {
"scaling": {
"type": "nine_slice",
"width": 7,
"height": 15,
"border": {
"left": 2,
"top": 2,
"right": 2,
"bottom": 1
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"gui": {
"scaling": {
"type": "nine_slice",
"width": 7,
"height": 15,
"border": {
"left": 2,
"top": 2,
"right": 2,
"bottom": 1
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"gui": {
"scaling": {
"type": "nine_slice",
"width": 64,
"height": 64,
"border": 1
}
}
}

0 comments on commit 74e3b86

Please sign in to comment.