1 package com.irtimaled.bbor.client.gui;
3 import com.irtimaled.bbor.client.renderers.RenderHelper;
4 import com.irtimaled.bbor.client.renderers.Renderer;
5 import com.irtimaled.bbor.common.MathHelper;
6 import net.minecraft.client.MinecraftClient;
7 import net.minecraft.client.gui.DrawableHelper;
8 import net.minecraft.client.util.math.MatrixStack;
10 import java.util.ArrayList;
11 import java.util.List;
13 public class ControlList extends DrawableHelper implements IControlSet {
14 public static final int CONTROLS_WIDTH = 310;
15 protected static final int PADDING = 8;
17 protected final int listLeft;
18 protected final List<ControlListEntry> entries = new ArrayList<>();
19 private final int scrollBarLeft;
20 private final int listHeight;
21 private final MinecraftClient minecraft;
22 private final int width;
23 private final int height;
24 private final int top;
25 private final int bottom;
27 protected int contentHeight = PADDING;
28 private double amountScrolled;
29 private boolean clickedScrollbar;
30 private boolean transparentBackground;
31 private IControl focused;
32 private boolean isDragging;
34 ControlList(int width, int height, int top, int bottom) {
35 this.minecraft = MinecraftClient.getInstance();
37 this.scrollBarLeft = width - 6;
41 this.listHeight = bottom - top;
42 this.listLeft = width / 2 - CONTROLS_WIDTH / 2;
45 void add(ControlListEntry entry) {
46 entry.index = entries.size();
50 private void addEntry(ControlListEntry entry) {
51 this.entries.add(entry);
52 this.contentHeight += entry.getControlHeight();
55 public void filter(String lowerValue) {
58 for (ControlListEntry entry : entries) {
59 entry.filter(lowerValue);
60 if (entry.isVisible()) {
61 height += entry.getControlHeight();
62 } else if (entry == focused) {
66 this.contentHeight = height + PADDING;
70 this.entries.forEach(ControlListEntry::close);
74 public boolean mouseClicked(double mouseX, double mouseY, int button) {
75 this.clickedScrollbar = button == 0 && mouseX >= (double) this.scrollBarLeft;
76 return isMouseOver(mouseX, mouseY) &&
77 (IControlSet.super.mouseClicked(mouseX, mouseY, button) ||
78 this.clickedScrollbar);
82 public boolean isMouseOver(double mouseX, double mouseY) {
83 return mouseY >= (double) this.top && mouseY <= (double) this.bottom;
87 public boolean changeFocus(boolean moveForward) {
88 boolean newControlFocused = IControlSet.super.changeFocus(moveForward);
89 if (newControlFocused) {
90 this.ensureVisible((ControlListEntry) this.getFocused());
93 return newControlFocused;
96 private void ensureVisible(ControlListEntry control) {
97 int controlTop = control.getControlTop();
98 int controlHeight = control.getControlHeight();
99 int distanceAboveTop = this.top - controlTop;
100 if (distanceAboveTop > 0) {
101 this.amountScrolled -= Math.max(controlHeight, distanceAboveTop + PADDING);
105 int distanceBelowBottom = controlTop + controlHeight - this.bottom;
106 if (distanceBelowBottom > 0) {
107 this.amountScrolled += Math.max(controlHeight, distanceBelowBottom + PADDING);
112 public boolean mouseDragged(double mouseX, double mouseY, int button, double p_mouseDragged_6_, double p_mouseDragged_8_) {
113 if (IControlSet.super.mouseDragged(mouseX, mouseY, button, p_mouseDragged_6_, p_mouseDragged_8_)) {
116 if (button == 0 && this.clickedScrollbar) {
117 if (mouseY < (double) this.top) {
118 this.amountScrolled = 0.0D;
119 } else if (mouseY > (double) this.bottom) {
120 this.amountScrolled = this.getMaxScroll();
122 double maxScroll = this.getMaxScroll();
123 if (maxScroll < 1.0D) {
127 double amountScrolled = maxScroll / (double) (this.listHeight - getScrollBarHeight());
128 if (amountScrolled < 1.0D) {
129 amountScrolled = 1.0D;
132 this.amountScrolled += p_mouseDragged_8_ * amountScrolled;
140 private int getMaxScroll() {
141 return Math.max(0, this.contentHeight - (this.listHeight - 4));
144 private int getScrollBarHeight() {
145 return MathHelper.clamp((int) ((float) (this.listHeight * this.listHeight) / (float) this.contentHeight),
147 this.listHeight - PADDING);
151 public boolean mouseScrolled(double mouseX, double mouseY, double scrollAmount) {
152 this.amountScrolled -= scrollAmount * 10;
156 public void render(MatrixStack matrixStack, int mouseX, int mouseY) {
157 this.amountScrolled = MathHelper.clamp(this.amountScrolled, 0.0D, this.getMaxScroll());
159 RenderHelper.disableLighting();
160 RenderHelper.disableFog();
161 if (!transparentBackground) drawListBackground();
163 int listTop = this.top + PADDING - (int) this.amountScrolled;
165 drawEntries(matrixStack, mouseX, mouseY, listTop);
167 RenderHelper.enableDepthTest();
168 RenderHelper.depthFuncAlways();
170 this.overlayBackground(0, this.top);
171 this.overlayBackground(this.bottom, this.height);
172 RenderHelper.depthFuncLessEqual();
173 RenderHelper.disableDepthTest();
174 RenderHelper.enableBlend();
175 RenderHelper.blendFuncGui();
176 RenderHelper.disableAlphaTest();
177 RenderHelper.shadeModelSmooth();
178 RenderHelper.disableTexture();
179 drawOverlayShadows();
181 int maxScroll = this.getMaxScroll();
183 drawScrollBar(maxScroll);
186 RenderHelper.enableTexture();
187 RenderHelper.shadeModelFlat();
188 RenderHelper.enableAlphaTest();
189 RenderHelper.disableBlend();
192 private void drawListBackground() {
193 this.minecraft.getTextureManager().bindTexture(DrawableHelper.OPTIONS_BACKGROUND_TEXTURE);
194 Renderer.startTextured()
195 .setColor(32, 32, 32)
197 .addPoint(0, this.bottom, 0.0D, (float) 0 / 32.0F, (float) (this.bottom + (int) this.amountScrolled) / 32.0F)
198 .addPoint(this.width, this.bottom, 0.0D, (float) this.width / 32.0F, (float) (this.bottom + (int) this.amountScrolled) / 32.0F)
199 .addPoint(this.width, this.top, 0.0D, (float) this.width / 32.0F, (float) (this.top + (int) this.amountScrolled) / 32.0F)
200 .addPoint(0, this.top, 0.0D, (float) 0 / 32.0F, (float) (this.top + (int) this.amountScrolled) / 32.0F)
204 private void drawEntries(MatrixStack matrixStack, int mouseX, int mouseY, int top) {
205 for (ControlListEntry entry : this.entries) {
206 if (!entry.isVisible()) continue;
208 entry.setX(this.listLeft);
211 int height = entry.getControlHeight();
212 int bottom = top + height;
213 if(top <= this.bottom && bottom >= this.top) {
214 drawEntry(matrixStack, mouseX, mouseY, top, entry, height);
220 protected void drawEntry(MatrixStack matrixStack, int mouseX, int mouseY, int top, ControlListEntry entry, int height) {
221 entry.render(matrixStack, mouseX, mouseY);
224 private void overlayBackground(int top, int bottom) {
225 this.minecraft.getTextureManager().bindTexture(DrawableHelper.OPTIONS_BACKGROUND_TEXTURE);
226 Renderer.startTextured()
227 .setColor(64, 64, 64)
229 .addPoint(0, bottom, -100.0D, 0.0D, (float) bottom / 32.0F)
230 .addPoint(this.width, bottom, -100.0D, (float) this.width / 32.0F, (float) bottom / 32.0F)
231 .addPoint(this.width, top, -100.0D, (float) this.width / 32.0F, (float) top / 32.0F)
232 .addPoint(0, top, -100.0D, 0.0D, (float) top / 32.0F)
236 private void drawScrollBar(int maxScroll) {
237 int scrollBarHeight = this.getScrollBarHeight();
238 int scrollBarTop = (int) this.amountScrolled * (this.listHeight - scrollBarHeight) / maxScroll + this.top;
239 if (scrollBarTop < this.top) {
240 scrollBarTop = this.top;
243 Renderer.startTextured()
245 .addPoint(this.scrollBarLeft, this.bottom, 0.0D, 0.0D, 1.0D)
246 .addPoint(this.width, this.bottom, 0.0D, 1.0D, 1.0D)
247 .addPoint(this.width, this.top, 0.0D, 1.0D, 0.0D)
248 .addPoint(this.scrollBarLeft, this.top, 0.0D, 0.0D, 0.0D)
251 Renderer.startTextured()
252 .setColor(128, 128, 128)
254 .addPoint(this.scrollBarLeft, scrollBarTop + scrollBarHeight, 0.0D, 0.0D, 1.0D)
255 .addPoint(this.width, scrollBarTop + scrollBarHeight, 0.0D, 1.0D, 1.0D)
256 .addPoint(this.width, scrollBarTop, 0.0D, 1.0D, 0.0D)
257 .addPoint(this.scrollBarLeft, scrollBarTop, 0.0D, 0.0D, 0.0D)
260 Renderer.startTextured()
261 .setColor(192, 192, 192)
263 .addPoint(this.scrollBarLeft, scrollBarTop + scrollBarHeight - 1, 0.0D, 0.0D, 1.0D)
264 .addPoint(this.width - 1, scrollBarTop + scrollBarHeight - 1, 0.0D, 1.0D, 1.0D)
265 .addPoint(this.width - 1, scrollBarTop, 0.0D, 1.0D, 0.0D)
266 .addPoint(this.scrollBarLeft, scrollBarTop, 0.0D, 0.0D, 0.0D)
270 private void drawOverlayShadows() {
271 Renderer.startTextured()
272 .addPoint(0, this.top + 4, 0.0D, 0.0D, 1.0D)
273 .addPoint(this.width, this.top + 4, 0.0D, 1.0D, 1.0D)
275 .addPoint(this.width, this.top, 0.0D, 1.0D, 0.0D)
276 .addPoint(0, this.top, 0.0D, 0.0D, 0.0D)
278 Renderer.startTextured()
279 .addPoint(this.width, this.bottom - 4, 0.0D, 1.0D, 0.0D)
280 .addPoint(0, this.bottom - 4, 0.0D, 0.0D, 0.0D)
282 .addPoint(0, this.bottom, 0.0D, 0.0D, 1.0D)
283 .addPoint(this.width, this.bottom, 0.0D, 1.0D, 1.0D)
287 ControlList section(String title, CreateControl... createControls) {
288 this.add(new ControlListSection(title, createControls));
292 void setTransparentBackground() {
293 this.transparentBackground = true;
297 public List<? extends IControl> controls() {
302 public IControl getFocused() {
307 public void setFocused(IControl control) {
308 this.focused = control;
312 public boolean isDragging() {
317 public void setDragging(boolean dragging) {
318 this.isDragging = dragging;