please confirm

This commit is contained in:
zelophed 2021-04-23 18:11:32 +02:00
parent f0dfc5a6bc
commit 33028e1087
18 changed files with 610 additions and 210 deletions

View file

@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.config.ModConfig;
public class BaseConfigScreen extends ConfigScreen {
@ -29,14 +30,14 @@ public class BaseConfigScreen extends ConfigScreen {
TextStencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("CLIENT CONFIG").formatted(TextFormatting.BOLD)).centered(true, true);
text.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2));
widgets.add(clientConfigWidget = new PonderButton(width / 2 - 100, height / 2 - 15 - 50, (_$, _$$) -> {
ScreenOpener.transitionTo(new SubMenuConfigScreen(this, AllConfigs.CLIENT.specification));
ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification));
}, 200, 30).showingUnscaled(text));
clientConfigWidget.fade(1);
TextStencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("COMMON CONFIG").formatted(TextFormatting.BOLD)).centered(true, true);
text2.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2));
widgets.add(commonConfigWidget = new PonderButton(width / 2 - 100, height / 2 - 15, (_$, _$$) -> {
ScreenOpener.transitionTo(new SubMenuConfigScreen(this, AllConfigs.COMMON.specification));
ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification));
}, 200, 30).showingUnscaled(text2));
commonConfigWidget.fade(1);
@ -47,7 +48,7 @@ public class BaseConfigScreen extends ConfigScreen {
serverConfigWidget.fade(1);
if (Minecraft.getInstance().world != null) {
serverConfigWidget.withCallback(() -> ScreenOpener.transitionTo(new ServerSubMenuConfigScreen(this, AllConfigs.SERVER.specification)));
serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification)));
} else {
serverConfigWidget.active = false;
text3.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, ConfigButton.Palette.button_disable_1, ConfigButton.Palette.button_disable_2));

View file

