|
1 | 1 | package top.fpsmaster.ui.screens.oobe; |
2 | 2 |
|
| 3 | +import net.minecraft.util.ResourceLocation; |
| 4 | +import org.lwjgl.opengl.GL11; |
3 | 5 | import top.fpsmaster.FPSMaster; |
4 | 6 | import top.fpsmaster.utils.math.anim.AnimClock; |
| 7 | +import top.fpsmaster.utils.math.anim.AnimMath; |
5 | 8 | import top.fpsmaster.utils.render.draw.Hover; |
| 9 | +import top.fpsmaster.utils.render.draw.Images; |
6 | 10 | import top.fpsmaster.utils.render.draw.Rects; |
7 | 11 | import top.fpsmaster.utils.render.gui.ScaledGuiScreen; |
8 | 12 |
|
9 | 13 | import java.awt.Color; |
10 | 14 |
|
11 | 15 | public class OobeDropdown { |
| 16 | + private static final ResourceLocation ARROW_ICON = new ResourceLocation("client/gui/settings/icons/arrow.png"); |
| 17 | + |
12 | 18 | private String label = ""; |
13 | 19 | private String[] items = new String[0]; |
14 | 20 | private int selectedIndex; |
15 | 21 | private boolean open; |
16 | 22 | private boolean enabled = true; |
17 | 23 | private float openProgress; |
18 | 24 | private final AnimClock clock = new AnimClock(); |
| 25 | + private boolean selectionChanged; |
| 26 | + private float hoverAnim; |
| 27 | + private float pressAnim; |
19 | 28 |
|
20 | 29 | public OobeDropdown setLabel(String label) { |
21 | 30 | this.label = label; |
@@ -47,39 +56,87 @@ public int getSelectedIndex() { |
47 | 56 | return selectedIndex; |
48 | 57 | } |
49 | 58 |
|
| 59 | + public boolean consumeSelectionChanged() { |
| 60 | + boolean changed = selectionChanged; |
| 61 | + selectionChanged = false; |
| 62 | + return changed; |
| 63 | + } |
| 64 | + |
50 | 65 | public void renderInScreen(ScaledGuiScreen screen, float x, float y, float width, float height, int mouseX, int mouseY) { |
51 | 66 | float dt = (float) clock.tick(); |
52 | 67 | float target = open && enabled ? 1f : 0f; |
53 | | - openProgress += (target - openProgress) * Math.min(1f, dt * 10f); |
| 68 | + openProgress += (target - openProgress) * Math.min(1f, dt * 12f); |
| 69 | + boolean hovered = enabled && Hover.is(x, y, width, height, mouseX, mouseY); |
| 70 | + hoverAnim = (float) AnimMath.base(hoverAnim, hovered ? 1.0 : 0.0, 0.22); |
| 71 | + pressAnim = (float) AnimMath.base(pressAnim, 0.0, 0.28); |
| 72 | + |
| 73 | + Color headColor = enabled |
| 74 | + ? (hovered ? new Color(247, 249, 255, 252) : new Color(244, 247, 255, 248)) |
| 75 | + : new Color(235, 239, 246, 205); |
| 76 | + Color labelColor = enabled ? new Color(110, 119, 136, 255) : new Color(146, 152, 164, 200); |
| 77 | + Color valueColor = enabled ? new Color(27, 35, 48, 255) : new Color(126, 132, 144, 200); |
| 78 | + |
| 79 | + float inset = pressAnim * 1.3f; |
| 80 | + float drawX = x + inset; |
| 81 | + float drawY = y + inset; |
| 82 | + float drawWidth = Math.max(4f, width - inset * 2f); |
| 83 | + float drawHeight = Math.max(4f, height - inset * 2f); |
54 | 84 |
|
55 | | - Rects.rounded(Math.round(x), Math.round(y), Math.round(width), Math.round(height), 12, new Color(255, 255, 255, enabled ? 224 : 168).getRGB()); |
56 | | - FPSMaster.fontManager.s16.drawString(label, x + 12f, y + 11f, new Color(58, 68, 96, enabled ? 255 : 140).getRGB()); |
| 85 | + Rects.rounded(Math.round(drawX), Math.round(drawY), Math.round(drawWidth), Math.round(drawHeight), 14, headColor.getRGB()); |
| 86 | + FPSMaster.fontManager.s16.drawString(label, drawX + 14f, drawY + 10f, labelColor.getRGB()); |
57 | 87 | String selected = items.length == 0 ? "" : items[selectedIndex]; |
58 | | - FPSMaster.fontManager.s16.drawString(selected, x + width - 64f, y + 11f, new Color(58, 68, 96, enabled ? 255 : 140).getRGB()); |
59 | | - FPSMaster.fontManager.s16.drawString(openProgress > 0.5f ? "^" : "v", x + width - 24f, y + 11f, new Color(58, 68, 96, enabled ? 255 : 140).getRGB()); |
| 88 | + float valueX = drawX + drawWidth - 20f - FPSMaster.fontManager.s16.getStringWidth(selected) - 16f; |
| 89 | + FPSMaster.fontManager.s16.drawString(selected, Math.max(drawX + 74f, valueX), drawY + 10f + pressAnim * 0.5f, valueColor.getRGB()); |
| 90 | + renderArrow(drawX + drawWidth - 18f, drawY + drawHeight / 2f, openProgress, new Color(104, 117, 247, 230)); |
60 | 91 |
|
61 | 92 | if (enabled && screen.consumePressInBounds(x, y, width, height, 0) != null) { |
| 93 | + pressAnim = 1.0f; |
62 | 94 | open = !open; |
63 | 95 | } |
64 | 96 |
|
65 | 97 | if (openProgress > 0.02f && enabled) { |
| 98 | + float optionHeight = 24f; |
| 99 | + float optionGap = 3f; |
| 100 | + float panelHeight = items.length * optionHeight + Math.max(0, items.length - 1) * optionGap + 10f; |
| 101 | + float panelY = y + height + 6f; |
| 102 | + int panelAlpha = Math.max(0, Math.min(255, (int) (openProgress * 255f))); |
| 103 | + |
| 104 | + Rects.rounded(Math.round(x), Math.round(panelY), Math.round(width), Math.round(panelHeight * openProgress), 10, |
| 105 | + new Color(255, 255, 255, Math.min(244, panelAlpha)).getRGB()); |
| 106 | + |
66 | 107 | for (int i = 0; i < items.length; i++) { |
67 | | - float optionY = y + height + 6f + i * 32f * openProgress; |
| 108 | + float optionY = panelY + 5f + i * (optionHeight + optionGap); |
68 | 109 | int alpha = Math.max(0, Math.min(255, (int) (openProgress * 255f))); |
69 | | - Rects.rounded(Math.round(x), Math.round(optionY), Math.round(width), 26, 10, |
70 | | - (i == selectedIndex ? new Color(122, 139, 255, Math.min(230, alpha)) : new Color(255, 255, 255, Math.min(232, alpha))).getRGB()); |
71 | | - FPSMaster.fontManager.s16.drawString(items[i], x + 12f, optionY + 9f, |
72 | | - (i == selectedIndex ? new Color(255, 255, 255, alpha) : new Color(58, 68, 96, alpha)).getRGB()); |
73 | | - if (openProgress > 0.95f && screen.consumePressInBounds(x, optionY, width, 28f, 0) != null) { |
| 110 | + boolean optionHovered = Hover.is(x + 4f, optionY, width - 8f, optionHeight, mouseX, mouseY); |
| 111 | + Color optionColor = i == selectedIndex |
| 112 | + ? new Color(104, 117, 247, Math.min(228, alpha)) |
| 113 | + : (optionHovered ? new Color(240, 244, 255, Math.min(236, alpha)) : new Color(255, 255, 255, 0)); |
| 114 | + if (optionColor.getAlpha() > 0) { |
| 115 | + Rects.rounded(Math.round(x + 4f), Math.round(optionY), Math.round(width - 8f), Math.round(optionHeight), 10, optionColor.getRGB()); |
| 116 | + } |
| 117 | + FPSMaster.fontManager.s16.drawString(items[i], x + 12f, optionY + 6f, |
| 118 | + (i == selectedIndex ? new Color(255, 255, 255, alpha) : new Color(78, 89, 108, alpha)).getRGB()); |
| 119 | + if (openProgress > 0.95f && screen.consumePressInBounds(x, optionY, width, optionHeight, 0) != null) { |
74 | 120 | selectedIndex = i; |
| 121 | + selectionChanged = true; |
| 122 | + pressAnim = 1.0f; |
75 | 123 | open = false; |
76 | 124 | } |
77 | 125 | } |
78 | 126 |
|
79 | 127 | ScaledGuiScreen.PointerEvent outside = screen.peekAnyPress(); |
80 | | - if (outside != null && openProgress > 0.95f && !Hover.is(x, y, width, height + items.length * 32f + 12f, outside.x, outside.y)) { |
| 128 | + if (outside != null && openProgress > 0.95f && !Hover.is(x, y, width, height + panelHeight + 4f, outside.x, outside.y)) { |
81 | 129 | open = false; |
82 | 130 | } |
83 | 131 | } |
84 | 132 | } |
| 133 | + |
| 134 | + private void renderArrow(float centerX, float centerY, float progress, Color color) { |
| 135 | + GL11.glPushMatrix(); |
| 136 | + GL11.glTranslatef(centerX, centerY, 0f); |
| 137 | + GL11.glRotatef(progress * 180f, 0f, 0f, 1f); |
| 138 | + GL11.glTranslatef(-centerX, -centerY, 0f); |
| 139 | + Images.draw(ARROW_ICON, centerX - 4f, centerY - 4f, 8f, 8f, color); |
| 140 | + GL11.glPopMatrix(); |
| 141 | + } |
85 | 142 | } |
0 commit comments