Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/top/fpsmaster/ui/click/MainPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ public void render(int mouseX, int mouseY, float partialTicks) {
float centerX = guiWidth / 2f;
float centerY = guiHeight / 2f;
float scissorX = centerX + (x - centerX) * scale;
float scissorY = centerY + (y + 10 - centerY) * scale;
float scissorY = centerY + (y - centerY + 10) * scale;
float scissorW = width * scale;
float scissorH = (height - 18) * scale;
float scissorH = (height - 12) * scale;

GL11.glEnable(GL11.GL_SCISSOR_TEST);
Scissor.apply(
Expand Down
128 changes: 83 additions & 45 deletions src/main/java/top/fpsmaster/ui/click/component/ScrollContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

import lombok.Getter;
import lombok.Setter;
import top.fpsmaster.utils.render.draw.Hover;
import top.fpsmaster.utils.render.draw.Rects;

import top.fpsmaster.utils.math.anim.AnimClock;
import top.fpsmaster.utils.math.anim.Animator;
import top.fpsmaster.utils.math.anim.Easings;
import top.fpsmaster.utils.render.draw.Hover;
import top.fpsmaster.utils.render.draw.Rects;
import top.fpsmaster.utils.render.gui.ScaledGuiScreen;

import java.awt.*;

public class ScrollContainer {
private float wheel = 0f; // 带动画的位置
private float wheel_anim = 0f; // 真实滚动到的位置
private static final float WHEEL_STEP = 50f;
private static final float MAX_OVERSCROLL = 45f;
private static final float OVERSCROLL_RESISTANCE = 0.38f;
private static final long SNAP_BACK_DELAY_NS = 50_000_000L;
private static final float TRACK_MIN_HEIGHT = 18f;
private static final float TRACK_SHRINK_FACTOR = 0.45f;

private float wheel = 0f;
private float wheelAnim = 0f;
@Getter
@Setter
private float height = 0f;
Expand All @@ -26,85 +32,117 @@ public class ScrollContainer {
private float scrollStart = 0f;
private boolean isScrolling = false;
private final String captureId = getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(this));
private long wheelDelay = 0L;

public void draw(ScaledGuiScreen screen, float x, float y, float width, float height, int mouseX, int mouseY, Runnable runnable) {
double dt = animClock.tick();
runnable.run();

// if the scroll bar needs to be render
float maxUp = Math.max(0f, this.height - height);
float minScroll = -maxUp;

if (this.height > height) {
// calc scroll bar height
float percent = (height / this.height);
float sHeight = percent * height;
float scrollPercent = (getScroll() / (this.height - height));
float sY = y - scrollPercent * (height - sHeight);
float sX = x + width + 1 - (float) scrollExpand;
float percent = height / this.height;
float baseHeight = Math.max(TRACK_MIN_HEIGHT, percent * height);
float visibleScroll = clamp(wheel, minScroll, 0f);
float scrollPercent = maxUp <= 0f ? 0f : visibleScroll / maxUp;
float trackHeight = baseHeight;
float trackY = y - scrollPercent * (height - baseHeight);

float overscrollTop = Math.max(0f, wheel);
float overscrollBottom = Math.max(0f, minScroll - wheel);
if (overscrollTop > 0f) {
trackHeight = shrinkTrack(baseHeight, overscrollTop);
trackY = y;
} else if (overscrollBottom > 0f) {
trackHeight = shrinkTrack(baseHeight, overscrollBottom);
trackY = y + height - trackHeight;
}

float trackX = x + width + 1 - (float) scrollExpand;
Rects.rounded(
Math.round(sX),
Math.round(sY),
Math.round(1f + (float) scrollExpand),
Math.round(sHeight),
1,
new Color(255, 255, 255, 100).getRGB()
Math.round(trackX),
Math.round(trackY),
Math.round(1f + (float) scrollExpand),
Math.round(trackHeight),
1,
new Color(255, 255, 255, 100).getRGB()
);
if (Hover.is(
sX - 1,
sY,
2f + (float) scrollExpand,
sHeight, mouseX, mouseY
)
) {

if (Hover.is(trackX - 1, trackY, 2f + (float) scrollExpand, trackHeight, mouseX, mouseY)) {
scrollExpand = 1.0;
if (screen.beginPointerCapture(captureId, 0, sX - 1, sY, 2f + (float) scrollExpand, sHeight)) {
if (screen.beginPointerCapture(captureId, 0, trackX - 1, trackY, 2f + (float) scrollExpand, trackHeight)) {
isScrolling = true;
scrollStart = mouseY - sY;
scrollStart = mouseY - trackY;
}
} else if (!isScrolling) {
scrollExpand = 0.0;
}

if (isScrolling) {
if (screen.isPointerCapturedBy(captureId, 0)) {
wheel_anim = -((mouseY - scrollStart - y) / height) * this.height;
float dragScroll = -((mouseY - scrollStart - y) / height) * this.height;
wheelAnim = applyOverscrollResistance(dragScroll, minScroll, 0f);
wheelDelay = System.nanoTime();
} else {
isScrolling = false;
screen.releasePointerCapture(captureId);
}
}
} else {
wheel_anim = 0f;
wheelAnim = 0f;
}

if (Hover.is(x,y,width,height, mouseX, mouseY)) {
if (this.height > height) {
int mouseDWheel = screen.consumeWheelDelta(x, y, width, height);
if (Hover.is(x, y, width, height, mouseX, mouseY) && this.height > height) {
int mouseDWheel = screen.consumeWheelDelta(x, y, width, height);
if (mouseDWheel != 0) {
wheelDelay = System.nanoTime();
if (mouseDWheel > 0) {
wheel_anim += 20f;
} else if (mouseDWheel < 0) {
wheel_anim -= 20f;
wheelAnim = applyOverscrollResistance(wheelAnim + WHEEL_STEP, minScroll, 0f);
} else {
wheelAnim = applyOverscrollResistance(wheelAnim - WHEEL_STEP, minScroll, 0f);
}

}
}
float maxUp = this.height - height;
wheel_anim = Math.min(Math.max(wheel_anim, -maxUp), 0f);
if (Float.isNaN(lastTarget) || wheel_anim != lastTarget) {
wheelAnimator.animateTo(wheel_anim, 0.12f, Easings.QUAD_OUT);
lastTarget = wheel_anim;

if (Float.isNaN(lastTarget) || wheelAnim != lastTarget) {
wheelAnimator.animateTo(wheelAnim, 0.12f, Easings.CUBIC_OUT);
lastTarget = wheelAnim;
} else if (System.nanoTime() - wheelDelay > SNAP_BACK_DELAY_NS) {
float bounded = clamp(wheelAnim, minScroll, 0f);
if (bounded != wheelAnim) {
wheelAnim = bounded;
}
}

wheelAnimator.update(dt);
wheel = (float) wheelAnimator.get();
}

public int getScroll() {
return (int)wheel;
return (int) wheel;
}

public float getRealScroll() {
return wheel_anim;
return wheelAnim;
}
}


private float applyOverscrollResistance(float value, float min, float max) {
if (value > max) {
return Math.min(max + MAX_OVERSCROLL, max + (value - max) * OVERSCROLL_RESISTANCE);
}
if (value < min) {
return Math.max(min - MAX_OVERSCROLL, min + (value - min) * OVERSCROLL_RESISTANCE);
}
return value;
}

private float shrinkTrack(float baseHeight, float overscroll) {
float shrink = Math.min(baseHeight - TRACK_MIN_HEIGHT, overscroll * TRACK_SHRINK_FACTOR);
return Math.max(TRACK_MIN_HEIGHT, baseHeight - shrink);
}

private float clamp(float value, float min, float max) {
return Math.max(min, Math.min(max, value));
}
}
Loading