@ -1,6 +1,8 @@
package com.simibubi.create.foundation.config.ui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@ -11,10 +13,9 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.StencilElement;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.utility.animation.Force;
import com.simibubi.create.foundation.utility.animation.PhysicalFloat;
@ -22,24 +23,16 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Direction;
public abstract class ConfigScreen extends NavigatableSimiScreen {
public abstract class ConfigScreen extends AbstractSimiScreen {
/*
*
* TODO
* zelo's list for configUI
*
* match style with ponderUI
* cache changes before setting values and saving to file
* don't exit on ESC
* reset text field focus for any click inside screen
* adjust transition animation of screens
* allow backspace in text fields
* adjust transition animation of screens -> disabled for now
* move config button's animations to ponder button or a new superclass
* get some proper icons for reset button and enum cycle
* some small shadow effect for top and bottom of the list
* add the 'think back' button back, just with a different caption
* add a title to the current config screen, maybe in the form of breadcrumbs
*
* some color themes maybe?
* at least a helper class to unite colors throughout different uis
@ -48,14 +41,14 @@ public abstract class ConfigScreen extends NavigatableSimiScreen {
*
* tooltip are hidden underneath the scrollbar, if the bar is near the middle
* misalignment of the label-streak and textboxes/enum stuff
* framebuffer blending is incorrect
*
* */
public static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f));
public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y);
public static final Map<String, Object> changes = new HashMap<>();
protected final Screen parent;
protected static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f));
protected static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y);
protected StencilElement testStencil;
public ConfigScreen(Screen parent) {
this.parent = parent;
@ -63,30 +56,12 @@ public abstract class ConfigScreen extends NavigatableSimiScreen {
@Override
public void tick() {
cogSpin.tick();
widgets.stream()
.filter(w -> w instanceof ConfigButton)
.forEach(w -> ((ConfigButton) w).tick());
super.tick();
}
@Override
protected void init() {
/*super.init();
if (backTrack != null) {
widgets.remove(backTrack);
backTrack = null;
}*/
testStencil = new TextStencilElement(client.fontRenderer, "POGGERS").at(width*0.5f, height*0.5f, 0);
cogSpin.tick();
}
@Override
public void renderBackground(@Nonnull MatrixStack ms) {
//fill(ms, 0, 0, this.width, this.height, 0xe8_101010);
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.GuiScreenEvent.BackgroundDrawnEvent(this, ms));
}
@ -99,11 +74,6 @@ public abstract class ConfigScreen extends NavigatableSimiScreen {
fill(ms, 0, 0, this.width, this.height, 0xff_282c34);
}
/*ms.push();
ms.translate(width*0.5f, height*0.5f, 0);
renderCog(ms, partialTicks);
ms.pop();*/
new StencilElement() {
@Override
protected void renderStencil(MatrixStack ms) {
@ -120,18 +90,6 @@ public abstract class ConfigScreen extends NavigatableSimiScreen {
}
protected void renderCog(MatrixStack ms, float partialTicks) {
ms.push();
ms.translate(-100, 100, -200);
ms.scale(200, 200, .1f);
GuiGameElement.of(cogwheelState)
.rotateBlock(22.5, cogSpin.getValue(partialTicks), 22.5)
.render(ms);
ms.pop();
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
int x = (int) (width * 0.5f);
@ -155,4 +113,16 @@ public abstract class ConfigScreen extends NavigatableSimiScreen {
String s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(key)).map(StringUtils::capitalize).collect(Collectors.joining(" "));
return s;
}
protected void renderCog(MatrixStack ms, float partialTicks) {
ms.push();
ms.translate(-100, 100, -100);
ms.scale(200, 200, .1f);
GuiGameElement.of(cogwheelState)
.rotateBlock(22.5, cogSpin.getValue(partialTicks), 22.5)
.render(ms);
ms.pop();
}
}

View file

@ -7,6 +7,7 @@ import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper;
@ -22,7 +23,7 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
public TextFieldWidget currentText;
public static TextFieldWidget currentText;
public boolean isForServer = false;
@ -31,12 +32,16 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
func_244605_b(false);
func_244606_c(false);
setRenderSelection(false);
currentText = null;
}
@Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
//render tmp background
fill(ms, left, top, left + width, top + height, 0x10_000000);
//fill(ms, left, top, left + width, top + height, 0x10_000000);
UIRenderHelper.angledGradient(ms, 90, left + width / 2, top, width, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, -90, left + width / 2, bottom, width, 5, 0x60_000000, 0x0);
super.render(ms, mouseX, mouseY, partialTicks);
}
@ -50,6 +55,13 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
RenderSystem.disableScissor();
}
@Override
public boolean mouseClicked(double x, double y, int button) {
children().stream().filter(e -> e instanceof NumberEntry<?>).forEach(e -> e.mouseClicked(x, y, button));
return super.mouseClicked(x, y, button);
}
@Override
public int getRowWidth() {
return width - 18;

View file

@ -30,4 +30,21 @@ public class ConfigTextField extends TextFieldWidget {
font.draw(ms, unit, x + getAdjustedWidth() - unitWidth, this.y + (this.height - 8) / 2, 0xcc_aaaaaa);
}
@Override
public void setFocused2(boolean focus) {
super.setFocused2(focus);
if (!focus) {
if (ConfigScreenList.currentText == this)
ConfigScreenList.currentText = null;
return;
}
if (ConfigScreenList.currentText != null && ConfigScreenList.currentText != this)
ConfigScreenList.currentText.setFocused2(false);
ConfigScreenList.currentText = this;
}
}

View file

@ -1,52 +0,0 @@
package com.simibubi.create.foundation.config.ui;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
public class ServerSubMenuConfigScreen extends SubMenuConfigScreen {
protected PonderButton missingPermissions = null;
public ServerSubMenuConfigScreen(Screen parent, ForgeConfigSpec configSpec) {
super(parent, configSpec);
}
public ServerSubMenuConfigScreen(Screen parent, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
super(parent, configSpec, configGroup);
}
@Override
protected void init() {
super.init();
list.isForServer = true;
if (client != null && client.player != null && client.player.hasPermissionLevel(2))
return;
list.children().forEach(e -> e.setEditable(false));
int col1 = 0xff_f78888;
int col2 = 0xff_cc2020;
missingPermissions = new PonderButton(width - 30, height - 50, () -> {})
.showing(new DelegatedStencilElement()
.withStencilRenderer((ms, w, h) -> AllIcons.I_MTD_CLOSE.draw(ms, 0, 0))
.withElementRenderer((ms, w, h) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, col1, col2))
).customColors(col1, col2);
missingPermissions.fade(1);
missingPermissions.getToolTip().add(new StringTextComponent("Locked").formatted(TextFormatting.BOLD));
missingPermissions.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You don't have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY));
widgets.add(missingPermissions);
}
}

