new ModMenu UI

This commit is contained in:
Oth3r 2024-08-30 20:29:03 -05:00
commit 457a8d10d3
5 changed files with 271 additions and 179 deletions

View file

@ -0,0 +1,32 @@
package one.oth3r.sit.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.function.Supplier;
public class ClickableImageWidget extends ButtonWidget {
private final Identifier image;
public ClickableImageWidget(int x, int y, int width, int height, Tooltip tooltip, Identifier image, ButtonWidget.PressAction onPress) {
super(x, y, width, height, Text.empty(), onPress, Supplier::get);
this.image = image;
this.setTooltip(tooltip);
}
@Override
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
context.setShaderColor(1.0f, 1.0f, 1.0f, this.alpha);
RenderSystem.enableBlend();
RenderSystem.enableDepthTest();
context.drawTexture(image, this.getX(), this.getY(), 0.0f, 0.0f, this.getWidth(), this.getHeight(), this.getWidth(), this.getHeight());
context.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
}
}

View file

@ -0,0 +1,79 @@
package one.oth3r.sit.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ConfirmLinkScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.utl.Data;
import java.net.URI;
public class ConfigScreen extends Screen {
protected final Screen parent;
public ConfigScreen(Screen parent) {
super(Text.translatable("screen.config"));
this.parent = parent;
}
@Override
protected void init() {
int startY = this.height / 4 + 48;
int spacing = 36;
TextureButtonWidget serverConfigButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("config.server"),
(button) -> client.setScreen(new UnderConstructionScreen(this, FileData.getServerConfig())), false)
.dimensions(250,30).texture(Identifier.of(Data.MOD_ID, "server_button"), 246, 26).build());
serverConfigButton.setPosition(this.width / 2 - (serverConfigButton.getWidth()/2), startY);
TextureButtonWidget sittingConfigButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("config.sitting"),
(button) -> client.setScreen(new UnderConstructionScreen(this, FileData.getSittingConfig())), false)
.dimensions(250,30).texture(Identifier.of(Data.MOD_ID, "sitting_button"), 246, 26).build());
sittingConfigButton.setPosition(this.width / 2 - (sittingConfigButton.getWidth()/2), startY+36);
TextureButtonWidget issuesButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("gui.button.issues"),
ConfirmLinkScreen.opening(this, URI.create("https://github.com/Oth3r/Sit/issues")), true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "issues"), 15, 15).build());
issuesButton.setPosition(this.width / 2 - 125, startY + 72 + 12);
this.addDrawableChild(ButtonWidget.builder(Text.translatable("gui.button.website"),
ConfirmLinkScreen.opening(this, URI.create("https://modrinth.com/mod/sit!"))
).dimensions(this.width / 2 - 100, startY + 72 + 12, 98, 20).build());
this.addDrawableChild(ButtonWidget.builder(Text.translatable("gui.done"), (button) -> {
close();
}).dimensions(this.width / 2 + 2, startY + 72 + 12, 98, 20).build());
TextureButtonWidget donateButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("gui.button.donate"),
ConfirmLinkScreen.opening(this, URI.create("https://Ko-fi.com/oth3r")), true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "donate"), 15, 15).build());
donateButton.setPosition(this.width / 2 + 105, startY + 72 + 12);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta);
//todo fade?
renderBanner(context,width/2 - 64,this.height / 4 -38,1);
}
@Override
public void close() {
this.client.setScreen(parent);
}
private void renderBanner(DrawContext context, int x, int y, float alpha) {
context.setShaderColor(1.0f, 1.0f, 1.0f, alpha);
RenderSystem.enableBlend();
context.drawTexture(Identifier.of(Data.MOD_ID, "textures/gui/banner.png"), x, y, 0.0f, 0.0f, 128, 72, 128, 72);
context.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.disableBlend();
}
}

View file

