diff options
Diffstat (limited to 'src/main/java/dev/isxander/yacl3/gui/controllers')
4 files changed, 698 insertions, 3 deletions
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; + } + +} |