View file

@ -1,8 +1,9 @@
package com.simibubi.create.foundation.config.ui;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableInt;
import org.lwjgl.glfw.GLFW;
import com.electronwill.nightconfig.core.AbstractConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
@ -11,30 +12,93 @@ import com.simibubi.create.foundation.config.ui.entries.BooleanEntry;
import com.simibubi.create.foundation.config.ui.entries.EnumEntry;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry;
import com.simibubi.create.foundation.config.ui.entries.ValueEntry;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.ConfirmationScreen;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
public class SubMenuConfigScreen extends ConfigScreen {
ForgeConfigSpec spec;
UnmodifiableConfig configGroup;
ConfigScreenList list;
public final ModConfig.Type type;
protected ForgeConfigSpec spec;
protected UnmodifiableConfig configGroup;
protected ConfigScreenList list;
protected PonderButton resetAll;
protected PonderButton saveChanges;
protected PonderButton discardChanges;
protected PonderButton goBack;
protected PonderButton serverLocked;
protected int listWidth;
protected String title;
public SubMenuConfigScreen(Screen parent, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
super(parent);
this.type = type;
this.spec = configSpec;
this.title = title;
this.configGroup = configGroup;
}
public SubMenuConfigScreen(Screen parent, ForgeConfigSpec configSpec) {
public SubMenuConfigScreen(Screen parent, ModConfig.Type type, ForgeConfigSpec configSpec) {
super(parent);
this.type = type;
this.spec = configSpec;
this.title = "root";
this.configGroup = configSpec.getValues();
}
protected void clearChanges() {
changes.clear();
list.children()
.stream()
.filter(e -> e instanceof ValueEntry)
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
}
protected void saveChanges() {
UnmodifiableConfig values = spec.getValues();
changes.forEach((path, value) -> {
ForgeConfigSpec.ConfigValue configValue = values.get(path);
configValue.set(value);
});
clearChanges();
}
protected void resetConfig(UnmodifiableConfig values) {
values.valueMap().forEach((key, obj) -> {
if (obj instanceof AbstractConfig) {
resetConfig((UnmodifiableConfig) obj);
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
if (!configValue.get().equals(valueSpec.getDefault()))
changes.put(String.join(".", configValue.getPath()), valueSpec.getDefault());
}
});
list.children()
.stream()
.filter(e -> e instanceof ValueEntry)
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
}
@Override
public void tick() {
super.tick();
@ -46,23 +110,88 @@ public class SubMenuConfigScreen extends ConfigScreen {
widgets.clear();
super.init();
int lWidth = Math.min(width - 66, 500);
list = new ConfigScreenList(client, lWidth, height - 30, 15, height - 15, 50);
//leave 40px on either side and dont be wider than 500px
listWidth = Math.min(width - 80, 500);
int yCenter = height / 2;
int listL = this.width / 2 - listWidth / 2;
int listR = this.width / 2 + listWidth / 2;
resetAll = new PonderButton(listR + 10, yCenter - 25, (x, y) -> {
new ConfirmationScreen()
.at(x, y)
.withText(ITextProperties.plain("You are about to reset all settings for the " + type.toString() + " config. Are you sure?"))
.withAction(success -> {
if (success)
resetConfig(spec.getValues());
})
.open(this);
})
.showing(AllIcons.I_CONFIG_RESET.asStencil());
resetAll.fade(1);
resetAll.getToolTip().add(new StringTextComponent("Reset All"));
resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all configs to their default value.", TextFormatting.GRAY, TextFormatting.GRAY));
saveChanges = new PonderButton(listL - 30, yCenter - 25, (x, y) -> {
if (changes.isEmpty())
return;
new ConfirmationScreen()
.at(x, y)
.withText(ITextProperties.plain("You are about to change " + changes.size() + " values. Are you sure?"))
.withAction(success -> {
if (success)
saveChanges();
})
.open(this);
})
.showing(AllIcons.I_CONFIG_SAVE.asStencil());
saveChanges.fade(1);
saveChanges.getToolTip().add(new StringTextComponent("Save Changes"));
saveChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to save your current changes.", TextFormatting.GRAY, TextFormatting.GRAY));
discardChanges = new PonderButton(listL - 30, yCenter + 5, (x, y) -> {
if (changes.isEmpty())
return;
new ConfirmationScreen()
.at(x, y)
.withText(ITextProperties.plain("You are about to discard " + changes.size() + " unsaved changes. Are you sure?"))
.withAction(success -> {
if (success)
clearChanges();
})
.open(this);
})
.showing(AllIcons.I_CONFIG_DISCARD.asStencil());
discardChanges.fade(1);
discardChanges.getToolTip().add(new StringTextComponent("Discard Changes"));
discardChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to discard all the changes you made.", TextFormatting.GRAY, TextFormatting.GRAY));
goBack = new PonderButton(listL - 30, yCenter + 65, this::attemptBackstep)
.showing(AllIcons.I_CONFIG_BACK);
goBack.fade(1);
goBack.getToolTip().add(new StringTextComponent("Go Back"));
widgets.add(resetAll);
widgets.add(saveChanges);
widgets.add(discardChanges);
widgets.add(goBack);
list = new ConfigScreenList(client, listWidth, height - 60, 45, height - 15, 50);
list.setLeftPos(this.width / 2 - list.getWidth() / 2);
children.add(list);
MutableInt y = new MutableInt(15);
configGroup.valueMap().forEach((key, obj) -> {
String humanKey = toHumanReadable(key);
configGroup.valueMap().forEach((s, o) -> {
String humanKey = toHumanReadable(s);
if (o instanceof AbstractConfig) {
SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) o);
if (obj instanceof AbstractConfig) {
SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) obj);
list.children().add(entry);
} else if (o instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) o;
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
Object value = configValue.get();
@ -77,21 +206,58 @@ public class SubMenuConfigScreen extends ConfigScreen {
if (entry != null) {
list.children().add(entry);
} else {
list.children().add(new ConfigScreenList.LabeledEntry("n-" + o.getClass().getSimpleName() + " " + humanKey + " : " + value));
list.children().add(new ConfigScreenList.LabeledEntry("n-" + obj.getClass().getSimpleName() + " " + humanKey + " : " + value));
}
} else {
list.children().add(new ConfigScreenList.LabeledEntry(humanKey + " : " + value));
}
}
y.add(50);
});
//extras for sever configs
if (type != ModConfig.Type.SERVER)
return;
list.isForServer = true;
boolean canEdit = client != null && client.player != null && client.player.hasPermissionLevel(2);
int colRed1 = 0xff_f78888;
int colRed2 = 0xff_cc2020;
int colGreen1 = 0xff_88f788;
int colGreen2 = 0xff_20cc20;
DelegatedStencilElement stencil = new DelegatedStencilElement();
serverLocked = new PonderButton(listR + 10, yCenter + 5, () -> {})
.showing(stencil);
serverLocked.fade(1);
if (!canEdit) {
list.children().forEach(e -> e.setEditable(false));
resetAll.active = false;
stencil.withStencilRenderer((ms, w, h) -> AllIcons.I_CONFIG_LOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colRed1, colRed2));
serverLocked.customColors(colRed1, colRed2);
serverLocked.getToolTip().add(new StringTextComponent("Locked").formatted(TextFormatting.BOLD));
serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You don't have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY));
} else {
stencil.withStencilRenderer((ms, w, h) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colGreen1, colGreen2));
serverLocked.customColors(colGreen1, colGreen2);
serverLocked.getToolTip().add(new StringTextComponent("Unlocked").formatted(TextFormatting.BOLD));
serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You have enough permissions to edit the server config. Changes you make here will be synced with the server once you saved them.", TextFormatting.GRAY, TextFormatting.GRAY));
}
widgets.add(serverLocked);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderWindow(ms, mouseX, mouseY, partialTicks);
int x = width/2;
drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, 0xff_eaeaea);
list.render(ms, mouseX, mouseY, partialTicks);
}
@ -106,4 +272,65 @@ public class SubMenuConfigScreen extends ConfigScreen {
init(client, width, height);
list.setScrollAmount(scroll);
}
@Nullable
@Override
public IGuiEventListener getFocused() {
if (ConfigScreenList.currentText != null)
return ConfigScreenList.currentText;
return super.getFocused();
}
@Override
public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) {
if (super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_))
return true;
if (code == GLFW.GLFW_KEY_BACKSPACE) {
attemptBackstep();
}
return false;
}
private void attemptBackstep() {
if (!changes.isEmpty() && parent instanceof BaseConfigScreen) {
new ConfirmationScreen()
.centered()
.addText(ITextProperties.plain("You still have " + changes.size() + " unsaved changes for this config."))
.addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?"))
.withAction(success -> {
if (!success)
return;
changes.clear();
ScreenOpener.open(parent);
})
.open(this);
} else {
ScreenOpener.open(parent);
}
}
@Override
public void onClose() {
if (changes.isEmpty()) {
super.onClose();
return;
}
new ConfirmationScreen()
.centered()
.addText(ITextProperties.plain("You still have " + changes.size() + " unsaved changes for this config."))
.addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?"))
.withAction(success -> {
if (!success)
return;
changes.clear();
super.onClose();
})
.open(this);
}
}

