]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/gui/ControlList.java
Update to 1.17.1 (#124)
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / gui / ControlList.java
1 package com.irtimaled.bbor.client.gui;
2
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 com.mojang.blaze3d.platform.GlStateManager;
7 import com.mojang.blaze3d.systems.RenderSystem;
8 import net.minecraft.client.MinecraftClient;
9 import net.minecraft.client.gui.DrawableHelper;
10 import net.minecraft.client.render.BufferBuilder;
11 import net.minecraft.client.render.GameRenderer;
12 import net.minecraft.client.render.Tessellator;
13 import net.minecraft.client.render.VertexFormat;
14 import net.minecraft.client.render.VertexFormats;
15 import net.minecraft.client.util.math.MatrixStack;
16
17 import java.util.ArrayList;
18 import java.util.List;
19
20 public class ControlList extends DrawableHelper implements IControlSet {
21     public static final int CONTROLS_WIDTH = 310;
22     protected static final int PADDING = 8;
23
24     protected final int listLeft;
25     protected final List<ControlListEntry> entries = new ArrayList<>();
26     private final int scrollBarLeft;
27     private final int listHeight;
28     private final int width;
29     private final int height;
30     private final int top;
31     private final int bottom;
32
33     protected int contentHeight = PADDING;
34     private double amountScrolled;
35     private boolean clickedScrollbar;
36     private boolean transparentBackground;
37     private IControl focused;
38     private boolean isDragging;
39
40     ControlList(int width, int height, int top, int bottom) {
41         this.width = width;
42         this.scrollBarLeft = width - 6;
43         this.height = height;
44         this.top = top;
45         this.bottom = bottom;
46         this.listHeight = bottom - top;
47         this.listLeft = width / 2 - CONTROLS_WIDTH / 2;
48     }
49
50     void add(ControlListEntry entry) {
51         entry.index = entries.size();
52         addEntry(entry);
53     }
54
55     private void addEntry(ControlListEntry entry) {
56         this.entries.add(entry);
57         this.contentHeight += entry.getControlHeight();
58     }
59
60     public void filter(String lowerValue) {
61         int height = 0;
62
63         for (ControlListEntry entry : entries) {
64             entry.filter(lowerValue);
65             if (entry.isVisible()) {
66                 height += entry.getControlHeight();
67             } else if (entry == focused) {
68                 focused = null;
69             }
70         }
71         this.contentHeight = height + PADDING;
72     }
73
74     void close() {
75         this.entries.forEach(ControlListEntry::close);
76     }
77
78     @Override
79     public boolean mouseClicked(double mouseX, double mouseY, int button) {
80         this.clickedScrollbar = button == 0 && mouseX >= (double) this.scrollBarLeft;
81         return isMouseOver(mouseX, mouseY) &&
82                 (IControlSet.super.mouseClicked(mouseX, mouseY, button) ||
83                         this.clickedScrollbar);
84     }
85
86     @Override
87     public boolean isMouseOver(double mouseX, double mouseY) {
88         return mouseY >= (double) this.top && mouseY <= (double) this.bottom;
89     }
90
91     @Override
92     public boolean changeFocus(boolean moveForward) {
93         boolean newControlFocused = IControlSet.super.changeFocus(moveForward);
94         if (newControlFocused) {
95             this.ensureVisible((ControlListEntry) this.getFocused());
96         }
97
98         return newControlFocused;
99     }
100
101     private void ensureVisible(ControlListEntry control) {
102         int controlTop = control.getControlTop();
103         int controlHeight = control.getControlHeight();
104         int distanceAboveTop = this.top - controlTop;
105         if (distanceAboveTop > 0) {
106             this.amountScrolled -= Math.max(controlHeight, distanceAboveTop + PADDING);
107             return;
108         }
109
110         int distanceBelowBottom = controlTop + controlHeight - this.bottom;
111         if (distanceBelowBottom > 0) {
112             this.amountScrolled += Math.max(controlHeight, distanceBelowBottom + PADDING);
113         }
114     }
115
116     @Override
117     public boolean mouseDragged(double mouseX, double mouseY, int button, double p_mouseDragged_6_, double p_mouseDragged_8_) {
118         if (IControlSet.super.mouseDragged(mouseX, mouseY, button, p_mouseDragged_6_, p_mouseDragged_8_)) {
119             return true;
120         }
121         if (button == 0 && this.clickedScrollbar) {
122             if (mouseY < (double) this.top) {
123                 this.amountScrolled = 0.0D;
124             } else if (mouseY > (double) this.bottom) {
125                 this.amountScrolled = this.getMaxScroll();
126             } else {
127                 double maxScroll = this.getMaxScroll();
128                 if (maxScroll < 1.0D) {
129                     maxScroll = 1.0D;
130                 }
131
132                 double amountScrolled = maxScroll / (double) (this.listHeight - getScrollBarHeight());
133                 if (amountScrolled < 1.0D) {
134                     amountScrolled = 1.0D;
135                 }
136
137                 this.amountScrolled += p_mouseDragged_8_ * amountScrolled;
138             }
139
140             return true;
141         }
142         return false;
143     }
144
145     private int getMaxScroll() {
146         return Math.max(0, this.contentHeight - (this.listHeight - 4));
147     }
148
149     private int getScrollBarHeight() {
150         return MathHelper.clamp((int) ((float) (this.listHeight * this.listHeight) / (float) this.contentHeight),
151                 32,
152                 this.listHeight - PADDING);
153     }
154
155     @Override
156     public boolean mouseScrolled(double mouseX, double mouseY, double scrollAmount) {
157         this.amountScrolled -= scrollAmount * 10;
158         return true;
159     }
160
161     public void render(MatrixStack matrixStack, int mouseX, int mouseY) {
162         this.amountScrolled = MathHelper.clamp(this.amountScrolled, 0.0D, this.getMaxScroll());
163
164         int listTop = this.top + PADDING - (int) this.amountScrolled;
165
166         drawEntries(matrixStack, mouseX, mouseY, listTop);
167
168         RenderHelper.enableDepthTest();
169         RenderHelper.depthFuncAlways();
170
171         this.overlayBackground(0, this.top);
172         this.overlayBackground(this.bottom, this.height);
173         RenderHelper.depthFuncLessEqual();
174         RenderHelper.disableDepthTest();
175         RenderHelper.enableBlend();
176         RenderHelper.blendFuncGui();
177         // RenderHelper.shadeModelSmooth();
178         RenderHelper.disableTexture();
179         drawOverlayShadows();
180
181         int maxScroll = this.getMaxScroll();
182         if (maxScroll > 0) {
183             drawScrollBar(maxScroll);
184         }
185
186         RenderHelper.enableTexture();
187         // RenderHelper.shadeModelFlat();
188         RenderHelper.disableBlend();
189     }
190
191     private void drawListBackground(MatrixStack matrixStack) {
192         MinecraftClient.getInstance().getTextureManager().bindTexture(DrawableHelper.OPTIONS_BACKGROUND_TEXTURE);
193         Renderer.startTextured()
194                 .setMatrixStack(matrixStack)
195                 .setColor(32, 32, 32)
196                 .setAlpha(255)
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)
201                 .render();
202     }
203
204     private void drawEntries(MatrixStack matrixStack, int mouseX, int mouseY, int top) {
205         for (ControlListEntry entry : this.entries) {
206             if (!entry.isVisible()) continue;
207
208             entry.setX(this.listLeft);
209             entry.setY(top);
210
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);
215             }
216             top = bottom;
217         }
218     }
219
220     protected void drawEntry(MatrixStack matrixStack, int mouseX, int mouseY, int top, ControlListEntry entry, int height) {
221         entry.render(matrixStack, mouseX, mouseY);
222     }
223
224     private void overlayBackground(int top, int bottom) {
225         Tessellator tessellator = Tessellator.getInstance();
226         BufferBuilder bufferBuilder = tessellator.getBuffer();
227         RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
228         RenderSystem.setShaderTexture(0, DrawableHelper.OPTIONS_BACKGROUND_TEXTURE);
229
230         bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
231         bufferBuilder
232                 .vertex(0, bottom, -100.0D)
233                 .texture(0.0F, (float) bottom / 32.0F)
234                 .color(64, 64, 64, 255)
235                 .next();
236         bufferBuilder
237                 .vertex(this.width, bottom, -100.0D)
238                 .texture((float) this.width / 32.0F, (float) bottom / 32.0F)
239                 .color(64, 64, 64, 255)
240                 .next();
241         bufferBuilder
242                 .vertex(this.width, top, -100.0D)
243                 .texture((float) this.width / 32.0F, (float) top / 32.0F)
244                 .color(64, 64, 64, 255)
245                 .next();
246         bufferBuilder
247                 .vertex(0, top, -100.0D)
248                 .texture(0.0f, (float) top / 32.0F)
249                 .color(64, 64, 64, 255)
250                 .next();
251         tessellator.draw();
252     }
253
254     private void drawScrollBar(int maxScroll) {
255         int scrollBarHeight = this.getScrollBarHeight();
256         int scrollBarTop = (int) this.amountScrolled * (this.listHeight - scrollBarHeight) / maxScroll + this.top;
257         if (scrollBarTop < this.top) {
258             scrollBarTop = this.top;
259         }
260
261         Tessellator tessellator = Tessellator.getInstance();
262         BufferBuilder bufferBuilder = tessellator.getBuffer();
263         RenderSystem.disableTexture();
264         RenderSystem.setShader(GameRenderer::getPositionColorShader);
265
266         bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
267
268         bufferBuilder.vertex(this.scrollBarLeft, this.bottom, 0.0D).color(0, 0, 0, 255).next();
269         bufferBuilder.vertex(this.width, this.bottom, 0.0D).color(0, 0, 0, 255).next();
270         bufferBuilder.vertex(this.width, this.top, 0.0D).color(0, 0, 0, 255).next();
271         bufferBuilder.vertex(this.scrollBarLeft, this.top, 0.0D).color(0, 0, 0, 255).next();
272
273         bufferBuilder.vertex(this.scrollBarLeft, scrollBarTop + scrollBarHeight, 0.0D).color(128, 128, 128, 255).next();
274         bufferBuilder.vertex(this.width, scrollBarTop + scrollBarHeight, 0.0D).color(128, 128, 128, 255).next();
275         bufferBuilder.vertex(this.width, scrollBarTop, 0.0D).color(128, 128, 128, 255).next();
276         bufferBuilder.vertex(this.scrollBarLeft, scrollBarTop, 0.0D).color(128, 128, 128, 255).next();
277
278         bufferBuilder.vertex(this.scrollBarLeft, scrollBarTop + scrollBarHeight - 1, 0.0D).color(192, 192, 192, 255).next();
279         bufferBuilder.vertex(this.width - 1, scrollBarTop + scrollBarHeight - 1, 0.0D).color(192, 192, 192, 255).next();
280         bufferBuilder.vertex(this.width - 1, scrollBarTop, 0.0D).color(192, 192, 192, 255).next();
281         bufferBuilder.vertex(this.scrollBarLeft, scrollBarTop, 0.0D).color(192, 192, 192, 255).next();
282
283         tessellator.draw();
284         RenderSystem.enableTexture();
285     }
286
287     private void drawOverlayShadows() {
288         RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
289         RenderSystem.enableBlend();
290         RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ZERO, GlStateManager.DstFactor.ONE);
291         RenderSystem.disableTexture();
292         RenderSystem.setShader(GameRenderer::getPositionColorShader);
293         Tessellator tessellator = Tessellator.getInstance();
294         BufferBuilder bufferBuilder = tessellator.getBuffer();
295
296         bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
297
298         bufferBuilder.vertex(0, this.top + 4, 0.0D).color(0, 0, 0, 0).next();
299         bufferBuilder.vertex(this.width, this.top + 4, 0.0D).color(0, 0, 0, 0).next();
300         bufferBuilder.vertex(this.width, this.top, 0.0D).color(0, 0, 0, 255).next();
301         bufferBuilder.vertex(0, this.top, 0.0D).color(0, 0, 0, 255).next();
302
303         bufferBuilder.vertex(this.width, this.bottom - 4, 0.0D).color(0, 0, 0, 0).next();
304         bufferBuilder.vertex(0, this.bottom - 4, 0.0D).color(0, 0, 0, 0).next();
305         bufferBuilder.vertex(0, this.bottom, 0.0D).color(0, 0, 0, 255).next();
306         bufferBuilder.vertex(this.width, this.bottom, 0.0D).color(0, 0, 0, 255).next();
307
308         tessellator.draw();
309         RenderSystem.enableTexture();
310         RenderSystem.disableBlend();
311     }
312
313     ControlList section(String title, CreateControl... createControls) {
314         this.add(new ControlListSection(title, createControls));
315         return this;
316     }
317
318     void setTransparentBackground() {
319         this.transparentBackground = true;
320     }
321
322     @Override
323     public List<? extends IControl> controls() {
324         return entries;
325     }
326
327     @Override
328     public IControl getFocused() {
329         return focused;
330     }
331
332     @Override
333     public void setFocused(IControl control) {
334         this.focused = control;
335     }
336
337     @Override
338     public boolean isDragging() {
339         return isDragging;
340     }
341
342     @Override
343     public void setDragging(boolean dragging) {
344         this.isDragging = dragging;
345     }
346 }