@ -1,185 +1,11 @@
package one.oth3r.sit.screen;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
public class ModMenu implements ModMenuApi {
// private static MutableText lang(String key, Object... args) {
// return Utl.lang("config."+key,args);
// }
// @Override
// public ConfigScreenFactory<?> getModConfigScreenFactory() {
// return parent -> YetAnotherConfigLib.createBuilder().save(config::save)
// .title(Text.of("Sit!"))
// .category(ConfigCategory.createBuilder()
// .name(lang("category.general"))
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.keep_active"))
// .description(OptionDescription.of(lang("general.keep_active.description")))
// .binding(config.defaults.keepActive, () -> config.keepActive, n -> config.keepActive = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.sit_while_seated"))
// .description(OptionDescription.of(lang("general.sit_while_seated.description")))
// .binding(config.defaults.sitWhileSeated, () -> config.sitWhileSeated, n -> config.sitWhileSeated = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .group(OptionGroup.createBuilder()
// .name(lang("general.sittable"))
// .description(OptionDescription.of(lang("general.sittable.description")))
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.sittable.stairs"))
// .binding(config.defaults.stairsOn, () -> config.stairsOn, n -> config.stairsOn = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.sittable.slabs"))
// .binding(config.defaults.slabsOn, () -> config.slabsOn, n -> config.slabsOn = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.sittable.carpets"))
// .binding(config.defaults.carpetsOn, () -> config.carpetsOn, n -> config.carpetsOn = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.sittable.full_blocks"))
// .binding(config.defaults.fullBlocksOn, () -> config.fullBlocksOn, n -> config.fullBlocksOn = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("general.sittable.custom"))
// .description(OptionDescription.of(lang("general.sittable.custom.description")))
// .binding(config.defaults.customOn, () -> config.customOn, n -> config.customOn = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter())
// .build())
// .build())
// .group(ListOption.<String>createBuilder()
// .name(lang("general.sittable_blocks"))
// .description(OptionDescription.of(
// lang("general.sittable_blocks.description")
// .append("\n\n").append(lang("example",
// Text.literal("\"")
// .append(Text.literal("minecraft:campfire").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA))))
// .append("|")
// .append(Text.literal("0.255").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED))))
// .append("|")
// .append(Text.literal("1").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN))))
// .append("|")
// .append(Text.literal("lit=false").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GOLD))))
// .append("\"").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GRAY)))))
// .append("\n\n").append(lang("general.sittable_blocks.description.2").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA))))
// .append("\n").append(lang("general.sittable_blocks.description.3").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED))))
// .append("\n").append(lang("general.sittable_blocks.description.4").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN))))
// .append("\n").append(lang("general.sittable_blocks.description.5").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GOLD))))
// .append("\n\n").append(lang("general.sittable_blocks.description.6").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.YELLOW))))))
// .binding(config.defaults.customBlocks, () -> config.customBlocks, n -> config.customBlocks = n)
// .controller(StringControllerBuilder::create)
// .initial("")
// .build())
// .build())
// .category(ConfigCategory.createBuilder()
// .name(lang("category.main_hand"))
// .option(Option.<config.HandRequirement>createBuilder()
// .name(lang("hand.requirement"))
// .description(OptionDescription.of(lang("hand.requirement.description")
// .append("\n\n").append(lang("hand.requirement.description.2",lang("hand.requirement.empty")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA))))
// .append("\n").append(lang("hand.requirement.description.3",lang("hand.requirement.restrictive")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN))))
// .append("\n").append(lang("hand.requirement.description.4",lang("hand.requirement.none")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED))))))
// .binding(config.defaults.mainReq, () -> config.mainReq, n -> config.mainReq = n)
// .controller(opt -> EnumControllerBuilder.create(opt).enumClass(config.HandRequirement.class)
// .formatValue(v -> lang("hand.requirement."+v.toString())))
// .build())
// .group(OptionGroup.createBuilder()
// .name(lang("hand.restriction"))
// .description(OptionDescription.of(lang("hand.restriction.description")))
// .option(Option.<Boolean>createBuilder()
// .name(lang("hand.restriction.blocks"))
// .binding(config.defaults.mainBlock,()-> config.mainBlock,n -> config.mainBlock = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("hand.restriction.food"))
// .binding(config.defaults.mainFood,()-> config.mainFood,n -> config.mainFood = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("hand.restriction.usable"))
// .description(OptionDescription.of(lang("hand.restriction.usable.description")))
// .binding(config.defaults.mainUsable,()-> config.mainUsable,n -> config.mainUsable = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .build())
// .group(ListOption.<String>createBuilder()
// .name(lang("hand.restriction.whitelist"))
// .description(OptionDescription.of(lang("hand.restriction.list.description")
// .append("\n\n").append(lang("example",
// Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))))
// .binding(config.defaults.mainWhitelist, () -> config.mainWhitelist, n -> config.mainWhitelist = n)
// .controller(StringControllerBuilder::create)
// .initial("")
// .build())
// .group(ListOption.<String>createBuilder()
// .name(lang("hand.restriction.blacklist"))
// .description(OptionDescription.of(lang("hand.restriction.list.description")
// .append("\n\n").append(lang("example",
// Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))))
// .binding(config.defaults.mainBlacklist, () -> config.mainBlacklist, n -> config.mainBlacklist = n)
// .controller(StringControllerBuilder::create)
// .initial("")
// .build())
// .build())
// .category(ConfigCategory.createBuilder()
// .name(lang("category.off_hand"))
// .option(Option.<config.HandRequirement>createBuilder()
// .name(lang("hand.requirement"))
// .description(OptionDescription.of(lang("hand.requirement.description")
// .append("\n\n").append(lang("hand.requirement.description.2",lang("hand.requirement.empty")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA))))
// .append("\n").append(lang("hand.requirement.description.3",lang("hand.requirement.restrictive")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN))))
// .append("\n").append(lang("hand.requirement.description.4",lang("hand.requirement.none")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED))))))
// .binding(config.defaults.offReq, () -> config.offReq, n -> config.offReq = n)
// .controller(opt -> EnumControllerBuilder.create(opt).enumClass(config.HandRequirement.class)
// .formatValue(v -> lang("hand.requirement."+v.toString())))
// .build())
// .group(OptionGroup.createBuilder()
// .name(lang("hand.restriction"))
// .description(OptionDescription.of(lang("hand.restriction.description")))
// .option(Option.<Boolean>createBuilder()
// .name(lang("hand.restriction.blocks"))
// .binding(config.defaults.offBlock,()-> config.offBlock,n -> config.offBlock = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("hand.restriction.food"))
// .binding(config.defaults.offFood,()-> config.offFood,n -> config.offFood = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .option(Option.<Boolean>createBuilder()
// .name(lang("hand.restriction.usable"))
// .description(OptionDescription.of(lang("hand.restriction.usable.description")))
// .binding(config.defaults.offUsable,()-> config.offUsable,n -> config.offUsable = n)
// .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter())
// .build())
// .build())
// .group(ListOption.<String>createBuilder()
// .name(lang("hand.restriction.whitelist"))
// .description(OptionDescription.of(lang("hand.restriction.list.description")
// .append("\n\n").append(lang("example",
// Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))))
// .binding(config.defaults.offWhitelist, () -> config.offWhitelist, n -> config.offWhitelist = n)
// .controller(StringControllerBuilder::create)
// .initial("")
// .build())
// .group(ListOption.<String>createBuilder()
// .name(lang("hand.restriction.blacklist"))
// .description(OptionDescription.of(lang("hand.restriction.list.description")
// .append("\n\n").append(lang("example",
// Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))))
// .binding(config.defaults.offBlacklist, () -> config.offBlacklist, n -> config.offBlacklist = n)
// .controller(StringControllerBuilder::create)
// .initial("")
// .build())
// .build())
// .build().generateScreen(parent);
// }
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return ConfigScreen::new;
}
}