View file

@ -25,10 +25,8 @@ public class BooleanEntry extends ValueEntry<Boolean> {
.centered(true, true)
.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height/2, height, width, 0xff_f78888, 0xff_cc2020));
button = new PonderButton(0, 0, () -> {
value.set(!value.get());
onValueChange();
}).showingUnscaled(enabled);
button = new PonderButton(0, 0, () -> setValue(!getValue()))
.showingUnscaled(enabled);
button.fade(1);
listeners.add(button);
@ -58,14 +56,9 @@ public class BooleanEntry extends ValueEntry<Boolean> {
}
@Override
protected void onValueChange() {
super.onValueChange();
button.showingUnscaled(value.get() ? enabled : disabled);
bumpCog(value.get() ? 15f : -16f);
public void onValueChange(Boolean newValue) {
super.onValueChange(newValue);
button.showingUnscaled(newValue ? enabled : disabled);
bumpCog(newValue ? 15f : -16f);
}
/*@Override
public boolean mouseClicked(double mX, double mY, int button) {
return this.button.mouseClicked(mX, mY, button) || super.mouseClicked(mX, mY, button);
}*/
}

View file

@ -35,12 +35,11 @@ public class EnumEntry extends ValueEntry<Enum<?>> {
}
protected void cycleValue(int direction) {
Enum<?> e = value.get();
Enum<?> e = getValue();
Enum<?>[] options = e.getDeclaringClass().getEnumConstants();
e = options[Math.floorMod(e.ordinal() + direction, options.length)];
value.set(e);
setValue(e);
bumpCog(direction * 15f);
onValueChange();
}
@Override
@ -79,8 +78,8 @@ public class EnumEntry extends ValueEntry<Enum<?>> {
}
@Override
protected void onValueChange() {
super.onValueChange();
valueText.withText(value.get().name());
public void onValueChange(Enum<?> newValue) {
super.onValueChange(newValue);
valueText.withText(newValue.name());
}
}

