1
mirror of https://github.com/Shiewk/Widgets.git synced 2026-04-28 11:34:17 +02:00

Gradient editor

- Made all widgets use new GradientWidgetSetting
- GradientOptions to store and for rendering
- Gradient editor screen to customize
- Rainbow preset
This commit is contained in:
Shy
2026-01-05 13:37:16 +01:00
parent 70c6248dc6
commit f372a9aace
35 changed files with 1809 additions and 240 deletions
+11
View File
@@ -40,3 +40,14 @@ Right-clicking on this screen will bring up a useful context menu with additiona
When you're done, just press Escape until you return to the game.
Now, everything is done. Your widgets automatically save for the next time you play.
## Color editor
Newer mod versions (2.3.0+) include a **color editor** which provides full customization for your widgets' background and text colors:
![Color editor screen](assets/images/color-editor.webp)
The color list on the left shows the colors which are currently configured; if you add more than one, it becomes a gradient. Clicking on the colors will select them.
The settings bar on the right of the color list can be used to customize gradient settings, import from other widgets, or use presets.
Below that, the color which is currently selected can be changed or deleted.
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

+1 -1
View File
@@ -6,7 +6,7 @@ minecraft_version=1.21.9
yarn_mappings=1.21.9+build.1
loader_version=0.17.2
# Mod Properties
mod_version=2.2.0
mod_version=2.3.0
maven_group=de.shiewk
archives_base_name=Widgets
# Dependencies
@@ -37,6 +37,10 @@ public abstract class ModWidget {
public abstract Text getDescription();
public abstract void onSettingsChanged(WidgetSettings settings);
public void onSettingsChanged() {
this.onSettingsChanged(this.getSettings());
}
public int getX(int scaledScreenWidth){
return settings.anchor.getAlignStartPosX(scaledScreenWidth) + settings.offsetX;
}
@@ -2,7 +2,7 @@ package de.shiewk.widgets.client;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetsMod;
import de.shiewk.widgets.client.screen.EditWidgetPositionsScreen;
import de.shiewk.widgets.client.screen.WidgetVisibilityToggle;
import de.shiewk.widgets.client.screen.WidgetConfigScreen;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
@@ -32,7 +32,7 @@ public class WidgetRenderer implements ClientTickEvents.StartTick, ClientLifecyc
public void renderWidgets(DrawContext drawContext, RenderTickCounter tickCounter) {
if (client.options.hudHidden) return;
if (client.currentScreen instanceof EditWidgetPositionsScreen) return;
if (client.currentScreen instanceof WidgetVisibilityToggle vt && !vt.shouldRenderWidgets()) return;
final Profiler profiler = Profilers.get();
profiler.push("widgets");
final TextRenderer textRenderer = client.textRenderer;
@@ -81,7 +81,7 @@ public class WidgetRenderer implements ClientTickEvents.StartTick, ClientLifecyc
@Override
public void onClientStarted(MinecraftClient client) {
for (ModWidget widget : WidgetManager.getAllWidgets()) {
widget.onSettingsChanged(widget.getSettings());
widget.onSettingsChanged();
}
}
}
@@ -10,7 +10,7 @@ import net.minecraft.text.Text;
import java.util.List;
public class ContextMenuScreen extends Screen {
public class ContextMenuScreen extends Screen implements WidgetVisibilityToggle {
public record Option(Text title, boolean highlighted, Runnable action){
@@ -133,4 +133,12 @@ public class ContextMenuScreen extends Screen {
y += 15;
}
}
@Override
public boolean shouldRenderWidgets() {
if (parent instanceof WidgetVisibilityToggle t) {
return t.shouldRenderWidgets();
}
return true;
}
}
@@ -23,7 +23,7 @@ import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
public class EditWidgetPositionsScreen extends AnimatedScreen {
public class EditWidgetPositionsScreen extends AnimatedScreen implements WidgetVisibilityToggle {
private final Screen parent;
private final Consumer<ModWidget> onEdit;
@@ -40,6 +40,11 @@ public class EditWidgetPositionsScreen extends AnimatedScreen {
client.setScreen(parent);
}
@Override
public boolean shouldRenderWidgets() {
return false;
}
private record AlignResult(double result, boolean isEnd){}
private static final int SELECT_COLOR = Color.GREEN.getRGB(), ALIGN_COLOR = Color.ORANGE.getRGB(), ALIGN_DISABLED_COLOR = Color.GRAY.getRGB();
@@ -38,7 +38,7 @@ public class WidgetConfigScreen extends Screen {
public void close() {
WidgetManager.saveWidgets(widgetsEdited);
for (ModWidget widget : widgetsEdited) {
widget.onSettingsChanged(widget.getSettings());
widget.onSettingsChanged();
}
assert client != null;
client.setScreen(parent);
@@ -12,7 +12,7 @@ import net.minecraft.util.Util;
import java.util.function.Consumer;
public class WidgetSettingsScreen extends AnimatedScreen {
public class WidgetSettingsScreen extends AnimatedScreen implements WidgetVisibilityToggle {
private static final Text previewText = Text.translatable("widgets.ui.preview");
private final ModWidget widget;
private final Runnable onChange;
@@ -20,7 +20,7 @@ public class WidgetSettingsScreen extends AnimatedScreen {
super(Text.translatable("widgets.ui.widgetSettings", widget.getName()), parent, 500);
this.widget = widget;
onChange = () -> {
widget.onSettingsChanged(widget.getSettings());
widget.onSettingsChanged();
changedWidgetConsumer.accept(widget);
};
}
@@ -60,4 +60,17 @@ public class WidgetSettingsScreen extends AnimatedScreen {
widget.tick();
}
}
@Override
public boolean shouldRenderWidgets() {
return false;
}
public ModWidget getWidget() {
return widget;
}
public Runnable getOnChange() {
return onChange;
}
}
@@ -0,0 +1,7 @@
package de.shiewk.widgets.client.screen;
public interface WidgetVisibilityToggle {
boolean shouldRenderWidgets();
}
@@ -0,0 +1,55 @@
package de.shiewk.widgets.client.screen.components;
import de.shiewk.widgets.ModWidget;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.client.gui.screen.narration.NarrationPart;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.util.Util;
public class WidgetDisplayWidget extends ClickableWidget {
protected final ModWidget widget;
protected final TextRenderer textRenderer;
protected final int centerX;
protected final int centerY;
public WidgetDisplayWidget(ModWidget widget, TextRenderer textRenderer, int centerX, int centerY) {
super(0, 0, (int) widget.scaledWidth(), (int) widget.scaledHeight(), widget.getName());
this.widget = widget;
this.textRenderer = textRenderer;
this.centerX = centerX;
this.centerY = centerY;
}
@Override
public int getX() {
return (int) (centerX - (widget.scaledWidth() / 2f));
}
@Override
public int getY() {
return (int) (centerY - (widget.scaledHeight() / 2f));
}
@Override
public int getWidth() {
return (int) widget.scaledWidth();
}
@Override
public int getHeight() {
return (int) widget.scaledHeight();
}
@Override
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
widget.render(context, Util.getMeasuringTimeNano(), textRenderer, getX(), getY());
}
@Override
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
builder.put(NarrationPart.HINT, widget.getName());
}
}
@@ -31,7 +31,7 @@ public class WidgetSettingsEditWidget extends ScrollableWidget {
customSetting.setFocused(false);
}
setWidth(width);
widget.onSettingsChanged(widget.getSettings());
widget.onSettingsChanged();
}
@Override
@@ -0,0 +1,221 @@
package de.shiewk.widgets.client.screen.gradienteditor;
import de.shiewk.widgets.WidgetsMod;
import de.shiewk.widgets.utils.WidgetUtils;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.cursor.StandardCursors;
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.IntSupplier;
import static net.minecraft.text.Text.empty;
import static net.minecraft.text.Text.translatable;
public class GradientEditorColorSection extends AlwaysSelectedEntryListWidget<GradientEditorColorSection.ListEntry> {
private final GradientEditorScreen editor;
private static final Identifier TEXTURE_BUTTON_PLUS = Identifier.of(WidgetsMod.MOD_ID, "textures/gui/button_plus.png"),
TEXTURE_ARROW_DOWN = Identifier.of(WidgetsMod.MOD_ID, "textures/gui/arrow_down.png");
private final List<ColorEntry> colorEntries;
public GradientEditorColorSection(GradientEditorScreen editor, MinecraftClient client, int x, int y, int width, int height, int focusedIndex) {
super(client, width, height, y, 64);
setX(x);
this.editor = editor;
colorEntries = new ObjectArrayList<>(editor.colors.size());
addEntry(new HeadingEntry(client.textRenderer), 18);
IntArrayList colors = editor.colors;
for (int i = 0; i < colors.size(); i++) {
int finalI = i;
ColorEntry col = new ColorEntry(() -> colors.getInt(finalI));
colorEntries.add(col);
addEntry(col);
addEntry(new ArrowDownEntry(), 48);
}
addEntry(new AddButtonEntry(), 70);
setFocused(colorEntries.get(focusedIndex));
}
@Override
public int getRowWidth() {
return 64;
}
@Override
protected void drawSelectionHighlight(DrawContext context, ListEntry entry, int color) {}
@Override
protected void drawMenuListBackground(DrawContext context) {
context.fill(getX(), getY(), getX()+getWidth(), getY()+getHeight(), 0x50_00_00_00);
}
@Override
protected void drawHeaderAndFooterSeparators(DrawContext context) {}
@Override
protected void drawScrollbar(DrawContext context, int mouseX, int mouseY) {}
@Override
public void setFocused(@Nullable Element focused) {
if (focused == null) return;
if (focused instanceof ListEntry se && !se.canFocus()) return;
if (super.getFocused() != focused){
WidgetUtils.playSound(SoundEvents.BLOCK_COPPER_BULB_TURN_ON);
}
if (focused instanceof ColorEntry color){
editor.setCurrentColorIndex(colorEntries.indexOf(color));
}
super.setFocused(focused);
}
public void focusLast() {
setFocused(colorEntries.getLast());
}
public abstract static class ListEntry extends AlwaysSelectedEntryListWidget.Entry<ListEntry> {
public boolean canFocus(){
return false;
}
@Override
public Text getNarration() {
return empty();
}
}
public static class ColorEntry extends ListEntry {
private final IntSupplier color;
public ColorEntry(IntSupplier color) {
this.color = color;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
int color = this.color.getAsInt();
int x = this.getX();
int y = this.getContentY();
if (hovered && !isFocused()){
context.setCursor(StandardCursors.POINTING_HAND);
context.fill(x, y, x+getWidth(), y+getHeight(), 0x30_ff_ff_ff);
}
int outlineColor;
if (isFocused() || hovered){
outlineColor = 0xff_ff_ff_00;
} else {
outlineColor = color | 0xff000000;
}
context.fill(x+1, y+1, x+getWidth()-1, y+getHeight()-1, color);
// Outline:
context.fill(x+1, y, x+getWidth()-1, y+1, outlineColor);
context.fill(x+1, y+getHeight()-1, x+getWidth()-1, y+getHeight(), outlineColor);
context.fill(x, y+1, x+1, y+getHeight()-1, outlineColor);
context.fill(x+getWidth()-1, y+1, x+getWidth(), y+getHeight()-1, outlineColor);
}
@Override
public boolean canFocus() {
return true;
}
}
private static class ArrowDownEntry extends ListEntry {
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
context.drawTexture(
RenderPipelines.GUI_TEXTURED,
TEXTURE_ARROW_DOWN,
getX() + 16,
getContentY() + 8,
0,
0,
32,
32,
32,
32,
0xff_8d_8d_8d
);
}
}
private static class HeadingEntry extends ListEntry {
private final TextRenderer textRenderer;
private HeadingEntry(TextRenderer textRenderer) {
this.textRenderer = textRenderer;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
Text text = translatable("widgets.ui.gradientEditor.colors");
int y = this.getContentY() + 2;
int rowWidth = 64;
int textWidth = textRenderer.getWidth(text);
int textX = getX() + (rowWidth - textWidth) / 2;
context.drawText(textRenderer, text, textX, y, 0xffffffff, true);
}
}
private class AddButtonEntry extends ListEntry {
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
context.drawTexture(
RenderPipelines.GUI_TEXTURED,
TEXTURE_BUTTON_PLUS,
getX(),
getContentY(),
0,
0,
64,
64,
64,
64,
hovered ? 0xff_cf_cf_cf : 0xff_8d_8d_8d
);
if (hovered){
context.setCursor(StandardCursors.POINTING_HAND);
context.drawTooltip(client.textRenderer, List.of(
translatable("widgets.ui.gradientEditor.colors.add.tooltip.0"),
translatable("widgets.ui.gradientEditor.colors.add.tooltip.1")
), mouseX, mouseY);
}
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
editor.addNewColor(editor.getCurrentColor());
return true;
}
}
@Override
public boolean isFocused() {
return true;
}
}
@@ -0,0 +1,200 @@
package de.shiewk.widgets.client.screen.gradienteditor;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.client.screen.WidgetVisibilityToggle;
import de.shiewk.widgets.client.screen.components.WidgetDisplayWidget;
import de.shiewk.widgets.color.GradientMode;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.GradientWidgetSetting;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import org.joml.Matrix3x2fStack;
import static net.minecraft.text.Text.translatable;
public class GradientEditorScreen extends Screen implements WidgetVisibilityToggle {
private static final GradientOptions topBarGradient = new GradientOptions(50, 20, new int[]{0xa0_00_00_00, 0x50_00_00_00});
final Screen parent;
final ModWidget widget;
final GradientWidgetSetting setting;
final Runnable onChange;
GradientMode mode;
final IntArrayList colors;
int gradientSpeed;
int gradientSize;
int currentColorIndex = 0;
private GradientEditorColorSection colorSection;
private GradientEditorSettingsSection settingsSection;
public GradientEditorScreen(Screen parent, ModWidget widget, GradientWidgetSetting setting, Runnable onChange) {
super(translatable("widgets.ui.gradientEditor"));
this.parent = parent;
this.widget = widget;
this.setting = setting;
this.onChange = onChange;
GradientOptions options = setting.getValue();
this.mode = options.mode();
this.gradientSpeed = (int) options.gradientSpeed();
this.gradientSize = (int) options.gradientSize();
this.colors = IntArrayList.of(options.colors());
}
@Override
protected void init() {
super.init();
reloadComponents();
}
private int getTopBarHeight() {
return 8 + this.textRenderer.fontHeight * 2;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
super.render(context, mouseX, mouseY, deltaTicks);
Matrix3x2fStack matrices = context.getMatrices();
long timeNanos = Util.getMeasuringTimeNano();
// Render top bar
topBarGradient.fillHorizontal(context, timeNanos, 0, 0, this.width, this.getTopBarHeight());
Text topBarText = translatable("widgets.ui.gradientEditor");
int width = textRenderer.getWidth(topBarText);
matrices.pushMatrix().translate(this.width / 2f - width, 5).scale(2);
context.drawText(textRenderer, topBarText, 0, 0, 0xff_ff_ff_ff, true);
matrices.popMatrix();
}
public void reloadComponents(){
clearChildren();
double colorScrollY = 0;
double settingsScrollY = 0;
if (this.colorSection != null){
colorScrollY = colorSection.getScrollY();
settingsScrollY = settingsSection.getScrollY();
}
int topBarHeight = getTopBarHeight();
int colorSectionWidth = 90;
int settingsSectionWidth = 110;
int mainAreaWidth = this.width - colorSectionWidth - settingsSectionWidth;
int mainAreaHeight = this.height - topBarHeight;
// sidebar
this.colorSection = new GradientEditorColorSection(this, this.client, 0, topBarHeight, colorSectionWidth, mainAreaHeight, this.getCurrentColorIndex());
this.settingsSection = new GradientEditorSettingsSection(this, this.client, colorSectionWidth, topBarHeight, settingsSectionWidth, mainAreaHeight);
addDrawableChild(this.colorSection);
addDrawableChild(this.settingsSection);
colorSection.setScrollY(colorScrollY);
settingsSection.setScrollY(settingsScrollY);
// main area
int mainAreaX = colorSectionWidth + settingsSectionWidth;
int mainAreaCenterX = mainAreaX + (mainAreaWidth / 2);
addDrawable(new WidgetDisplayWidget(this.widget, this.textRenderer, mainAreaCenterX, (mainAreaHeight) / 2 + topBarHeight));
}
@Override
public void renderBackground(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
super.renderBackground(context, mouseX, mouseY, deltaTicks);
}
@Override
public void close() {
refreshSettingValue();
client.setScreen(parent);
}
private void refreshSettingValue() {
settingsSection.onUpdatedColor();
setting.setValue(toGradientOptions());
widget.onSettingsChanged();
onChange.run();
}
private GradientOptions toGradientOptions() {
return new GradientOptions(this.mode, this.gradientSize, this.gradientSpeed, this.colors.toIntArray());
}
@Override
public boolean shouldRenderWidgets() {
return false;
}
public void addNewColor(int initialColor) {
colors.add(initialColor);
this.reloadComponents();
this.colorSection.focusLast();
refreshSettingValue();
}
public void setGradientSize(double v) {
this.gradientSize = (int) v;
refreshSettingValue();
}
public void setGradientSpeed(double v) {
this.gradientSpeed = (int) v;
refreshSettingValue();
}
public int getCurrentColor() {
return colors.getInt(currentColorIndex);
}
public int getCurrentColorIndex() {
return currentColorIndex;
}
public void setCurrentColorIndex(int i) {
this.currentColorIndex = i;
if (settingsSection != null) settingsSection.onUpdatedColor();
}
public void setCurrentColor(int newColor) {
colors.set(getCurrentColorIndex(), newColor);
refreshSettingValue();
}
public void removeCurrentColor() {
colors.removeInt(getCurrentColorIndex());
setCurrentColorIndex(0);
refreshSettingValue();
reloadComponents();
}
public void cycleMode() {
this.mode = GradientMode.values()[(this.mode.ordinal() + 1) % GradientMode.values().length];
refreshSettingValue();
}
public void swapColors(int[] colors) {
this.colors.clear();
for (int color : colors) {
this.colors.add(color);
}
setCurrentColorIndex(0);
this.reloadComponents();
refreshSettingValue();
}
public void swap(GradientOptions options) {
setGradientSize(options.gradientSize());
setGradientSpeed(options.gradientSpeed());
this.mode = options.mode();
swapColors(options.colors());
}
}
@@ -0,0 +1,650 @@
package de.shiewk.widgets.client.screen.gradienteditor;
import de.shiewk.widgets.WidgetsMod;
import de.shiewk.widgets.client.WidgetManager;
import de.shiewk.widgets.client.screen.ContextMenuScreen;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.color.GradientPreset;
import de.shiewk.widgets.widgets.settings.GradientWidgetSetting;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.cursor.StandardCursors;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.input.CharInput;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.Arrays;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import static de.shiewk.widgets.utils.WidgetUtils.colorARGBToHexRGBA;
import static net.minecraft.text.Text.empty;
import static net.minecraft.text.Text.translatable;
public class GradientEditorSettingsSection extends AlwaysSelectedEntryListWidget<GradientEditorSettingsSection.ListEntry> {
private final GradientEditorScreen editor;
private final HexValueInputEntry hexInput;
private final ColorPickerHueSliderEntry hueSlider;
public GradientEditorSettingsSection(GradientEditorScreen editor, MinecraftClient client, int x, int y, int width, int height) {
super(client, width, height, y, 110);
setX(x);
this.editor = editor;
addEntry(new HeadingEntry(translatable("widgets.ui.gradientEditor.gradientSettings")), 18);
addEntry(new SliderEntry(1, 100, editor.gradientSize, d -> translatable("widgets.ui.gradientEditor.size", d), editor::setGradientSize), 20);
addEntry(new SliderEntry(0, 100, editor.gradientSpeed, d -> translatable("widgets.ui.gradientEditor.speed", d), editor::setGradientSpeed), 20);
addEntry(new ToggleModeButtonEntry(), 20);
addEntry(new ImportButtonEntry(), 20);
addEntry(new UsePresetButtonEntry(), 20);
addEntry(new HeadingEntry(translatable("widgets.ui.gradientEditor.editColor")), 18);
addEntry(new ColorChangerEntry(0), 22);
addEntry(new ColorChangerEntry(1), 22);
addEntry(new ColorChangerEntry(2), 22);
addEntry(new ColorChangerEntry(3), 22);
addEntry(new HeadingEntry(translatable("widgets.ui.gradientEditor.editColor.orPick")), 18);
addEntry(new ColorPickerEntry(), getRowWidth());
addEntry(hueSlider = new ColorPickerHueSliderEntry(), 22);
addEntry(new ColorChangerEntry(3, false), 22);
addEntry(hexInput = new HexValueInputEntry(), 20);
addEntry(new RemoveColorButtonEntry(), 20);
}
@Override
public int getRowWidth() {
return 110;
}
@Override
protected void drawMenuListBackground(DrawContext context) {
context.fill(getX(), getY(), getX()+getWidth(), getY()+getHeight(), 0x20_00_00_00);
}
@Override protected void drawHeaderAndFooterSeparators(DrawContext context) {}
@Override protected void drawSelectionHighlight(DrawContext context, ListEntry entry, int color) {}
@Override protected void drawScrollbar(DrawContext context, int mouseX, int mouseY) {}
public abstract static class ListEntry extends Entry<ListEntry> {
@Override
public Text getNarration() {
return empty();
}
}
public void onUpdatedColor(){
hexInput.refreshText();
hueSlider.refreshHue();
}
private float getCurrentHue(){
float[] hsb = getHsb();
return hsb[0];
}
private float @NotNull [] getHsb() {
int currentRGBA = editor.getCurrentColor();
return Color.RGBtoHSB((currentRGBA >> 16) & 0xff, (currentRGBA >> 8) & 0xff, currentRGBA & 0xff, null);
}
private class HeadingEntry extends ListEntry {
private final Text text;
private HeadingEntry(Text text) {
this.text = text;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
int y = this.getContentY() + 2;
int rowWidth = 110;
int textWidth = client.textRenderer.getWidth(text);
int textX = getX() + (rowWidth - textWidth) / 2;
context.drawText(client.textRenderer, text, textX, y, 0xffffffff, true);
}
}
private class SliderEntry extends ListEntry {
private final SliderWidget slider;
private SliderEntry(int min, int max, int initial, IntFunction<Text> textGetter, IntConsumer onUpdateValue) {
double value = (double) (initial - min) / (max - min);
slider = new Slider(textGetter, value, onUpdateValue, min, max);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
slider.active = editor.colors.size() > 1;
slider.setDimensionsAndPosition(getContentWidth(), getContentHeight(), getContentX(), getContentY());
slider.render(context, mouseX, mouseY, deltaTicks);
if (hovered && !slider.active) {
context.setCursor(StandardCursors.NOT_ALLOWED);
slider.setTooltip(Tooltip.of(translatable("widgets.ui.gradientEditor.gradientSettings.addMoreColors")));
} else {
slider.setTooltip(null);
}
}
@Override public boolean mouseClicked(Click click, boolean doubled) { return slider.mouseClicked(click, doubled); }
@Override public boolean mouseDragged(Click click, double offsetX, double offsetY) { return slider.mouseDragged(click, offsetX, offsetY); }
@Override public boolean mouseReleased(Click click) { return slider.mouseReleased(click); }
@Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { return slider.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); }
@Override public void mouseMoved(double mouseX, double mouseY) { slider.mouseMoved(mouseX, mouseY); }
private static class Slider extends SliderWidget {
private final IntFunction<Text> textGetter;
private final IntConsumer onUpdateValue;
private final int min;
private final int max;
public Slider(IntFunction<Text> textGetter, double value, IntConsumer onUpdateValue, int min, int max) {
super(0, 0, 0, 0, empty(), value);
this.textGetter = textGetter;
this.onUpdateValue = onUpdateValue;
this.min = min;
this.max = max;
this.updateMessage();
}
@Override
protected void updateMessage() {
this.setMessage(textGetter.apply(getTranslatedValue()));
}
@Override
protected void applyValue() {
onUpdateValue.accept(getTranslatedValue());
}
private int getTranslatedValue() {
return (int) (min + (this.value * (max - min)));
}
}
}
private class ToggleModeButtonEntry extends ListEntry {
private final ButtonWidget button = new ButtonWidget.Builder(empty(), this::press).build();
public ToggleModeButtonEntry() {
refreshButtonValues();
}
private void press(ButtonWidget button) {
editor.cycleMode();
refreshButtonValues();
}
private void refreshButtonValues() {
button.setMessage(translatable("widgets.ui.gradientEditor.mode", editor.mode.name));
if (editor.colors.size() > 1){
button.setTooltip(Tooltip.of(editor.mode.description));
} else {
button.setTooltip(Tooltip.of(translatable("widgets.ui.gradientEditor.gradientSettings.addMoreColors")));
}
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
button.active = editor.colors.size() > 1;
button.setDimensionsAndPosition(getContentWidth(), getContentHeight(), getContentX(), getContentY());
button.render(context, mouseX, mouseY, deltaTicks);
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return button.mouseClicked(click, doubled);
}
}
private class ImportButtonEntry extends ListEntry {
private final ButtonWidget button = new ButtonWidget.Builder(translatable("widgets.ui.gradientEditor.importOther"), this::press).build();
private void press(ButtonWidget button) {
Screen currentScreen = client.currentScreen;
int menuX = (int) client.mouse.getScaledX(client.getWindow());
int menuY = (int) client.mouse.getScaledY(client.getWindow());
client.setScreen(new ContextMenuScreen(
button.getMessage(),
currentScreen,
menuX, menuY,
WidgetManager.getAllWidgets()
.stream()
.map(widget -> new ContextMenuScreen.Option(
widget.getName(),
() -> client.setScreen(new ContextMenuScreen(
widget.getName(),
currentScreen,
menuX,
menuY,
widget.getSettings().getCustomSettings()
.stream()
.filter(o -> o instanceof GradientWidgetSetting)
.map(option -> new ContextMenuScreen.Option(
option.getName(),
() -> editor.swap(((GradientWidgetSetting) option).getValue())
)).toList()
))
)).toList()
));
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
button.setDimensionsAndPosition(getContentWidth(), getContentHeight(), getContentX(), getContentY());
button.render(context, mouseX, mouseY, deltaTicks);
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return button.mouseClicked(click, doubled);
}
}
private class UsePresetButtonEntry extends ListEntry {
private final ButtonWidget button = new ButtonWidget.Builder(translatable("widgets.ui.gradientEditor.usePreset"), this::press).build();
private void press(ButtonWidget button) {
Screen currentScreen = client.currentScreen;
int menuX = (int) client.mouse.getScaledX(client.getWindow());
int menuY = (int) client.mouse.getScaledY(client.getWindow());
client.setScreen(new ContextMenuScreen(
translatable("widgets.ui.gradientEditor.usePreset"),
currentScreen,
menuX, menuY,
Arrays.stream(GradientPreset.presets).map(preset -> new ContextMenuScreen.Option(
preset.name(),
() -> editor.swap(preset.gradient())
)).toList()
));
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
button.setDimensionsAndPosition(getContentWidth(), getContentHeight(), getContentX(), getContentY());
button.render(context, mouseX, mouseY, deltaTicks);
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return button.mouseClicked(click, doubled);
}
}
private class ColorChangerEntry extends ListEntry {
private final int component;
private final boolean showLabel;
public ColorChangerEntry(int component) {
this(component, true);
}
public ColorChangerEntry(int component, boolean showLabel) {
this.component = component;
this.showLabel = showLabel;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
double sliderProg = getComponentValue() / 255d;
GradientOptions bg = new GradientOptions(100, 0, new int[]{getBackgroundStartColor(), getBackgroundEndColor()});
int contentY = getContentY();
int contentWidth = getContentWidth();
int contentX = getContentX();
int contentHeight = getContentHeight();
bg.fillHorizontal(context, 0, contentX, contentY + 1, contentX + contentWidth, contentY + contentHeight - 1);
context.drawVerticalLine((int) (contentX + (contentWidth * sliderProg)), contentY - 1, contentY + contentHeight, 0xff_ff_ff_ff);
if (showLabel){
String label = getLabelWithValue();
int w = client.textRenderer.getWidth(label);
context.drawText(client.textRenderer, label, contentX + (contentWidth - w) / 2, contentY + 5, 0xffffffff, true);
}
if (hovered){
context.setCursor(StandardCursors.RESIZE_EW);
}
}
private int getComponentValue() {
int currentColor = editor.getCurrentColor();
return switch (component) {
case 0 -> (currentColor & 0x00_ff_00_00) >>> 16;
case 1 -> (currentColor & 0x00_00_ff_00) >>> 8;
case 2 -> (currentColor & 0x00_00_00_ff);
case 3 -> (currentColor & 0xff_00_00_00) >>> 24;
default -> throw new IllegalStateException();
};
}
@Override
public boolean mouseDragged(Click click, double offsetX, double offsetY) {
double mouseX = click.x();
int newComponentValue = (int) ((mouseX - getContentX()) / getContentWidth() * 255);
setComponentValue(newComponentValue);
return true;
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return mouseDragged(click, 0, 0);
}
@Override
public boolean keyPressed(KeyInput input) {
if (input.isLeft()) {
setComponentValue(getComponentValue() - 1);
} else if (input.isRight()) {
setComponentValue(getComponentValue() + 1);
}
return true;
}
private void setComponentValue(int val) {
val = MathHelper.clamp(val, 0, 255);
final int currentColor = editor.getCurrentColor();
int newColor = switch (component){
case 0 -> (currentColor & 0xff_00_ff_ff) | val << 16;
case 1 -> (currentColor & 0xff_ff_00_ff) | val << 8;
case 2 -> (currentColor & 0xff_ff_ff_00) | val;
case 3 -> (currentColor & 0x00_ff_ff_ff) | val << 24;
default -> throw new IllegalStateException();
};
editor.setCurrentColor(newColor);
}
private String getLabelWithValue() {
return switch (component){
case 0 -> "R: " + getComponentValue();
case 1 -> "G: " + getComponentValue();
case 2 -> "B: " + getComponentValue();
case 3 -> "A: " + getComponentValue();
default -> throw new IllegalStateException();
};
}
private int getBackgroundEndColor() {
final int currentColor = editor.getCurrentColor();
return switch (component){
case 0 -> currentColor | 0x00_ff_00_00;
case 1 -> currentColor | 0x00_00_ff_00;
case 2 -> currentColor | 0x00_00_00_ff;
case 3 -> currentColor | 0xff_00_00_00;
default -> throw new IllegalStateException();
};
}
private int getBackgroundStartColor() {
final int currentColor = editor.getCurrentColor();
return switch (component){
case 0 -> currentColor & 0xff_00_ff_ff;
case 1 -> currentColor & 0xff_ff_00_ff;
case 2 -> currentColor & 0xff_ff_ff_00;
case 3 -> currentColor & 0x00_ff_ff_ff;
default -> throw new IllegalStateException();
};
}
}
private class RemoveColorButtonEntry extends ListEntry {
private final ButtonWidget button = new ButtonWidget.Builder(translatable("widgets.ui.gradientEditor.removeColor"), this::press).build();
private void press(ButtonWidget button) {
button.active = false;
editor.removeCurrentColor();
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
button.active = editor.colors.size() > 1;
button.setDimensionsAndPosition(getContentWidth(), getContentHeight(), getContentX(), getContentY());
button.render(context, mouseX, mouseY, deltaTicks);
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return button.mouseClicked(click, doubled);
}
}
private class HexValueInputEntry extends ListEntry {
private final TextFieldWidget inputField = new TextFieldWidget(client.textRenderer, 0, 0, empty());
public HexValueInputEntry() {
this.refreshText();
inputField.setMaxLength(9);
}
private void onChangeInputField(String s) {
boolean valid = false;
if (s.startsWith("#")) s = s.substring(1);
if (s.length() == 6) {
s += "ff";
}
if (s.length() == 8) {
try {
String alpha = s.substring(6, 8);
String rgb = s.substring(0, 6);
String argbHex = alpha + rgb;
int cl = Integer.parseUnsignedInt(argbHex, 16);
if (cl != editor.getCurrentColor()) {
editor.setCurrentColor(cl);
}
valid = true;
} catch (NumberFormatException ignored) {}
}
inputField.setEditableColor(valid ? 0xffffffff : 0xffff0000);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
inputField.setDimensionsAndPosition(getContentWidth(), getContentHeight(), getContentX(), getContentY());
inputField.render(context, mouseX, mouseY, deltaTicks);
}
public void refreshText(){
inputField.setChangedListener(null);
inputField.setText('#' + colorARGBToHexRGBA(editor.getCurrentColor()));
inputField.setCursorToStart(false);
inputField.setEditableColor(0xffffffff);
inputField.setChangedListener(this::onChangeInputField);
}
@Override
public void setFocused(boolean focused) {
inputField.setFocused(focused);
}
@Override public boolean mouseClicked(Click click, boolean doubled) { return inputField.mouseClicked(click, doubled); }
@Override public boolean mouseDragged(Click click, double offsetX, double offsetY) { return inputField.mouseDragged(click, offsetX, offsetY); }
@Override public boolean mouseReleased(Click click) { return inputField.mouseReleased(click); }
@Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { return inputField.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); }
@Override public void mouseMoved(double mouseX, double mouseY) { inputField.mouseMoved(mouseX, mouseY); }
@Override public boolean charTyped(CharInput input) { return inputField.charTyped(input); }
@Override public boolean keyReleased(KeyInput input) { return inputField.keyReleased(input); }
@Override public boolean keyPressed(KeyInput input) { return inputField.keyPressed(input); }
}
private class ColorPickerEntry extends ListEntry {
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
context.fill(
getContentX(),
getContentY(),
getContentX() + getContentWidth(),
getContentY() + getContentHeight(),
getBackgroundFillColor()
);
context.drawTexture(
RenderPipelines.GUI_TEXTURED,
getOverlayTextureIdentifier(),
getContentX(), getContentY(),
0, 0,
getContentWidth(), getContentHeight(),
getContentWidth(), getContentHeight()
);
float[] hsb = getHsb();
int pointerOffsetX = (int) (hsb[1] * getContentWidth());
int pointerOffsetY = (int) ((1f - hsb[2]) * getContentHeight());
context.fill(
getContentX() + pointerOffsetX - 2, getContentY() + pointerOffsetY - 2,
getContentX() + pointerOffsetX + 2, getContentY() + pointerOffsetY + 2,
0xffffffff
);
context.fill(
getContentX() + pointerOffsetX - 1, getContentY() + pointerOffsetY - 1,
getContentX() + pointerOffsetX + 1, getContentY() + pointerOffsetY + 1,
editor.getCurrentColor() | 0xff000000
);
if (hovered){
context.setCursor(StandardCursors.ARROW);
}
}
@Override
public boolean mouseDragged(Click click, double offsetX, double offsetY) {
double x = click.x() - getContentX();
double y = click.y() - getContentY();
float saturation = (float) Math.clamp(x / getContentWidth(), 0d, 1d);
float brightness = (float) Math.clamp(1d - y / getContentHeight(), 0d, 1d);
int newColorRgb = Color.HSBtoRGB(hueSlider.sliderProgress, saturation, brightness) & 0x00ffffff;
int alpha = editor.getCurrentColor() & 0xff000000;
editor.setCurrentColor(newColorRgb | alpha);
return true;
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return mouseDragged(click, 0, 0);
}
private int getBackgroundFillColor() {
return Color.HSBtoRGB(hueSlider.sliderProgress, 1, 1);
}
private static Identifier OVERLAY_TEXTURE_ID;
public Identifier getOverlayTextureIdentifier(){
if (OVERLAY_TEXTURE_ID == null){
NativeImageBackedTexture texture = generateOverlayTexture();
OVERLAY_TEXTURE_ID = Identifier.of(WidgetsMod.MOD_ID, "textures/gui/generated/color-picker-overlay");
client.getTextureManager().registerTexture(OVERLAY_TEXTURE_ID, texture);
}
return OVERLAY_TEXTURE_ID;
}
private NativeImageBackedTexture generateOverlayTexture() {
NativeImageBackedTexture texture = new NativeImageBackedTexture("widgets:textures/gui/generated/color-picker-overlay", 256, 256, false);
NativeImage image = texture.getImage();
for (int x = 0; x < 256; x++) {
for (int y = 0; y < 256; y++) {
double alphaWhite = (255d - x) / 255d;
double alphaBlack = y / 255d;
double outAlpha = alphaBlack + alphaWhite * (1d - alphaBlack);
int rgb = (int) Math.round(outAlpha > 0 ? (255d * alphaWhite * (1d - alphaBlack)) / outAlpha : 0);
int a = (int) Math.round(outAlpha * 255.0);
image.setColorArgb(x, y, new Color(rgb, rgb, rgb, a).getRGB());
}
}
texture.upload();
return texture;
}
}
private class ColorPickerHueSliderEntry extends ListEntry {
private static final GradientOptions sliderGradient = new GradientOptions(
16.666666f,
0,
new int[]{0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff, 0xff0000ff, 0xffff00ff, 0xffff0000}
);
private float sliderProgress;
public ColorPickerHueSliderEntry(){
refreshHue();
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks) {
sliderGradient.fillHorizontal(context, 0, getContentX(), getContentY() + 1, getContentX() + getContentWidth(), getContentY() + getContentHeight() - 1);
context.drawVerticalLine((int) (getContentX() + (getContentWidth() * sliderProgress)), getContentY() - 1, getContentY() + getContentHeight(), 0xff_ff_ff_ff);
if (hovered){
context.setCursor(StandardCursors.RESIZE_EW);
}
}
@Override
public boolean mouseDragged(Click click, double offsetX, double offsetY) {
double x = click.x() - getContentX();
float newHue = (float) Math.clamp(x / getContentWidth(), 0, 1);
this.sliderProgress = newHue;
float[] hsb = getHsb();
int newRgb = Color.HSBtoRGB(newHue, hsb[1], hsb[2]) & 0x00ffffff;
int alpha = editor.getCurrentColor() & 0xff000000;
int newColor = newRgb | alpha;
if (newColor != editor.getCurrentColor()){
editor.setCurrentColor(newColor);
}
return true;
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
return this.mouseDragged(click, 0, 0);
}
public void refreshHue() {
this.sliderProgress = getCurrentHue();
}
}
}
@@ -0,0 +1,18 @@
package de.shiewk.widgets.color;
import net.minecraft.text.Text;
import static net.minecraft.text.Text.translatable;
public enum GradientMode {
SWEEP(translatable("widgets.gradient.sweep"), translatable("widgets.gradient.sweep.description")),
PULSE(translatable("widgets.gradient.pulse"), translatable("widgets.gradient.pulse.description"));
public final Text name;
public final Text description;
GradientMode(Text name, Text description) {
this.name = name;
this.description = description;
}
}
@@ -0,0 +1,153 @@
package de.shiewk.widgets.color;
import de.shiewk.widgets.render.state.HorizontalGradientGuiRenderState;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import org.joml.Matrix3x2fStack;
import java.util.Objects;
import static de.shiewk.widgets.utils.WidgetUtils.fadeColor;
public record GradientOptions(GradientMode mode, float gradientSize, float gradientSpeed, int[] colors) {
public GradientOptions(GradientMode mode, float gradientSize, float gradientSpeed, int[] colors) {
this.mode = Objects.requireNonNullElse(mode, GradientMode.SWEEP);
this.gradientSize = gradientSize;
this.gradientSpeed = gradientSpeed;
this.colors = Objects.requireNonNullElse(colors, new int[]{ -1 });
}
public GradientOptions(float gradientSize, float gradientSpeed, int[] colors) {
this(GradientMode.SWEEP, gradientSize, gradientSpeed, colors);
}
public void fillHorizontal(DrawContext context, long timeNanos, int x, int y, int endX, int endY) {
if (colors.length == 1) {
context.fill(x, y, endX, endY, colors[0]);
return;
}
switch (mode){
case SWEEP -> fillHorizonalSweep(context, timeNanos, x, y, endX, endY);
case PULSE -> fillHorizonalPulse(context, timeNanos, x, y, endX, endY);
}
}
private void fillHorizonalSweep(DrawContext context, long timeNanos, int x, int y, int endX, int endY) {
context.enableScissor(x, y, endX, endY);
int width = endX - x;
float sizeFactor = gradientSize / 100f;
int partSize = Math.max(1, Math.round(width * sizeFactor));
int totalGradientCycle = colors.length * partSize;
float speedPxPerSec = width * (gradientSpeed / 100f);
float timeSeconds = timeNanos / 1_000_000_000f;
float offset = gradientSpeed == 0 ? 0 : (timeSeconds * speedPxPerSec + x) % totalGradientCycle;
Matrix3x2fStack matrices = context.getMatrices().pushMatrix();
matrices.translate(-offset, 0);
int currentPos = 0;
int colorIndex = 0;
while (currentPos < width + totalGradientCycle) {
int color1 = colors[colorIndex % colors.length];
int color2 = colors[(colorIndex + 1) % colors.length];
HorizontalGradientGuiRenderState.draw(
context, x + currentPos, y, x + currentPos + partSize, endY,
color1, color2
);
currentPos += partSize;
colorIndex++;
}
matrices.popMatrix();
context.disableScissor();
}
private void fillHorizonalPulse(DrawContext context, long timeNanos, int x, int y, int endX, int endY) {
context.fill(x, y, endX, endY, getCurrentPulseColor(timeNanos));
}
private int getCurrentPulseColor(long timeNanos) {
float progress = timeNanos / 1_000_000_000f * gradientSpeed / gradientSize;
int color1 = colors[(int) (progress % colors.length)];
int color2 = colors[(int) ((progress + 1) % colors.length)];
float delta = progress % 1;
return fadeColor(color1, color2, delta);
}
public void drawHorizontalLine(DrawContext context, long mt, int posX, int endX, int posY) {
this.fillHorizontal(context, mt, posX, posY, endX, posY + 1);
}
public void drawText(DrawContext context, TextRenderer textRenderer, long timeNanos, String displayText, int x, int y, boolean shadow) {
if (colors.length == 1){
context.drawText(textRenderer, displayText, x, y, colors[0], shadow);
} else {
switch (mode){
case SWEEP -> drawTextSweep(context, textRenderer, timeNanos, displayText, x, y, shadow);
case PULSE -> drawTextPulse(context, textRenderer, timeNanos, displayText, x, y, shadow);
}
}
}
public void drawText(DrawContext context, TextRenderer textRenderer, long timeNanos, Text displayText, int x, int y, boolean shadow) {
if (colors.length == 1){
context.drawText(textRenderer, displayText, x, y, colors[0], shadow);
}
this.drawText(context, textRenderer, timeNanos, displayText.getString(), x, y, shadow);
}
private void drawTextSweep(DrawContext context, TextRenderer textRenderer, long timeNanos, String displayText, int x, int y, boolean shadow) {
int pos = 0;
for (int i = 0; i < displayText.length(); i++) {
String s = String.valueOf(displayText.charAt(i));
int w = textRenderer.getWidth(s);
int col = computeSweepTextColorAt(gradientSpeed == 0 ? pos : pos + x, timeNanos);
context.drawText(textRenderer, s, x +pos, y, col, shadow);
pos += w;
}
}
private int computeSweepTextColorAt(float pos, long timeNanos) {
pos += timeNanos / 500_000_000f * gradientSpeed;
float partSize = gradientSize * 2;
int part = (int) (pos / partSize);
double off = pos % partSize / partSize;
int color1 = colors[part % colors.length];
int color2 = colors[(part+1) % colors.length];
return fadeColor(color1, color2, off);
}
private void drawTextPulse(DrawContext context, TextRenderer textRenderer, long timeNanos, String displayText, int x, int y, boolean shadow) {
context.drawText(textRenderer, displayText, x, y, getCurrentPulseColor(timeNanos), shadow);
}
public static GradientOptions solidColor(int color) {
return new GradientOptions(1, 0, new int[]{color});
}
public void drawVerticalLine(DrawContext context, long timeNanos, int posX, int posY, int endY) {
fillHorizontal(context, timeNanos, posX, posY, posX + 1, endY);
}
public GradientOptions multiplyAlpha(double v) {
int[] newColors = new int[colors.length];
for (int i = 0; i < colors.length; i++) {
int color = colors[i];
int rgb = color & 0xffffff;
int newAlpha = (int) (((color & 0xff000000) >>> 24) * v);
newColors[i] = (newAlpha << 24) | rgb;
}
return new GradientOptions(mode, gradientSize, gradientSpeed, newColors);
}
}
@@ -0,0 +1,29 @@
package de.shiewk.widgets.color;
import net.minecraft.text.Text;
import static net.minecraft.text.Text.translatable;
public record GradientPreset(Text name, GradientOptions gradient) {
public static final GradientPreset[] presets = new GradientPreset[]{
new GradientPreset(
translatable("widgets.gradient.preset.rainbow"),
new GradientOptions(
GradientMode.PULSE,
14,
20,
new int[]{
0xff_ff_00_00,
0xff_ff_88_00,
0xff_ff_ff_00,
0xff_00_ff_00,
0xff_00_ff_ff,
0xff_50_00_80,
0xff_ff_00_ff,
}
)
)
};
}
@@ -0,0 +1,102 @@
package de.shiewk.widgets.render.state;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.ScreenRect;
import net.minecraft.client.gui.render.state.SimpleGuiElementRenderState;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.texture.TextureSetup;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3x2f;
@Environment(EnvType.CLIENT)
public final class HorizontalGradientGuiRenderState implements SimpleGuiElementRenderState {
private final RenderPipeline pipeline;
private final TextureSetup textureSetup;
private final Matrix3x2f pose;
private final ScreenRect scissorArea;
private final ScreenRect bounds;
private final int x;
private final int y;
private final int endX;
private final int endY;
private final int colorLeft;
private final int colorRight;
private HorizontalGradientGuiRenderState(
RenderPipeline pipeline,
TextureSetup textureSetup,
Matrix3x2f pose,
ScreenRect scissorArea,
int x,
int y,
int endX,
int endY, int colorLeft, int colorRight
) {
this.pipeline = pipeline;
this.textureSetup = textureSetup;
this.pose = pose;
this.scissorArea = scissorArea;
this.x = x;
this.y = y;
this.endX = endX;
this.endY = endY;
this.colorLeft = colorLeft;
this.colorRight = colorRight;
this.bounds = createBounds(x, y, endX, endY, pose, scissorArea);
}
@Override
public void setupVertices(VertexConsumer vertices) {
vertices.vertex(pose, x, y).color(colorLeft);
vertices.vertex(pose, x, endY).color(colorLeft);
vertices.vertex(pose, endX, endY).color(colorRight);
vertices.vertex(pose, endX, y).color(colorRight);
}
@Override
public RenderPipeline pipeline() {
return pipeline;
}
@Override
public TextureSetup textureSetup() {
return textureSetup;
}
@Override
public @Nullable ScreenRect scissorArea() {
return scissorArea;
}
@Nullable
private static ScreenRect createBounds(int x0, int y0, int x1, int y1, Matrix3x2f pose, @Nullable ScreenRect scissorArea) {
ScreenRect screenRect = (new ScreenRect(x0, y0, x1 - x0 + 1, y1 - y0)).transformEachVertex(pose);
return scissorArea != null ? scissorArea.intersection(screenRect) : screenRect;
}
@Override
public @Nullable ScreenRect bounds() {
return bounds;
}
public static void draw(DrawContext context, int x, int y, int endX, int endY, int colorLeft, int colorRight) {
context.state.addSimpleElement(
new HorizontalGradientGuiRenderState(
RenderPipelines.GUI,
TextureSetup.empty(),
new Matrix3x2f(context.getMatrices()),
context.scissorStack.peekLast(),
x, y, endX, endY,
colorLeft, colorRight
)
);
}
}
@@ -3,6 +3,7 @@ package de.shiewk.widgets.utils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.sound.PositionedSoundInstance;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.tick.TickManager;
import java.util.function.BooleanSupplier;
@@ -35,4 +36,25 @@ public class WidgetUtils {
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(ev, 1f, 1f));
}
public static int fadeColor(int color1, int color2, double delta) {
int alpha = (int) MathHelper.lerp(delta, (color1 >> 24) & 0xff, (color2 >> 24) & 0xff);
int red = (int) MathHelper.lerp(delta, (color1 >> 16) & 0xff, (color2 >> 16) & 0xff);
int green = (int) MathHelper.lerp(delta, (color1 >> 8) & 0xff, (color2 >> 8) & 0xff);
int blue = (int) MathHelper.lerp(delta, color1 & 0xff, color2 & 0xff);
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
public static String colorARGBToHexRGBA(int color) {
int a = color >> 24 & 0xff;
int r = color >> 16 & 0xff;
int g = color >> 8 & 0xff;
int b = color & 0xff;
return toHexSingle(r) + toHexSingle(g) + toHexSingle(b) + toHexSingle(a);
}
private static String toHexSingle(int comp){
String s = Integer.toHexString(comp);
return "0".repeat(2 - s.length()) + s;
}
}
@@ -1,10 +1,8 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.EnumWidgetSetting;
import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting;
import de.shiewk.widgets.widgets.settings.RGBAColorWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
@@ -28,17 +26,13 @@ public class ArmorHudWidget extends ResizableWidget {
new ToggleWidgetSetting("show_durability", translatable("widgets.widgets.armorHud.showDurability"), true),
new IntSliderWidgetSetting("width", translatable("widgets.widgets.basictext.width"), 16, 42, 128),
new EnumWidgetSetting<>("alignment", translatable("widgets.widgets.basictext.alignment"), BasicTextWidget.TextAlignment.class, BasicTextWidget.TextAlignment.CENTER, BasicTextWidget.TextAlignment::displayText),
new RGBAColorWidgetSetting("backgroundcolor", translatable("widgets.widgets.basictext.background"), 0, 0, 0, 80),
new GradientWidgetSetting("backgroundcolor", translatable("widgets.widgets.basictext.background"), 0x50_00_00_00),
new EnumWidgetSetting<>("durability_style", translatable("widgets.widgets.armorHud.durabilityStyle"), DurabilityStyle.class, DurabilityStyle.NUMBER, DurabilityStyle::getDisplayName),
new ToggleWidgetSetting("rainbow", translatable("widgets.widgets.common.rainbow"), false),
new IntSliderWidgetSetting("rainbow_speed", translatable("widgets.widgets.common.rainbow.speed"), 1, 3, 10),
new RGBAColorWidgetSetting("textcolor", translatable("widgets.widgets.basictext.textcolor"), 255, 255, 255, 255)
new GradientWidgetSetting("textcolor", translatable("widgets.widgets.basictext.textcolor"), 0xff_ff_ff_ff)
));
getSettings().optionById("width").setShowCondition(() -> this.showDurability);
getSettings().optionById("alignment").setShowCondition(() -> this.showDurability);
getSettings().optionById("durability_style").setShowCondition(() -> this.showDurability);
getSettings().optionById("rainbow_speed").setShowCondition(() -> this.rainbow);
getSettings().optionById("textcolor").setShowCondition(() -> !this.rainbow);
}
public enum DurabilityStyle {
@@ -50,22 +44,25 @@ public class ArmorHudWidget extends ResizableWidget {
}
}
private int padding = 1;
private boolean showDurability = true;
private DurabilityStyle durabilityStyle;
protected int padding = 1;
protected boolean showDurability = true;
protected DurabilityStyle durabilityStyle;
protected ItemStack helmet;
protected ItemStack chestplate;
protected ItemStack leggings;
protected ItemStack boots;
protected boolean rainbow = false;
protected int rainbowSpeed = 3;
protected int preferredWidth = 42;
protected BasicTextWidget.TextAlignment textAlignment = BasicTextWidget.TextAlignment.CENTER;
protected int backgroundColor = 0x50_00_00_00, textColor = 0xff_ff_ff_ff;
protected GradientOptions backgroundColor, textColor;
@Override
public void renderScaled(DrawContext context, long measuringTimeNano, TextRenderer textRenderer, int posX, int posY) {
context.fill(posX, posY, posX+width(), posY+height(), backgroundColor);
backgroundColor.fillHorizontal(
context,
measuringTimeNano,
posX, posY,
posX+width(), posY+height()
);
if (helmet != null){
renderItem(context, measuringTimeNano, textRenderer, helmet, posX + padding, posY + padding);
}
@@ -99,14 +96,14 @@ public class ArmorHudWidget extends ResizableWidget {
switch (textAlignment){
case RIGHT -> {
int width = textRenderer.getWidth(text);
context.drawText(textRenderer, text, posX + width() - width - padding * 2, posY + 5, rainbow ? BasicTextWidget.rainbowColor(mt, rainbowSpeed) : textColor, true);
textColor.drawText(context, textRenderer, mt, text, posX + width() - width - padding * 2, posY + 5, true);
}
case CENTER -> {
int width = textRenderer.getWidth(text);
context.drawText(textRenderer, text, posX + ((preferredWidth + padding*2) - width) / 2 + 8, posY + 5, rainbow ? BasicTextWidget.rainbowColor(mt, rainbowSpeed) : textColor, true);
textColor.drawText(context, textRenderer, mt, text, posX + ((preferredWidth + padding*2) - width) / 2 + 8, posY + 5, true);
}
case LEFT -> {
context.drawText(textRenderer, text, posX + 16 + padding, posY + 5, rainbow ? BasicTextWidget.rainbowColor(mt, rainbowSpeed) : textColor, true);
textColor.drawText(context, textRenderer, mt, text, posX + 16 + padding, posY + 5, true);
}
}
}
@@ -156,10 +153,8 @@ public class ArmorHudWidget extends ResizableWidget {
this.padding = (int) settings.optionById("padding").getValue();
this.showDurability = (boolean) settings.optionById("show_durability").getValue();
this.durabilityStyle = (DurabilityStyle) settings.optionById("durability_style").getValue();
this.rainbow = (boolean) settings.optionById("rainbow").getValue();
this.rainbowSpeed = (int) settings.optionById("rainbow_speed").getValue();
this.textColor = (int) settings.optionById("textcolor").getValue();
this.backgroundColor = (int) settings.optionById("backgroundcolor").getValue();
this.textColor = (GradientOptions) settings.optionById("textcolor").getValue();
this.backgroundColor = (GradientOptions) settings.optionById("backgroundcolor").getValue();
this.preferredWidth = (int) settings.optionById("width").getValue();
this.textAlignment = (BasicTextWidget.TextAlignment) settings.optionById("alignment").getValue();
}
@@ -1,6 +1,7 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.utils.WidgetUtils;
import de.shiewk.widgets.widgets.settings.EnumWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
@@ -52,9 +53,7 @@ public class BandwidthWidget extends BasicTextWidget {
new EnumWidgetSetting<>("unit", Text.translatable("widgets.widgets.bandwidth.unit"), Unit.class, Unit.KB, unit -> literal(unit.name)),
new ToggleWidgetSetting("fastupdate", translatable("widgets.widgets.bandwidth.fastupdate"), false)
));
getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor && !this.rainbow);
getSettings().optionById("rainbow").setShowCondition(() -> !this.dynamicColor);
getSettings().optionById("rainbow_speed").setShowCondition(() -> !this.dynamicColor && this.rainbow);
getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor);
}
private int t = 0;
@@ -75,11 +74,11 @@ public class BandwidthWidget extends BasicTextWidget {
formatAndSetRenderText(literal(unit.sizeFormatter.apply(avgBytesPerSecond)));
if (this.dynamicColor){
if (avgBytesPerSecond < 100000){
this.textColor = 0xff00ff00;
this.textColor = GradientOptions.solidColor(0xff00ff00);
} else if (avgBytesPerSecond < 750000) {
this.textColor = 0xffffff00;
this.textColor = GradientOptions.solidColor(0xffffff00);
} else {
this.textColor = 0xffff3030;
this.textColor = GradientOptions.solidColor(0xffff3030);
}
}
}
@@ -1,12 +1,9 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.widgets.settings.WidgetSettingOption;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.*;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.client.WidgetRenderer;
import de.shiewk.widgets.widgets.settings.EnumWidgetSetting;
import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting;
import de.shiewk.widgets.widgets.settings.RGBAColorWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
@@ -67,15 +64,11 @@ public abstract class BasicTextWidget extends ResizableWidget {
private int padding = 0;
private TextRenderer renderer = null;
private boolean textShadow = true;
protected boolean rainbow = false;
private int rainbowSpeed = 3;
private static ObjectArrayList<WidgetSettingOption<?>> getCustomSettings(List<WidgetSettingOption<?>> otherCustomOptions) {
final ObjectArrayList<WidgetSettingOption<?>> list = new ObjectArrayList<>(otherCustomOptions);
list.add(new RGBAColorWidgetSetting("backgroundcolor", translatable("widgets.widgets.basictext.background"), 0, 0, 0, 80));
list.add(new ToggleWidgetSetting("rainbow", translatable("widgets.widgets.common.rainbow"), false));
list.add(new RGBAColorWidgetSetting("textcolor", translatable("widgets.widgets.basictext.textcolor"), 255, 255, 255, 255));
list.add(new IntSliderWidgetSetting("rainbow_speed", translatable("widgets.widgets.common.rainbow.speed"), 1, 3, 10));
list.add(new GradientWidgetSetting("backgroundcolor", translatable("widgets.widgets.basictext.background"), 0x50_00_00_00));
list.add(new GradientWidgetSetting("textcolor", translatable("widgets.widgets.basictext.textcolor"), 0xff_ff_ff_ff));
list.add(new IntSliderWidgetSetting("width", translatable("widgets.widgets.basictext.width"), 10, DEFAULT_WIDTH, 80*3));
list.add(new IntSliderWidgetSetting("height", translatable("widgets.widgets.basictext.height"), 9, DEFAULT_HEIGHT, 80));
list.add(new ToggleWidgetSetting("shadow", translatable("widgets.widgets.basictext.textshadow"), true));
@@ -87,17 +80,14 @@ public abstract class BasicTextWidget extends ResizableWidget {
protected BasicTextWidget(Identifier id, List<WidgetSettingOption<?>> otherCustomOptions) {
super(id, getCustomSettings(otherCustomOptions));
getSettings().optionById("padding").setShowCondition(() -> this.textAlignment != TextAlignment.CENTER);
getSettings().optionById("textcolor").setShowCondition(() -> !this.rainbow);
getSettings().optionById("rainbow_speed").setShowCondition(() -> this.rainbow);
}
protected static final int
DEFAULT_WIDTH = 80,
DEFAULT_HEIGHT = 9 + 12,
DEFAULT_BACKGROUND_COLOR = new Color(0, 0, 0, 80).getRGB(),
DEFAULT_TEXT_COLOR = new Color(255, 255 ,255, 255).getRGB();
DEFAULT_HEIGHT = 9 + 12;
protected int backgroundColor = DEFAULT_BACKGROUND_COLOR, textColor = DEFAULT_TEXT_COLOR, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;
protected int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;
protected GradientOptions backgroundColor, textColor;
protected TextAlignment textAlignment = TextAlignment.CENTER;
protected TextStyle textStyle = TextStyle.PLAIN;
@@ -115,18 +105,14 @@ public abstract class BasicTextWidget extends ResizableWidget {
public void renderScaled(DrawContext context, long n, TextRenderer textRenderer, int posX, int posY) {
if (!shouldRender) return;
renderer = textRenderer;
context.fill(posX, posY, posX + width(), posY + height(), this.backgroundColor);
this.backgroundColor.fillHorizontal(context, n, posX, posY, posX + width(), posY + height());
Matrix3x2fStack matrices = context.getMatrices()
.pushMatrix();
matrices.translate(posX + textX, posY + textY, matrices);
context.drawText(textRenderer, renderText, 0, 0, rainbow ? rainbowColor(n, rainbowSpeed) : this.textColor, textShadow);
this.textColor.drawText(context, textRenderer, n, renderText, 0, 0, textShadow);
matrices.popMatrix();
}
public static int rainbowColor(long n, float speed) {
return Color.HSBtoRGB(n / 10_000_000_000f * speed, 1, 1);
}
@Override
public final void tick() {
tickWidget();
@@ -165,15 +151,13 @@ public abstract class BasicTextWidget extends ResizableWidget {
@Override
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
this.backgroundColor = (int) settings.optionById("backgroundcolor").getValue();
this.textColor = (int) settings.optionById("textcolor").getValue();
this.backgroundColor = (GradientOptions) settings.optionById("backgroundcolor").getValue();
this.textColor = (GradientOptions) settings.optionById("textcolor").getValue();
this.width = (int) settings.optionById("width").getValue();
this.height = (int) settings.optionById("height").getValue();
this.textAlignment = (TextAlignment) settings.optionById("alignment").getValue();
this.padding = (int) settings.optionById("padding").getValue();
this.textShadow = (boolean) settings.optionById("shadow").getValue();
this.textStyle = (TextStyle) settings.optionById("text_style").getValue();
this.rainbow = (boolean) settings.optionById("rainbow").getValue();
this.rainbowSpeed = (int) settings.optionById("rainbow_speed").getValue();
}
}
@@ -1,8 +1,9 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.GradientWidgetSetting;
import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting;
import de.shiewk.widgets.widgets.settings.RGBAColorWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
@@ -14,58 +15,48 @@ import net.minecraft.util.Identifier;
import java.awt.*;
import java.util.List;
import static net.minecraft.text.Text.translatable;
public class CoordinatesWidget extends ResizableWidget {
public CoordinatesWidget(Identifier id) {
super(id, List.of(
new ToggleWidgetSetting("x", Text.translatable("widgets.widgets.coordinates.showX"), true),
new ToggleWidgetSetting("y", Text.translatable("widgets.widgets.coordinates.showY"), true),
new ToggleWidgetSetting("z", Text.translatable("widgets.widgets.coordinates.showZ"), true),
new RGBAColorWidgetSetting("backgroundcolor", Text.translatable("widgets.widgets.basictext.background"), 0, 0, 0, 80),
new ToggleWidgetSetting("rainbow", translatable("widgets.widgets.common.rainbow"), false),
new RGBAColorWidgetSetting("textcolor", Text.translatable("widgets.widgets.basictext.textcolor"), 255, 255, 255, 255),
new IntSliderWidgetSetting("rainbow_speed", translatable("widgets.widgets.common.rainbow.speed"), 1, 3, 10),
new GradientWidgetSetting("backgroundcolor", Text.translatable("widgets.widgets.basictext.background"), 0x50_00_00_00),
new GradientWidgetSetting("textcolor", Text.translatable("widgets.widgets.basictext.textcolor"), 0xffffffff),
new IntSliderWidgetSetting("width", Text.translatable("widgets.widgets.basictext.width"), 10, WIDTH, 80*3),
new IntSliderWidgetSetting("paddingX", Text.translatable("widgets.widgets.basictext.paddingX"), 0, 5, 20),
new IntSliderWidgetSetting("paddingY", Text.translatable("widgets.widgets.basictext.paddingY"), 0, 5, 20),
new ToggleWidgetSetting("shadow", Text.translatable("widgets.widgets.basictext.textshadow"), true)
));
getSettings().optionById("textcolor").setShowCondition(() -> !this.rainbow);
getSettings().optionById("rainbow_speed").setShowCondition(() -> this.rainbow);
}
private String textX = "X", textY = "Y", textZ = "Z";
private int txc = 0, tyc = 0, tzc = 0, rainbowSpeed = 3;
private boolean shadow = true, rainbow = false;
private int txc = 0, tyc = 0, tzc = 0;
private boolean shadow = true;
@Override
public void renderScaled(DrawContext context, long mt, TextRenderer textRenderer, int posX, int posY) {
context.fill(posX, posY, posX + width(), posY + height(), this.backgroundColor);
this.backgroundColor.fillHorizontal(context, mt, posX, posY, posX + width(), posY + height());
int y = this.paddingY;
if (showX){
y++;
context.drawText(textRenderer, "X: ", posX + paddingX, posY + y, textColor(mt), shadow);
context.drawText(textRenderer, textX, posX + txc, posY + y, textColor(mt), shadow);
this.textColor.drawText(context, textRenderer, mt, "X: ", posX + paddingX, posY + y, shadow);
this.textColor.drawText(context, textRenderer, mt, textX, posX + txc, posY + y, shadow);
y += textRenderer.fontHeight + 1;
}
if (showY){
y++;
context.drawText(textRenderer, "Y: ", posX + paddingX, posY + y, textColor(mt), shadow);
context.drawText(textRenderer, textY, posX + tyc, posY + y, textColor(mt), shadow);
this.textColor.drawText(context, textRenderer, mt, "Y: ", posX + paddingX, posY + y, shadow);
this.textColor.drawText(context, textRenderer, mt, textY, posX + tyc, posY + y, shadow);
y += textRenderer.fontHeight + 1;
}
if (showZ){
y++;
context.drawText(textRenderer, "Z: ", posX + paddingX, posY + y, textColor(mt), shadow);
context.drawText(textRenderer, textZ, posX + tzc, posY + y, textColor(mt), shadow);
this.textColor.drawText(context, textRenderer, mt, "Z: ", posX + paddingX, posY + y, shadow);
this.textColor.drawText(context, textRenderer, mt, textZ, posX + tzc, posY + y, shadow);
}
}
private int textColor(long n) {
return rainbow ? BasicTextWidget.rainbowColor(n, rainbowSpeed) : textColor;
}
@Override
public void tick() {
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
@@ -95,20 +86,17 @@ public class CoordinatesWidget extends ResizableWidget {
return Text.translatable("widgets.widgets.coordinates.description");
}
protected static final int
WIDTH = 80,
PADDING = 6,
DEFAULT_BACKGROUND_COLOR = new Color(0, 0, 0, 80).getRGB(),
DEFAULT_TEXT_COLOR = new Color(255, 255 ,255, 255).getRGB();
protected static final int WIDTH = 80, PADDING = 6;
protected int backgroundColor = DEFAULT_BACKGROUND_COLOR, textColor = DEFAULT_TEXT_COLOR, paddingX = PADDING, paddingY = PADDING, width = WIDTH;
protected GradientOptions backgroundColor, textColor;
protected int paddingX = PADDING, paddingY = PADDING, width = WIDTH;
protected boolean showX = true, showY = true, showZ = true;
@Override
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
this.backgroundColor = (int) settings.optionById("backgroundcolor").getValue();
this.textColor = (int) settings.optionById("textcolor").getValue();
this.backgroundColor = (GradientOptions) settings.optionById("backgroundcolor").getValue();
this.textColor = (GradientOptions) settings.optionById("textcolor").getValue();
this.showX = (boolean) settings.optionById("x").getValue();
this.showY = (boolean) settings.optionById("y").getValue();
this.showZ = (boolean) settings.optionById("z").getValue();
@@ -116,8 +104,6 @@ public class CoordinatesWidget extends ResizableWidget {
this.paddingY = (int) settings.optionById("paddingY").getValue();
this.width = (int) settings.optionById("width").getValue();
this.shadow = (boolean) settings.optionById("shadow").getValue();
this.rainbow = (boolean) settings.optionById("rainbow").getValue();
this.rainbowSpeed = (int) settings.optionById("rainbow_speed").getValue();
}
@Override
@@ -1,10 +1,8 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.EnumWidgetSetting;
import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting;
import de.shiewk.widgets.widgets.settings.RGBAColorWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gl.RenderPipelines;
@@ -51,34 +49,18 @@ public class InventoryWidget extends ResizableWidget {
super(id, List.of(
new EnumWidgetSetting<>("mode", translatable("widgets.widgets.inventory.mode"), InventoryMode.class, InventoryMode.TEXTURE_PACK, InventoryMode::display),
new ToggleWidgetSetting("show_hotbar", translatable("widgets.widgets.inventory.showHotbar"), true),
new ToggleWidgetSetting("rainbow_grid", translatable("widgets.widgets.inventory.rainbowGrid"), false),
new IntSliderWidgetSetting("grid_rainbow_speed", translatable("widgets.widgets.common.rainbow.speed"), 1, 3, 10),
new RGBAColorWidgetSetting("grid_color", translatable("widgets.widgets.inventory.gridColor"), 0, 0, 0, 255),
new ToggleWidgetSetting("rainbow_boxes", translatable("widgets.widgets.inventory.rainbowBoxes"), false),
new IntSliderWidgetSetting("box_rainbow_speed", translatable("widgets.widgets.common.rainbow.speed"), 1, 3, 10),
new RGBAColorWidgetSetting("box_color", translatable("widgets.widgets.inventory.boxColor"), 80, 80, 80, 128)
new GradientWidgetSetting("grid_color", translatable("widgets.widgets.inventory.gridColor"), 0xff000000),
new GradientWidgetSetting("box_color", translatable("widgets.widgets.inventory.boxColor"), 0x88505050)
));
getSettings().optionById("rainbow_grid").setShowCondition(() -> this.mode == InventoryMode.GRID);
getSettings().optionById("grid_rainbow_speed").setShowCondition(() -> this.mode == InventoryMode.GRID && this.rainbowGrid);
getSettings().optionById("grid_color").setShowCondition(() -> this.mode == InventoryMode.GRID && !this.rainbowGrid);
getSettings().optionById("rainbow_boxes").setShowCondition(() -> this.mode == InventoryMode.BOXES);
getSettings().optionById("box_rainbow_speed").setShowCondition(() -> this.mode == InventoryMode.BOXES && this.rainbowBoxes);
getSettings().optionById("box_color").setShowCondition(() -> this.mode == InventoryMode.BOXES && !this.rainbowBoxes);
getSettings().optionById("grid_color").setShowCondition(() -> this.mode == InventoryMode.GRID);
getSettings().optionById("box_color").setShowCondition(() -> this.mode == InventoryMode.BOXES);
getSettings().optionById("show_hotbar").setShowCondition(() -> this.mode.canDisableHotbar);
}
private InventoryMode mode = InventoryMode.TEXTURE_PACK;
private PlayerInventory inventory;
private boolean rainbowGrid = false;
private int gridColor = 0xff000000;
private int gridRainbowSpeed = 3;
private boolean rainbowBoxes = false;
private int boxColor = 0xff000000;
private int boxRainbowSpeed = 3;
private GradientOptions gridColor, boxColor;
private boolean showHotbar = false;
@Override
@@ -109,30 +91,28 @@ public class InventoryWidget extends ResizableWidget {
context.disableScissor();
}
case GRID -> {
int gridColor = rainbowGrid ? BasicTextWidget.rainbowColor(mt, gridRainbowSpeed) : this.gridColor;
context.drawHorizontalLine(posX, posX+width(), posY, gridColor);
context.drawHorizontalLine(posX, posX+width(), posY + 18, gridColor);
context.drawHorizontalLine(posX, posX+width(), posY + 36, gridColor);
context.drawHorizontalLine(posX, posX+width(), posY + 54, gridColor);
gridColor.drawHorizontalLine(context, mt, posX, posX+width(), posY);
gridColor.drawHorizontalLine(context, mt, posX, posX+width(), posY + 18);
gridColor.drawHorizontalLine(context, mt, posX, posX+width(), posY + 36);
gridColor.drawHorizontalLine(context, mt, posX, posX+width(), posY + 54);
if (showHotbar){
context.drawHorizontalLine(posX, posX+width(), posY + 58, gridColor);
context.drawHorizontalLine(posX, posX+width(), posY + 76, gridColor);
gridColor.drawHorizontalLine(context, mt, posX, posX+width(), posY + 58);
gridColor.drawHorizontalLine(context, mt, posX, posX+width(), posY + 76);
}
context.drawVerticalLine(posX, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*2, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*3, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*4, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*5, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*6, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*7, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*8, posY, posY+height(), gridColor);
context.drawVerticalLine(posX+18*9, posY, posY+height(), gridColor);
gridColor.drawVerticalLine(context, mt, posX, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*2, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*3, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*4, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*5, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*6, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*7, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*8, posY, posY+height());
gridColor.drawVerticalLine(context, mt, posX+18*9, posY, posY+height());
}
case BOXES -> {
int boxColor = rainbowBoxes ? ((BasicTextWidget.rainbowColor(mt, boxRainbowSpeed) & 0xffffff) | (this.boxColor & 0xff000000)) : this.boxColor;
for (int ry = 0; ry < 4; ry++) {
if (ry == 0 && !showHotbar) continue;
for (int rx = 0; rx < 9; rx++) {
@@ -140,7 +120,7 @@ public class InventoryWidget extends ResizableWidget {
int itemY = ry == 0 ? posY + 58 : posY + (ry-1) * 18;
int itemX = posX + rx * 18;
context.fill(itemX, itemY, itemX + 16, itemY + 16, boxColor);
boxColor.fillHorizontal(context, mt, itemX, itemY, itemX + 16, itemY + 16);
}
}
}
@@ -206,13 +186,9 @@ public class InventoryWidget extends ResizableWidget {
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
this.mode = (InventoryMode) settings.optionById("mode").getValue();
this.rainbowGrid = (boolean) settings.optionById("rainbow_grid").getValue();
this.gridRainbowSpeed = (int) settings.optionById("grid_rainbow_speed").getValue();
this.gridColor = (int) settings.optionById("grid_color").getValue();
this.rainbowBoxes = (boolean) settings.optionById("rainbow_boxes").getValue();
this.boxRainbowSpeed = (int) settings.optionById("box_rainbow_speed").getValue();
this.boxColor = (int) settings.optionById("box_color").getValue();
this.gridColor = (GradientOptions) settings.optionById("grid_color").getValue();
this.boxColor = (GradientOptions) settings.optionById("box_color").getValue();
this.showHotbar = (boolean) settings.optionById("show_hotbar").getValue() || !mode.canDisableHotbar;
}
@@ -1,8 +1,8 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting;
import de.shiewk.widgets.widgets.settings.RGBAColorWidgetSetting;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.GradientWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
@@ -11,40 +11,24 @@ import net.minecraft.client.option.KeyBinding;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import java.awt.*;
import java.util.List;
import java.util.Objects;
import static net.minecraft.text.Text.translatable;
public class KeyStrokesWidget extends ResizableWidget {
public KeyStrokesWidget(Identifier id) {
super(id, List.of(
new ToggleWidgetSetting("showjump", Text.translatable("widgets.widgets.keystrokes.showJumpKey"), true),
new RGBAColorWidgetSetting("bgpressed", Text.translatable("widgets.widgets.keystrokes.colorBackgroundPressed"), 255, 255, 255, 80),
new RGBAColorWidgetSetting("bgunpressed", Text.translatable("widgets.widgets.keystrokes.colorBackgroundUnpressed"), 0, 0, 0, 80),
new ToggleWidgetSetting("rainbow", translatable("widgets.widgets.common.rainbow"), false),
new IntSliderWidgetSetting("rainbow_speed", translatable("widgets.widgets.common.rainbow.speed"), 1, 3, 10),
new RGBAColorWidgetSetting("keypressed", Text.translatable("widgets.widgets.keystrokes.colorKeyPressed"), 255, 255, 255, 255),
new RGBAColorWidgetSetting("keyunpressed", Text.translatable("widgets.widgets.keystrokes.colorKeyUnpressed"), 255, 255, 255, 255)
new GradientWidgetSetting("bgpressed", Text.translatable("widgets.widgets.keystrokes.colorBackgroundPressed"), 0x50ffffff),
new GradientWidgetSetting("bgunpressed", Text.translatable("widgets.widgets.keystrokes.colorBackgroundUnpressed"), 0x50000000),
new GradientWidgetSetting("keypressed", Text.translatable("widgets.widgets.keystrokes.colorKeyPressed"), 0xffffffff),
new GradientWidgetSetting("keyunpressed", Text.translatable("widgets.widgets.keystrokes.colorKeyUnpressed"), 0xffffffff)
));
getSettings().optionById("keypressed").setShowCondition(() -> !this.rainbow);
getSettings().optionById("keyunpressed").setShowCondition(() -> !this.rainbow);
getSettings().optionById("rainbow_speed").setShowCondition(() -> this.rainbow);
}
private GradientOptions colorBackgroundPressed, colorBackgroundUnpressed, colorKeyUnpressed, colorKeyPressed;
private boolean showJumpKey = true;
private int colorBackgroundPressed = new Color(255, 255, 255, 80).getRGB(),
colorBackgroundUnpressed = new Color(0, 0, 0, 80).getRGB(),
colorKeyUnpressed = 0xffffffff,
colorKeyPressed = 0xffffffff;
protected boolean rainbow = false;
protected int rainbowSpeed = 3;
protected static class Key {
protected final KeyBinding binding;
protected boolean isPressed;
@@ -78,49 +62,28 @@ public class KeyStrokesWidget extends ResizableWidget {
if (showJumpKey) renderSpaceBar(context, measuringTimeNano, posX, posY + 44, KEY_JUMP);
}
protected void renderSpaceBar(final DrawContext context,
final long measuringTimeNano,
final int posX,
final int posY,
final Key key){
long l = measuringTimeNano - key.lastChanged;
protected void renderSpaceBar(final DrawContext context, long mt, int posX, int posY, Key key){
long l = mt - key.lastChanged;
if (l < 100000000){
if (key.isPressed){
context.fill(posX, posY, posX + 64, posY + 10, fadeColor(colorBackgroundUnpressed, colorBackgroundPressed, 0.00000001d * l));
} else {
context.fill(posX, posY, posX + 64, posY + 10, fadeColor(colorBackgroundPressed, colorBackgroundUnpressed, 0.00000001d * l));
}
double alpha = 0.00000001d * l;
colorBackgroundUnpressed.multiplyAlpha(key.isPressed ? 1-alpha : alpha).fillHorizontal(context, mt, posX, posY, posX + 64, posY + 10);
colorBackgroundPressed.multiplyAlpha(key.isPressed ? alpha : 1-alpha).fillHorizontal(context, mt, posX, posY, posX + 64, posY + 10);
} else {
context.fill(posX, posY, posX + 64, posY + 10, key.isPressed ? colorBackgroundPressed : colorBackgroundUnpressed);
(key.isPressed ? colorBackgroundPressed : colorBackgroundUnpressed).fillHorizontal(context, mt, posX, posY, posX + 64, posY + 10);
}
context.fill(posX + 5, posY + 4, posX + 59, posY + 5, rainbow ? BasicTextWidget.rainbowColor(measuringTimeNano, rainbowSpeed) : (key.isPressed ? colorKeyPressed : colorKeyUnpressed));
(key.isPressed ? colorKeyPressed : colorKeyUnpressed).fillHorizontal(context, mt, posX + 5, posY + 4, posX + 59, posY + 5);
}
protected void renderKeyStroke(final DrawContext context,
final TextRenderer textRenderer,
final long measuringTimeNano,
final int posX,
final int posY,
final KeyLarge key){
long l = measuringTimeNano - key.lastChanged;
protected void renderKeyStroke(DrawContext context, TextRenderer textRenderer, long mt, int posX, int posY, KeyLarge key){
long l = mt - key.lastChanged;
if (l < 100000000){
if (key.isPressed){
context.fill(posX, posY, posX+20, posY+20, fadeColor(colorBackgroundUnpressed, colorBackgroundPressed, 0.00000001d * l));
} else {
context.fill(posX, posY, posX+20, posY+20, fadeColor(colorBackgroundPressed, colorBackgroundUnpressed, 0.00000001d * l));
}
double alpha = 0.00000001d * l;
colorBackgroundUnpressed.multiplyAlpha(key.isPressed ? 1-alpha : alpha).fillHorizontal(context, mt, posX, posY, posX + 20, posY + 20);
colorBackgroundPressed.multiplyAlpha(key.isPressed ? alpha : 1-alpha).fillHorizontal(context, mt, posX, posY, posX + 20, posY + 20);
} else {
context.fill(posX, posY, posX+20, posY+20, key.isPressed ? colorBackgroundPressed : colorBackgroundUnpressed);
(key.isPressed ? colorBackgroundPressed : colorBackgroundUnpressed).fillHorizontal(context, mt, posX, posY, posX + 20, posY + 20);
}
context.drawText(textRenderer, key.boundToKey, posX+10-(key.boundToLength/2), posY + 6, rainbow ? BasicTextWidget.rainbowColor(measuringTimeNano, rainbowSpeed) : (key.isPressed ? colorKeyPressed : colorKeyUnpressed), true);
}
private int fadeColor(int color1, int color2, double delta) {
int alpha = (int) MathHelper.lerp(delta, (color1 >> 24) & 0xff, (color2 >> 24) & 0xff);
int red = (int) MathHelper.lerp(delta, (color1 >> 16) & 0xff, (color2 >> 16) & 0xff);
int green = (int) MathHelper.lerp(delta, (color1 >> 8) & 0xff, (color2 >> 8) & 0xff);
int blue = (int) MathHelper.lerp(delta, color1 & 0xff, color2 & 0xff);
return (alpha << 24) | (red << 16) | (green << 8) | blue;
(key.isPressed ? colorKeyPressed : colorKeyUnpressed).drawText(context, textRenderer, mt, key.boundToKey, posX+10-(key.boundToLength/2), posY+6, true);
}
@Override
@@ -168,11 +131,9 @@ public class KeyStrokesWidget extends ResizableWidget {
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
this.showJumpKey = (boolean) settings.optionById("showjump").getValue();
this.colorBackgroundPressed = (int) settings.optionById("bgpressed").getValue();
this.colorBackgroundUnpressed = (int) settings.optionById("bgunpressed").getValue();
this.colorKeyPressed = (int) settings.optionById("keypressed").getValue();
this.colorKeyUnpressed = (int) settings.optionById("keyunpressed").getValue();
this.rainbow = (boolean) settings.optionById("rainbow").getValue();
this.rainbowSpeed = (int) settings.optionById("rainbow_speed").getValue();
this.colorBackgroundPressed = (GradientOptions) settings.optionById("bgpressed").getValue();
this.colorBackgroundUnpressed = (GradientOptions) settings.optionById("bgunpressed").getValue();
this.colorKeyPressed = (GradientOptions) settings.optionById("keypressed").getValue();
this.colorKeyUnpressed = (GradientOptions) settings.optionById("keyunpressed").getValue();
}
}
@@ -1,6 +1,7 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.utils.WidgetUtils;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
@@ -21,9 +22,7 @@ public class PingWidget extends BasicTextWidget {
new ToggleWidgetSetting("dynamic_color", Text.translatable("widgets.widgets.ping.dynamicColor"), true),
new ToggleWidgetSetting("hide_in_singleplayer", Text.translatable("widgets.widgets.common.hideInSingleplayer"), false)
));
getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor && !this.rainbow);
getSettings().optionById("rainbow").setShowCondition(() -> !this.dynamicColor);
getSettings().optionById("rainbow_speed").setShowCondition(() -> !this.dynamicColor && this.rainbow);
getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor);
}
private boolean dynamicColor = false;
@@ -53,18 +52,18 @@ public class PingWidget extends BasicTextWidget {
}
if (valuesRead == 0){
formatAndSetRenderText(literal("??? ms"));
if (this.dynamicColor) this.textColor = 0xff00ff00;
if (this.dynamicColor) this.textColor = GradientOptions.solidColor(0xff00ff00);
return;
}
long avgPing = ping / valuesRead;
formatAndSetRenderText(literal(avgPing + " ms"));
if (this.dynamicColor){
if (avgPing < 50){
this.textColor = 0xff00ff00;
this.textColor = GradientOptions.solidColor(0xff00ff00);
} else if (avgPing < 120) {
this.textColor = 0xffffff00;
this.textColor = GradientOptions.solidColor(0xffffff00);
} else {
this.textColor = 0xffff3030;
this.textColor = GradientOptions.solidColor(0xffff3030);
}
}
}
@@ -2,6 +2,7 @@ package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.WidgetsMod;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
@@ -22,9 +23,7 @@ public class TPSWidget extends BasicTextWidget {
new ToggleWidgetSetting("dynamic_color", translatable("widgets.widgets.tps.dynamicColor"), true),
new IntSliderWidgetSetting("window_size", translatable("widgets.widgets.tps.windowSize"), 2, 5, 20)
));
getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor && !this.rainbow);
getSettings().optionById("rainbow").setShowCondition(() -> !this.dynamicColor);
getSettings().optionById("rainbow_speed").setShowCondition(() -> !this.dynamicColor && this.rainbow);
getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor);
}
public static final TPSWidget INSTANCE = new TPSWidget(Identifier.of(WidgetsMod.MOD_ID, "tps"));
@@ -86,7 +85,7 @@ public class TPSWidget extends BasicTextWidget {
} else {
formatAndSetRenderText(literal("???"));
}
if (dynamicColor) this.textColor = 0xff00ff00;
if (dynamicColor) this.textColor = GradientOptions.solidColor(0xff00ff00);
} else {
tps = Math.round(tps * 10f) / 10f;
if (showLabel){
@@ -96,11 +95,11 @@ public class TPSWidget extends BasicTextWidget {
}
if (dynamicColor){
if (tps >= targetTickRate * 0.990){
this.textColor = 0xff00ff00;
this.textColor = GradientOptions.solidColor(0xff00ff00);
} else if (tps >= targetTickRate * 0.740){
this.textColor = 0xffffff00;
this.textColor = GradientOptions.solidColor(0xffffff00);
} else {
this.textColor = 0xffff0000;
this.textColor = GradientOptions.solidColor(0xffff0000);
}
}
}
@@ -0,0 +1,129 @@
package de.shiewk.widgets.widgets.settings;
import com.google.gson.JsonElement;
import de.shiewk.widgets.client.screen.WidgetSettingsScreen;
import de.shiewk.widgets.client.screen.gradienteditor.GradientEditorScreen;
import de.shiewk.widgets.color.GradientMode;
import de.shiewk.widgets.color.GradientOptions;
import de.shiewk.widgets.utils.WidgetUtils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.cursor.StandardCursors;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import static de.shiewk.widgets.client.WidgetManager.gson;
import static de.shiewk.widgets.utils.WidgetUtils.colorARGBToHexRGBA;
public class GradientWidgetSetting extends WidgetSettingOption<GradientOptions> {
public GradientWidgetSetting(String id, Text name, GradientMode defaultMode, int defaultGradientSize, int defaultGradientSpeed, int defaultColor) {
super(id, name);
this.value = new GradientOptions(
defaultMode,
defaultGradientSize,
defaultGradientSpeed,
new int[]{defaultColor}
);
}
public GradientWidgetSetting(String id, Text name, int defaultColor) {
this(id, name, GradientMode.SWEEP, 40, 10, defaultColor);
}
private GradientOptions value;
@Override
public JsonElement saveState() {
return gson.toJsonTree(getValue());
}
@Override
public void loadState(JsonElement state) {
if (state.isJsonPrimitive() && state.getAsJsonPrimitive().isNumber()){
this.value = new GradientOptions(
this.value.mode(),
this.value.gradientSize(),
this.value.gradientSpeed(),
new int[]{ state.getAsInt() }
);
} else {
this.value = gson.fromJson(state, GradientOptions.class);
}
}
@Override
public GradientOptions getValue() {
return this.value;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
final long n = Util.getMeasuringTimeNano();
GradientOptions gradient = this.getValue();
gradient.fillHorizontal(
context,
n,
getX(),
getY(),
getX() + getWidth(),
getY() + getHeight()
);
int outlineColor;
String displayText;
int[] colors = gradient.colors();
if (colors.length == 1){
outlineColor = colors[0] | 0xff_00_00_00;
displayText = "#" + colorARGBToHexRGBA(colors[0]);
} else {
outlineColor = 0xff_ff_ff_ff;
displayText = Text.translatable("widgets.ui.widgetSettings.colors", colors.length).getString();
}
context.drawHorizontalLine(getX(), getX()+getWidth(), getY(), outlineColor);
context.drawHorizontalLine(getX(), getX()+getWidth(), getY()+getHeight(), outlineColor);
context.drawVerticalLine(getX(), getY(), getY() + getHeight(), outlineColor);
context.drawVerticalLine(getX() + getWidth(), getY(), getY() + getHeight(), outlineColor);
int width = textRenderer.getWidth(displayText);
context.drawText(
textRenderer,
displayText,
getX() + (getWidth() / 2 - (width / 2)),
getY() + (getHeight() / 2 - 4),
0xff_ff_ff_ff,
true
);
if (this.isHovered(mouseX, mouseY)){
context.setCursor(StandardCursors.POINTING_HAND);
}
}
@Override
public int getWidth() {
return 72;
}
@Override
public int getHeight() {
return 24;
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.currentScreen instanceof WidgetSettingsScreen screen) {
WidgetUtils.playSound(SoundEvents.BLOCK_COPPER_BULB_TURN_ON);
client.setScreen(new GradientEditorScreen(client.currentScreen, screen.getWidget(), this, screen.getOnChange()));
}
return true;
}
public void setValue(GradientOptions value) {
this.value = value;
}
}
@@ -2,6 +2,7 @@ package de.shiewk.widgets.widgets.settings;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import de.shiewk.widgets.client.screen.WidgetVisibilityToggle;
import de.shiewk.widgets.utils.WidgetUtils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
@@ -19,6 +20,10 @@ import org.jetbrains.annotations.NotNull;
import java.awt.*;
/**
* @deprecated Use {@link GradientWidgetSetting}
*/
@Deprecated(forRemoval = true, since = "2.3.0")
public class RGBAColorWidgetSetting extends WidgetSettingOption<Integer> {
public RGBAColorWidgetSetting(String id, Text name, int defaultR, int defaultG, int defaultB, int defaultAlpha) {
super(id, name);
@@ -118,7 +123,7 @@ public class RGBAColorWidgetSetting extends WidgetSettingOption<Integer> {
return true;
}
public class ChangeScreen extends Screen {
public class ChangeScreen extends Screen implements WidgetVisibilityToggle {
private final Screen parent;
private int x;
@@ -205,6 +210,11 @@ public class RGBAColorWidgetSetting extends WidgetSettingOption<Integer> {
return super.mouseClicked(click, doubled);
}
@Override
public boolean shouldRenderWidgets() {
return false;
}
public class ColorBar extends ClickableWidget {
private final int component;
@@ -14,6 +14,7 @@ import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
public abstract class WidgetSettingOption<T> implements Drawable, Widget {
private final String id;
private final Text name;
private int x = 0;
@@ -1,6 +1,11 @@
{
"widgets.gradient.preset.rainbow": "Regenbogen",
"widgets.gradient.pulse": "Pulse",
"widgets.gradient.pulse.description": "Färbt Text oder Oberfläche mit einer einzelnen Farbe und geht dabei zwischen den ausgewählten Farben über",
"widgets.gradient.sweep": "Sweep",
"widgets.gradient.sweep.description": "Färbt Text oder Oberfläche mit einem sich bewegenden Farbverlauf",
"widgets.key.category": "Widgets",
"widgets.key.config": "Öffne Widgets-Einstellungen",
"widgets.key.config": "Widgets-Einstellungen öffnen",
"widgets.ui.anchor.bottom_center": "Unten mittig",
"widgets.ui.anchor.bottom_left": "Unten links",
"widgets.ui.anchor.bottom_right": "Unten rechts",
@@ -20,9 +25,24 @@
"widgets.ui.editPositions.snap": "Positionen ausrichten: %s",
"widgets.ui.editPositions.snap.help": "Richtet die Position des Widgets mit Positionen der anderen Widgets aus",
"widgets.ui.enabled": "Aktiviert",
"widgets.ui.gradientEditor": "Farbe bearbeiten",
"widgets.ui.gradientEditor.colors": "Dieser Verlauf:",
"widgets.ui.gradientEditor.colors.add.tooltip.0": "Diesem Farbverlauf eine Farbe hinzufügen",
"widgets.ui.gradientEditor.colors.add.tooltip.1": "(Bleibe bei einer Farbe, um den Farbverlauf zu deaktivieren)",
"widgets.ui.gradientEditor.editColor": "Farbe bearbeiten:",
"widgets.ui.gradientEditor.editColor.orPick": "Alternative Auswahl:",
"widgets.ui.gradientEditor.gradientSettings": "Verlaufsoptionen:",
"widgets.ui.gradientEditor.gradientSettings.addMoreColors": "Füge mindestens zwei Farben hinzu, um den Farbverlauf zu bearbeiten.",
"widgets.ui.gradientEditor.importOther": "Von Widget importieren",
"widgets.ui.gradientEditor.mode": "Modus: %s",
"widgets.ui.gradientEditor.removeColor": "Farbe entfernen",
"widgets.ui.gradientEditor.size": "Größe: %s%%",
"widgets.ui.gradientEditor.speed": "Geschwindigkeit: %s%%",
"widgets.ui.gradientEditor.usePreset": "Voreinstellung nutzen",
"widgets.ui.preview": "Vorschau",
"widgets.ui.search": "Suchen...",
"widgets.ui.widgetSettings": "Bearbeite %s Einstellungen",
"widgets.ui.widgetSettings.colors": "%s Farben",
"widgets.widgets.armorHud": "Rüstungsstatus",
"widgets.widgets.armorHud.description": "Zeigt die Rüstung, die du gerade trägst, und ihre Haltbarkeit.",
"widgets.widgets.armorHud.durabilityStyle": "Haltbarkeitsstil",
@@ -31,7 +51,7 @@
"widgets.widgets.armorHud.padding": "Abstand",
"widgets.widgets.armorHud.showDurability": "Haltbarkeitsbeschriftung anzeigen",
"widgets.widgets.bandwidth": "Bandbreite",
"widgets.widgets.bandwidth.description": "Zeigt, wie viele Daten an den aktuell Server gesendet werden/vom Server an den Klient gesendet werden.",
"widgets.widgets.bandwidth.description": "Zeigt, wie viele Daten aktuell vom Server an den Klienten gesendet werden.",
"widgets.widgets.bandwidth.dynamicColor": "Farbe dynamisch anzeigen",
"widgets.widgets.bandwidth.fastupdate": "Schnelle Aktualisierung",
"widgets.widgets.bandwidth.unit": "Einheit",
@@ -70,8 +90,6 @@
"widgets.widgets.combo.description": "Zeigt deine momentane Combo an",
"widgets.widgets.combo.displayThreshold": "Minimum sichtbar",
"widgets.widgets.common.hideInSingleplayer": "In Einzelspielerwelten verbergen",
"widgets.widgets.common.rainbow": "Regenbogen-Text",
"widgets.widgets.common.rainbow.speed": "Regenbogengeschwindigkeit",
"widgets.widgets.common.realtime": "Echtzeit-Update (braucht mehr Leistung)",
"widgets.widgets.common.showLabel": "Beschriftung anzeigen",
"widgets.widgets.common.sizePercent": "Widgetgröße (%)",
@@ -101,8 +119,6 @@
"widgets.widgets.inventory.mode.texture_pack": "Texturenpaket",
"widgets.widgets.inventory.mode.transparent": "Transparent",
"widgets.widgets.inventory.mode.vanilla": "Standard",
"widgets.widgets.inventory.rainbowBoxes": "Regenbogenzellen",
"widgets.widgets.inventory.rainbowGrid": "Regenbogengitter",
"widgets.widgets.inventory.showHotbar": "Schnellzugriffsleiste anzeigen",
"widgets.widgets.keystrokes": "Keystrokes",
"widgets.widgets.keystrokes.colorBackgroundPressed": "Hintergrundfarbe (Taste gedrückt)",
@@ -1,4 +1,9 @@
{
"widgets.gradient.preset.rainbow": "Rainbow",
"widgets.gradient.pulse": "Pulse",
"widgets.gradient.pulse.description": "Paints the text or surface with one solid color, cycling through your selected palette",
"widgets.gradient.sweep": "Sweep",
"widgets.gradient.sweep.description": "Paints the text or surface with a moving gradient",
"widgets.key.category": "Widgets",
"widgets.key.config": "Open Widget Management",
"widgets.ui.anchor.bottom_center": "Bottom center",
@@ -20,9 +25,24 @@
"widgets.ui.editPositions.snap": "Align positions: %s",
"widgets.ui.editPositions.snap.help": "Aligns the widget with positions of other widgets",
"widgets.ui.enabled": "Enabled",
"widgets.ui.gradientEditor": "Color editor",
"widgets.ui.gradientEditor.colors": "This gradient:",
"widgets.ui.gradientEditor.colors.add.tooltip.0": "Add a color to this gradient",
"widgets.ui.gradientEditor.colors.add.tooltip.1": "(Leave this as one color to disable the gradient)",
"widgets.ui.gradientEditor.editColor": "Edit color:",
"widgets.ui.gradientEditor.editColor.orPick": "Alternative picker:",
"widgets.ui.gradientEditor.gradientSettings": "Gradient settings:",
"widgets.ui.gradientEditor.gradientSettings.addMoreColors": "Add more than one color to customize the gradient",
"widgets.ui.gradientEditor.importOther": "Import from widget",
"widgets.ui.gradientEditor.mode": "Mode: %s",
"widgets.ui.gradientEditor.removeColor": "Remove color",
"widgets.ui.gradientEditor.size": "Size: %s%%",
"widgets.ui.gradientEditor.speed": "Speed: %s%%",
"widgets.ui.gradientEditor.usePreset": "Use preset",
"widgets.ui.preview": "Preview",
"widgets.ui.search": "Search...",
"widgets.ui.widgetSettings": "Edit %s settings",
"widgets.ui.widgetSettings.colors": "%s colors",
"widgets.widgets.armorHud": "Armor Status",
"widgets.widgets.armorHud.description": "Shows the armor you are currently wearing and its durability.",
"widgets.widgets.armorHud.durabilityStyle": "Durability style",
@@ -31,7 +51,7 @@
"widgets.widgets.armorHud.padding": "Padding",
"widgets.widgets.armorHud.showDurability": "Show durability label",
"widgets.widgets.bandwidth": "Bandwidth",
"widgets.widgets.bandwidth.description": "Shows how much data is being read/sent from the server you're connected to.",
"widgets.widgets.bandwidth.description": "Shows how much data the server you're connected to is sending.",
"widgets.widgets.bandwidth.dynamicColor": "Dynamic Color",
"widgets.widgets.bandwidth.fastupdate": "Fast update",
"widgets.widgets.bandwidth.unit": "Unit",
@@ -70,8 +90,6 @@
"widgets.widgets.combo.description": "Shows your current Combo.",
"widgets.widgets.combo.displayThreshold": "Display Threshold",
"widgets.widgets.common.hideInSingleplayer": "Hide in singleplayer worlds",
"widgets.widgets.common.rainbow": "Rainbow text",
"widgets.widgets.common.rainbow.speed": "Rainbow speed",
"widgets.widgets.common.realtime": "Real-time updating (may use more performance)",
"widgets.widgets.common.showLabel": "Show label",
"widgets.widgets.common.sizePercent": "Widget size (%)",
@@ -101,8 +119,6 @@
"widgets.widgets.inventory.mode.texture_pack": "Texture pack",
"widgets.widgets.inventory.mode.transparent": "Transparent",
"widgets.widgets.inventory.mode.vanilla": "Vanilla",
"widgets.widgets.inventory.rainbowBoxes": "Rainbow boxes",
"widgets.widgets.inventory.rainbowGrid": "Rainbow Grid",
"widgets.widgets.inventory.showHotbar": "Show hotbar",
"widgets.widgets.keystrokes": "Keystrokes",
"widgets.widgets.keystrokes.colorBackgroundPressed": "Background color (key pressed)",
Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B