View file

@ -0,0 +1,85 @@
package one.oth3r.sit.screen;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
public class TextureButtonWidget extends ButtonWidget {
//todo gray support
protected final Identifier texture;
protected final int textureWidth;
protected final int textureHeight;
protected final boolean tooltip;
TextureButtonWidget(int width, int height, Text message, int textureWidth, int textureHeight, Identifier texture, ButtonWidget.PressAction onPress, @Nullable ButtonWidget.NarrationSupplier narrationSupplier, boolean tooltip) {
super(0, 0, width, height, message, onPress, narrationSupplier == null ? DEFAULT_NARRATION_SUPPLIER : narrationSupplier);
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
this.texture = texture;
this.tooltip = tooltip;
if (tooltip) setTooltip(Tooltip.of(message));
}
@Override
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
super.renderWidget(context, mouseX, mouseY, delta);
int x = this.getX() + this.getWidth() / 2 - this.textureWidth / 2;
int y = this.getY() + this.getHeight() / 2 - this.textureHeight / 2;
context.drawGuiTexture(this.texture, x, y, this.textureWidth, this.textureHeight);
}
@Override
public void drawMessage(DrawContext context, TextRenderer textRenderer, int color) {
if (!this.tooltip) super.drawMessage(context, textRenderer, color);
}
public static class Builder {
private final Text text;
private final ButtonWidget.PressAction onPress;
private final boolean hideText;
private int width = 150;
private int height = 20;
@Nullable
private Identifier texture;
private int textureWidth;
private int textureHeight;
@Nullable
ButtonWidget.NarrationSupplier narrationSupplier;
public Builder(Text text, ButtonWidget.PressAction onPress, boolean hideText) {
this.text = text;
this.onPress = onPress;
this.hideText = hideText;
}
public Builder dimensions(int width, int height) {
this.width = width;
this.height = height;
return this;
}
public Builder texture(Identifier texture, int width, int height) {
this.texture = texture;
this.textureWidth = width;
this.textureHeight = height;
return this;
}
public Builder narration(ButtonWidget.NarrationSupplier narrationSupplier) {
this.narrationSupplier = narrationSupplier;
return this;
}
public TextureButtonWidget build() {
if (this.texture == null) {
throw new IllegalStateException("Sprite not set");
}
return new TextureButtonWidget(width,height,text,textureWidth,textureHeight,texture,onPress,narrationSupplier,hideText);
}
}
}