View file

@ -39,7 +39,7 @@ public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
public NumberEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
textField = new ConfigTextField(Minecraft.getInstance().fontRenderer, 0, 0, 200, 30, unit);
textField.setText(String.valueOf(value.get()));
textField.setText(String.valueOf(getValue()));
Object range = spec.getRange();
try {
@ -74,8 +74,7 @@ public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
throw new IllegalArgumentException();
textField.setTextColor(0xff_20cc20);
value.set(number);
onValueChange();
setValue(number);
} catch (IllegalArgumentException ignored) {
textField.setTextColor(0xff_cc2020);
@ -105,9 +104,13 @@ public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
}
@Override
protected void onReset() {
super.onReset();
textField.setText(String.valueOf(value.get()));
public void onValueChange(T newValue) {
super.onValueChange(newValue);
String newText = String.valueOf(newValue);
if (textField.getText().equals(newText))
return;
textField.setText(newText);
}
@Override

View file

@ -4,7 +4,6 @@ import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.ConfigButton;
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
import com.simibubi.create.foundation.config.ui.ServerSubMenuConfigScreen;
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.TextStencilElement;
@ -12,21 +11,18 @@ import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraftforge.common.ForgeConfigSpec;
public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
protected PonderButton button;
public SubMenuEntry(Screen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) {
public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) {
super(label);
TextStencilElement text = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Click to open").centered(true, true);
text.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2));
button = new PonderButton(0, 0, () -> ScreenOpener.transitionTo(isForServer() ?
new ServerSubMenuConfigScreen(parent, spec, config) :
new SubMenuConfigScreen(parent, spec, config))
).showingUnscaled(text);
button = new PonderButton(0, 0, () -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config)))
.showingUnscaled(text);
button.fade(1);
listeners.add(button);

