diff options
45 files changed, 965 insertions, 37 deletions
diff --git a/common/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java b/common/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java new file mode 100644 index 0000000..0d14b41 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java @@ -0,0 +1,18 @@ +package dev.isxander.yacl3.platform; + +import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; +import dev.isxander.yacl3.config.v2.api.SerialEntry; +import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; + +public class YACLConfig { + public static final ConfigClassHandler<YACLConfig> HANDLER = ConfigClassHandler.createBuilder(YACLConfig.class) + .id(YACLPlatform.rl("config")) + .serializer(config -> GsonConfigSerializerBuilder.create(config) + .setPath(YACLPlatform.getConfigDir().resolve("yacl.json5")) + .setJson5(true) + .build()) + .build(); + + @SerialEntry + public boolean showColorPickerIndicator = true; +} diff --git a/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/colorpicker.png b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/colorpicker.png Binary files differnew file mode 100644 index 0000000..1d11f72 --- /dev/null +++ b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/colorpicker.png diff --git a/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/colorpicker.png.mcmeta b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/colorpicker.png.mcmeta new file mode 100644 index 0000000..20d1be9 --- /dev/null +++ b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/colorpicker.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "nine_slice", + "width": 236, + "height": 34, + "border": 3 + } + } +} diff --git a/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/transparent.png b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/transparent.png Binary files differnew file mode 100644 index 0000000..0a803ef --- /dev/null +++ b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/transparent.png diff --git a/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/transparent.png.mcmeta b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/transparent.png.mcmeta new file mode 100644 index 0000000..9d21305 --- /dev/null +++ b/common/src/main/resources/assets/yet_another_config_lib/textures/gui/sprites/controller/transparent.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "tile", + "width": 7, + "height": 7, + "border": 3 + } + } +} diff --git a/src/main/java/dev/isxander/yacl3/gui/AbstractWidget.java b/src/main/java/dev/isxander/yacl3/gui/AbstractWidget.java index 6f92749..1f7c29b 100644 --- a/src/main/java/dev/isxander/yacl3/gui/AbstractWidget.java +++ b/src/main/java/dev/isxander/yacl3/gui/AbstractWidget.java @@ -1,7 +1,8 @@ package dev.isxander.yacl3.gui; +import com.mojang.blaze3d.vertex.VertexConsumer; import dev.isxander.yacl3.api.utils.Dimension; -import dev.isxander.yacl3.gui.utils.ButtonTextureRenderer; +import dev.isxander.yacl3.gui.utils.YACLRenderHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; @@ -9,8 +10,10 @@ import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.sounds.SoundEvents; +import org.joml.Matrix4f; import java.awt.Color; @@ -75,7 +78,7 @@ public abstract class AbstractWidget implements GuiEventListener, Renderable, Na int width = x2 - x1; int height = y2 - y1; - ButtonTextureRenderer.render(graphics, x1, y1, width, height, enabled, hovered); + YACLRenderHelper.renderButtonTexture(graphics, x1, y1, width, height, enabled, hovered); } protected void drawOutline(GuiGraphics graphics, int x1, int y1, int x2, int y2, int width, int color) { @@ -85,6 +88,37 @@ public abstract class AbstractWidget implements GuiEventListener, Renderable, Na graphics.fill(x1, y1, x1 + width, y2, color); } + protected void fillSidewaysGradient(GuiGraphics graphics, int x1, int y1, int x2, int y2, int startColor, int endColor) { + //Fills a gradient, left to right + //Uses practically the same method as the GuiGraphics class, but with the x/y moved + //Has a custom "z" value in case needed for later + VertexConsumer vertex = graphics.bufferSource().getBuffer(RenderType.gui()); + Matrix4f matrix4f = graphics.pose().last().pose(); + vertex.vertex(matrix4f, x1, y1, 0).color(startColor).endVertex(); + vertex.vertex(matrix4f, x1, y2, 0).color(startColor).endVertex(); + vertex.vertex(matrix4f, x2, y2, 0).color(endColor).endVertex(); + vertex.vertex(matrix4f, x2, y1, 0).color(endColor).endVertex(); + } + + + protected void drawRainbowGradient(GuiGraphics graphics, int x1, int y1, int x2, int y2) { + //Draws a rainbow gradient, left to right + int[] colors = new int[] {Color.red.getRGB(), Color.yellow.getRGB(), Color.green.getRGB(), + Color.cyan.getRGB(), Color.blue.getRGB(), Color.magenta.getRGB(), Color.red.getRGB()}; //all the colors in the gradient + int width = x2 - x1; + int maxColors = colors.length - 1; + for (int color = 0; color < maxColors; color++) { + //First checks if the final color is being rendered, if true -> uses x2 int instead of x1 + //if false -> it adds the width divided by the max colors multiplied by the current color plus one to the x1 int + //the x2 int for the fillSidewaysGradient is the same formula, excluding the additional plus one. + //The gradient colors is determined by the color int and the color int plus one, which is why red is in the colors array twice + fillSidewaysGradient(graphics, + x1 + (width / maxColors * color), y1, + color == maxColors - 1 ? x2 : x1 + (width / maxColors * (color + 1)), y2, + colors[color], colors[color + 1]); + } + } + protected int multiplyColor(int hex, float amount) { Color color = new Color(hex, true); diff --git a/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java b/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java index ec70d60..1d3be9f 100644 --- a/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java +++ b/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java @@ -7,19 +7,21 @@ import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.utils.Dimension; import dev.isxander.yacl3.api.utils.MutableDimension; import dev.isxander.yacl3.api.utils.OptionUtils; -import dev.isxander.yacl3.gui.tab.ScrollableNavigationBar; +import dev.isxander.yacl3.gui.controllers.PopupControllerScreen; +import dev.isxander.yacl3.gui.controllers.ControllerPopupWidget; import dev.isxander.yacl3.gui.tab.ListHolderWidget; +import dev.isxander.yacl3.gui.tab.ScrollableNavigationBar; import dev.isxander.yacl3.gui.tab.TabExt; import dev.isxander.yacl3.gui.utils.GuiUtils; import dev.isxander.yacl3.impl.utils.YACLConstants; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineLabel; import net.minecraft.client.gui.components.Tooltip; -import net.minecraft.client.gui.components.tabs.Tab; import net.minecraft.client.gui.components.tabs.TabManager; import net.minecraft.client.gui.components.tabs.TabNavigationBar; import net.minecraft.client.gui.navigation.ScreenRectangle; @@ -34,7 +36,6 @@ import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; public class YACLScreen extends Screen { @@ -52,6 +53,9 @@ public class YACLScreen extends Screen { private boolean pendingChanges; + public ControllerPopupWidget<?> currentPopupController = null; + public boolean popupControllerVisible = false; + public YACLScreen(YetAnotherConfigLib config, Screen parent) { super(config.title()); this.config = config; @@ -87,6 +91,33 @@ public class YACLScreen extends Screen { config.initConsumer().accept(this); } + public void addPopupControllerWidget(ControllerPopupWidget<?> controllerPopupWidget) { + + //Safety check for the color picker + if (currentPopupController != null) { + clearPopupControllerWidget(); + } + + currentPopupController = controllerPopupWidget; + popupControllerVisible = true; + + OptionListWidget optionListWidget = null; + if(this.tabNavigationBar.getTabManager().getCurrentTab() instanceof CategoryTab categoryTab) { + optionListWidget = categoryTab.optionList.getList(); + } + if(optionListWidget != null) { + this.minecraft.setScreen(new PopupControllerScreen(this, controllerPopupWidget)); + } + } + + public void clearPopupControllerWidget() { + if(Minecraft.getInstance().screen instanceof PopupControllerScreen popupControllerScreen) { + popupControllerScreen.onClose(); + } + popupControllerVisible = false; + currentPopupController = null; + } + /*? if <=1.20.4 {*/ @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { diff --git a/src/main/java/dev/isxander/yacl3/gui/controllers/ColorController.java b/src/main/java/dev/isxander/yacl3/gui/controllers/ColorController.java index 56e6d30..3c0a5fc 100644 --- a/src/main/java/dev/isxander/yacl3/gui/controllers/ColorController.java +++ b/src/main/java/dev/isxander/yacl3/gui/controllers/ColorController.java @@ -8,6 +8,7 @@ import dev.isxander.yacl3.gui.AbstractWidget; import dev.isxander.yacl3.gui.YACLScreen; import dev.isxander.yacl3.gui.controllers.string.IStringController; import dev.isxander.yacl3.gui.controllers.string.StringControllerElement; +import dev.isxander.yacl3.platform.YACLConfig; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; @@ -101,10 +102,13 @@ public class ColorController implements IStringController<Color> { public static class ColorControllerElement extends StringControllerElement { private final ColorController colorController; + private ColorPickerWidget colorPickerWidget; protected MutableDimension<Integer> colorPreviewDim; - private final List<Character> allowedChars; + public boolean hoveredOverColorPreview = false; + private boolean colorPickerVisible = false; + private int previewOutlineFadeTicks = 0; public ColorControllerElement(ColorController control, YACLScreen screen, Dimension<Integer> dim) { super(control, screen, dim, true); @@ -114,13 +118,18 @@ public class ColorController implements IStringController<Color> { @Override protected void drawValueText(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + hovered = isMouseOver(mouseX, mouseY); + if (isHovered()) { - colorPreviewDim.move(-inputFieldBounds.width() - 5, 0); + colorPreviewDim.move(-inputFieldBounds.width() - 8, -2); + colorPreviewDim.expand(4, 4); + previewOutlineFadeTicks++; super.drawValueText(graphics, mouseX, mouseY, delta); } graphics.fill(colorPreviewDim.x(), colorPreviewDim.y(), colorPreviewDim.xLimit(), colorPreviewDim.yLimit(), colorController.option().pendingValue().getRGB()); - drawOutline(graphics, colorPreviewDim.x(), colorPreviewDim.y(), colorPreviewDim.xLimit(), colorPreviewDim.yLimit(), 1, 0xFF000000); + Color outlineColor = getPreviewOutlineColor(hoveredOverColorPreview || isMouseOverColorPreview(mouseX, mouseY)); + drawOutline(graphics, colorPreviewDim.x(), colorPreviewDim.y(), colorPreviewDim.xLimit(), colorPreviewDim.yLimit(), 1, outlineColor.getRGB()); } @Override @@ -193,6 +202,14 @@ public class ColorController implements IStringController<Color> { int previewSize = (dim.height() - getYPadding() * 2) / 2; colorPreviewDim = Dimension.ofInt(dim.xLimit() - getXPadding() - previewSize, dim.centerY() - previewSize / 2, previewSize, previewSize); + + if(colorPickerWidget != null) { + colorPickerWidget.setDimension(colorPickerWidget.getDimension().withY(this.getDimension().y())); + //checks if the color controller is being partially rendered offscreen + if(this.getDimension().y() < screen.tabArea.top() || this.getDimension().yLimit() > screen.tabArea.bottom()) { + removeColorPicker(); + } + } } @Override @@ -210,11 +227,121 @@ public class ColorController implements IStringController<Color> { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { + //Detects if the user has clicked the color preview + if(isMouseOverColorPreview(mouseX, mouseY)) { + playDownSound(); + createOrRemoveColorPicker(); + if(YACLConfig.HANDLER.instance().showColorPickerIndicator) { + YACLConfig.HANDLER.instance().showColorPickerIndicator = false; + YACLConfig.HANDLER.save(); + } + } caretPos = Math.max(1, caretPos); setSelectionLength(); return true; } + return false; } + + public boolean isMouseOverColorPreview(double mouseX, double mouseY) { + return colorPreviewDim.isPointInside((int) mouseX, (int) mouseY); + } + + public void createOrRemoveColorPicker() { + colorPickerVisible = !colorPickerVisible; + if(colorPickerVisible) { + colorPickerWidget = createColorPicker(); + screen.addPopupControllerWidget(colorPickerWidget); + } else { + removeColorPicker(); + } + } + + @Override + public void unfocus() { + if(colorPickerVisible) { + removeColorPicker(); + } + previewOutlineFadeTicks = 0; + super.unfocus(); + } + + public Color getPreviewOutlineColor(boolean colorPreviewHovered) { + Color outlineColor = new Color(0xFF000000); + Color highlightedColor = getHighlightedOutlineColor(); + + if(!hovered && !colorPreviewHovered) { + previewOutlineFadeTicks = 0; + return outlineColor; + } + + int fadeInTicks = 80; + int fadeOutTicks = fadeInTicks + 120; + + if(colorPreviewHovered) { + //white/light grey if the color preview is being hovered + previewOutlineFadeTicks = 0; + return highlightedColor; + } else if(YACLConfig.HANDLER.instance().showColorPickerIndicator) { + if(previewOutlineFadeTicks <= fadeInTicks) { + //fade to white + return getFadedColor(outlineColor, highlightedColor, previewOutlineFadeTicks, fadeInTicks); + } else if (previewOutlineFadeTicks <= fadeOutTicks) { + //fade to black + return getFadedColor(highlightedColor, outlineColor, previewOutlineFadeTicks - fadeInTicks, fadeOutTicks - fadeInTicks); + } + + if(previewOutlineFadeTicks >= fadeInTicks + fadeOutTicks + 10) { + //reset fade + previewOutlineFadeTicks = 0; + } + } + + return outlineColor; + } + + private Color getFadedColor(Color original, Color fadeToColor, int fadeTick, int maxFadeTicks) { + int red = fadeToColor.getRed() - original.getRed(); + int green = fadeToColor.getGreen() - original.getGreen(); + int blue = fadeToColor.getBlue() - original.getBlue(); + return new Color( + original.getRed() + ((red * fadeTick) / maxFadeTicks), + original.getGreen() + ((green * fadeTick) / maxFadeTicks), + original.getBlue() + ((blue * fadeTick) / maxFadeTicks) + ); + } + + private Color getHighlightedOutlineColor() { + //Brightness detector in case a developer has their starting color bright + //Makes the outline indicating to a user that the mini color preview can be clicked a light grey rather than white + //For reference, there is about a 10 digit moving room in saturation and light + Color pendingValue = colorController.option().pendingValue(); + float[] HSL = Color.RGBtoHSB(pendingValue.getRed(), pendingValue.getGreen(), pendingValue.getBlue(), null); + Color highlightedColor = new Color(0xFFFFFFFF); + if(HSL[1] < 0.1f && HSL[2] > 0.9f) { + highlightedColor = new Color(0xFFC6C6C6); + } + return highlightedColor; + } + + public ColorPickerWidget colorPickerWidget() { + return colorPickerWidget; + } + + public boolean colorPickerVisible() { + return colorPickerVisible; + } + + public ColorPickerWidget createColorPicker() { + return new ColorPickerWidget(colorController, screen, getDimension(), this); + } + + public void removeColorPicker() { + screen.clearPopupControllerWidget(); + this.colorPickerVisible = false; + this.colorPickerWidget = null; + this.hoveredOverColorPreview = false; //set to false in favor of the manual checking here to be done + } } } diff --git a/src/main/java/dev/isxander/yacl3/gui/controllers/ColorPickerWidget.java b/src/main/java/dev/isxander/yacl3/gui/controllers/ColorPickerWidget.java new file mode 100644 index 0000000..c7664dc --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/gui/controllers/ColorPickerWidget.java @@ -0,0 +1,459 @@ +package dev.isxander.yacl3.gui.controllers; + +import dev.isxander.yacl3.api.utils.Dimension; +import dev.isxander.yacl3.api.utils.MutableDimension; +import dev.isxander.yacl3.gui.YACLScreen; +import dev.isxander.yacl3.gui.utils.YACLRenderHelper; +import dev.isxander.yacl3.platform.YACLPlatform; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +import java.awt.*; + +public class ColorPickerWidget extends ControllerPopupWidget<ColorController> { + /*? if >1.20.1 {*/ + private static final ResourceLocation COLOR_PICKER_LOCATION = YACLPlatform.rl("controller/colorpicker"); + private static final ResourceLocation TRANSPARENT_TEXTURE_LOCATION = YACLPlatform.rl("controller/transparent"); + /*? } else {*//* + // nineslice and repeating only work on a 256x atlas + private static final ResourceLocation COLOR_PICKER_ATLAS = YACLPlatform.rl("textures/gui/colorpicker-atlas.png"); + *//*?}*/ + + private final ColorController controller; + private final ColorController.ColorControllerElement entryWidget; + protected MutableDimension<Integer> colorPickerDim; + protected MutableDimension<Integer> previewColorDim; + protected MutableDimension<Integer> saturationLightDim; + protected MutableDimension<Integer> hueGradientDim; + protected MutableDimension<Integer> alphaGradientDim; + private boolean mouseDown; + private boolean hueSliderDown; + private boolean satLightGradientDown; + private boolean alphaSliderDown; + private int hueThumbX; + private int satLightThumbX; + private int alphaThumbX; + private boolean charTyped; + + //The width of the outline between each color picker element(color preview, saturation/light gradient, hue gradient) + //Note: Additional space may need to be manually made upon increasing the outline + private final int outline = 1; + + //The main color preview's portion of the color picker as a whole + //example: if previewPortion is set to 7, then the color preview will take up + //a 7th of the color picker's width + private final int previewPortion = 7; + + //The height in pixels of the hue slider + //example: if the sliderHeight is set to 7, then the hue slider will be 7 pixels, with some extra padding between + //the color preview and the HSL gradient to allow for an outline(determined by the "outline" int) + private final int sliderHeight = 7; + + //The x padding between the color preview and saturation/light gradient. + //Does NOT account for the outline on its own + private final int paddingX = 1; + + //The y padding between the hue gradient and color preview & saturation/light gradient. + //Does NOT account for the outline on its own + private final int paddingY = 3; + + + private float[] HSL; + private float hue; + private float saturation; + private float light; + private int alpha; + + public ColorPickerWidget(ColorController control, YACLScreen screen, Dimension<Integer> dim, ColorController.ColorControllerElement entryWidget) { + super(control, screen, dim, entryWidget); + this.controller = control; + this.entryWidget = entryWidget; + + setDimension(dim); + + updateHSL(); + setThumbX(); + } + + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + updateHSL(); + + int thumbWidth = 4; + int thumbHeight = 4; + + graphics.pose().pushPose(); + graphics.pose().translate(0, 0, 10); // render over text + + //Background + /*? if >1.20.3 { */ + graphics.blitSprite(COLOR_PICKER_LOCATION, colorPickerDim.x() - 5, colorPickerDim.y() - 5, 1, colorPickerDim.width() + 10, colorPickerDim.height() + 10); + /*? } else {*//* + graphics.blitNineSliced(COLOR_PICKER_ATLAS, colorPickerDim.x() - 5, colorPickerDim.y() - 5, colorPickerDim.width() + 10, colorPickerDim.height() + 10, 3, 236, 34, 0, 0); + *//*?}*/ + + //Main color preview + //outline + graphics.fill(previewColorDim.x() - outline, previewColorDim.y() - outline, previewColorDim.xLimit() + outline, previewColorDim.yLimit() + outline, Color.black.getRGB()); + //transparent texture - must be rendered BEFORE the main color preview + if(controller.allowAlpha()) { + /*? if >1.20.3 { */ + graphics.blitSprite(TRANSPARENT_TEXTURE_LOCATION, previewColorDim.x(), previewColorDim.y(), 3, previewColorDim.width(), previewColorDim.height()); + /*? } else {*//* + graphics.blitRepeating(COLOR_PICKER_ATLAS, previewColorDim.x(), previewColorDim.y(), previewColorDim.width(), previewColorDim.height(), 236, 0, 8, 8); + *//*?}*/ + } + //main color preview + graphics.fill(previewColorDim.x(), previewColorDim.y(), previewColorDim.xLimit(), previewColorDim.yLimit(), controller.option().pendingValue().getRGB()); + + //Saturation/light gradient + //outline + graphics.fill(saturationLightDim.x() - outline, saturationLightDim.y() - outline, saturationLightDim.xLimit() + outline, saturationLightDim.yLimit() + outline, Color.black.getRGB()); + //White to pending color's RGB from hue, left to right + fillSidewaysGradient(graphics, saturationLightDim.x(), saturationLightDim.y(), saturationLightDim.xLimit(), saturationLightDim.yLimit(), 0xFFFFFFFF, (int) getRgbFromHueX()); + //Transparent to black, top to bottom + graphics.fillGradient(saturationLightDim.x(), saturationLightDim.y(), saturationLightDim.xLimit(), saturationLightDim.yLimit(), 0x00000000, 0xFF000000); + //Sat/light thumb shadow + graphics.fill(satLightThumbX - thumbWidth / 2 - 2, getSatLightThumbY() + thumbHeight / 2 + 2, satLightThumbX + thumbWidth / 2 + 1, getSatLightThumbY() - thumbHeight / 2 - 1, 0xFF404040); + //Sat/light thumb - extra 1 pixel on left and top to make it centered + graphics.fill(satLightThumbX - thumbWidth / 2 - 1, getSatLightThumbY() + thumbHeight / 2 + 1, satLightThumbX + thumbWidth / 2, getSatLightThumbY() - thumbHeight / 2, -1); + + //Hue gradient + //outline + graphics.fill(hueGradientDim.x() - outline, hueGradientDim.y() - outline, hueGradientDim.xLimit() + outline, hueGradientDim.yLimit() + outline, Color.black.getRGB()); + //Hue rainbow gradient + drawRainbowGradient(graphics, hueGradientDim.x(), hueGradientDim.y(), hueGradientDim.xLimit(), hueGradientDim.yLimit()); + //Hue slider thumb shadow + graphics.fill(hueThumbX - thumbWidth / 2 - 1, hueGradientDim.y() - outline - 1, hueThumbX + thumbWidth / 2 + 1, hueGradientDim.yLimit() + outline + 1, 0xFF404040); + //Hue slider thumb + graphics.fill(hueThumbX - thumbWidth / 2, hueGradientDim.y() - outline, hueThumbX + thumbWidth / 2, hueGradientDim.yLimit() + outline, -1); + + if(controller.allowAlpha()) { + //outline + graphics.fill(alphaGradientDim.x() - outline, alphaGradientDim.y() - outline, alphaGradientDim.xLimit() + outline, alphaGradientDim.yLimit() + outline, Color.black.getRGB()); + //Transparent texture + /*? if >1.20.3 { */ + graphics.blitSprite(TRANSPARENT_TEXTURE_LOCATION, alphaGradientDim.x(), alphaGradientDim.y(), 3, alphaGradientDim.width(), sliderHeight); + /*? } else {*//* + graphics.blitRepeating(COLOR_PICKER_ATLAS, alphaGradientDim.x(), alphaGradientDim.y(), alphaGradientDim.width(), sliderHeight, 236, 0, 8, 8); + *//*?}*/ + //Pending color to transparent + fillSidewaysGradient(graphics, alphaGradientDim.x(), alphaGradientDim.y(), alphaGradientDim.xLimit(), alphaGradientDim.yLimit(), getRgbWithoutAlpha(), 0x00000000); + //Alpha slider thumb shadow + graphics.fill(alphaThumbX - thumbWidth / 2 - 1, alphaGradientDim.y() - outline - 1, alphaThumbX + thumbWidth / 2 + 1, alphaGradientDim.yLimit() + outline + 1, 0xFF404040); + //Alpha slider thumb + graphics.fill(alphaThumbX - thumbWidth / 2, alphaGradientDim.y() - outline, alphaThumbX + thumbWidth / 2, alphaGradientDim.yLimit() + outline, -1); + } + + //graphics.blitRepeating(COLOR_PICKER_ATLAS, colorPickerDim.x(), colorPickerDim.y(), colorPickerDim.width(), colorPickerDim.height(), 237, 0, 4, 4); + + graphics.pose().popPose(); + } + + public boolean clickedHueSlider(double mouseX, double mouseY) { + if (satLightGradientDown || alphaSliderDown) return false; + + if (mouseY >= hueGradientDim.y() && mouseY <= hueGradientDim.yLimit()) { + if (mouseX >= hueGradientDim.x() && mouseX <= hueGradientDim.xLimit()) { + hueSliderDown = true; + } + } + + if (hueSliderDown) { + hueThumbX = (int) Mth.clamp(mouseX, hueGradientDim.x(), hueGradientDim.xLimit()); + } + + return hueSliderDown; + } + + public boolean clickedSatLightGradient(double mouseX, double mouseY) { + if (hueSliderDown || alphaSliderDown) return false; + + if (mouseX >= saturationLightDim.x() && mouseX <= saturationLightDim.xLimit()) { + if (mouseY >= saturationLightDim.y() && mouseY <= saturationLightDim.yLimit()) { + satLightGradientDown = true; + } + } + + if(satLightGradientDown) { + satLightThumbX = (int) Mth.clamp(mouseX, saturationLightDim.x(), saturationLightDim.xLimit()); + } + + return satLightGradientDown; + } + + public boolean clickedAlphaSlider(double mouseX, double mouseY) { + if (satLightGradientDown || hueSliderDown) return false; + + if (mouseX >= alphaGradientDim.x() && mouseX <= alphaGradientDim.xLimit()) { + if (mouseY >= alphaGradientDim.y() && mouseY <= alphaGradientDim.yLimit()) { + alphaSliderDown = true; + } + } + + if (alphaSliderDown) { + alphaThumbX = (int) Mth.clamp(mouseX, alphaGradientDim.x(), alphaGradientDim.xLimit()); + } + + return alphaSliderDown; + } + + public void setColorFromMouseClick(double mouseX, double mouseY) { + if (clickedSatLightGradient(mouseX, mouseY)) { + setSatLightFromMouse(mouseX, mouseY); + } else if (clickedHueSlider(mouseX, mouseY)) { + setHueFromMouse(mouseX); + } else if (controller.allowAlpha() && clickedAlphaSlider(mouseX, mouseY)) { + setAlphaFromMouse(mouseX); + } + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (isMouseOver(mouseX, mouseY)) { + mouseDown = true; + hueSliderDown = false; + satLightGradientDown = false; + alphaSliderDown = false; + setColorFromMouseClick(mouseX, mouseY); + return true; + } else if (entryWidget.isMouseOver(mouseX, mouseY)) { + return entryWidget.mouseClicked(mouseX, mouseY, button); + } else { + close(); //removes color picker + return false; + } + } + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + mouseDown = false; + return false; + } + @Override + public boolean isMouseOver(double mouseX, double mouseY) { + //Checks if the mouse is either over the color picker or the color controller + //The addition/subtraction of the outline and extra 3 pixels is to account for both the outline and the background + if (mouseX >= colorPickerDim.x() - outline - 3 && mouseX <= colorPickerDim.xLimit() + outline + 3 + && mouseY >= colorPickerDim.y() - outline - 3 && mouseY <= colorPickerDim.yLimit() + outline + 3) { + return true; + } + return false; + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (mouseDown || isMouseOver(mouseX, mouseY)) { + setColorFromMouseClick(mouseX, mouseY); + return true; + } + return entryWidget.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + @Override + public boolean charTyped(char chr, int modifiers) { + //Done to allow for typing whilst the color picker is visible + charTyped = true; + return entryWidget.charTyped(chr, modifiers); + } + + @Override + public void setDimension(Dimension<Integer> dim) { + super.setDimension(dim); + + int colorPickerHeight = (dim.height() * 2) + 7; + int colorPickerX = dim.centerX() - getXPadding() * 2; + int colorPickerY = dim.y() - colorPickerHeight - sliderHeight; + int alphaSliderHeight = 0; + if (controller.allowAlpha()) { + alphaSliderHeight = sliderHeight + outline + paddingY; + colorPickerHeight += alphaSliderHeight; + colorPickerY -= alphaSliderHeight; + } + + //Check if the color picker should be moved to beneath the controller + //Add additional numbers after colorPickerY to reduce the "strictness" of this detection + if (colorPickerY < screen.tabArea.top()) { + colorPickerY = dim.yLimit() + sliderHeight; + } + + //A single dimension for the entire color picker as a whole + //Division is used for the main color preview, saturation/light picker, and hue slider to determine their dimensions + colorPickerDim = Dimension.ofInt(colorPickerX, colorPickerY, dim.xLimit() - colorPickerX, colorPickerHeight); + + previewColorDim = Dimension.ofInt(colorPickerDim.x(), colorPickerDim.y(), (colorPickerDim.x() + (colorPickerDim.xLimit() / previewPortion) - paddingX) - colorPickerDim.x(), (colorPickerDim.yLimit() - sliderHeight - paddingY) - colorPickerDim.y() - alphaSliderHeight); + saturationLightDim = Dimension.ofInt(colorPickerDim.x() + (colorPickerDim.xLimit() / previewPortion) + paddingX + 1, colorPickerDim.y(), colorPickerDim.xLimit() - (colorPickerDim.x() + (colorPickerDim.xLimit() / previewPortion) + paddingX + 1), (colorPickerDim.yLimit() - sliderHeight - paddingY) - colorPickerDim.y() - alphaSliderHeight); + hueGradientDim = Dimension.ofInt(colorPickerDim.x(), colorPickerDim.yLimit() - sliderHeight - alphaSliderHeight, colorPickerDim.width(), sliderHeight); + if (controller.allowAlpha()) { + alphaGradientDim = Dimension.ofInt(hueGradientDim.x(), hueGradientDim.y() + alphaSliderHeight, hueGradientDim.width(), sliderHeight); + } + } + + @Override + public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + entryWidget.hoveredOverColorPreview = entryWidget.isMouseOverColorPreview(mouseX, mouseY); + } + + @Override + public void close() { + entryWidget.removeColorPicker(); + } + + @Override + public Component popupTitle() { + return Component.translatable("yacl.control.color.color_picker_title"); + } + + public void setThumbX() { + //Sets the thumb x for both hue and sat/light + hueThumbX = getHueThumbX(); + satLightThumbX = getSatLightThumbX(); + if (controller.allowAlpha()) { + alphaThumbX = getAlphaThumbX(); + } + } + + protected int getHueThumbX() { + int min = hueGradientDim.x(); + int max = hueGradientDim.xLimit(); + int value = (int) (min + hueGradientDim.width() * this.hue); + + return Mth.clamp(value, min, max); + } + + protected int getSatLightThumbX() { + int min = saturationLightDim.x(); + int max = saturationLightDim.xLimit(); + int value = (int) (min + (saturationLightDim.width() * this.saturation)); + + return Mth.clamp(value, min, max); + } + + protected int getSatLightThumbY() { + int min = saturationLightDim.y(); + int max = saturationLightDim.yLimit(); + int value = (int) (min + (saturationLightDim.height() * (1.0f - this.light))); + + return Mth.clamp(value, min, max); + } + + protected int getAlphaThumbX() { + int min = alphaGradientDim.x(); + int max = alphaGradientDim.xLimit(); + int value = max - (alphaGradientDim.width() * this.alpha / 255); + + return Mth.clamp(value, min, max); + } + + public void setHueFromMouse(double mouseX) { + //Changes the hue of the pending color based on the mouseX's pos. + //relative to the colorPickerDim's x/xLimit + if(mouseX < hueGradientDim.x()) { + this.hue = 0f; + } else if (mouseX > hueGradientDim.xLimit()) { + this.hue = 1f; + } else { + float newHue = (float) (mouseX - hueGradientDim.x()) / hueGradientDim.width(); + + this.hue = Mth.clamp(newHue, 0f, 1f); + } + + setColorControllerFromHSL(); + } + + public void setSatLightFromMouse(double mouseX, double mouseY) { + if(mouseX < saturationLightDim.x()) { + this.saturation = 0f; + } else if (mouseX > saturationLightDim.xLimit()) { + this.saturation = 1f; + } else { + float newSat = (float) (mouseX - saturationLightDim.x()) / saturationLightDim.width(); + + this.saturation = Mth.clamp(newSat, 0f, 1.0f); + } + + if(mouseY < saturationLightDim.y()) { + this.light = 1f; + } else if (mouseY > saturationLightDim.yLimit()) { + this.light = 0f; + } else { + float newLight = (float) (mouseY - saturationLightDim.y()) / saturationLightDim.height(); + + this.light = Mth.clamp(1f - newLight, 0f, 1.0f); + } + + setColorControllerFromHSL(); + } + + public void setAlphaFromMouse(double mouseX) { + //Changes the alpha of the pending color based on the mouseX's pos. + if(mouseX < alphaGradientDim.x()) { + this.alpha = 255; + } else if (mouseX > alphaGradientDim.xLimit()) { + this.alpha = 0; + } else { + int newAlpha = (int) ((mouseX - alphaGradientDim.xLimit()) / alphaGradientDim.width() * -255); + + this.alpha = Mth.clamp(newAlpha, 0, 255); + } + + setColorControllerFromHSL(); + } + + public void setColorControllerFromHSL() { + //Updates the current color controller's pending value based from HSL to RGB + float trueHue = (float) (hueThumbX - colorPickerDim.x()) / colorPickerDim.width(); + Color color = Color.getHSBColor(trueHue, saturation, light); + Color returnColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); + controller.option().requestSet(returnColor); + } + + protected void updateHSL() { + this.HSL = getHSL(); + this.hue = hue(); + this.saturation = saturation(); + this.light = light(); + this.alpha = getAlpha(); + if(charTyped) { + setThumbX(); + charTyped = false; + } + } + + protected float[] getHSL() { + Color pendingValue = controller.option().pendingValue(); + return Color.RGBtoHSB(pendingValue.getRed(), pendingValue.getGreen(), pendingValue.getBlue(), null); + } + + protected float hue() { + //Gets the hue of the pending value + return HSL[0]; + } + + protected float saturation() { + //Gets the saturation of the pending value + return HSL[1]; + } + + protected float light() { + //Gets the light/brightness/value(has a few different names, all refer to the same thing) of the pending value + return HSL[2]; + } + + protected int getAlpha() { + return controller.option().pendingValue().getAlpha(); + } + + protected float getRgbFromHueX() { + float trueHue = (float) (hueThumbX - colorPickerDim.x()) / colorPickerDim.width(); + + return Color.HSBtoRGB(trueHue, 1, 1); + } + + protected int getRgbWithoutAlpha() { + Color pendingColor = controller.option().pendingValue(); + Color returnColor = new Color(pendingColor.getRed(), pendingColor.getGreen(), pendingColor.getBlue(), 255); + return returnColor.getRGB(); + } +} diff --git a/src/main/java/dev/isxander/yacl3/gui/controllers/ControllerPopupWidget.java b/src/main/java/dev/isxander/yacl3/gui/controllers/ControllerPopupWidget.java new file mode 100644 index 0000000..e2f19bc --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/gui/controllers/ControllerPopupWidget.java @@ -0,0 +1,39 @@ +package dev.isxander.yacl3.gui.controllers; + +import dev.isxander.yacl3.api.Controller; +import dev.isxander.yacl3.api.utils.Dimension; +import dev.isxander.yacl3.gui.YACLScreen; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.network.chat.Component; + +public abstract class ControllerPopupWidget<T extends Controller<?>> extends ControllerWidget<Controller<?>> implements GuiEventListener { + public final ControllerWidget<?> entryWidget; + public ControllerPopupWidget(T control, YACLScreen screen, Dimension<Integer> dim, ControllerWidget<?> entryWidget) { + super(control, screen, dim); + this.entryWidget = entryWidget; + } + + public ControllerWidget<?> entryWidget() { + return entryWidget; + } + + public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {} + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + return entryWidget.keyPressed(keyCode, scanCode, modifiers); + } + + public void close() {} + + public Component popupTitle() { + return Component.translatable("yacl.control.text.blank"); + } + + @Override + protected int getHoveredControlWidth() { + return 0; + } + +} diff --git a/src/main/java/dev/isxander/yacl3/gui/controllers/PopupControllerScreen.java b/src/main/java/dev/isxander/yacl3/gui/controllers/PopupControllerScreen.java new file mode 100644 index 0000000..f6a5db3 --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/gui/controllers/PopupControllerScreen.java @@ -0,0 +1,70 @@ +package dev.isxander.yacl3.gui.controllers; + +import dev.isxander.yacl3.gui.YACLScreen; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.Screen; + +public class PopupControllerScreen extends Screen { + private final YACLScreen backgroundYaclScreen; + private final ControllerPopupWidget<?> controllerPopup; + public PopupControllerScreen(YACLScreen backgroundYaclScreen, ControllerPopupWidget<?> controllerPopup) { + super(controllerPopup.popupTitle()); //Gets narrated by the narrator + this.backgroundYaclScreen = backgroundYaclScreen; + this.controllerPopup = controllerPopup; + } + + + @Override + protected void init() { + this.addRenderableWidget(this.controllerPopup); + } + + @Override + public void resize(Minecraft minecraft, int width, int height) { + minecraft.setScreen(backgroundYaclScreen); + } + + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + controllerPopup.renderBackground(graphics, mouseX, mouseY, delta); + this.backgroundYaclScreen.render(graphics, -1, -1, delta); //mouseX/Y set to -1 to prevent hovering outlines + + super.render(graphics, mouseX, mouseY, delta); + } + + @Override + public void renderBackground( + GuiGraphics guiGraphics + /*? if >1.20.1 {*/, + int mouseX, + int mouseY, + float partialTick + /*?}*/ + ) { + + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, /*? if >1.20.1 {*/ double scrollX, /*?}*/ double scrollY) { + backgroundYaclScreen.mouseScrolled(mouseX, mouseY, /*? if >1.20.1 {*/ scrollX, /*?}*/ scrollY); //mouseX & mouseY are needed here + return super.mouseScrolled(mouseX, mouseY, /*? if >1.20.1 {*/ scrollX, /*?}*/ scrollY); + } + + @Override + public boolean charTyped(char codePoint, int modifiers) { + return controllerPopup.charTyped(codePoint, modifiers); + } + + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + return controllerPopup.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + public void onClose() { + this.minecraft.screen = backgroundYaclScreen; + } + +} diff --git a/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java b/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java index b6524a7..1852d98 100644 --- a/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java +++ b/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java @@ -1,6 +1,7 @@ package dev.isxander.yacl3.gui.image; import dev.isxander.yacl3.impl.utils.YACLConstants; +import dev.isxander.yacl3.platform.YACLPlatform; import net.minecraft.CrashReport; import net.minecraft.CrashReportCategory; import net.minecraft.ReportedException; @@ -104,7 +105,7 @@ public class YACLImageReloadListener /*? if fabric {*/ @Override public ResourceLocation getFabricId() { - return new ResourceLocation("yet_another_config_lib_v3", "image_reload_listener"); + return YACLPlatform.rl("image_reload_listener"); } /*?}*/ } diff --git a/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java b/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java index f458557..61c07c7 100644 --- a/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java +++ b/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java @@ -30,7 +30,7 @@ public class ScrollableNavigationBar extends TabNavigationBar { this.accessor = (TabNavigationBarAccessor) this; // add tab tooltips to the tab buttons - for (TabButton tabButton : accessor.getTabButtons()) { + for (TabButton tabButton : accessor.yacl$getTabButtons()) { if (tabButton.tab() instanceof TabExt tab) { tabButton.setTooltip(tab.getTooltip()); } @@ -39,8 +39,8 @@ public class ScrollableNavigationBar extends TabNavigationBar { @Override public void arrangeElements() { - ImmutableList<TabButton> tabButtons = accessor.getTabButtons(); - int noScrollWidth = accessor.getWidth() - NAVBAR_MARGIN*2; + ImmutableList<TabButton> tabButtons = accessor.yacl$getTabButtons(); + int noScrollWidth = accessor.yacl$getWidth() - NAVBAR_MARGIN*2; int allTabsWidth = 0; // first pass: set the width of each tab button @@ -63,12 +63,12 @@ public class ScrollableNavigationBar extends TabNavigationBar { allTabsWidth = noScrollWidth; } - Layout layout = ((TabNavigationBarAccessor) this).getLayout(); + Layout layout = ((TabNavigationBarAccessor) this).yacl$getLayout(); layout.arrangeElements(); layout.setY(0); scrollOffset = 0; - layout.setX(Math.max((accessor.getWidth() - allTabsWidth) / 2, NAVBAR_MARGIN)); + layout.setX(Math.max((accessor.yacl$getWidth() - allTabsWidth) / 2, NAVBAR_MARGIN)); this.maxScrollOffset = Math.max(0, allTabsWidth - noScrollWidth); } @@ -95,7 +95,7 @@ public class ScrollableNavigationBar extends TabNavigationBar { } public void setScrollOffset(int scrollOffset) { - Layout layout = ((TabNavigationBarAccessor) this).getLayout(); + Layout layout = ((TabNavigationBarAccessor) this).yacl$getLayout(); layout.setX(layout.getX() + this.scrollOffset); this.scrollOffset = Mth.clamp(scrollOffset, 0, maxScrollOffset); @@ -117,12 +117,16 @@ public class ScrollableNavigationBar extends TabNavigationBar { protected void ensureVisible(TabButton tabButton) { if (tabButton.getX() < NAVBAR_MARGIN) { this.setScrollOffset(this.scrollOffset - (NAVBAR_MARGIN - tabButton.getX())); - } else if (tabButton.getX() + tabButton.getWidth() > accessor.getWidth() - NAVBAR_MARGIN) { - this.setScrollOffset(this.scrollOffset + (tabButton.getX() + tabButton.getWidth() - (accessor.getWidth() - NAVBAR_MARGIN))); + } else if (tabButton.getX() + tabButton.getWidth() > accessor.yacl$getWidth() - NAVBAR_MARGIN) { + this.setScrollOffset(this.scrollOffset + (tabButton.getX() + tabButton.getWidth() - (accessor.yacl$getWidth() - NAVBAR_MARGIN))); } } public ImmutableList<Tab> getTabs() { - return accessor.getTabs(); + return accessor.yacl$getTabs(); + } + + public TabManager getTabManager() { + return accessor.yacl$getTabManager(); } } diff --git a/src/main/java/dev/isxander/yacl3/gui/utils/ButtonTextureRenderer.java b/src/main/java/dev/isxander/yacl3/gui/utils/YACLRenderHelper.java index aa52a3f..b49557b 100644 --- a/src/main/java/dev/isxander/yacl3/gui/utils/ButtonTextureRenderer.java +++ b/src/main/java/dev/isxander/yacl3/gui/utils/YACLRenderHelper.java @@ -1,10 +1,11 @@ package dev.isxander.yacl3.gui.utils; import com.mojang.blaze3d.systems.RenderSystem; +import dev.isxander.yacl3.platform.YACLPlatform; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.resources.ResourceLocation; -public class ButtonTextureRenderer { +public class YACLRenderHelper { /*? if >1.20.1 {*/ private static final net.minecraft.client.gui.components.WidgetSprites SPRITES = new net.minecraft.client.gui.components.WidgetSprites( new ResourceLocation("widget/button"), // normal @@ -16,7 +17,7 @@ public class ButtonTextureRenderer { private static final ResourceLocation SLIDER_LOCATION = new ResourceLocation("textures/gui/slider.png"); *//*?}*/ - public static void render(GuiGraphics graphics, int x, int y, int width, int height, boolean enabled, boolean focused) { + public static void renderButtonTexture(GuiGraphics graphics, int x, int y, int width, int height, boolean enabled, boolean focused) { /*? if >1.20.1 {*/ graphics.blitSprite(SPRITES.get(enabled, focused), x, y, width, height); /*?} else {*//* @@ -31,4 +32,12 @@ public class ButtonTextureRenderer { graphics.blitNineSliced(SLIDER_LOCATION, x, y, width, height, 20, 4, 200, 20, 0, textureV); *//*?}*/ } + + public static ResourceLocation getSpriteLocation(String path) { + /*? if >1.20.3 {*/ + return YACLPlatform.rl(path); + /*? } else {*//* + return YACLPlatform.rl("textures/gui/sprites/" + path + ".png"); + *//*?}*/ + } } diff --git a/src/main/java/dev/isxander/yacl3/mixin/TabNavigationBarAccessor.java b/src/main/java/dev/isxander/yacl3/mixin/TabNavigationBarAccessor.java index f0da81d..8850390 100644 --- a/src/main/java/dev/isxander/yacl3/mixin/TabNavigationBarAccessor.java +++ b/src/main/java/dev/isxander/yacl3/mixin/TabNavigationBarAccessor.java @@ -7,28 +7,27 @@ import net.minecraft.client.gui.components.tabs.TabManager; import net.minecraft.client.gui.components.tabs.TabNavigationBar; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(TabNavigationBar.class) public interface TabNavigationBarAccessor { /*? if >1.20.4 {*//* - @Accessor - net.minecraft.client.gui.layouts.LinearLayout getLayout(); + @Accessor("layout") + net.minecraft.client.gui.layouts.LinearLayout yacl$getLayout(); *//*? } else {*/ - @Accessor - net.minecraft.client.gui.layouts.GridLayout getLayout(); + @Accessor("layout") + net.minecraft.client.gui.layouts.GridLayout yacl$getLayout(); /*?}*/ - @Accessor - int getWidth(); + @Accessor("width") + int yacl$getWidth(); - @Accessor - TabManager getTabManager(); + @Accessor("tabManager") + TabManager yacl$getTabManager(); - @Accessor - ImmutableList<Tab> getTabs(); + @Accessor("tabs") + ImmutableList<Tab> yacl$getTabs(); - @Accessor - ImmutableList<TabButton> getTabButtons(); + @Accessor("tabButtons") + ImmutableList<TabButton> yacl$getTabButtons(); } diff --git a/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java b/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java new file mode 100644 index 0000000..0d14b41 --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java @@ -0,0 +1,18 @@ +package dev.isxander.yacl3.platform; + +import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; +import dev.isxander.yacl3.config.v2.api.SerialEntry; +import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; + +public class YACLConfig { + public static final ConfigClassHandler<YACLConfig> HANDLER = ConfigClassHandler.createBuilder(YACLConfig.class) + .id(YACLPlatform.rl("config")) + .serializer(config -> GsonConfigSerializerBuilder.create(config) + .setPath(YACLPlatform.getConfigDir().resolve("yacl.json5")) + .setJson5(true) + .build()) + .build(); + + @SerialEntry + public boolean showColorPickerIndicator = true; +} diff --git a/src/main/java/dev/isxander/yacl3/platform/YACLPlatform.java b/src/main/java/dev/isxander/yacl3/platform/YACLPlatform.java index d134e70..0a4fc04 100644 --- a/src/main/java/dev/isxander/yacl3/platform/YACLPlatform.java +++ b/src/main/java/dev/isxander/yacl3/platform/YACLPlatform.java @@ -2,6 +2,7 @@ package dev.isxander.yacl3.platform; /*?if fabric {*/ import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.resources.ResourceLocation; /*?} elif neoforge {*//* import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLPaths; @@ -13,6 +14,10 @@ import net.minecraftforge.fml.loading.FMLPaths; import java.nio.file.Path; public final class YACLPlatform { + public static ResourceLocation rl(String path) { + return new ResourceLocation("yet_another_config_lib_v3", path); + } + public static Env getEnvironment() { /*?if fabric {*/ return switch (FabricLoader.getInstance().getEnvironmentType()) { diff --git a/src/main/resources/assets/yet_another_config_lib/lang/be_by.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/be_by.json index 16f84f0..16f84f0 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/be_by.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/be_by.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/el_gr.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/el_gr.json index b7bc2d2..b7bc2d2 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/el_gr.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/el_gr.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/en_us.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/en_us.json index c04d29e..6556648 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/en_us.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/en_us.json @@ -4,6 +4,8 @@ "yacl.control.action.execute": "EXECUTE", + "yacl.control.color.color_picker_title": "Color Picker", + "yacl.control.text.blank": "<blank>", "yacl.gui.save": "Save Changes", @@ -28,4 +30,5 @@ "yacl.restart.message": "One or more options needs you to restart the game to apply the changes.", "yacl.restart.yes": "Close Minecraft", "yacl.restart.no": "Ignore" + } diff --git a/src/main/resources/assets/yet_another_config_lib/lang/et_ee.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/et_ee.json index 5f5274a..5f5274a 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/et_ee.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/et_ee.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/fr_fr.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/fr_fr.json index bc069cf..bc069cf 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/fr_fr.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/fr_fr.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/it_it.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/it_it.json index 1489071..1489071 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/it_it.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/it_it.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/nl_nl.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/nl_nl.json index c432cda..c432cda 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/nl_nl.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/nl_nl.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/pl_pl.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/pl_pl.json index 49074ea..49074ea 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/pl_pl.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/pl_pl.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/pt_br.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/pt_br.json index 9d4ef8d..9d4ef8d 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/pt_br.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/pt_br.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/ru_ru.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/ru_ru.json index 5725d34..5725d34 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/ru_ru.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/ru_ru.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/sl_si.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/sl_si.json index 743dd4d..743dd4d 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/sl_si.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/sl_si.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/tt_ru.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/tt_ru.json index 06d005a..06d005a 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/tt_ru.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/tt_ru.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/zh_cn.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/zh_cn.json index 9307c9b..9307c9b 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/zh_cn.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/zh_cn.json diff --git a/src/main/resources/assets/yet_another_config_lib/lang/zh_tw.json b/src/main/resources/assets/yet_another_config_lib_v3/lang/zh_tw.json index 0ac792f..0ac792f 100644 --- a/src/main/resources/assets/yet_another_config_lib/lang/zh_tw.json +++ b/src/main/resources/assets/yet_another_config_lib_v3/lang/zh_tw.json diff --git a/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/colorpicker-atlas.png b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/colorpicker-atlas.png Binary files differnew file mode 100644 index 0000000..2a47705 --- /dev/null +++ b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/colorpicker-atlas.png diff --git a/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/colorpicker.png b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/colorpicker.png Binary files differnew file mode 100644 index 0000000..1d11f72 --- /dev/null +++ b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/colorpicker.png diff --git a/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/colorpicker.png.mcmeta b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/colorpicker.png.mcmeta new file mode 100644 index 0000000..20d1be9 --- /dev/null +++ b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/colorpicker.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "nine_slice", + "width": 236, + "height": 34, + "border": 3 + } + } +} diff --git a/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/transparent.png b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/transparent.png Binary files differnew file mode 100644 index 0000000..0a803ef --- /dev/null +++ b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/transparent.png diff --git a/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/transparent.png.mcmeta b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/transparent.png.mcmeta new file mode 100644 index 0000000..9d21305 --- /dev/null +++ b/src/main/resources/assets/yet_another_config_lib_v3/textures/gui/sprites/controller/transparent.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "tile", + "width": 7, + "height": 7, + "border": 3 + } + } +} diff --git a/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java b/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java index b3b49b6..9bb361e 100644 --- a/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java +++ b/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java @@ -24,7 +24,7 @@ import java.util.List; public class AutogenConfigTest { public static final ConfigClassHandler<AutogenConfigTest> INSTANCE = ConfigClassHandler.createBuilder(AutogenConfigTest.class) - .id(new ResourceLocation("yacl3", "config")) + .id(new ResourceLocation("yacl3-test", "config")) .serializer(config -> GsonConfigSerializerBuilder.create(config) .setPath(YACLPlatform.getConfigDir().resolve("yacl-test-v2.json5")) .setJson5(true) diff --git a/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java b/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java index a8f49b0..72c4454 100644 --- a/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java +++ b/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java @@ -37,6 +37,16 @@ public class ConfigTest { @SerialEntry public Color colorOption = Color.red; @SerialEntry + public Color topColorOption = Color.blue; + @SerialEntry + public Color alphaColorOption = Color.green; + @SerialEntry + public Color buttonColorOption = new Color(0, 255, 255); + @SerialEntry + public Color alternativePreviewOutline = Color.white; + @SerialEntry + public Color anotherAlphaColorOption = new Color(3, 24, 255, 158); + @SerialEntry public double doubleField = 0.5; @SerialEntry public float floatField = 0.5f; diff --git a/src/testmod/java/dev/isxander/yacl3/test/GuiTest.java b/src/testmod/java/dev/isxander/yacl3/test/GuiTest.java index 473b04a..34ae06a 100644 --- a/src/testmod/java/dev/isxander/yacl3/test/GuiTest.java +++ b/src/testmod/java/dev/isxander/yacl3/test/GuiTest.java @@ -83,7 +83,7 @@ public class GuiTest { .append(Component.literal("e").withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal("e"))))) .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://isxander.dev"))) ) - .webpImage(new ResourceLocation("yacl3", "reach-around-placement.webp")) + .webpImage(new ResourceLocation("yacl3-test", "reach-around-placement.webp")) .build()) .binding( defaults.booleanToggle, @@ -100,7 +100,6 @@ public class GuiTest { .name(Component.literal("Custom Boolean Toggle")) .description(val -> OptionDescription.createBuilder() .text(Component.literal("You can customize controllers like so! YACL is truly infinitely customizable! This tooltip is long in order to demonstrate the cool, smooth scrolling of these descriptions. Did you know, they are also super clickable?! I know, cool right, YACL 3.x really is amazing.")) - .image(Path.of("D:\\Xander\\Downloads\\_MG_0860-Enhanced-NR.png"), new ResourceLocation("yacl", "f.webp")) // TODO: Add img file to git? .build()) .binding( defaults.customBooleanToggle, @@ -180,7 +179,8 @@ public class GuiTest { () -> config.colorOption, value -> config.colorOption = value ) - .customController(ColorController::new) + .controller(opt -> ColorControllerBuilder.create(opt) + .allowAlpha(true)) .build()) .build()) .group(OptionGroup.createBuilder() @@ -389,6 +389,67 @@ public class GuiTest { .build()) .build()) .category(ConfigCategory.createBuilder() + .name(Component.literal("Color Picker Test")) + .option(Option.<Color>createBuilder() + .name(Component.literal("Top Color Option")) + .binding( + defaults.topColorOption, + () -> config.topColorOption, + value -> config.topColorOption = value + ) + .customController(ColorController::new) + .description(OptionDescription.of(Component.literal("A Color Controller's Color Picker will appear beneath the color if there is not enough room above it."))) + .build()) + .option(LabelOption.create(Component.literal("Enabling a Color Controller's Color Picker at the top of the screen will appear beneath it if there isn't enough room above. This also applies to color controllers with alpha enabled."))) + .option(Option.<Color>createBuilder() + .name(Component.literal("Alpha Color Option")) + .binding( + defaults.alphaColorOption, + () -> config.alphaColorOption, + value -> config.alphaColorOption = value + ) + .customController(opt -> new ColorController(opt, true)) + .description(OptionDescription.of(Component.literal("A Color Picker will also allow you to choose a Color Controller's alpha if it is enabled."))) + .build()) + .option(ButtonOption.createBuilder() + .name(Component.literal("Button \"Option\"")) + .action((screen, opt) -> opt.setAvailable(false)) + .build()) + .option(LabelOption.create(Component.literal("You can try and hit the button above while the color picker below is visible, but you shouldn't be able to."))) + .option(Option.<Color>createBuilder() + .name(Component.literal("Button Color Option")) + .binding( + defaults.buttonColorOption, + () -> config.buttonColorOption, + value -> config.buttonColorOption = value + ) + .customController(ColorController::new) + .description(OptionDescription.of(Component.literal("Other controller's buttons are disabled while a color picker is visible!"))) + .build()) + .option(LabelOption.create(Component.literal("The color picker button will be outlined with a light grey color instead of white if the controller's color is very light. This is all determined using the hue and value(brightness) of the color."))) + .option(Option.<Color>createBuilder() + .name(Component.literal("Alternative Color Outline")) + .binding( + defaults.alternativePreviewOutline, + () -> config.alternativePreviewOutline, + value -> config.alternativePreviewOutline = value + ) + .customController(opt -> new ColorController(opt, true)) + .description(OptionDescription.of(Component.literal("This helps users who don't know about the color picker discover it, even if a developer chooses a lighter color"))) + .build()) + .option(LabelOption.create(Component.literal("An extra color controller with alpha enabled to show that it too has the alternative color outline"))) + .option(Option.<Color>createBuilder() + .name(Component.literal("Alpha Color Option 2")) + .binding( + defaults.anotherAlphaColorOption, + () -> config.anotherAlphaColorOption, + value -> config.anotherAlphaColorOption = value + ) + .customController(opt -> new ColorController(opt, true)) + .description(OptionDescription.of(Component.literal("Yay!!!!!!"))) + .build()) + .build()) + .category(ConfigCategory.createBuilder() .name(Component.literal("Category Test")) .option(LabelOption.create(Component.literal("This is a test category!"))) .build()) diff --git a/src/testmod/resources/assets/yacl3/textures/reach-around-placement.webp b/src/testmod/resources/assets/yacl3/textures/reach-around-placement.webp Binary files differdeleted file mode 100644 index 1937809..0000000 --- a/src/testmod/resources/assets/yacl3/textures/reach-around-placement.webp +++ /dev/null diff --git a/src/testmod/resources/assets/yacl3/textures/sample-1.webp b/src/testmod/resources/assets/yacl3/textures/sample-1.webp Binary files differdeleted file mode 100644 index 0da983e..0000000 --- a/src/testmod/resources/assets/yacl3/textures/sample-1.webp +++ /dev/null diff --git a/src/testmod/resources/assets/yacl3/textures/sample-2.webp b/src/testmod/resources/assets/yacl3/textures/sample-2.webp Binary files differdeleted file mode 100644 index e887f8c..0000000 --- a/src/testmod/resources/assets/yacl3/textures/sample-2.webp +++ /dev/null diff --git a/src/testmod/resources/assets/yacl3/textures/sample-3.webp b/src/testmod/resources/assets/yacl3/textures/sample-3.webp Binary files differdeleted file mode 100644 index eda78a9..0000000 --- a/src/testmod/resources/assets/yacl3/textures/sample-3.webp +++ /dev/null diff --git a/src/testmod/resources/assets/yacl3/textures/sample-4.webp b/src/testmod/resources/assets/yacl3/textures/sample-4.webp Binary files differdeleted file mode 100644 index 8bbe329..0000000 --- a/src/testmod/resources/assets/yacl3/textures/sample-4.webp +++ /dev/null diff --git a/src/testmod/resources/assets/yacl3/textures/sample-5.webp b/src/testmod/resources/assets/yacl3/textures/sample-5.webp Binary files differdeleted file mode 100644 index ed91379..0000000 --- a/src/testmod/resources/assets/yacl3/textures/sample-5.webp +++ /dev/null |