View file

@ -0,0 +1,70 @@
package one.oth3r.sit.screen;
import net.minecraft.client.gui.screen.ConfirmLinkScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import one.oth3r.sit.file.CustomFile;
import one.oth3r.sit.utl.Data;
import java.net.URI;
import java.nio.file.Paths;
public class UnderConstructionScreen<T extends CustomFile<T>> extends Screen {
protected final Screen parent;
protected T file;
public UnderConstructionScreen(Screen parent, T file) {
super(Text.translatable("screen.config"));
this.parent = parent;
this.file = file;
}
@Override
protected void init() {
int startY = this.height / 5-4;
ButtonWidget foxPNG = this.addDrawableChild(new ClickableImageWidget(70,70,140,140, Tooltip.of(Text.of("Art by @bunnestbun")),
Identifier.of(Data.MOD_ID, "textures/gui/fox.png"), ConfirmLinkScreen.opening(this, URI.create("https://www.instagram.com/bunnestbun/"))));
foxPNG.setPosition(this.width / 2 - (foxPNG.getWidth()/2), startY-35);
ButtonWidget openFileButton = this.addDrawableChild(new ButtonWidget.Builder(Text.translatable("gui.button.file"),
(button) -> Util.getOperatingSystem().open(this.file.getFile()))
.dimensions(0, 0, 118 ,20).build());
openFileButton.setPosition(this.width / 2 - 70, startY+110);
TextureButtonWidget folderButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("gui.button.folder"),
(button) -> Util.getOperatingSystem().open(Paths.get(this.file.getFile().getParent())), true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "folder"), 15, 15).build());
folderButton.setPosition(this.width / 2 + 50, startY + 110);
TextureButtonWidget resetButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("gui.button.reset"),
(button) -> {
this.file.reset();
this.file.save();
}, true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "reset_file"), 15, 15).build());
resetButton.setPosition(this.width / 2 -70, startY + 135);
ButtonWidget revertButton = this.addDrawableChild(new ButtonWidget.Builder(Text.translatable("gui.button.revert"),
(button) -> this.file.save())
.dimensions(0, 0, 118,20).build());
revertButton.setPosition(this.width / 2 - 48, startY+135);
ButtonWidget saveExitButton = this.addDrawableChild(new ButtonWidget.Builder(Text.translatable("gui.button.save"),
(button) -> {
this.file.save();
this.client.setScreen(parent);
})
.dimensions(0, 0, 140,20).build());
saveExitButton.setPosition(this.width / 2 - 70, startY+168);
}
@Override
public void close() {
this.client.setScreen(parent);
}
}