Писал чату жпт что бы как в нурике сделал, ну вроде сходство 2%. Убого но можно сделать нормальной если уменишить, мне лень package wtf.Soul.ui.dropdown; import java.util.ArrayList; import java.util.List; import com.mojang.blaze3d.matrix.MatrixStack; import wtf.Soul.Expensive; import wtf.Soul.functions.api.Category; import wtf.Soul.functions.api.Function; import wtf.Soul.ui.dropdown.components.ModuleComponent; import wtf.Soul.ui.dropdown.impl.Component; import wtf.Soul.ui.dropdown.impl.IBuilder; import wtf.Soul.ui.styles.Style; import wtf.Soul.utils.math.MathUtil; import wtf.Soul.utils.render.ColorUtils; import wtf.Soul.utils.render.DisplayUtils; import wtf.Soul.utils.render.Scissor; import wtf.Soul.utils.render.font.Fonts; import lombok.Getter; import lombok.Setter; import net.minecraft.client.Minecraft; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector4f; @Getter @setter public class Panel implements IBuilder { private final Category category; protected float x; protected float y; protected final float width = 135f; // Увеличиваем ширину панели protected final float height = 300f; // Увеличиваем высоту панели private List<ModuleComponent> modules = new ArrayList<>(); private float scroll, animatedScroll; private float scroll1, animatedScrool1; public Panel(Category category) { this.category = category; // Добавляем модули к панели for (Function function : Expensive.getInstance().getFunctionRegistry().getFunctions()) { if (function.getCategory() == category) { ModuleComponent component = new ModuleComponent(function); component.setPanel(this); modules.add(component); } } } @Override public void render(MatrixStack stack, float mouseX, float mouseY) { Style style = Expensive.getInstance().getStyleManager().getCurrentStyle(); // Анимация прокрутки animatedScroll = MathUtil.fast(animatedScroll, scroll, 10); // Отображение панели с заголовком DisplayUtils.drawRoundedRect(x - 10, y, width, height, new Vector4f(14, 14, 14, 14), ColorUtils.rgba(30, 30, 30, 200)); // Отображаем категорию в шапке Fonts.montserrat.drawCenteredText(stack, category.name(), x -8 + width / 2f, y + 5, style.getSecondColor().getRGB(), 12f, 0.1f); // Рендерим модули внутри панели drawComponents(stack, mouseX, mouseY); } private void drawComponents(MatrixStack stack, float mouseX, float mouseY) { float offset = 20f; float header = 25; float panelHeight = height - header; Scissor.push(); Scissor.setFromComponentCoordinates(x, y + header, width, panelHeight); // Обрабатываем прокрутку if (modules.size() * 22 > panelHeight - 10) { scroll = MathHelper.clamp(scroll, -(modules.size() * 22 - panelHeight + 10), 0); } else { scroll = 0; } for (ModuleComponent component : modules) { component.setX(x + 5); component.setY(y + offset + animatedScroll); component.setWidth(width - 10); component.setHeight(20); component.render(stack, mouseX, mouseY); offset += component.getHeight() + 5; } Scissor.pop(); } @Override public void mouseClick(float mouseX, float mouseY, int button) { for (ModuleComponent component : modules) { component.mouseClick(mouseX, mouseY, button); } } @Override public void mouseRelease(float mouseX, float mouseY, int button) { for (ModuleComponent component : modules) { component.mouseRelease(mouseX, mouseY, button); } } @Override public void keyPressed(int key, int scanCode, int modifiers) { for (ModuleComponent component : modules) { component.keyPressed(key, scanCode, modifiers); } } @Override public void charTyped(char codePoint, int modifiers) { for (ModuleComponent component : modules) { component.charTyped(codePoint, modifiers); } } } package wtf.Soul.ui.dropdown; import java.util.ArrayList; import java.util.List; import wtf.Soul.utils.client.ClientUtil; import wtf.Soul.utils.client.Vec2i; import wtf.Soul.utils.render.*; import net.minecraft.client.Minecraft; import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.platform.GlStateManager; import wtf.Soul.functions.api.Category; import wtf.Soul.utils.CustomFramebuffer; import wtf.Soul.utils.client.IMinecraft; import wtf.Soul.utils.math.MathUtil; import lombok.Getter; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.math.vector.Vector4f; import net.minecraft.util.text.ITextComponent; import ru.hogoshi.Animation; import ru.hogoshi.util.Easings; public class DropDown extends Screen implements IMinecraft { private final List<Panel> panels = new ArrayList<>(); @Getter private static Animation animation = new Animation(); public DropDown(ITextComponent titleIn) { super(titleIn); for (Category category : Category.values()) { if (category == Category.Theme) continue; panels.add(new Panel(category)); } panels.add(new PanelStyle(Category.Theme)); } @Override public boolean isPauseScreen() { return false; } @Override protected void init() { animation = animation.animate(1, 0.25f, Easings.EXPO_OUT); super.init(); } public static float scale = 1.0f;; @Override public void closeScreen() { super.closeScreen(); GLFW.glfwSetCursor(Minecraft.getInstance().getMainWindow().getHandle(), Cursors.ARROW); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double delta) { // TODO Auto-generated method stub Vec2i fixMouse = adjustMouseCoordinates((int) mouseX, (int) mouseY); Vec2i fix = ClientUtil.getMouse(fixMouse.getX(), fixMouse.getY()); mouseX = fix.getX(); mouseY = fix.getY(); for (Panel panel : panels) { if (MathUtil.isHovered((float) mouseX, (float) mouseY, panel.getX(), panel.getY(), panel.getWidth(), panel.getHeight())) { panel.setScroll((float) (panel.getScroll() + (delta * 20))); } } return super.mouseScrolled(mouseX, mouseY, delta); } @Override public boolean charTyped(char codePoint, int modifiers) { for (Panel panel : panels) { panel.charTyped(codePoint, modifiers); } return super.charTyped(codePoint, modifiers); } @Override public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { animation.update(); if (animation.getValue() < 0.1) { closeScreen(); } final float off = 10; float width = panels.size() * (105 + off); updateScaleBasedOnScreenWidth(); int windowWidth = ClientUtil.calc(mc.getMainWindow().getScaledWidth()); int windowHeight = ClientUtil.calc(mc.getMainWindow().getScaledHeight()); Vec2i fixMouse = adjustMouseCoordinates(mouseX, mouseY); Vec2i fix = ClientUtil.getMouse(fixMouse.getX(), fixMouse.getY()); mouseX = fix.getX(); mouseY = fix.getY(); GlStateManager.pushMatrix(); GlStateManager.translatef(windowWidth / 2f, windowHeight / 2f, 0); GlStateManager.scaled(animation.getValue(), animation.getValue(), 1); GlStateManager.scaled(scale, scale, 1); GlStateManager.translatef(-windowWidth / 2f, -windowHeight / 2f, 0); for (Panel panel : panels) { panel.setY((windowHeight / 2f - 250 / 2f)); panel.setX((windowWidth / 2f) - 375 + panel.getCategory().ordinal() * (120 + off) + off / 2f); float animationValue = (float) animation.getValue() * scale; float halfAnimationValueRest = (1 - animationValue) / 2f; float testX = panel.getX() + (panel.getWidth() * halfAnimationValueRest); float testY = panel.getY() + (panel.getHeight() * halfAnimationValueRest); float testW = panel.getWidth() * animationValue; float testH = panel.getHeight() * animationValue; testX = testX * animationValue + ((windowWidth - testW) * halfAnimationValueRest); Scissor.push(); Scissor.setFromComponentCoordinates(testX, testY, testW, testH - 0.5f); panel.render(matrixStack, mouseX, mouseY); Scissor.unset(); Scissor.pop(); } GlStateManager.popMatrix(); mc.gameRenderer.setupOverlayRendering(); } private void updateScaleBasedOnScreenWidth() { final float PANEL_WIDTH = 135f; final float MARGIN = 10; final float MIN_SCALE = 1f; float totalPanelWidth = panels.size() * (PANEL_WIDTH + MARGIN); float screenWidth = mc.getMainWindow().getScaledWidth(); if (totalPanelWidth >= screenWidth) { scale = screenWidth / totalPanelWidth; scale = MathHelper.clamp(scale, MIN_SCALE, 1.0f); } else { scale = 1f; } } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { for (Panel panel : panels) { panel.keyPressed(keyCode, scanCode, modifiers); } // TODO Auto-generated method stub if (keyCode == GLFW.GLFW_KEY_ESCAPE) { animation = animation.animate(0, 0.25f, Easings.EXPO_OUT); return false; } return super.keyPressed(keyCode, scanCode, modifiers); } private Vec2i adjustMouseCoordinates(int mouseX, int mouseY) { int windowWidth = mc.getMainWindow().getScaledWidth(); int windowHeight = mc.getMainWindow().getScaledHeight(); float adjustedMouseX = (mouseX - windowWidth / 2f) / scale + windowWidth / 2f; float adjustedMouseY = (mouseY - windowHeight / 2f) / scale + windowHeight / 2f; return new Vec2i((int) adjustedMouseX, (int) adjustedMouseY); } private double pathX(float mouseX, float scale) { if (scale == 1) return mouseX; int windowWidth = mc.getMainWindow().scaledWidth(); int windowHeight = mc.getMainWindow().scaledHeight(); mouseX /= (scale); mouseX -= (windowWidth / 2f) - (windowWidth / 2f) * (scale); return mouseX; } private double pathY(float mouseY, float scale) { if (scale == 1) return mouseY; int windowWidth = mc.getMainWindow().scaledWidth(); int windowHeight = mc.getMainWindow().scaledHeight(); mouseY /= scale; mouseY -= (windowHeight / 2f) - (windowHeight / 2f) * (scale); return mouseY; } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { Vec2i fixMouse = adjustMouseCoordinates((int) mouseX, (int) mouseY); Vec2i fix = ClientUtil.getMouse(fixMouse.getX(), fixMouse.getY()); mouseX = fix.getX(); mouseY = fix.getY(); for (Panel panel : panels) { panel.mouseClick((float) mouseX, (float) mouseY, button); } return super.mouseClicked(mouseX, mouseY, button); } @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { // TODO Auto-generated method stub Vec2i fixMouse = adjustMouseCoordinates((int) mouseX, (int) mouseY); Vec2i fix = ClientUtil.getMouse(fixMouse.getX(), fixMouse.getY()); mouseX = fix.getX(); mouseY = fix.getY(); for (Panel panel : panels) { panel.mouseRelease((float) mouseX, (float) mouseY, button); } return super.mouseReleased(mouseX, mouseY, button); } } package wtf.Soul.ui.dropdown; import com.mojang.blaze3d.matrix.MatrixStack; import wtf.Soul.Expensive; import wtf.Soul.functions.api.Category; import wtf.Soul.ui.styles.Style; import wtf.Soul.utils.math.MathUtil; import wtf.Soul.utils.render.*; import wtf.Soul.utils.render.font.Fonts; import lombok.Getter; import net.minecraft.client.Minecraft; import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; @Getter public class PanelStyle extends Panel { public PanelStyle(Category category) { super(category); // TODO Auto-generated constructor stub } float max = 0; @Override public void render(MatrixStack stack, float mouseX, float mouseY) { Style currentStyle = Expensive.getInstance().getStyleManager().getCurrentStyle(); float header = 25; float headerFont = 8; setAnimatedScrool1(MathUtil.fast(getAnimatedScrool1(), getScroll(), 10)); DisplayUtils.drawRoundedRect(x, y + 19, width - 10, height - 90, 7, ColorUtils.rgba(21, 21, 21, 255)); DisplayUtils.drawRoundedRect(x + 3.8f, y + 22.5f, width - 8, height - 53, 12, ColorUtils.rgba(21, 21, 21, 255)); Fonts.montserrat.drawCenteredText(stack, "Theme Editor", x + width / 2f, y + header / 2f - Fonts.montserrat.getHeight(headerFont) / 2f + 18, currentStyle.getSecondColor().getRGB(), headerFont - 1.5f, 0.1f); if (max > height - 24 * 2) { setScroll(MathHelper.clamp(getScroll(), -max + height - header - 10, 0)); setAnimatedScrool1(MathHelper.clamp(getAnimatedScrool1(), -max + height - header - 10, 0)); } else { setScroll(0); setAnimatedScrool1(0); } float animationValue = (float) DropDown.getAnimation().getValue() * DropDown.scale; float halfAnimationValueRest = (1 - animationValue) / 2f; float height = getHeight(); float testX = getX() + (getWidth() * halfAnimationValueRest); float testY = getY() + 25 + (height * halfAnimationValueRest); float testW = getWidth() * animationValue; float testH = height * animationValue - 56; testX = testX * animationValue + ((Minecraft.getInstance().getMainWindow().getScaledWidth() - testW) * halfAnimationValueRest); Scissor.push(); Scissor.setFromComponentCoordinates(testX, testY, testW, testH); int offset = 1; boolean hovered = false; float x = this.x + 5; float y = this.y + header + 5 + offset + getAnimatedScrool1(); float H = 12; for (Style style : Expensive.getInstance().getStyleManager().getStyleList()) { if (MathUtil.isHovered(mouseX, mouseY, x + 5, y, width - 10 - 10, H)) { hovered = true; } if (Expensive.getInstance().getStyleManager().getCurrentStyle() == style) { Fonts.montserrat.drawText(stack, style.getStyleName(), x + 0.5f * 1.5f + width / 2 - 28, y + H / 2 + 7 - Fonts.montserrat.getHeight(6) / 2, style.getFirstColor().getRGB(), 6f, 0.05f); DisplayUtils.drawRoundedRect(x + 5f, y + 7, width / 2 - 40, H, 10, style.getFirstColor().getRGB()); } DisplayUtils.drawRoundedRect(x + 5f, y + 7.5f, width / 2 - 40, H, 2, style.getFirstColor().getRGB()); Fonts.montserrat.drawText(stack, style.getStyleName(), x + 0.5f * 1.5f + width / 2 - 28, y + H / 2 + 7 - Fonts.montserrat.getHeight(6) / 2, -1, 6f, 0.05f); y += 5+H; offset++; } if (MathUtil.isHovered(mouseX, mouseY, x, y, width, height)) { if (hovered) { GLFW.glfwSetCursor(Minecraft.getInstance().getMainWindow().getHandle(), Cursors.HAND); } else { GLFW.glfwSetCursor(Minecraft.getInstance().getMainWindow().getHandle(), Cursors.ARROW); } } Scissor.unset(); Scissor.pop(); max = offset * Expensive.getInstance().getStyleManager().getStyleList().size() * 1.21f; } @Override public void keyPressed(int key, int scanCode, int modifiers) { } @Override public void mouseClick(float mouseX, float mouseY, int button) { float header = 25; int offset = 0; float x = this.x + 5; float y = this.y + offset + header + 5 + getAnimatedScrool1(); for (Style style : Expensive.getInstance().getStyleManager().getStyleList()) { float barHeight = 12; float barY = y + 7.5f; if (MathUtil.isHovered(mouseX, mouseY, x + 5, barY, width / 2 - 40, barHeight)) { Expensive.getInstance().getStyleManager().setCurrentStyle(style); } y += 5 + barHeight; offset++; } } @Override public void mouseRelease(float mouseX, float mouseY, int button) { } }