View file

@ -6,44 +6,49 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.ArrayUtils;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
import com.simibubi.create.foundation.config.ui.ConfigButton;
import com.simibubi.create.foundation.config.ui.ConfigScreen;
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
protected static final IFormattableTextComponent modComponent = new StringTextComponent("* ").formatted(TextFormatting.BOLD, TextFormatting.DARK_BLUE).append(StringTextComponent.EMPTY.copy().formatted(TextFormatting.RESET));
protected static final int resetWidth = 28;//including 6px offset on either side
public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]");
//public static DelegatedStencilElement.ElementRenderer idle = (ms, w, h) -> UIRenderHelper.angledGradient(ms, 0, 0, h / 2, h, w, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2);
protected ForgeConfigSpec.ConfigValue<T> value;
protected ForgeConfigSpec.ValueSpec spec;
protected PonderButton resetButton;
protected boolean editable = true;
protected String unit = null;
protected String path;
public ValueEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label);
this.value = value;
this.spec = spec;
this.path = String.join(".", value.getPath());
TextStencilElement text = new TextStencilElement(Minecraft.getInstance().fontRenderer, "R").centered(true, true);
text.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2));
resetButton = new PonderButton(0, 0, (_$, _$$) -> {
value.set((T) spec.getDefault());
setValue((T) spec.getDefault());
this.onReset();
}, resetWidth - 12, 16).showingUnscaled(text);
}, resetWidth - 12, 16)
.showing(AllIcons.I_CONFIG_RESET.asStencil()/*.withElementRenderer(idle)*/);
resetButton.fade(1);
listeners.add(resetButton);
@ -82,12 +87,20 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
@Override
protected void setEditable(boolean b) {
editable = b;
resetButton.active = editable && !value.get().equals(spec.getDefault());
resetButton.active = editable && !isCurrentValueDefault();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
if (isCurrentValueChanged()) {
IFormattableTextComponent original = label.getComponent();
IFormattableTextComponent changed = modComponent.copy().append(original);
label.withText(changed);
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
label.withText(original);
} else {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
}
resetButton.x = x + width - resetWidth + 6;
resetButton.y = y + 15;
@ -99,18 +112,40 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
return (int) (totalWidth * labelWidthMult);
}
protected void onReset() {
onValueChange();
public void setValue(@Nonnull T value) {
if (value.equals(this.value.get())) {
ConfigScreen.changes.remove(path);
onValueChange(value);
return;
}
protected void onValueChange() {
resetButton.active = editable && !value.get().equals(spec.getDefault());
ConfigScreen.changes.put(path, value);
onValueChange(value);
}
if (!isForServer())
return;
@Nonnull
public T getValue() {
//noinspection unchecked
return (T) ConfigScreen.changes.getOrDefault(path, this.value.get());
}
String path = String.join(".", value.getPath());
AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(path, value.get()));
protected boolean isCurrentValueChanged() {
return ConfigScreen.changes.containsKey(path);
}
protected boolean isCurrentValueDefault() {
return spec.getDefault().equals(getValue());
}
public void onReset() {
onValueChange(getValue());
}
public void onValueChange() {
onValueChange(getValue());
}
public void onValueChange(T newValue) {
resetButton.active = editable && !isCurrentValueDefault();
}
protected void bumpCog() {bumpCog(10f);}

View file

@ -124,7 +124,14 @@ public class AllIcons implements IScreenRenderable {
I_MTD_SCAN = next(),
I_MTD_REPLAY = next(),
I_MTD_USER_MODE = next(),
I_MTD_SLOW_MODE = next();
I_MTD_SLOW_MODE = next(),
I_CONFIG_UNLOCKED = newRow(),
I_CONFIG_LOCKED = next(),
I_CONFIG_DISCARD = next(),
I_CONFIG_SAVE = next(),
I_CONFIG_RESET = next(),
I_CONFIG_BACK = next();
public AllIcons(int x, int y) {
iconX = x * 16;
@ -179,6 +186,11 @@ public class AllIcons implements IScreenRenderable {
vertex(peek, builder, j, k, rgb, vec4, u1, v2);
}
@OnlyIn(Dist.CLIENT)
public DelegatedStencilElement asStencil() {
return new DelegatedStencilElement().withStencilRenderer((ms, w, h) -> this.draw(ms, 0, 0)).withBounds(16, 16);
}
@OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u, float v) {
builder.vertex(peek.getModel(), (float) vec.x, (float) vec.y, (float) vec.z)

View file

@ -0,0 +1,186 @@
package com.simibubi.create.foundation.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.Style;
public class ConfirmationScreen extends AbstractSimiScreen {
private Screen source;
private Consumer<Boolean> action = _success -> {};
private List<ITextProperties> text = new ArrayList<>();
private boolean centered = false;
private int x;
private int y;
private int textWidth;
private int textHeight;
private PonderButton confirm;
private PonderButton cancel;
/*
* Removes text lines from the back of the list
* */
public ConfirmationScreen removeTextLines(int amount) {
if (amount > text.size())
return clearText();
text.subList(text.size() - amount, text.size()).clear();
return this;
}
public ConfirmationScreen clearText() {
this.text.clear();
return this;
}
public ConfirmationScreen addText(ITextProperties text) {
this.text.add(text);
return this;
}
public ConfirmationScreen withText(ITextProperties text) {
return clearText().addText(text);
}
public ConfirmationScreen at(int x, int y) {
this.x = Math.max(x, 0);
this.y = Math.max(y, 0);
this.centered = false;
return this;
}
public ConfirmationScreen centered() {
this.centered = true;
return this;
}
public ConfirmationScreen withAction(Consumer<Boolean> action) {
this.action = action;
return this;
}
public void open(@Nonnull Screen source) {
this.source = source;
Minecraft client = source.getMinecraft();
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
this.client.currentScreen = this;
}
@Override
protected void init() {
widgets.clear();
ArrayList<ITextProperties> copy = new ArrayList<>(text);
text.clear();
copy.forEach(t -> text.addAll(client.fontRenderer.getTextHandler().wrapLines(t, 300, Style.EMPTY)));
textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4;
textWidth = 300;
if (x + textWidth > width) {
x = width - textWidth;
}
if (y + textHeight + 30 > height) {
y = height - textHeight - 30;
}
if (centered) {
x = width/2 - textWidth/2 - 2;
y = height/2 - textHeight/2 - 16;
}
TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true);
confirm = new PonderButton(x + 4, y + textHeight + 2, (_$, _$$) -> accept(true), textWidth/2 - 10, 20)
.showingUnscaled(confirmText);
confirm.fade(1);
TextStencilElement cancelText = new TextStencilElement(client.fontRenderer, "Cancel").centered(true, true);
cancel = new PonderButton(x + textWidth/2 + 6, y + textHeight + 2, (_$, _$$) -> accept(false), textWidth/2 - 10, 20)
.showingUnscaled(cancelText);
cancel.fade(1);
widgets.add(confirm);
widgets.add(cancel);
}
@Override
public void onClose() {
accept(false);
}
private void accept(boolean success) {
client.currentScreen = source;
action.accept(success);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
PonderUI.renderBox(ms, x, y, textWidth, textHeight, false);
int offset = client.fontRenderer.FONT_HEIGHT + 1;
int lineY = y - offset;
ms.push();
ms.translate(0, 0, 200);
for (ITextProperties line : text) {
lineY = lineY + offset;
if (line == null)
continue;
client.fontRenderer.draw(ms, line.getString(), x, lineY, 0xeaeaea);
}
ms.pop();
}
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
UIRenderHelper.prepFramebufferSize();
ms.push();
//ms.translate(0, 0, -50);
//ms.scale(1, 1, 0.01f);
UIRenderHelper.framebuffer.bindFramebuffer(true);
source.render(ms, mouseX, mouseY, partialTicks);
UIRenderHelper.framebuffer.unbindFramebuffer();
Minecraft.getInstance().getFramebuffer().bindFramebuffer(true);
ms.pop();
//RenderSystem.disableAlphaTest();
RenderSystem.disableBlend();
UIRenderHelper.drawFramebuffer(1);
RenderSystem.enableBlend();
RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
this.fillGradient(ms, 0, 0, this.width, this.height, 0x70101010, 0x80101010);
//RenderSystem.enableAlphaTest();
}
@Override
public void resize(@Nonnull Minecraft client, int width, int height) {
super.resize(client, width, height);
source.resize(client, width, height);
}
}

View file

@ -7,7 +7,6 @@ public class DelegatedStencilElement extends StencilElement {
protected static final ElementRenderer EMPTY_RENDERER = (ms, width, height) -> {};
protected static final ElementRenderer DEFAULT_ELEMENT = (ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, -3, 5, height+4, width+6, 0xff_10dd10, 0xff_1010dd);
protected ElementRenderer stencil;
protected ElementRenderer element;

View file

@ -65,7 +65,7 @@ public class ScreenOpener {
if (screenHistory.isEmpty())
return false;
Screen previouslyRenderedScreen = screenHistory.get(0);
if (!(previouslyRenderedScreen instanceof AbstractSimiScreen))
if (!(previouslyRenderedScreen instanceof NavigatableSimiScreen))
return false;
if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen))
return false;

View file

@ -4,6 +4,8 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3f;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.KHRDebug;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper;
@ -22,8 +24,6 @@ public class UIRenderHelper {
public static void enableStencil() {
RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil());
if (framebuffer != null)
RenderSystem.recordRenderCall(() -> framebuffer.enableStencil());
}
public static Framebuffer framebuffer;
@ -33,11 +33,13 @@ public class UIRenderHelper {
MainWindow mainWindow = Minecraft.getInstance().getWindow();
framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true, Minecraft.IS_RUNNING_ON_MAC);
framebuffer.setFramebufferColor(0, 0, 0, 0);
KHRDebug.glObjectLabel(GL30.GL_FRAMEBUFFER, framebuffer.framebufferObject, "UIBuffer");
framebuffer.enableStencil();
// framebuffer.deleteFramebuffer();
});
}
public static void prepFramebufferSize() {
public static void prepFramebufferSize() {//TODO move this to a mixin
MainWindow window = Minecraft.getInstance().getWindow();
if (framebuffer.framebufferWidth != window.getFramebufferWidth() || framebuffer.framebufferHeight != window.getFramebufferHeight()) {
framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC);
@ -54,10 +56,6 @@ public class UIRenderHelper {
float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight;
RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.disableLighting();
RenderSystem.disableAlphaTest();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
framebuffer.bindFramebufferTexture();
@ -73,8 +71,6 @@ public class UIRenderHelper {
tessellator.draw();
framebuffer.unbindFramebufferTexture();
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
}
//angle in degrees; 0° -> fading to the right

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.ponder;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.ScreenOpener;
@ -106,7 +107,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (transition.getChaseTarget() == 0) {
if (transition.getChaseTarget() == 0 || transition.settled()) {
renderBackground(ms);
return;
}
@ -125,7 +126,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.push();// 2
ms.translate(0, 0, -1000);
UIRenderHelper.framebuffer.bindFramebuffer(true);
lastScreen.render(ms, mouseX, mouseY, 10);
lastScreen.render(ms, mouseX, mouseY, partialTicks);
ms.pop();// 2
// use the buffer texture
@ -147,7 +148,12 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.translate(dpx, dpy, 0);
ms.scale((float) scale, (float) scale, 1);
ms.translate(-dpx, -dpy, 0);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.disableAlphaTest();
UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue));
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
ms.pop();// 1
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 17 KiB