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

Initial Commit (1.0)

This commit is contained in:
Shy
2024-09-07 18:54:20 +02:00
commit 6ef0f3758d
42 changed files with 2893 additions and 0 deletions
@@ -0,0 +1,8 @@
package de.shiewk.widgets;
public interface Dimensionable {
int width();
int height();
double getX(int mx);
double getY(int my);
}
@@ -0,0 +1,13 @@
package de.shiewk.widgets;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import de.shiewk.widgets.client.screen.WidgetConfigScreen;
public class ModMenuConfig implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return WidgetConfigScreen::new;
}
}
@@ -0,0 +1,45 @@
package de.shiewk.widgets;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.List;
import java.util.Objects;
public abstract class ModWidget implements Dimensionable {
private final Identifier id;
private final WidgetSettings settings;
protected ModWidget(Identifier id, List<WidgetSettingOption> customSettings) {
Objects.requireNonNull(id, "id");
this.id = id;
this.settings = WidgetSettings.ofId(id, customSettings);
}
public final Identifier getId() {
return id;
}
public final WidgetSettings getSettings() {
return settings;
}
public abstract void render(DrawContext context, long measuringTimeNano, TextRenderer textRenderer, int posX, int posY);
public abstract void tick();
public abstract Text getName();
public abstract Text getDescription();
public abstract void onSettingsChanged(WidgetSettings settings);
@Override
public double getX(int mx) {
return (int) WidgetUtils.translateToScreen(settings.posX, mx);
}
@Override
public double getY(int my) {
return (int) WidgetUtils.translateToScreen(settings.posY, my);
}
}
@@ -0,0 +1,86 @@
package de.shiewk.widgets;
import com.google.gson.JsonElement;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.text.Text;
import java.util.function.Consumer;
public abstract class WidgetSettingOption implements Drawable, Widget {
private final String id;
private final Text name;
private int x = 0;
private int y = 0;
private boolean focused = false;
protected WidgetSettingOption(String id, Text name) {
this.id = id;
this.name = name;
}
public final String getId() {
return id;
}
public final Text getName() {
return name;
}
public abstract JsonElement saveState();
public abstract void loadState(JsonElement state);
public boolean mouseClicked(double mouseX, double mouseY, int button) {
return false;
}
public boolean mouseReleased(double mouseX, double mouseY, int button){
return false;
}
public boolean charTyped(char chr, int modifiers) {
return false;
}
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
return false;
}
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
return false;
}
@Override
public void setX(int x) {
this.x = x;
}
@Override
public void setY(int y) {
this.y = y;
}
@Override
public int getX() {
return x;
}
@Override
public int getY() {
return y;
}
@Override
public final void forEachChild(Consumer<ClickableWidget> consumer) {
throw new UnsupportedOperationException();
}
public boolean isFocused() {
return focused;
}
public void setFocused(boolean focused) {
this.focused = focused;
}
}
@@ -0,0 +1,104 @@
package de.shiewk.widgets;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.shiewk.widgets.client.WidgetManager;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import java.util.List;
import static de.shiewk.widgets.WidgetUtils.translateToWidgetSettingsValue;
import static de.shiewk.widgets.WidgetsMod.LOGGER;
public class WidgetSettings {
public double posX = 0; // posx * 100 = screen width
public double posY = 0; // posy * 100 = screen height
private boolean enabled = false;
private final ObjectArrayList<WidgetSettingOption> customSettings;
private WidgetSettings(JsonObject data, List<WidgetSettingOption> settings){
customSettings = new ObjectArrayList<>(settings);
if (data != null){
final JsonElement enabled = data.get("enabled");
this.enabled = enabled.isJsonPrimitive() && enabled.getAsJsonPrimitive().isBoolean() && enabled.getAsBoolean();
final JsonElement x = data.get("x");
this.posX = x.isJsonPrimitive() ? x.getAsJsonPrimitive().isNumber() ? x.getAsDouble() : 0 : 0;
final JsonElement y = data.get("y");
this.posY = y.isJsonPrimitive() ? y.getAsJsonPrimitive().isNumber() ? y.getAsDouble() : 0 : 0;
final JsonElement s = data.get("settings");
if (s != null && s.isJsonObject()){
final JsonObject savedSettings = s.getAsJsonObject();
for (WidgetSettingOption setting : this.customSettings) {
final String settingId = setting.getId();
if (savedSettings.has(settingId)){
try {
setting.loadState(savedSettings.get(settingId));
} catch (Throwable e){
LOGGER.error("Could not load setting '{}' from element {}:", settingId, savedSettings.get(settingId));
LOGGER.error(e.toString());
for (StackTraceElement element : e.getStackTrace()) {
LOGGER.error(element.toString());
}
}
}
}
}
}
}
public static WidgetSettings ofId(Identifier id, List<WidgetSettingOption> customSettings){
final JsonObject data = WidgetManager.loadWidget(id);
return new WidgetSettings(data, customSettings);
}
public void setPosX(double v, int widgetWidth, int maxWidth) {
posX = MathHelper.clamp(v, 0, 100 - translateToWidgetSettingsValue(widgetWidth, maxWidth));
}
public void setPosY(double v, int widgetHeight, int maxHeight) {
posY = MathHelper.clamp(v, 0, 100 - translateToWidgetSettingsValue(widgetHeight, maxHeight));
}
public boolean isEnabled(){
return enabled;
}
public void setEnabled(ModWidget widget, boolean enabled){
this.enabled = enabled;
if (enabled){
WidgetManager.enable(widget);
} else {
WidgetManager.disable(widget);
}
}
public void toggleEnabled(ModWidget widget){
setEnabled(widget, !enabled);
}
public final JsonObject saveState(){
JsonObject object = new JsonObject();
object.addProperty("x", posX);
object.addProperty("y", posY);
object.addProperty("enabled", enabled);
JsonObject customSettings = new JsonObject();
for (WidgetSettingOption customSetting : this.customSettings) {
customSettings.add(customSetting.getId(), customSetting.saveState());
}
object.add("settings", customSettings);
return object;
}
public WidgetSettingOption optionById(String id){
for (WidgetSettingOption customSetting : customSettings) {
if (customSetting.getId().equals(id)){
return customSetting;
}
}
return null;
}
public ObjectArrayList<WidgetSettingOption> getCustomSettings() {
return customSettings.clone();
}
}
@@ -0,0 +1,18 @@
package de.shiewk.widgets;
public class WidgetUtils {
public static double translateToWidgetSettingsValue(double value, int max){
return (value / max) * 100;
}
public static double translateToScreen(double value, int max){
return value / 100d * max;
}
public static double computeEasing(double x) {
return 1d - Math.pow(1d - x, 3.5d);
}
}
@@ -0,0 +1,14 @@
package de.shiewk.widgets;
import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class WidgetsMod implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("Widgets");
public static final String MOD_ID = "widgets";
@Override
public void onInitialize() {
}
}
@@ -0,0 +1,98 @@
package de.shiewk.widgets.client;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonWriter;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetsMod;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.function.Function;
public class WidgetManager {
static final ObjectArrayList<ModWidget> enabled = new ObjectArrayList<>(); // for performance
private static final ObjectArrayList<ModWidget> allWidgets = new ObjectArrayList<>();
public static void register(ModWidget widget){
allWidgets.add(widget);
if (widget.getSettings().isEnabled()){
enable(widget);
}
}
public static ObjectArrayList<ModWidget> getEnabledWidgets() {
return new ObjectArrayList<>(enabled);
}
public static ObjectArrayList<ModWidget> getAllWidgets() {
return new ObjectArrayList<>(allWidgets);
}
public static void enable(ModWidget widget) {
enabled.add(widget);
}
public static void disable(ModWidget widget) {
enabled.remove(widget);
}
static Function<Identifier, File> saveFileFactory;
private static final Gson gson = new Gson();
public static void saveWidgets(List<ModWidget> widgets) {
for (ModWidget widget : widgets) {
WidgetsMod.LOGGER.info("Saving widget {}", widget.getId());
final File saveFile = saveFileFactory.apply(widget.getId());
try {
if (saveFile.getParentFile().isDirectory() || saveFile.getParentFile().mkdirs()){
if (saveFile.isFile() || saveFile.createNewFile()){
try (FileWriter fw = new FileWriter(saveFile)){
try (JsonWriter jw = new JsonWriter(fw)){
Streams.write(widget.getSettings().saveState(), jw);
}
}
} else {
WidgetsMod.LOGGER.error("Could not create file: {}", saveFile.getPath());
}
} else {
WidgetsMod.LOGGER.error("Could not create directory: {}", saveFile.getParentFile().getPath());
}
} catch (IOException e){
WidgetsMod.LOGGER.error("An I/O operation failed while saving widget {} ({})", widget, widget.getId());
WidgetsMod.LOGGER.error(e.toString());
for (StackTraceElement element : e.getStackTrace()) {
WidgetsMod.LOGGER.error(String.valueOf(element));
}
}
}
}
public static @Nullable JsonObject loadWidget(Identifier id) {
WidgetsMod.LOGGER.info("Loading widget data of {}", id);
final File saveFile = saveFileFactory.apply(id);
if (!saveFile.isFile()){
return null;
}
try {
try (FileReader fr = new FileReader(saveFile)){
return gson.fromJson(fr, JsonObject.class);
}
} catch (IOException e){
WidgetsMod.LOGGER.error("An I/O operation failed while loading widget {}", id);
WidgetsMod.LOGGER.error(e.toString());
for (StackTraceElement element : e.getStackTrace()) {
WidgetsMod.LOGGER.error(String.valueOf(element));
}
return null;
}
}
}
@@ -0,0 +1,78 @@
package de.shiewk.widgets.client;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.client.screen.EditWidgetPositionsScreen;
import de.shiewk.widgets.client.screen.WidgetConfigScreen;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.util.Util;
import net.minecraft.util.profiler.Profiler;
import static de.shiewk.widgets.WidgetUtils.translateToScreen;
public class WidgetRenderer implements HudRenderCallback, ClientTickEvents.StartTick, ClientLifecycleEvents.ClientStarted {
private static MinecraftClient client;
@Override
public void onHudRender(DrawContext drawContext, RenderTickCounter tickCounter) {
if (client.options.hudHidden) return;
if (client.currentScreen instanceof EditWidgetPositionsScreen) return;
final Profiler profiler = client.getProfiler();
profiler.push("widgets");
final TextRenderer textRenderer = client.textRenderer;
final long timeNano = Util.getMeasuringTimeNano();
final int windowWidth = drawContext.getScaledWindowWidth();
final int windowHeight = drawContext.getScaledWindowHeight();
final ObjectArrayList<ModWidget> enabled = WidgetManager.enabled;
for (int i = 0, enabledSize = enabled.size(); i < enabledSize; i++) {
final ModWidget widget = enabled.get(i);
profiler.push(widget.getId().toString());
final WidgetSettings settings = widget.getSettings();
widget.render(
drawContext,
timeNano,
textRenderer,
(int) Math.round(Math.min(translateToScreen(settings.posX, windowWidth), windowWidth - widget.width())),
(int) Math.round(Math.min(translateToScreen(settings.posY, windowHeight), windowHeight - widget.height()))
);
profiler.pop();
}
profiler.pop();
}
@Override
public void onStartTick(MinecraftClient client) {
final Profiler profiler = (WidgetRenderer.client = client).getProfiler();
profiler.push("widgets");
final ObjectArrayList<ModWidget> enabled = WidgetManager.enabled;
for (int i = 0, enabledSize = enabled.size(); i < enabledSize; i++) {
final ModWidget widget = enabled.get(i);
profiler.push(widget.getId().toString());
widget.tick();
profiler.pop();
}
profiler.pop();
if (WidgetsModClient.configKeyBinding.wasPressed()){
client.setScreen(new WidgetConfigScreen(client.currentScreen));
}
}
@Override
public void onClientStarted(MinecraftClient client) {
for (ModWidget widget : WidgetManager.getAllWidgets()) {
widget.onSettingsChanged(widget.getSettings());
}
}
}
@@ -0,0 +1,62 @@
package de.shiewk.widgets.client;
import de.shiewk.widgets.WidgetsMod;
import de.shiewk.widgets.client.screen.WidgetConfigScreen;
import de.shiewk.widgets.widgets.*;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
import java.io.File;
public class WidgetsModClient implements ClientModInitializer {
static KeyBinding configKeyBinding;
@Override
public void onInitializeClient() {
HudRenderCallback.EVENT.register(new WidgetRenderer());
ClientTickEvents.START_CLIENT_TICK.register(new WidgetRenderer());
ClientLifecycleEvents.CLIENT_STARTED.register(new WidgetRenderer());
// manage widgets keybind
configKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"widgets.key.config",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_RIGHT_SHIFT,
"widgets.key.category"
));
// in-game /widgetsmod command
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) ->
dispatcher.register(ClientCommandManager.literal("widgetsmod").executes(ctx -> {
WidgetsMod.LOGGER.info("Ran in-game command");
final MinecraftClient client = ctx.getSource().getClient();
client.send(() -> client.setScreen(new WidgetConfigScreen(client.currentScreen)));
return 0;
})
)
);
WidgetManager.saveFileFactory = id -> new File(MinecraftClient.getInstance().runDirectory.getPath() + "/config/widgets/" + id.getNamespace() + "/" + id.getPath() + ".json");
WidgetManager.register(new FPSWidget(Identifier.of(WidgetsMod.MOD_ID, "fps")));
WidgetManager.register(new ClockWidget(Identifier.of(WidgetsMod.MOD_ID, "clock")));
WidgetManager.register(new CoordinatesWidget(Identifier.of(WidgetsMod.MOD_ID, "coordinates")));
WidgetManager.register(new BandwidthWidget(Identifier.of(WidgetsMod.MOD_ID, "bandwidth")));
WidgetManager.register(new PingWidget(Identifier.of(WidgetsMod.MOD_ID, "ping")));
WidgetManager.register(new ServerIPWidget(Identifier.of(WidgetsMod.MOD_ID, "server_ip")));
WidgetManager.register(new PlayerCountWidget(Identifier.of(WidgetsMod.MOD_ID, "player_count")));
WidgetManager.register(new CPSWidget(Identifier.of(WidgetsMod.MOD_ID, "cps")));
}
}
@@ -0,0 +1,39 @@
package de.shiewk.widgets.client.screen;
import de.shiewk.widgets.WidgetUtils;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
public abstract class AnimatedScreen extends Screen {
protected final Screen parent;
private final int animationDurationMs;
private final long creationTime = Util.getMeasuringTimeNano();
protected AnimatedScreen(Text title, Screen parent, int animationDurationMs) {
super(title);
this.parent = parent;
this.animationDurationMs = animationDurationMs;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
double timeMs = (Util.getMeasuringTimeNano() - creationTime) / 1000000d;
final boolean shouldAnimate = timeMs < animationDurationMs;
if (shouldAnimate){
double translation = WidgetUtils.computeEasing(timeMs / animationDurationMs) * this.width;
context.getMatrices().push();
context.getMatrices().translate(-translation, 0, 0);
parent.render(context, (int) (mouseX + translation), mouseY, delta);
context.getMatrices().translate(this.width, 0, 0);
mouseX -= (int) translation;
}
super.render(context, mouseX, mouseY, delta);
this.renderScreenContents(context, mouseX, mouseY, delta);
if (shouldAnimate){
context.getMatrices().pop();
}
}
public abstract void renderScreenContents(DrawContext context, int mouseX, int mouseY, float delta);
}
@@ -0,0 +1,198 @@
package de.shiewk.widgets.client.screen;
import de.shiewk.widgets.Dimensionable;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.client.WidgetManager;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
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.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.function.Consumer;
import static de.shiewk.widgets.WidgetUtils.translateToScreen;
import static de.shiewk.widgets.WidgetUtils.translateToWidgetSettingsValue;
public class EditWidgetPositionsScreen extends AnimatedScreen {
private record Alignment(int x, int y, int width, int height) implements Dimensionable {
@Override
public double getX(int mx) {
return x;
}
@Override
public double getY(int my) {
return y;
}
}
private final Screen parent;
private final Consumer<ModWidget> onEdit;
private boolean alignX = true;
private boolean alignY = true;
public EditWidgetPositionsScreen(Screen parent, Consumer<ModWidget> onEdit) {
super(Text.translatable("widgets.ui.editPositions"), parent, 500);
this.parent = parent;
this.onEdit = onEdit;
}
@Override
public void close() {
assert client != null;
client.setScreen(parent);
}
private record AlignResult(double result, boolean isEnd){}
private @Nullable AlignResult alignX(double x, int width, ModWidget widget){
double endX = x + width;
int factor = alignX ? 2 : 0;
for (Dimensionable rect : this.getAlignments(widget)) {
if (rect == widget) continue;
final double nwx = rect.getX(this.width);
final double nww = rect.width();
if (endX < nwx + factor && endX > nwx - factor){
return new AlignResult(nwx - width, true);
} else if (x < nwx + factor && x > nwx - factor){
return new AlignResult(nwx, false);
} else if (endX < nwx+nww + factor && endX > nwx + nww - factor){
return new AlignResult(nwx + nww - width, true);
} else if (x < nwx+nww + factor && x > nwx + nww - factor){
return new AlignResult(nwx + nww, false);
}
}
return null;
}
private Iterable<? extends Dimensionable> getAlignments(Dimensionable rel) {
ObjectArrayList<Dimensionable> alignments = new ObjectArrayList<>();
for (ModWidget widget : WidgetManager.getEnabledWidgets()) {
alignments.add(widget);
}
alignments.add(new Alignment(2, 2, this.width / 2 - 2, this.height / 2 - 2));
alignments.add(new Alignment(this.width / 2, this.height / 2, this.width / 2 - 2, this.height / 2 - 2));
alignments.add(new Alignment(2, this.height / 2, this.width / 2 - 2, this.height / 2 - 2));
alignments.add(new Alignment(this.width / 2, 2, this.width / 2 - 2, this.height / 2 - 2));
alignments.add(new Alignment(this.width / 2 - rel.width() / 2, this.height / 2 - rel.height() / 2, rel.width(), rel.height()));
return alignments;
}
private @Nullable AlignResult alignY(double y, int height, ModWidget widget){
double endY = y + height;
int factor = alignY ? 2 : 0;
for (Dimensionable rect : this.getAlignments(widget)) {
if (rect == widget) continue;
final double nwy = rect.getY(this.height);
final double nwh = rect.height();
if (endY < nwy + factor && endY > nwy - factor){
return new AlignResult(nwy - height, true);
} else if (y < nwy + factor && y > nwy - factor){
return new AlignResult(nwy, false);
} else if (endY < nwy+nwh + factor && endY > nwy + nwh - factor){
return new AlignResult(nwy + nwh - height, true);
} else if (y < nwy+nwh + factor && y > nwy + nwh - factor){
return new AlignResult(nwy + nwh, false);
}
}
return null;
}
private static final int SELECT_COLOR = Color.GREEN.getRGB(), ALIGN_COLOR = Color.ORANGE.getRGB(), ALIGN_DISABLED_COLOR = Color.GRAY.getRGB();
private ModWidget selectedWidget = null;
private ModWidget hoveredWidget = null;
@Override
public void renderScreenContents(DrawContext context, int mouseX, int mouseY, float delta) {
assert client != null;
for (ModWidget widget : WidgetManager.getEnabledWidgets()) {
final WidgetSettings settings = widget.getSettings();
final int ww = widget.width();
double wx = Math.min(translateToScreen(settings.posX, this.width), this.width - ww);
final int wh = widget.height();
double wy = Math.min(translateToScreen(settings.posY, this.height), this.height - wh);
if (selectedWidget == widget){
final AlignResult alignedX = alignX(wx, ww, widget);
if (alignedX != null){
context.drawVerticalLine((int) (!alignedX.isEnd() ? alignedX.result() : alignedX.result() + ww), 0, this.height, alignX ? ALIGN_COLOR : ALIGN_DISABLED_COLOR);
wx = alignedX.result();
}
final AlignResult alignedY = alignY(wy, wh, widget);
if (alignedY != null){
context.drawHorizontalLine(0, this.width, (int) (!alignedY.isEnd() ? alignedY.result() : alignedY.result() + wh), alignY ? ALIGN_COLOR : ALIGN_DISABLED_COLOR);
wy = alignedY.result();
}
}
if (hoveredWidget == null || hoveredWidget == widget){
if (mouseX <= wx + ww && mouseX >= wx && mouseY <= wy + wh && mouseY >= wy){
if (hoveredWidget == null){
hoveredWidget = widget;
}
} else {
hoveredWidget = null;
}
}
if (selectedWidget == null ? hoveredWidget == widget : selectedWidget == widget){
context.drawBorder((int) Math.round(wx-1), (int) Math.round(wy-1), ww+2, wh+2, SELECT_COLOR);
context.drawBorder((int) Math.round(wx), (int) Math.round(wy), ww, wh, SELECT_COLOR);
}
widget.render(context, Util.getMeasuringTimeNano(), textRenderer, (int) Math.round(wx), (int) Math.round(wy));
}
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
if (button == 0 && selectedWidget != null){
final AlignResult alignedX = alignX(translateToScreen(selectedWidget.getSettings().posX, this.width), selectedWidget.width(), selectedWidget);
if (alignedX != null){
selectedWidget.getSettings().setPosX(translateToWidgetSettingsValue(alignedX.result(), this.width), selectedWidget.width(), this.width);
}
final AlignResult alignedY = alignY(translateToScreen(selectedWidget.getSettings().posY, this.height), selectedWidget.height(), selectedWidget);
if (alignedY != null){
selectedWidget.getSettings().setPosY(translateToWidgetSettingsValue(alignedY.result(), this.height), selectedWidget.height(), this.height);
}
onEdit.accept(selectedWidget);
selectedWidget = null;
}
return super.mouseReleased(mouseX, mouseY, button);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (button == 0 && hoveredWidget != null){
selectedWidget = hoveredWidget;
}
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (button == 0){
assert client != null;
final ModWidget widget = selectedWidget;
if (widget != null){
final WidgetSettings settings = widget.getSettings();
final int ww = widget.width();
final int wx = (int) Math.min(translateToScreen(settings.posX, this.width), this.width - ww);
final int wh = widget.height();
final int wy = (int) Math.min(translateToScreen(settings.posY, this.height), this.height - wh);
if (mouseX <= wx + ww + deltaX && mouseX >= wx + deltaX){
if (mouseY <= wy + wh + deltaY && mouseY >= wy + deltaY){
double newPosX = settings.posX + translateToWidgetSettingsValue(deltaX, this.width);
double newPosY = settings.posY + translateToWidgetSettingsValue(deltaY, this.height);
settings.setPosX(newPosX, ww, this.width);
settings.setPosY(newPosY, wh, this.height);
return true;
}
}
}
}
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
}
@@ -0,0 +1,129 @@
package de.shiewk.widgets.client.screen;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetUtils;
import de.shiewk.widgets.client.WidgetManager;
import de.shiewk.widgets.client.screen.components.WidgetListWidget;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.AxisGridWidget;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import java.util.ArrayList;
import java.util.Objects;
import java.util.function.Consumer;
public class WidgetConfigScreen extends Screen {
private final Screen parent;
private final long creationTime = Util.getMeasuringTimeNano();
private String search = "";
private WidgetListWidget widgetList = null;
private final ArrayList<ModWidget> widgetsEdited = new ArrayList<>();
private final Consumer<ModWidget> onWidgetEdit = this::changedSettings;
private double getScreenTimeMs(){
return (Util.getMeasuringTimeNano() - creationTime) / 1000000d;
}
public WidgetConfigScreen(Screen parent) {
super(Text.translatable("widgets.ui.config"));
this.parent = parent;
}
@Override
public void close() {
WidgetManager.saveWidgets(widgetsEdited);
for (ModWidget widget : widgetsEdited) {
widget.onSettingsChanged(widget.getSettings());
}
assert client != null;
client.setScreen(parent);
}
@Override
protected void init() {
super.init();
AxisGridWidget agw = new AxisGridWidget(3, height - 22, width - 6, 20, AxisGridWidget.DisplayAxis.HORIZONTAL);
final TextFieldWidget searchField = new TextFieldWidget(textRenderer, this.width - 160, 20, Text.empty());
searchField.setPlaceholder(Text.translatable("widgets.ui.search"));
searchField.setChangedListener(this::search);
if (this.widgetList != null){
searchField.setText(this.getSearchQuery());
}
agw.add(searchField);
agw.add(new ButtonWidget.Builder(Text.translatable("widgets.ui.editPositions"), this::switchToEditPositions).build());
agw.refreshPositions();
agw.forEachChild(this::addDrawableChild);
if (Objects.equals(search, "")){
search("");
}
}
private String getSearchQuery() {
return search;
}
public void setSearchQuery(String search) {
this.search = search;
}
private void search(String query) {
this.setSearchQuery(query);
widgetList = new WidgetListWidget(0, 0, width-4, height-24, Text.translatable("widgets.ui.config"), client, WidgetManager.getAllWidgets().stream().filter(this::searchQueryMatches).toList(), textRenderer, this.onWidgetEdit);
}
private void switchToEditPositions(ButtonWidget widget) {
widget.active = false;
assert client != null;
client.setScreen(new EditWidgetPositionsScreen(this, this.onWidgetEdit));
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (super.mouseClicked(mouseX, mouseY, button)){
return true;
} else return widgetList.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
if (super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount)){
return true;
} else return widgetList.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
assert client != null;
final double time = getScreenTimeMs();
if (time < 400){
context.getMatrices().push();
final float v = (float) WidgetUtils.computeEasing(time / 400d);
context.getMatrices().translate(width / 2d - (width * v / 2d), height / 2d - (height * v / 2d), 0);
context.getMatrices().scale(v, v, 1);
}
super.render(context, mouseX, mouseY, delta);
if (widgetList != null){
widgetList.render(context, mouseX, mouseY, delta);
}
if (time < 400){
context.getMatrices().pop();
}
}
private boolean searchQueryMatches(ModWidget widget) {
return widget.getName().getString().contains(search) || widget.getDescription().getString().contains(search) || widget.getId().toString().contains(search);
}
public void changedSettings(ModWidget widget) {
if (!widgetsEdited.contains(widget)){
widgetsEdited.add(widget);
}
}
}
@@ -0,0 +1,50 @@
package de.shiewk.widgets.client.screen;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.client.screen.components.WidgetSettingsEditWidget;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
public class WidgetSettingsScreen extends AnimatedScreen {
private static final Text previewText = Text.translatable("widgets.ui.preview");
private final ModWidget widget;
private final Runnable onChange;
public WidgetSettingsScreen(Screen parent, ModWidget widget) {
super(Text.translatable("widgets.ui.widgetSettings", widget.getName()), parent, 500);
this.widget = widget;
onChange = () -> {
widget.onSettingsChanged(widget.getSettings());
if (parent instanceof WidgetConfigScreen widgetConfigScreen){
widgetConfigScreen.changedSettings(widget);
}
};
}
@Override
protected void init() {
super.init();
addDrawableChild(new WidgetSettingsEditWidget(0, 0, this.width / 2 - 8, this.height, textRenderer, widget, this.onChange));
}
@Override
public void renderScreenContents(DrawContext context, int mouseX, int mouseY, float delta) {
context.drawText(textRenderer, previewText, this.width * 3 / 4 - textRenderer.getWidth(previewText) / 2, this.height / 50, 0xffffffff, false);
widget.render(context, Util.getMeasuringTimeNano(), textRenderer, this.width * 3 / 4 - widget.width() / 2, this.height / 2 - widget.height() / 2);
}
@Override
public void close() {
assert client != null;
client.setScreen(parent);
}
@Override
public void tick() {
super.tick();
if (!widget.getSettings().isEnabled()){
widget.tick();
}
}
}
@@ -0,0 +1,92 @@
package de.shiewk.widgets.client.screen.components;
import de.shiewk.widgets.ModWidget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.client.gui.screen.narration.NarrationPart;
import net.minecraft.client.gui.widget.GridWidget;
import net.minecraft.client.gui.widget.ScrollableWidget;
import net.minecraft.client.gui.widget.SimplePositioningWidget;
import net.minecraft.text.Text;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class WidgetListWidget extends ScrollableWidget {
private final MinecraftClient client;
private final List<ModWidget> widgets;
private final List<WidgetWidget> elements = new ArrayList<>();
private final TextRenderer textRenderer;
private final Consumer<ModWidget> onEdit;
public WidgetListWidget(int x, int y, int width, int height, Text message, MinecraftClient client, List<ModWidget> widgets, TextRenderer textRenderer, Consumer<ModWidget> onEdit) {
super(x, y, width, height, message);
this.client = client;
this.widgets = widgets;
this.textRenderer = textRenderer;
this.onEdit = onEdit;
init();
}
private void init(){
GridWidget gw = new GridWidget();
gw.getMainPositioner().margin(4, 4, 4, 4);
final GridWidget.Adder adder = gw.createAdder(this.width / 208);
for (ModWidget widget : widgets) {
adder.add(new WidgetWidget(0, 0, 200, 100, client, widget, textRenderer, onEdit));
}
gw.refreshPositions();
SimplePositioningWidget.setPos(gw, 0, 0, this.width, this.getContentsHeight(), 0.5F, 0.5F);
gw.forEachChild(w -> this.addWidget((WidgetWidget) w));
}
protected void addWidget(WidgetWidget drawableElement) {
this.elements.add(drawableElement);
}
@Override
protected int getContentsHeight() {
final int rowSize = this.width / 208;
final int rows = widgets.size() % rowSize == 0 ? widgets.size() / rowSize : widgets.size() / rowSize + 1;
return 10 + (rows * 108);
}
@Override
protected double getDeltaYPerScroll() {
return 35;
}
@Override
protected void renderContents(DrawContext context, int mouseX, int mouseY, float delta) {
for (WidgetWidget element : elements) {
element.render(context, mouseX, (int) (mouseY + getScrollY()), delta);
}
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouseY += getScrollY();
for (Element element : elements) {
if (element.mouseClicked(mouseX, mouseY, 0)){
return true;
}
}
return false;
}
@Override
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
for (ModWidget widget : widgets) {
builder.put(NarrationPart.HINT, widget.getName());
}
}
@Override
protected void drawBox(DrawContext context, int x, int y, int width, int height) {}
}
@@ -0,0 +1,135 @@
package de.shiewk.widgets.client.screen.components;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetSettingOption;
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.widget.ScrollableWidget;
import net.minecraft.text.Text;
import java.awt.*;
public class WidgetSettingsEditWidget extends ScrollableWidget {
private static final int COLOR_FG = Color.WHITE.getRGB(), COLOR_BG = new Color(0, 0, 0, 60).getRGB();
private final TextRenderer textRenderer;
private final ModWidget widget;
private final Runnable onChange;
private WidgetSettingOption focus = null;
private int contentsHeight = 10;
public WidgetSettingsEditWidget(int x, int y, int width, int height, TextRenderer textRenderer, ModWidget widget, Runnable onChange) {
super(x, y, width, height, Text.empty());
this.textRenderer = textRenderer;
this.widget = widget;
this.onChange = onChange;
for (WidgetSettingOption customSetting : widget.getSettings().getCustomSettings()) {
customSetting.setFocused(false);
}
}
@Override
protected int getContentsHeight() {
return this.contentsHeight;
}
@Override
protected double getDeltaYPerScroll() {
return 20;
}
@Override
protected void renderContents(DrawContext context, int mouseX, int mouseY, float delta) {
context.getMatrices().push();
context.getMatrices().scale(2, 2, 2);
context.drawText(textRenderer, widget.getName(), this.width / 4 - textRenderer.getWidth(widget.getName()) / 2, this.height / 100, COLOR_FG, true);
context.getMatrices().pop();
int y = textRenderer.fontHeight * 2 + this.height / 50 + 5;
for (WidgetSettingOption setting : widget.getSettings().getCustomSettings()) {
if (this.width - setting.getWidth() > textRenderer.getWidth(setting.getName()) + 20){
setting.setX(this.getX() + this.width - setting.getWidth() - 5);
setting.setY(y);
context.drawText(textRenderer, setting.getName(), getX() + 10, y + (setting.getHeight() / 2), COLOR_FG, true);
} else {
setting.setX(this.getX() + this.width / 2 - setting.getWidth() / 2);
setting.setY(y + 9 + 5);
context.drawText(textRenderer, setting.getName(), getX() + getWidth() / 2 - textRenderer.getWidth(setting.getName()) / 2, y, COLOR_FG, true);
y += 9 + 5;
}
setting.render(context, mouseX, (int) (mouseY + getScrollY()), delta);
y += setting.getHeight();
y += 5;
}
this.contentsHeight = y;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouseY += getScrollY();
for (WidgetSettingOption customSetting : widget.getSettings().getCustomSettings()) {
if (mouseX >= customSetting.getX() && mouseX <= customSetting.getX() + customSetting.getWidth()
&& mouseY >= customSetting.getY() && mouseY <= customSetting.getY() + customSetting.getHeight()){
focus = customSetting;
customSetting.setFocused(true);
if (customSetting.mouseClicked(mouseX, mouseY + getScrollY(), button)){
onChange.run();
return true;
}
}
}
return super.mouseClicked(mouseX, mouseY - getScrollY(), button);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
for (WidgetSettingOption customSetting : widget.getSettings().getCustomSettings()) {
if (customSetting.mouseReleased(mouseX, mouseY + getScrollY(), button)){
onChange.run();
return true;
}
}
return super.mouseReleased(mouseX, mouseY, button);
}
@Override
public boolean charTyped(char chr, int modifiers) {
if (this.focus != null){
if (this.focus.charTyped(chr, modifiers)){
onChange.run();
return true;
}
}
return super.charTyped(chr, modifiers);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (this.focus != null){
if (this.focus.keyPressed(keyCode, scanCode, modifiers)){
onChange.run();
return true;
}
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
if (this.focus != null){
if (this.focus.keyReleased(keyCode, scanCode, modifiers)){
onChange.run();
return true;
}
}
return super.keyReleased(keyCode, scanCode, modifiers);
}
@Override
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
}
@Override
protected void drawBox(DrawContext context, int x, int y, int width, int height) {
context.fill(x, y, x+width, y+height, COLOR_BG);
}
}
@@ -0,0 +1,130 @@
package de.shiewk.widgets.client.screen.components;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetUtils;
import de.shiewk.widgets.client.screen.WidgetSettingsScreen;
import net.minecraft.client.MinecraftClient;
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.widget.ClickableWidget;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import java.awt.*;
import java.util.Iterator;
import java.util.function.Consumer;
public class WidgetWidget extends ClickableWidget {
protected static final int COLOR_BG = new Color(0, 0, 0, 80).getRGB(),
COLOR_BG_HOVER = new Color(40, 40, 40, 80).getRGB(),
COLOR_FG = Color.WHITE.getRGB(),
COLOR_DISABLED = new Color(200, 0, 0, 200).getRGB(),
COLOR_DISABLED_HOVER = new Color(255, 0, 0, 200).getRGB(),
COLOR_ENABLED = new Color(0, 200, 0, 200).getRGB(),
COLOR_ENABLED_HOVER = new Color(0, 255, 0, 200).getRGB();
private final MinecraftClient client;
private final ModWidget widget;
private final TextRenderer textRenderer;
private final Consumer<ModWidget> onEdit;
private long toggleTime = 0;
public WidgetWidget(int x, int y, int width, int height, MinecraftClient client, ModWidget widget, TextRenderer textRenderer, Consumer<ModWidget> onEdit) {
super(x, y, width, height, widget.getName());
this.client = client;
this.widget = widget;
this.textRenderer = textRenderer;
this.onEdit = onEdit;
}
@Override
public boolean isMouseOver(double mouseX, double mouseY) {
return this.active && this.visible && mouseX >= (double)this.getX() && mouseY >= (double)this.getY() && mouseX < (double)(this.getX() + this.width) && mouseY < (double)(this.getY() + this.height - 24);
}
@Override
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
boolean hover = this.isMouseOver(mouseX, mouseY);
boolean widgetEnabled = widget.getSettings().isEnabled();
context.fill(this.getX(), this.getY(), this.getX() + this.getWidth(), this.getY() + this.getHeight(), hover ? COLOR_BG_HOVER : COLOR_BG);
context.getMatrices().push();
context.getMatrices().scale(2, 2, 1);
int titleSize = textRenderer.getWidth(widget.getName());
context.drawText(textRenderer, widget.getName(), getX() / 2 + getWidth() / 4 - titleSize / 2, getY() / 2 + 4, COLOR_FG, false);
context.getMatrices().pop();
int y = this.getY() + 12 + textRenderer.fontHeight * 2;
for (Iterator<OrderedText> it = textRenderer.wrapLines(widget.getDescription(), this.getWidth() - 10).iterator(); it.hasNext(); y += 9) {
OrderedText t = it.next();
context.drawText(textRenderer, t, getX() + 5 + ((getWidth() - 5) / 2) - (textRenderer.getWidth(t) / 2), y, COLOR_FG, false);
}
this.renderToggleButton(context, mouseX, mouseY, delta, widgetEnabled);
}
@Override
protected boolean clicked(double mouseX, double mouseY) {
if (isMouseOver(mouseX, mouseY)){
client.setScreen(new WidgetSettingsScreen(client.currentScreen, widget));
return true;
} else if (isMouseOverToggle(mouseX, mouseY)){
this.toggleWidget();
return true;
} else {
return false;
}
}
private void toggleWidget() {
widget.getSettings().toggleEnabled(widget);
toggleTime = Util.getMeasuringTimeNano();
onEdit.accept(widget);
}
private void renderToggleButton(DrawContext context, int mouseX, int mouseY, float delta, boolean widgetEnabled){
boolean hoverToggle = this.isMouseOverToggle(mouseX, mouseY);
final int toggleColor;
final int toggleColorInvert;
if (hoverToggle){
if (widgetEnabled){
toggleColor = COLOR_ENABLED_HOVER;
toggleColorInvert = COLOR_DISABLED_HOVER;
} else {
toggleColor = COLOR_DISABLED_HOVER;
toggleColorInvert = COLOR_ENABLED_HOVER;
}
} else {
if (widgetEnabled){
toggleColor = COLOR_ENABLED;
toggleColorInvert = COLOR_DISABLED;
} else {
toggleColor = COLOR_DISABLED;
toggleColorInvert = COLOR_ENABLED;
}
}
if (toggleTime > Util.getMeasuringTimeNano() - 250000000){
context.fill(this.getX(), this.getY() + this.getHeight() - 24, this.getX() + this.getWidth(), this.getY() + this.getHeight(), toggleColorInvert);
context.fill(this.getX(), this.getY() + this.getHeight() - 24, (int) (WidgetUtils.computeEasing((Util.getMeasuringTimeNano() - toggleTime) / 250000000d) * this.getWidth() + this.getX()), this.getY() + this.getHeight(), toggleColor);
} else {
context.fill(this.getX(), this.getY() + this.getHeight() - 24, this.getX() + this.getWidth(), this.getY() + this.getHeight(), toggleColor);
}
context.drawCenteredTextWithShadow(textRenderer, Text.translatable(widgetEnabled ? "widgets.ui.enabled" : "widgets.ui.disabled"), this.getX() + (this.getWidth() / 2), this.getY() + this.getHeight() - 16, COLOR_FG);
}
private boolean isMouseOverToggle(double mouseX, double mouseY) {
return this.active && this.visible && mouseX >= this.getX() && mouseY >= (this.getY() + this.height - 24) && mouseX < (this.getX() + this.width) && mouseY < (this.getY() + this.height);
}
@Override
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
}
public ModWidget getWidget() {
return widget;
}
}
@@ -0,0 +1,27 @@
package de.shiewk.widgets.mixin;
import de.shiewk.widgets.widgets.CPSWidget;
import net.minecraft.client.Mouse;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Mouse.class)
public class MixinMouse {
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/Mouse;leftButtonClicked:Z"), method = "onMouseButton")
public void onLeftClick(long window, int button, int action, int mods, CallbackInfo ci){
if (action == 1) CPSWidget.clickLeft();
}
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/Mouse;middleButtonClicked:Z"), method = "onMouseButton")
public void onMiddleClick(long window, int button, int action, int mods, CallbackInfo ci){
if (action == 1) CPSWidget.clickMiddle();
}
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/Mouse;rightButtonClicked:Z"), method = "onMouseButton")
public void onRightClick(long window, int button, int action, int mods, CallbackInfo ci){
if (action == 1) CPSWidget.clickRight();
}
}
@@ -0,0 +1,73 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.MultiValueDebugSampleLogImpl;
import java.util.List;
public class BandwidthWidget extends BasicTextWidget {
public BandwidthWidget(Identifier id) {
super(id, List.of(
new ToggleWidgetSetting("dynamic_color", Text.translatable("widgets.widgets.bandwidth.dynamicColor"), true)
));
}
private int t = 0;
private boolean dynamicColor = false;
@Override
public void tick() {
t++;
if (t >= 20){
t = 0;
final MultiValueDebugSampleLogImpl packetSizeLog = MinecraftClient.getInstance().getDebugHud().getPacketSizeLog();
final int logLength = packetSizeLog.getLength();
final int avgCompileLength = 60;
long size = 0;
for (int i = logLength-1; i > logLength-avgCompileLength; i--) {
if (i < 0) break;
size += packetSizeLog.get(i);
}
long avgBytesPerSecond = size / avgCompileLength * 20;
this.renderText = Text.of(formatByteSize(avgBytesPerSecond));
if (this.dynamicColor){
if (avgBytesPerSecond < 100000){
this.textColor = 0x00ff00;
} else if (avgBytesPerSecond < 750000) {
this.textColor = 0xffff00;
} else {
this.textColor = 0xff3030;
}
}
}
}
private String formatByteSize(long bytes) {
if (bytes > 1000) {
double mb = bytes / 100 / 10d;
return mb + " KB/s";
} else {
return bytes + " B/s";
}
}
@Override
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
this.dynamicColor = ((ToggleWidgetSetting) settings.optionById("dynamic_color")).getValue();
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.bandwidth");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.bandwidth.description");
}
}
@@ -0,0 +1,58 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetSettingOption;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.RGBAColorWidgetSetting;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.awt.*;
import java.util.List;
public abstract class BasicTextWidget extends ModWidget {
protected Text renderText = Text.empty();
private static ObjectArrayList<WidgetSettingOption> getCustomSettings(List<WidgetSettingOption> otherCustomOptions) {
final ObjectArrayList<WidgetSettingOption> list = new ObjectArrayList<>(otherCustomOptions);
list.add(new RGBAColorWidgetSetting("backgroundcolor", Text.translatable("widgets.widgets.basictext.background"), 0, 0, 0, 80));
list.add(new RGBAColorWidgetSetting("textcolor", Text.translatable("widgets.widgets.basictext.textcolor"), 255, 255, 255, 255));
return list;
}
protected BasicTextWidget(Identifier id, List<WidgetSettingOption> otherCustomOptions) {
super(id, getCustomSettings(otherCustomOptions));
}
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();
protected int backgroundColor = DEFAULT_BACKGROUND_COLOR, textColor = DEFAULT_TEXT_COLOR;
@Override
public int width() {
return DEFAULT_WIDTH;
}
@Override
public int height() {
return DEFAULT_HEIGHT;
}
@Override
public void render(DrawContext context, long n, TextRenderer textRenderer, int posX, int posY) {
context.fill(posX, posY, posX + width(), posY + height(), this.backgroundColor);
context.drawCenteredTextWithShadow(textRenderer, renderText, posX + (width() / 2), posY + 6, this.textColor);
}
@Override
public void onSettingsChanged(WidgetSettings settings) {
this.backgroundColor = ((RGBAColorWidgetSetting) settings.optionById("backgroundcolor")).getColor();
this.textColor = ((RGBAColorWidgetSetting) settings.optionById("textcolor")).getColor();
}
}
@@ -0,0 +1,136 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.EnumWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class CPSWidget extends BasicTextWidget {
public static class Click {
private int ticks = 0;
public int tick(){
return ticks++;
}
}
private static boolean countLeftClicks = true;
private static boolean countMiddleClicks = true;
private static boolean countRightClicks = true;
private static final ObjectArrayList<Click> leftClicks = new ObjectArrayList<>();
private static final ObjectArrayList<Click> middleClicks = new ObjectArrayList<>();
private static final ObjectArrayList<Click> rightClicks = new ObjectArrayList<>();
private Appearance appearance = Appearance.UNIFIED;
public enum Appearance {
SPLIT_PIPE("pipe"),
SPLIT_SLASH("slash"),
UNIFIED("unified");
public final String key;
Appearance(String key) {
this.key = key;
}
}
public CPSWidget(Identifier id) {
super(id, List.of(
new EnumWidgetSetting<>("appearance", Text.translatable("widgets.widgets.cps.appearance"), Appearance.class, Appearance.UNIFIED, appearance -> Text.translatable("widgets.widgets.cps.appearance."+appearance.key)),
new ToggleWidgetSetting("left", Text.translatable("widgets.widgets.cps.left"), true),
new ToggleWidgetSetting("middle", Text.translatable("widgets.widgets.cps.middle"), false),
new ToggleWidgetSetting("right", Text.translatable("widgets.widgets.cps.right"), true)
));
}
public static void clickLeft() {
if (countLeftClicks){
leftClicks.add(new Click());
}
}
public static void clickMiddle() {
if (countMiddleClicks){
middleClicks.add(new Click());
}
}
public static void clickRight() {
if (countRightClicks){
rightClicks.add(new Click());
}
}
@Override
public void tick() {
int left = 0;
int right = 0;
int middle = 0;
if (countLeftClicks) {
leftClicks.removeIf(click -> click.tick() >= 20);
left = leftClicks.size();
}
if (countRightClicks) {
rightClicks.removeIf(click -> click.tick() >= 20);
right = rightClicks.size();
}
if (countMiddleClicks) {
middleClicks.removeIf(click -> click.tick() >= 20);
middle = middleClicks.size();
}
switch (appearance){
case UNIFIED -> renderText = Text.literal((left + right + middle) + " CPS");
case SPLIT_PIPE, SPLIT_SLASH -> {
final StringBuilder sb = getClickText(left, middle, right);
renderText = Text.literal(sb + " CPS");
}
}
}
private @NotNull StringBuilder getClickText(int left, int middle, int right) {
StringBuilder sb = new StringBuilder();
if (countLeftClicks){
sb.append(left);
}
if (countMiddleClicks){
if (!sb.isEmpty()){
sb.append(appearance == Appearance.SPLIT_PIPE ? " | " : "/");
}
sb.append(middle);
}
if (countRightClicks){
if (!sb.isEmpty()){
sb.append(appearance == Appearance.SPLIT_PIPE ? " | " : "/");
}
sb.append(right);
}
return sb;
}
@Override
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
countLeftClicks = ((ToggleWidgetSetting) settings.optionById("left")).getValue();
countMiddleClicks = ((ToggleWidgetSetting) settings.optionById("middle")).getValue();
countRightClicks = ((ToggleWidgetSetting) settings.optionById("right")).getValue();
appearance = (Appearance) ((EnumWidgetSetting<?>) settings.optionById("appearance")).getValue();
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.cps");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.cps.description");
}
}
@@ -0,0 +1,149 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.EnumWidgetSetting;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.List;
public class ClockWidget extends BasicTextWidget {
private int width = DEFAULT_WIDTH;
public enum TimeOption {
NO_TIME("none"),
HOUR_24("24hour"),
AM_PM("am_pm");
public final String key;
TimeOption(String key) {
this.key = key;
}
}
public enum DateOption {
NO_DATE(null),
FULL_MONTH_DAY("MMMM dd"),
DAY_FULL_MONTH("dd. MMMM"),
ABB_MONTH_DAY("MMM dd"),
DAY_ABB_MONTH("dd. MMM"),
MONTH_DAY("MM/dd"),
MONTH_DAY_2("dd.MM"),
FULL_MONTH_DAY_YEAR("MMMM dd, y"),
ABB_MONTH_DAY_YEAR("MMM dd, y"),
DAY_FULL_MONTH_YEAR("dd. MMMM y"),
DAY_ABB_MONTH_YEAR("dd. MMM y"),
MONTH_DAY_YEAR("MM/dd/y"),
MONTH_DAY_YEAR_2("dd.MM.y");
public final String format;
DateOption(String format) {
this.format = format;
}
public Text getName(){
return this.format == null ? Text.translatable("widgets.widgets.clock.dateFormat.none") : Text.of(new SimpleDateFormat(format).format(Date.from(Instant.now())));
}
}
public enum WeekOption {
NO_DAY_OF_WEEK(null),
ABBREVIATED("E"),
FULL("EEEE");
public final String format;
WeekOption(String format) {
this.format = format;
}
public Text getName(){
return this.format == null ? Text.translatable("widgets.widgets.clock.weekFormat.none") : Text.of(new SimpleDateFormat(format).format(Date.from(Instant.now())));
}
}
public ClockWidget(Identifier id) {
super(id, List.of(
new EnumWidgetSetting<>("hour_format",
Text.translatable("widgets.widgets.clock.hourFormat"),
TimeOption.class,
TimeOption.HOUR_24,
timeOption -> Text.translatable("widgets.widgets.clock.hourFormat."+timeOption.key)),
new ToggleWidgetSetting("show_seconds",
Text.translatable("widgets.widgets.clock.showSeconds"),
true),
new EnumWidgetSetting<>("date_format",
Text.translatable("widgets.widgets.clock.dateFormat"),
DateOption.class,
DateOption.NO_DATE,
DateOption::getName),
new EnumWidgetSetting<>("week_format",
Text.translatable("widgets.widgets.clock.weekFormat"),
WeekOption.class,
WeekOption.NO_DAY_OF_WEEK,
WeekOption::getName)
));
}
private SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss aa EEEE");
@Override
public int width() {
return width;
}
@Override
public void tick() {
renderText = Text.literal(dateFormat.format(Date.from(Instant.now())));
}
@Override
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
String datePattern = "HH:mm:ss";
TimeOption timeOption = (TimeOption) ((EnumWidgetSetting<?>) settings.optionById("hour_format")).getValue();
DateOption dateOption = (DateOption) ((EnumWidgetSetting<?>) settings.optionById("date_format")).getValue();
WeekOption weekOption = (WeekOption) ((EnumWidgetSetting<?>) settings.optionById("week_format")).getValue();
boolean showSeconds = ((ToggleWidgetSetting) settings.optionById("show_seconds")).getValue();
if (timeOption == TimeOption.HOUR_24){
datePattern = showSeconds ? "HH:mm:ss" : "HH:mm";
} else if (timeOption == TimeOption.AM_PM){
datePattern = showSeconds ? "hh:mm:ss aa" : "hh:mm aa";
} else if (timeOption == TimeOption.NO_TIME){
datePattern = "";
}
if (dateOption.format != null){
if (datePattern.isEmpty()) {
datePattern = dateOption.format + datePattern;
} else {
datePattern = dateOption.format + " " + datePattern;
}
}
if (weekOption.format != null){
if (datePattern.isEmpty()){
datePattern = weekOption.format + datePattern;
} else {
datePattern = weekOption.format + ", " + datePattern;
}
}
dateFormat = new SimpleDateFormat(datePattern);
width = Math.max(DEFAULT_WIDTH, MinecraftClient.getInstance().textRenderer.getWidth(dateFormat.format(Date.from(Instant.now()))) + 20);
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.clock");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.clock.description");
}
}
@@ -0,0 +1,115 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetSettings;
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;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.awt.*;
import java.util.List;
public class CoordinatesWidget extends ModWidget {
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 RGBAColorWidgetSetting("textcolor", Text.translatable("widgets.widgets.basictext.textcolor"), 255, 255, 255, 255)
));
}
private String textX = "X", textY = "Y", textZ = "Z";
private int txc = 0, tyc = 0, tzc = 0;
@Override
public void render(DrawContext context, long measuringTimeNano, TextRenderer textRenderer, int posX, int posY) {
context.fill(posX, posY, posX + width(), posY + height(), this.backgroundColor);
final int PADDING = CoordinatesWidget.PADDING;
int y = PADDING;
if (showX){
y++;
context.drawText(textRenderer, "X: ", posX + PADDING, posY + y, textColor, true);
context.drawText(textRenderer, textX, posX + txc, posY + y, textColor, true);
y += textRenderer.fontHeight + 1;
}
if (showY){
y++;
context.drawText(textRenderer, "Y: ", posX + PADDING, posY + y, textColor, true);
context.drawText(textRenderer, textY, posX + tyc, posY + y, textColor, true);
y += textRenderer.fontHeight + 1;
}
if (showZ){
y++;
context.drawText(textRenderer, "Z: ", posX + PADDING, posY + y, textColor, true);
context.drawText(textRenderer, textZ, posX + tzc, posY + y, textColor, true);
}
}
@Override
public void tick() {
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
txc = width() - textRenderer.getWidth(textX) - PADDING;
tyc = width() - textRenderer.getWidth(textY) - PADDING;
tzc = width() - textRenderer.getWidth(textZ) - PADDING;
final ClientPlayerEntity player = MinecraftClient.getInstance().player;
if (player == null){
textX = "?";
textY = "?";
textZ = "?";
} else {
textX = String.valueOf(player.getBlockX());
textY = String.valueOf(player.getBlockY());
textZ = String.valueOf(player.getBlockZ());
}
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.coordinates");
}
@Override
public Text getDescription() {
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 int backgroundColor = DEFAULT_BACKGROUND_COLOR, textColor = DEFAULT_TEXT_COLOR;
protected boolean showX = true, showY = true, showZ = true;
@Override
public void onSettingsChanged(WidgetSettings settings) {
this.backgroundColor = ((RGBAColorWidgetSetting) settings.optionById("backgroundcolor")).getColor();
this.textColor = ((RGBAColorWidgetSetting) settings.optionById("textcolor")).getColor();
this.showX = ((ToggleWidgetSetting) settings.optionById("x")).getValue();
this.showY = ((ToggleWidgetSetting) settings.optionById("y")).getValue();
this.showZ = ((ToggleWidgetSetting) settings.optionById("z")).getValue();
}
@Override
public int width() {
return WIDTH;
}
@Override
public int height() {
int height = 2 * PADDING;
if (showX) height += 11;
if (showY) height += 11;
if (showZ) height += 11;
return height;
}
}
@@ -0,0 +1,28 @@
package de.shiewk.widgets.widgets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.List;
public class FPSWidget extends BasicTextWidget {
public FPSWidget(Identifier id) {
super(id, List.of());
}
@Override
public void tick() {
this.renderText = Text.literal(MinecraftClient.getInstance().getCurrentFps() + " FPS");
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.fps");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.fps.description");
}
}
@@ -0,0 +1,69 @@
package de.shiewk.widgets.widgets;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.profiler.MultiValueDebugSampleLogImpl;
import java.util.List;
public class PingWidget extends BasicTextWidget {
long lastPingQuery = 0;
public PingWidget(Identifier id) {
super(id, List.of(
new ToggleWidgetSetting("dynamic_color", Text.translatable("widgets.widgets.ping.dynamicColor"), true)
));
}
private boolean dynamicColor = false;
@Override
public void tick() {
final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler();
if (networkHandler != null){
if (lastPingQuery < Util.getMeasuringTimeMs() - 5000){
networkHandler.pingMeasurer.ping();
lastPingQuery = Util.getMeasuringTimeMs();
}
final MultiValueDebugSampleLogImpl pingLog = networkHandler.pingMeasurer.log;
final int logLength = pingLog.getLength();
final int avgCompileLength = 3;
long ping = 0;
for (int i = logLength-1; i > logLength-avgCompileLength; i--) {
if (i < 0) break;
ping += pingLog.get(i);
}
long avgPing = ping / avgCompileLength;
this.renderText = Text.of(avgPing + " ms");
if (this.dynamicColor){
if (avgPing < 50){
this.textColor = 0x00ff00;
} else if (avgPing < 120) {
this.textColor = 0xffff00;
} else {
this.textColor = 0xff3030;
}
}
}
}
@Override
public void onSettingsChanged(WidgetSettings settings) {
super.onSettingsChanged(settings);
this.dynamicColor = ((ToggleWidgetSetting) settings.optionById("dynamic_color")).getValue();
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.ping");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.ping.description");
}
}
@@ -0,0 +1,31 @@
package de.shiewk.widgets.widgets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.List;
public class PlayerCountWidget extends BasicTextWidget{
public PlayerCountWidget(Identifier id) {
super(id, List.of());
}
@Override
public void tick() {
final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler();
String online = networkHandler == null ? "?" : String.valueOf(networkHandler.getPlayerUuids().size());
this.renderText = Text.literal(Text.translatable("widgets.widgets.playerCount.online", online).getString());
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.playerCount");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.playerCount.description");
}
}
@@ -0,0 +1,47 @@
package de.shiewk.widgets.widgets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.List;
public class ServerIPWidget extends BasicTextWidget {
public ServerIPWidget(Identifier id) {
super(id, List.of());
}
private int width;
private int t = 0;
@Override
public void tick() {
final ServerInfo serverEntry = MinecraftClient.getInstance().getCurrentServerEntry();
if (serverEntry != null){
this.renderText = Text.of(serverEntry.address);
} else {
this.renderText = Text.translatable("menu.singleplayer");
}
t++;
if (t >= 20){
t = 0;
this.width = MinecraftClient.getInstance().textRenderer.getWidth(this.renderText) + 20;
}
}
@Override
public int width() {
return Math.max(super.width(), this.width);
}
@Override
public Text getName() {
return Text.translatable("widgets.widgets.serverIP");
}
@Override
public Text getDescription() {
return Text.translatable("widgets.widgets.serverIP.description");
}
}
@@ -0,0 +1,106 @@
package de.shiewk.widgets.widgets.settings;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import de.shiewk.widgets.WidgetSettingOption;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import java.awt.*;
import java.util.function.Function;
public class EnumWidgetSetting<T extends Enum<T>> extends WidgetSettingOption {
private final Class<T> enumClass;
private T value;
private final Function<T, Text> enumNameGetter;
private int height = 0;
private boolean mouseClick = false;
private boolean changed = false;
public EnumWidgetSetting(String id, Text name, Class<T> enumClass, T defaultValue, Function<T, Text> enumNameGetter) {
super(id, name);
this.enumClass = enumClass;
this.value = defaultValue;
this.enumNameGetter = enumNameGetter;
}
public T getValue(){
return value;
}
@Override
public JsonElement saveState() {
return new JsonPrimitive(value.name());
}
@Override
public void loadState(JsonElement state) {
if (state.isJsonPrimitive() && state.getAsJsonPrimitive().isString()){
final String name = state.getAsString();
for (T constant : enumClass.getEnumConstants()) {
if (constant.name().equals(name)){
this.value = constant;
}
}
}
}
private static final int COLOR_SELECTED = new Color(0, 0x5f, 0x68, 255).getRGB(),
COLOR_UNSELECTED = new Color(0, 0, 0, 50).getRGB(),
COLOR_UNSELECTED_HOVER = new Color(80, 80, 80, 50).getRGB(),
COLOR_TEXT = new Color(255, 255, 255, 255).getRGB();
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
int y = 0;
int nx = 5;
final int bx = getX() + getWidth();
for (T constant : enumClass.getEnumConstants()) {
final Text name = enumNameGetter.apply(constant);
final int textRendererWidth = textRenderer.getWidth(name);
if (nx != 5 && nx + textRendererWidth + 20 > this.getWidth()){
y += 24;
nx = 5;
}
final boolean hover = mouseX <= bx - nx && mouseX >= bx - nx - 10 - textRendererWidth && mouseY <= y + 19 + getY() && mouseY >= y + getY();
context.fill(bx - 10 - textRendererWidth - nx, y + getY(), bx - nx, y + 19 + getY(), constant == value ? COLOR_SELECTED : hover ? COLOR_UNSELECTED_HOVER : COLOR_UNSELECTED);
context.drawText(textRenderer, name, bx - nx - 5 - textRendererWidth, y + 5 + getY(), COLOR_TEXT, true);
if (hover && mouseClick){
this.value = constant;
this.changed = true;
}
nx += textRendererWidth + 20;
}
mouseClick = false;
this.height = y + 34;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouseClick = true;
return false;
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouseClick = false;
boolean changed = this.changed;
this.changed = false;
return changed;
}
@Override
public int getWidth() {
return 200;
}
@Override
public int getHeight() {
return height;
}
}
@@ -0,0 +1,123 @@
package de.shiewk.widgets.widgets.settings;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import de.shiewk.widgets.WidgetSettingOption;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
import java.awt.*;
public class RGBAColorWidgetSetting extends WidgetSettingOption {
public RGBAColorWidgetSetting(String id, Text name, int defaultR, int defaultG, int defaultB, int defaultAlpha) {
super(id, name);
this.r = defaultR;
this.g = defaultG;
this.b = defaultB;
this.a = defaultAlpha;
}
private int r;
private int g;
private int b;
private int a;
private boolean mouseClicked = false;
private int sv = 0;
@Override
public JsonElement saveState() {
return new JsonPrimitive(getColor());
}
public int getColor(){
return new Color(r, g, b, a).getRGB();
}
@Override
public void loadState(JsonElement state) {
if (state.isJsonPrimitive() && state.getAsJsonPrimitive().isNumber()){
final Color color = new Color(state.getAsJsonPrimitive().getAsInt(), true);
this.r = color.getRed();
this.g = color.getGreen();
this.b = color.getBlue();
this.a = color.getAlpha();
}
}
@Override
public int getWidth() {
return 28 + 127 + 7;
}
@Override
public int getHeight() {
return 95;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
int o = 0;
for (int i = 0; i <= 255; i+=2) {
context.drawVerticalLine(this.getX() + 5 + 7 + o, this.getY() + 5, this.getY() + 20, new Color(i, g, b, a).getRGB());
context.drawVerticalLine(this.getX() + 5 + 7 + o, this.getY() + 25, this.getY() + 40, new Color(r, i, b, a).getRGB());
context.drawVerticalLine(this.getX() + 5 + 7 + o, this.getY() + 45, this.getY() + 60, new Color(r, g, i, a).getRGB());
context.drawVerticalLine(this.getX() + 5 + 7 + o, this.getY() + 65, this.getY() + 80, new Color(r, g, b, i).getRGB());
o++;
}
context.drawText(textRenderer, "R", this.getX() + 7 - textRenderer.getWidth("R"), this.getY() + 5 + 4, 0xffffff, true);
context.drawText(textRenderer, "G", this.getX() + 7 - textRenderer.getWidth("G"), this.getY() + 25 + 4, 0xffffff, true);
context.drawText(textRenderer, "B", this.getX() + 7 - textRenderer.getWidth("B"), this.getY() + 45 + 4, 0xffffff, true);
context.drawText(textRenderer, "A", this.getX() + 7 - textRenderer.getWidth("A"), this.getY() + 65 + 4, 0xffffff, true);
context.drawText(textRenderer, String.valueOf(r), this.getX() + this.getWidth() - 19, this.getY() + 5 + 4, 0xffffff, true);
context.drawText(textRenderer, String.valueOf(g), this.getX() + this.getWidth() - 19, this.getY() + 25 + 4, 0xffffff, true);
context.drawText(textRenderer, String.valueOf(b), this.getX() + this.getWidth() - 19, this.getY() + 45 + 4, 0xffffff, true);
context.drawText(textRenderer, String.valueOf(a), this.getX() + this.getWidth() - 19, this.getY() + 65 + 4, 0xffffff, true);
context.drawVerticalLine(this.getX() + 5 + 7 + r/2, this.getY() + 4, this.getY() + 21, 0xffffffff);
context.drawVerticalLine(this.getX() + 5 + 7 + g/2, this.getY() + 24, this.getY() + 41, 0xffffffff);
context.drawVerticalLine(this.getX() + 5 + 7 + b/2, this.getY() + 44, this.getY() + 61, 0xffffffff);
context.drawVerticalLine(this.getX() + 5 + 7 + a/2, this.getY() + 64, this.getY() + 81, 0xffffffff);
if (mouseClicked){
int col = MathHelper.clamp((mouseX - this.getX() - 5 - 7) * 2, 0, 255);
if (sv == 0){
if (mouseY > this.getY() + 5 && mouseY < this.getY() + 20){
sv = 1;
} else if (mouseY > this.getY() + 25 && mouseY < this.getY() + 40){
sv = 2;
} else if (mouseY > this.getY() + 45 && mouseY < this.getY() + 60){
sv = 3;
} else if (mouseY > this.getY() + 65 && mouseY < this.getY() + 80){
sv = 4;
}
}
switch (sv){
case 1 -> r = col;
case 2 -> g = col;
case 3 -> b = col;
case 4 -> a = col;
}
}
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
this.mouseClicked = true;
sv = 0;
return false;
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
this.mouseClicked = false;
final boolean c = this.sv != 0;
this.sv = 0;
return c;
}
}
@@ -0,0 +1,78 @@
package de.shiewk.widgets.widgets.settings;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import de.shiewk.widgets.WidgetSettingOption;
import de.shiewk.widgets.WidgetUtils;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import java.awt.*;
public class ToggleWidgetSetting extends WidgetSettingOption {
private boolean value;
private long toggleTime = 0;
public ToggleWidgetSetting(String id, Text name, boolean defaultValue) {
super(id, name);
this.value = defaultValue;
}
public boolean getValue(){
return value;
}
@Override
public JsonElement saveState() {
return new JsonPrimitive(value);
}
@Override
public void loadState(JsonElement state) {
if (state.isJsonPrimitive() && state.getAsJsonPrimitive().isBoolean()){
this.value = state.getAsBoolean();
}
}
protected static final int COLOR_ENABLED = new Color(0, 255, 0, 255).getRGB(),
COLOR_ENABLED_THUMB = new Color(0, 175, 0, 255).getRGB(),
COLOR_DISABLED = new Color(255, 0, 0, 255).getRGB(),
COLOR_DISABLED_THUMB = new Color(255, 200, 200, 255).getRGB();
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
int col = value ? COLOR_ENABLED : COLOR_DISABLED;
int thumb = value ? COLOR_ENABLED_THUMB : COLOR_DISABLED_THUMB;
int thumbLoc = (Util.getMeasuringTimeNano() - toggleTime) < 300000000f ?
(int) (getX() + MathHelper.lerp(WidgetUtils.computeEasing((Util.getMeasuringTimeNano() - toggleTime) / 300000000f),
value ? 2 : getWidth() - 4 - 12,
value ? getWidth() - 4 - 12 : 2))
: value ? getX() + getWidth() - 4 - 12 : getX() + 4;
context.fill(getX() + 2, getY() + 2, getX() + getWidth() - 2, getY() + getHeight() - 2, col);
context.fill(thumbLoc, getY() + 4, thumbLoc + 12, getY() + getHeight() - 4, thumb);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
toggle();
return true;
}
public void toggle(){
this.value = !value;
this.toggleTime = Util.getMeasuringTimeNano();
}
@Override
public int getWidth() {
return 50;
}
@Override
public int getHeight() {
return 20;
}
}