/* * This file is part of OneConfig. * OneConfig - Next Generation Config Library for Minecraft: Java Edition * Copyright (C) 2021, 2022 Polyfrost. * * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * OneConfig is licensed under the terms of version 3 of the GNU Lesser * General Public License as published by the Free Software Foundation, AND * under the Additional Terms Applicable to OneConfig, as published by Polyfrost, * either version 1.0 of the Additional Terms, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License. If not, see . You should * have also received a copy of the Additional Terms Applicable * to OneConfig, as published by Polyfrost. If not, see * */ package cc.polyfrost.oneconfig.config.elements; import cc.polyfrost.oneconfig.gui.animations.Animation; import cc.polyfrost.oneconfig.gui.animations.ColorAnimation; import cc.polyfrost.oneconfig.gui.animations.DummyAnimation; import cc.polyfrost.oneconfig.gui.animations.EaseOutQuad; import cc.polyfrost.oneconfig.internal.assets.Colors; import cc.polyfrost.oneconfig.internal.assets.SVGs; import cc.polyfrost.oneconfig.renderer.RenderManager; import cc.polyfrost.oneconfig.renderer.font.Fonts; import cc.polyfrost.oneconfig.utils.InputHandler; import cc.polyfrost.oneconfig.utils.color.ColorPalette; import cc.polyfrost.oneconfig.utils.gui.GuiUtils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.function.Supplier; @SuppressWarnings({"unused"}) public abstract class BasicOption { public final int size; protected final Field field; protected Object parent; public final String name; public final String description; public final String category; public final String subcategory; private final ColorAnimation nameColorAnimation = new ColorAnimation(new ColorPalette(Colors.WHITE_90, Colors.WHITE, Colors.WHITE_90)); protected int nameColor = Colors.WHITE_90; private final ArrayList> dependencies = new ArrayList<>(); private final ArrayList listeners = new ArrayList<>(); private final ArrayList> hideConditions = new ArrayList<>(); private Animation descriptionAnimation = new DummyAnimation(0f); private float hoverTime = 0f; /** * Initialize option * * @param field variable attached to option (null for category) * @param parent the parent object of the field, used for getting and setting the variable * @param name name of option * @param description The description * @param category The category * @param subcategory The subcategory * @param size size of option, 0 for single column, 1 for double. */ public BasicOption(Field field, Object parent, String name, String description, String category, String subcategory, int size) { this.field = field; this.parent = parent; this.name = name; this.description = description; this.category = category; this.subcategory = subcategory; this.size = size; if (field != null) field.setAccessible(true); } /** * @param object Java object to set the variable to */ protected void set(Object object) throws IllegalAccessException { if (field == null) return; field.set(parent, object); for (Runnable listener : listeners) listener.run(); } /** * @return value of variable as Java object */ public Object get() throws IllegalAccessException { if (field == null) return null; return field.get(parent); } /** * @return height of option to align other options accordingly */ public abstract int getHeight(); /** * Function that gets called when drawing option * * @param vg NanoVG context * @param x x position * @param y y position */ public abstract void draw(long vg, int x, int y, InputHandler inputHandler); /** * Function that gets called last drawing option, * should be used for things that draw above other options * * @param vg NanoVG context * @param x x position * @param y y position */ public void drawLast(long vg, int x, int y, InputHandler inputHandler) { } /** * Function that gets called when a key is typed * * @param key char that has been typed * @param keyCode code of key */ public void keyTyped(char key, int keyCode) { } public void drawDescription(long vg, int x, int y, InputHandler inputHandler) { if (description.trim().equals("")) return; boolean hovered = inputHandler.isAreaHovered(getNameX(x), y, RenderManager.getTextWidth(vg, name, 14f, Fonts.MEDIUM), 32f); nameColor = nameColorAnimation.getColor(hovered, false); if (hovered) hoverTime += GuiUtils.getDeltaTime(); else hoverTime = 0; boolean shouldDrawDescription = shouldDrawDescription(); if (descriptionAnimation.getEnd() != 1f && shouldDrawDescription) { descriptionAnimation = new EaseOutQuad(150, descriptionAnimation.get(0), 1f, false); } else if (descriptionAnimation.getEnd() != 0f && !shouldDrawDescription) { descriptionAnimation = new EaseOutQuad(150, descriptionAnimation.get(0), 0f, false); } if (!shouldDrawDescription && descriptionAnimation.isFinished()) return; float textWidth = RenderManager.getTextWidth(vg, description, 16, Fonts.MEDIUM); RenderManager.setAlpha(vg, descriptionAnimation.get()); RenderManager.drawRoundedRect(vg, x, y - 42f, textWidth + 68f, 44f, Colors.GRAY_700, 8f); RenderManager.drawDropShadow(vg, x, y - 42f, textWidth + 68f, 44f, 32f, 0f, 8f); RenderManager.drawSvg(vg, SVGs.INFO_ARROW, x + 16, y - 30f, 20f, 20f, Colors.WHITE_80); RenderManager.drawText(vg, description, x + 52, y - 19, Colors.WHITE_80, 16, Fonts.MEDIUM); RenderManager.setAlpha(vg, 1f); } /** * @return If this option should draw its description */ protected boolean shouldDrawDescription() { return hoverTime > 350; } /** * Get the X of the name of the option, used to trigger the description * * @param x The x coordinate of the option * @return The x coordinate of the option's name */ protected float getNameX(int x) { return x; } /** * @return If the option is enabled, based on the dependencies */ public boolean isEnabled() { for (Supplier dependency : dependencies) { if (!dependency.get()) return false; } return true; } public boolean isHidden() { for (Supplier condition : hideConditions) { if (condition.get()) return true; } return false; } /** * Add a condition to this option * * @param supplier The dependency */ public void addDependency(Supplier supplier) { this.dependencies.add(supplier); } /** * Add a listener to this option * * @param runnable The listener */ public void addListener(Runnable runnable) { this.listeners.add(runnable); } /** * Hide an option if a condition is met * * @param supplier The condition */ public void addHideCondition(Supplier supplier) { this.hideConditions.add(supplier); } /** * @return The field */ public Field getField() { return field; } /** * @return The parent of the field */ public Object getParent() { return parent; } /** * @param parent The new parent object */ public void setParent(Object parent) { this.parent = parent; } }