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 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;
17 import java.util.ArrayList;
18 import java.util.List;
20 public class ControlList extends DrawableHelper implements IControlSet {
21 public static final int CONTROLS_WIDTH = 310;
22 protected static final int PADDING = 8;
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;
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;
40 ControlList(int width, int height, int top, int bottom) {
42 this.scrollBarLeft = width - 6;
46 this.listHeight = bottom - top;
47 this.listLeft = width / 2 - CONTROLS_WIDTH / 2;
50 void add(ControlListEntry entry) {
51 entry.index = entries.size();
55 private void addEntry(ControlListEntry entry) {
56 this.entries.add(entry);
57 this.contentHeight += entry.getControlHeight();
60 public void filter(String lowerValue) {
63 for (ControlListEntry entry : entries) {
64 entry.filter(lowerValue);
65 if (entry.isVisible()) {
66 height += entry.getControlHeight();
67 } else if (entry == focused) {
71 this.contentHeight = height + PADDING;
75 this.entries.forEach(ControlListEntry::close);
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);
87 public boolean isMouseOver(double mouseX, double mouseY) {
88 return mouseY >= (double) this.top && mouseY <= (double) this.bottom;
92 public boolean changeFocus(boolean moveForward) {
93 boolean newControlFocused = IControlSet.super.changeFocus(moveForward);
94 if (newControlFocused) {
95 this.ensureVisible((ControlListEntry) this.getFocused());
98 return newControlFocused;
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);
110 int distanceBelowBottom = controlTop + controlHeight - this.bottom;
111 if (distanceBelowBottom > 0) {
112 this.amountScrolled += Math.max(controlHeight, distanceBelowBottom + PADDING);
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_)) {
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();
127 double maxScroll = this.getMaxScroll();
128 if (maxScroll < 1.0D) {
132 double amountScrolled = maxScroll / (double) (this.listHeight - getScrollBarHeight());
133 if (amountScrolled < 1.0D) {
134 amountScrolled = 1.0D;
137 this.amountScrolled += p_mouseDragged_8_ * amountScrolled;
145 private int getMaxScroll() {
146 return Math.max(0, this.contentHeight - (this.listHeight - 4));
149 private int getScrollBarHeight() {
150 return MathHelper.clamp((int) ((float) (this.listHeight * this.listHeight) / (float) this.contentHeight),
152 this.listHeight - PADDING);
156 public boolean mouseScrolled(double mouseX, double mouseY, double scrollAmount) {
157 this.amountScrolled -= scrollAmount * 10;
161 public void render(MatrixStack matrixStack, int mouseX, int mouseY) {
162 this.amountScrolled = MathHelper.clamp(this.amountScrolled, 0.0D, this.getMaxScroll());
164 int listTop = this.top + PADDING - (int) this.amountScrolled;
166 drawEntries(matrixStack, mouseX, mouseY, listTop);
168 RenderHelper.enableDepthTest();
169 RenderHelper.depthFuncAlways();
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();
181 int maxScroll = this.getMaxScroll();
183 drawScrollBar(maxScroll);
186 RenderHelper.enableTexture();
187 // RenderHelper.shadeModelFlat();
188 RenderHelper.disableBlend();
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)
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 Tessellator tessellator = Tessellator.getInstance();
226 BufferBuilder bufferBuilder = tessellator.getBuffer();
227 RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
228 RenderSystem.setShaderTexture(0, DrawableHelper.OPTIONS_BACKGROUND_TEXTURE);
230 bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
232 .vertex(0, bottom, -100.0D)
233 .texture(0.0F, (float) bottom / 32.0F)
234 .color(64, 64, 64, 255)
237 .vertex(this.width, bottom, -100.0D)
238 .texture((float) this.width / 32.0F, (float) bottom / 32.0F)
239 .color(64, 64, 64, 255)
242 .vertex(this.width, top, -100.0D)
243 .texture((float) this.width / 32.0F, (float) top / 32.0F)
244 .color(64, 64, 64, 255)
247 .vertex(0, top, -100.0D)
248 .texture(0.0f, (float) top / 32.0F)
249 .color(64, 64, 64, 255)
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;
261 Tessellator tessellator = Tessellator.getInstance();
262 BufferBuilder bufferBuilder = tessellator.getBuffer();
263 RenderSystem.disableTexture();
264 RenderSystem.setShader(GameRenderer::getPositionColorShader);
266 bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
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();
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();
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();
284 RenderSystem.enableTexture();
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();
296 bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
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();
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();
309 RenderSystem.enableTexture();
310 RenderSystem.disableBlend();
313 ControlList section(String title, CreateControl... createControls) {
314 this.add(new ControlListSection(title, createControls));
318 void setTransparentBackground() {
319 this.transparentBackground = true;
323 public List<? extends IControl> controls() {
328 public IControl getFocused() {
333 public void setFocused(IControl control) {
334 this.focused = control;
338 public boolean isDragging() {
343 public void setDragging(boolean dragging) {
344 this.isDragging = dragging;