diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java index 4063c63b2..b2e9a3edd 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java @@ -1,16 +1,15 @@ package com.simibubi.create.foundation.config.ui; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.gui.StencilElement; +import com.simibubi.create.foundation.gui.TextStencilElement; + import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TextFormatting; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.gui.CombinedStencilElement; -import com.simibubi.create.foundation.gui.StencilElement; -import com.simibubi.create.foundation.gui.TextStencilElement; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.widgets.StencilWidget; - public class BaseConfigScreen extends ConfigScreen { ConfigButton clientConfigWidget; @@ -26,50 +25,44 @@ public class BaseConfigScreen extends ConfigScreen { widgets.clear(); super.init(); - StencilElement text = new TextStencilElement.Centered(client.fontRenderer, new StringTextComponent("CLIENT CONFIG").formatted(TextFormatting.BOLD), 200).at(0, 11, 0); - widgets.add(clientConfigWidget = ConfigButton.createFromTextElement( - width/2 - 100, - height/2 - 15 - 50, - 200, - 30, + StencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("CLIENT CONFIG").formatted(TextFormatting.BOLD)).centered(true, true); + widgets.add(clientConfigWidget = ConfigButton.createFromStencilElement( + width / 2 - 100, + height / 2 - 15 - 50, text - )); + ) + .withBounds(200, 30) + .withCallback(() -> ScreenOpener.transitionTo(new SubMenuConfigScreen(this, AllConfigs.CLIENT.specification))) + ); - StencilElement text2 = new TextStencilElement.Centered(client.fontRenderer, new StringTextComponent("COMMON CONFIG").formatted(TextFormatting.BOLD), 200).at(0, 11, 0); - widgets.add(commonConfigWidget = ConfigButton.createFromTextElement( - width/2 - 100, - height/2 - 15, - 200, - 30, + StencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("COMMON CONFIG").formatted(TextFormatting.BOLD)).centered(false, true).at(0, 11, 0); + widgets.add(commonConfigWidget = ConfigButton.createFromStencilElement( + width / 2 - 100, + height / 2 - 15, text2 - )); + ) + .withBounds(200, 30) + ); commonConfigWidget.active = false; commonConfigWidget.updateColorsFromState(); StencilElement text3 = new TextStencilElement.Centered(client.fontRenderer, new StringTextComponent("SERVER CONFIG").formatted(TextFormatting.BOLD), 200).at(0, 11, 0); - widgets.add(serverConfigWidget = ConfigButton.createFromTextElement( - width/2 - 100, - height/2 - 15 + 50, - 200, - 30, + widgets.add(serverConfigWidget = ConfigButton.createFromStencilElement( + width / 2 - 100, + height / 2 - 15 + 50, text3 - )); + ) + .withBounds(200, 30) + ); serverConfigWidget.active = false; serverConfigWidget.updateColorsFromState(); } - @Override - public void tick() { - super.tick(); - - widgets.stream() - .filter(w -> w instanceof ConfigButton) - .forEach(w -> ((ConfigButton) w).tick()); - } - @Override protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { super.renderWindow(ms, mouseX, mouseY, partialTicks); + + testStencil.at(200, 200, 0).render(ms); } } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigButton.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigButton.java index ffe8a18f4..4017283d7 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigButton.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigButton.java @@ -1,6 +1,7 @@ package com.simibubi.create.foundation.config.ui; import javax.annotation.Nonnull; + import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; @@ -20,26 +21,30 @@ public class ConfigButton extends StencilWidget { protected boolean wasHovered; - public static ConfigButton createFromTextElement(int x, int y, int width, int height, StencilElement text) { - ConfigButton button = new ConfigButton(x, y, width, height); + public static ConfigButton createFromStencilElement(int x, int y, StencilElement text) { + ConfigButton button = new ConfigButton(x, y); StencilElement box = new StencilElement() { @Override protected void renderStencil(MatrixStack ms) { - fill(ms, 0, 0 , width, 0 + 1, 0xff_000000); - fill(ms, 0, height, width +1, height + 1, 0xff_000000); + fill(ms, 0, 0 , width , 0 + 1, 0xff_000000); + fill(ms, 0, height, width + 1, height + 1, 0xff_000000); fill(ms, 0 , 0, 0 + 1, height, 0xff_000000); fill(ms, width, 0, width + 1, height, 0xff_000000); } @Override protected void renderElement(MatrixStack ms) { - UIRenderHelper.angledGradient(ms, 0, 0, 15, 32, 201, button.gradientColor1, button.gradientColor2); + UIRenderHelper.angledGradient(ms, 0, 0, height/2, height+2, width+2, button.gradientColor1, button.gradientColor2); } }; button.stencilElement = CombinedStencilElement.of(box, text); return button; } + protected ConfigButton(int x, int y) { + super(x, y); + } + protected ConfigButton(int x, int y, int width, int height) { super(x, y, width, height); } @@ -48,12 +53,20 @@ public class ConfigButton extends StencilWidget { super(x, y, width, height, stencilElement); } + public ConfigButton withBounds(int width, int height) { + this.width = width; + this.height = height; + return this; + } + public void tick() { colorAnimation.tickChaser(); } @Override public void onClick(double x, double y) { + runCallback(x, y); + gradientColor1 = Palette.button_click_1; gradientColor2 = Palette.button_click_2; startGradientAnimation(Palette.getColorForButtonState(true, active, hovered), Palette.getColorForButtonState(false, active, hovered), true, 0.15); diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java index 0a7d55628..95a7ea2e8 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java @@ -4,8 +4,12 @@ import net.minecraft.block.BlockState; import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.Direction; +import net.minecraftforge.common.ForgeConfigSpec; +import java.util.Arrays; +import java.util.stream.Collectors; import javax.annotation.Nonnull; +import org.apache.commons.lang3.StringUtils; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllBlocks; @@ -14,11 +18,12 @@ 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.gui.UIRenderHelper; +import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; import com.simibubi.create.foundation.utility.animation.Force; import com.simibubi.create.foundation.utility.animation.PhysicalFloat; -public class ConfigScreen extends NavigatableSimiScreen { +public abstract class ConfigScreen extends NavigatableSimiScreen { private final Screen parent; protected static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f)); @@ -33,12 +38,23 @@ public 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(); + /*super.init(); + if (backTrack != null) { + widgets.remove(backTrack); + backTrack = null; + }*/ + + testStencil = new TextStencilElement(client.fontRenderer, "POGGERS").at(width*0.5f, height*0.5f, 0); } @@ -108,4 +124,9 @@ public class ConfigScreen extends NavigatableSimiScreen { return super.mouseScrolled(mouseX, mouseY, delta); } + + public static String toHumanReadable(String key) { + String s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(key)).map(StringUtils::capitalize).collect(Collectors.joining(" ")); + return s; + } } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java new file mode 100644 index 000000000..9b4d62b98 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java @@ -0,0 +1,91 @@ +package com.simibubi.create.foundation.config.ui; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.gui.StencilElement; +import com.simibubi.create.foundation.gui.TextStencilElement; +import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.widget.list.ExtendedList; + +public class ConfigScreenList extends ExtendedList { + + + public ConfigScreenList(Minecraft client, int width, int height, int top, int bottom, int elementHeight) { + super(client, width, height, top, bottom, elementHeight); + func_244605_b(false); + func_244606_c(false); + } + + @Override + public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + //render tmp background + fill(ms, left, top, left+width, top+height, 0x44_000000); + + super.render(ms, mouseX, mouseY, partialTicks); + } + + @Override + public int getRowWidth() { + return width-10; + } + + @Override + protected int getScrollbarPositionX() { + return left + this.width; + } + + public void tick() { + children().forEach(Entry::tick); + } + + public static abstract class Entry extends ExtendedList.AbstractListEntry { + public void tick() { + + } + } + + public static class LabeledEntry extends Entry { + protected StencilElement label; + + public LabeledEntry(String label) { + this.label = new TextStencilElement(Minecraft.getInstance().fontRenderer, label); + } + + @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) { + UIRenderHelper.streak(ms, 0, x, y+height/2, height, width/2, 0x0); + label.at(x + 5, y + height/2 - 4, 0).render(ms); + } + } + + public static class WrappedEntry extends Entry { + + AbstractSimiWidget widget; + + public WrappedEntry(AbstractSimiWidget widget) { + this.widget = widget; + } + + @Override + public void tick() { + if (widget instanceof ConfigButton) + ((ConfigButton) widget).tick(); + } + + @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) { + widget.x = x; + widget.y = y; + widget.setWidth(width); + widget.setHeight(height); + widget.render(ms, mouseX, mouseY, partialTicks); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + return widget.mouseClicked(x, y, button); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java new file mode 100644 index 000000000..d469b1bcb --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java @@ -0,0 +1,97 @@ +package com.simibubi.create.foundation.config.ui; + +import javax.annotation.Nonnull; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraftforge.common.ForgeConfigSpec; + +import org.apache.commons.lang3.mutable.MutableInt; +import com.electronwill.nightconfig.core.AbstractConfig; +import com.electronwill.nightconfig.core.UnmodifiableConfig; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.gui.TextStencilElement; +import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; + +public class SubMenuConfigScreen extends ConfigScreen { + + ForgeConfigSpec spec; + UnmodifiableConfig configGroup; + ConfigScreenList list; + + + public SubMenuConfigScreen(Screen parent, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) { + super(parent); + this.spec = configSpec; + this.configGroup = configGroup; + } + + public SubMenuConfigScreen(Screen parent, ForgeConfigSpec configSpec) { + super(parent); + this.spec = configSpec; + this.configGroup = configSpec.getValues(); + } + + @Override + public void tick() { + super.tick(); + list.tick(); + } + + @Override + protected void init() { + widgets.clear(); + super.init(); + + int lWidth = width - 66; + list = new ConfigScreenList(client, lWidth, height - 30, 15, height - 15, 50); + list.setLeftPos(this.width /2 - list.getWidth()/2); + + children.add(list); + + MutableInt y = new MutableInt(15); + + configGroup.valueMap().forEach((s, o) -> { + if (o instanceof AbstractConfig) { + SubMenuEntry entry = new SubMenuEntry(this, toHumanReadable(s), spec, (UnmodifiableConfig) o); + list.children().add(entry); + + } else if (o instanceof ForgeConfigSpec.ConfigValue) { + ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue) o; + ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath()); + Object value = configValue.get(); + + AbstractSimiWidget widget = createWidgetForValue(configValue, valueSpec, value, s, this); + widget.y = y.getValue(); + //list.children().add(new ConfigScreenList.WrappedEntry(widget)); + list.children().add(new ConfigScreenList.LabeledEntry(toHumanReadable(s) + " : " + value)); + //widgets.add(widget); + } + + y.add(50); + }); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + super.renderWindow(ms, mouseX, mouseY, partialTicks); + + list.render(ms, mouseX, mouseY, partialTicks); + } + + @Override + public void resize(@Nonnull Minecraft client, int width, int height) { + double scroll = list.getScrollAmount(); + init(client, width, height); + list.setScrollAmount(scroll); + } + + public static AbstractSimiWidget createWidgetForValue(ForgeConfigSpec.ConfigValue configValue, ForgeConfigSpec.ValueSpec valueSpec, Object value, String key, SubMenuConfigScreen parent) { + String title = toHumanReadable(key); + title += " : " + value; + TextStencilElement text = new TextStencilElement(parent.client.fontRenderer, title).at(5, 11, 0); + return ConfigButton.createFromStencilElement(parent.width/2 - 100, 0, text); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/SubMenuEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/SubMenuEntry.java new file mode 100644 index 000000000..18a75d5d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/SubMenuEntry.java @@ -0,0 +1,46 @@ +package com.simibubi.create.foundation.config.ui.entries; + +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.SubMenuConfigScreen; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.gui.TextStencilElement; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraftforge.common.ForgeConfigSpec; + +public class SubMenuEntry extends ConfigScreenList.LabeledEntry { + + protected ConfigButton button; + + public SubMenuEntry(Screen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) { + super(label); + TextStencilElement text = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Click to open").centered(true, true); + button = ConfigButton.createFromStencilElement(0, 0, text) + .withCallback(() -> ScreenOpener.transitionTo(new SubMenuConfigScreen(parent, spec, config))); + } + + @Override + public void tick() { + super.tick(); + button.tick(); + } + + @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) { + super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); + + button.x = x + width/2; + button.y = y; + button.withBounds(width/2, height); + button.render(ms, mouseX, mouseY, partialTicks); + } + + @Override + public boolean mouseClicked(double p_231044_1_, double p_231044_3_, int p_231044_5_) { + return button.mouseClicked(p_231044_1_, p_231044_3_, p_231044_5_); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java index 1e2174214..066ff0993 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java @@ -62,6 +62,10 @@ public abstract class AbstractSimiScreen extends Screen { for (Widget widget : widgets) if (widget.mouseClicked(x, y, button)) result = true; + + if (!result) { + result = super.mouseClicked(x, y, button); + } return result; } diff --git a/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java index 7a8077ea8..caa577f58 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java @@ -27,21 +27,21 @@ public class CombinedStencilElement extends StencilElement { protected void renderStencil(MatrixStack ms) { ms.push(); element1.transform(ms); - element1.renderStencil(ms); + element1.withBounds(width, height).renderStencil(ms); ms.pop(); ms.push(); element2.transform(ms); - element2.renderStencil(ms); + element2.withBounds(width, height).renderStencil(ms); ms.pop(); } @Override protected void renderElement(MatrixStack ms) { if (mode.rendersFirst()) - element1.renderElement(ms); + element1.withBounds(width, height).renderElement(ms); if (mode.rendersSecond()) - element2.renderElement(ms); + element2.withBounds(width, height).renderElement(ms); } public enum ElementMode { diff --git a/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java new file mode 100644 index 000000000..08973b0b2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java @@ -0,0 +1,49 @@ +package com.simibubi.create.foundation.gui; + +import com.mojang.blaze3d.matrix.MatrixStack; + +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; + + public DelegatedStencilElement() { + stencil = EMPTY_RENDERER; + element = DEFAULT_ELEMENT; + } + + public DelegatedStencilElement(ElementRenderer stencil, ElementRenderer element) { + this.stencil = stencil; + this.element = element; + } + + public DelegatedStencilElement withStencilRenderer(ElementRenderer renderer) { + stencil = renderer; + return this; + } + + public DelegatedStencilElement withElementRenderer(ElementRenderer renderer) { + element = renderer; + return this; + } + + @Override + protected void renderStencil(MatrixStack ms) { + stencil.render(ms, width, height); + } + + @Override + protected void renderElement(MatrixStack ms) { + element.render(ms, width, height); + } + + @FunctionalInterface + public interface ElementRenderer { + void render(MatrixStack ms, int width, int height); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java index 161de3618..220b5fa8c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java @@ -1,21 +1,41 @@ package com.simibubi.create.foundation.gui; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.AbstractGui; import org.lwjgl.opengl.GL11; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -public abstract class StencilElement { +public abstract class StencilElement implements IScreenRenderable { + protected int width = 0; + protected int height = 0; float x, y , z; - public StencilElement at(float x, float y, float z) { + public T at(float x, float y, float z) { this.x = x; this.y = y; this.z = z; - return this; + //noinspection unchecked + return (T) this; + } + + public T withBounds(int width, int height) { + this.width = width; + this.height = height; + //noinspection unchecked + return (T) this; + } + + @Override + public void draw(MatrixStack ms, AbstractGui screen, int x, int y) { + this.at(x, y, 0).render(ms); + } + + @Override + public void draw(MatrixStack ms, int x, int y) { + this.at(x, y, 0).render(ms); } public void render(MatrixStack ms) { @@ -29,6 +49,22 @@ public abstract class StencilElement { ms.pop(); } + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + protected abstract void renderStencil(MatrixStack ms); protected abstract void renderElement(MatrixStack ms); diff --git a/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java index c1382507a..b278c7151 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java @@ -6,17 +6,17 @@ import net.minecraft.util.text.StringTextComponent; import com.mojang.blaze3d.matrix.MatrixStack; -public class TextStencilElement extends StencilElement { - - protected static final ElementRenderer DEFAULT_RENDERER = ((ms, width, _height) -> UIRenderHelper.angledGradient(ms, 15, -3, 5, 14, width+6, 0xff_10dd10, 0x1010dd)); +public class TextStencilElement extends DelegatedStencilElement { protected FontRenderer font; protected IFormattableTextComponent component; - protected ElementRenderer elementRenderer = DEFAULT_RENDERER; + protected boolean centerVertically = false; + protected boolean centerHorizontally = false; public TextStencilElement(FontRenderer font) { super(); this.font = font; + height = 10; } public TextStencilElement(FontRenderer font, String text) { @@ -29,11 +29,6 @@ public class TextStencilElement extends StencilElement { this.component = component; } - public TextStencilElement withElementRenderer(ElementRenderer renderer) { - elementRenderer = renderer; - return this; - } - public TextStencilElement withText(String text) { component = new StringTextComponent(text); return this; @@ -44,25 +39,35 @@ public class TextStencilElement extends StencilElement { return this; } + public TextStencilElement centered(boolean vertical, boolean horizontal) { + this.centerVertically = vertical; + this.centerHorizontally = horizontal; + return this; + } + @Override protected void renderStencil(MatrixStack ms) { - font.draw(ms, component, 0, 0, 0xff_000000); + + float x = 0, y = 0; + if (centerHorizontally) + x = width / 2f - font.getWidth(component) / 2f; + + if (centerVertically) + y = height / 2f - font.FONT_HEIGHT / 2f; + + font.draw(ms, component, x, y, 0xff_000000); + //font.draw(ms, component, 0, 0, 0xff_000000); } @Override protected void renderElement(MatrixStack ms) { - elementRenderer.render(ms, font.getWidth(component), 10); + element.render(ms, font.getWidth(component), height); } - @FunctionalInterface - public interface ElementRenderer { - void render(MatrixStack ms, int width, int height); - } + public static class Centered extends TextStencilElement { - int width; - public Centered(FontRenderer font, String text, int width) { super(font, text); this.width = width; @@ -81,7 +86,7 @@ public class TextStencilElement extends StencilElement { @Override protected void renderElement(MatrixStack ms) { - elementRenderer.render(ms, width, 10); + element.render(ms, width, 10); } } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java index c409480bd..5fca88e7c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java @@ -22,6 +22,8 @@ public class UIRenderHelper { public static void enableStencil() { RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil()); + if (framebuffer != null) + RenderSystem.recordRenderCall(() -> framebuffer.enableStencil()); } public static Framebuffer framebuffer; @@ -77,8 +79,8 @@ public class UIRenderHelper { //angle in degrees; 0° -> fading to the right //x and y specify the middle point of the starting edge - //width is the total width of the streak - public static void streak(MatrixStack ms, float angle, int x, int y, int width, int length, int color) { + //breadth is the total width of the streak + public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, int color) { int a1 = 0xa0 << 24; int a2 = 0x80 << 24; int a3 = 0x10 << 24; @@ -94,7 +96,7 @@ public class UIRenderHelper { ms.translate(x, y, 0); ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90)); - streak(ms, width/2, length, c1, c2, c3, c4); + streak(ms, breadth/2, length, c1, c2, c3, c4); ms.pop(); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java index f6ba1668c..f48ebcb51 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.gui.widgets; import java.util.LinkedList; import java.util.List; +import java.util.function.BiConsumer; import com.mojang.blaze3d.matrix.MatrixStack; @@ -14,7 +15,8 @@ import javax.annotation.Nonnull; public abstract class AbstractSimiWidget extends Widget { protected List toolTip; - + protected BiConsumer onClick = (_$, _$$) -> {}; + public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) { super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY); toolTip = new LinkedList<>(); @@ -28,4 +30,17 @@ public abstract class AbstractSimiWidget extends Widget { public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { } + public T withCallback(BiConsumer cb) { + this.onClick = cb; + //noinspection unchecked + return (T) this; + } + + public T withCallback(Runnable cb) { + return withCallback((_$, _$$) -> cb.run()); + } + + public void runCallback(double mouseX, double mouseY) { + onClick.accept((int) mouseX, (int) mouseY); + } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/StencilWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/StencilWidget.java index b58638d1e..5e8a464af 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/StencilWidget.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/StencilWidget.java @@ -1,5 +1,8 @@ package com.simibubi.create.foundation.gui.widgets; +import java.util.function.Consumer; +import java.util.function.UnaryOperator; + import javax.annotation.Nonnull; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.StencilElement; @@ -8,6 +11,10 @@ public class StencilWidget extends AbstractSimiWidget { protected StencilElement stencilElement; + protected StencilWidget(int x, int y) { + super(x, y, 42, 42); + } + protected StencilWidget(int x, int y, int width, int height) { super(x, y, width, height); } @@ -22,11 +29,25 @@ public class StencilWidget extends AbstractSimiWidget { ms.push(); ms.translate(x, y, 0); - stencilElement.render(ms); + stencilElement.withBounds(width, height).render(ms); ms.pop(); } + public T modifyElement(Consumer consumer) { + if (stencilElement != null) + consumer.accept(stencilElement); + //noinspection unchecked + return (T) this; + } + + public T mapElement(UnaryOperator function) { + if (stencilElement != null) + stencilElement = function.apply(stencilElement); + //noinspection unchecked + return (T) this; + } + public StencilElement getStencilElement() { return stencilElement; } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java index a5e31246c..3067d8c75 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java @@ -21,9 +21,9 @@ import javax.annotation.Nonnull; public class PonderButton extends AbstractSimiWidget { private IScreenRenderable icon; + private boolean scaleIcon = true; private ItemStack item; protected boolean pressed; - private BiConsumer onClick; private int xFadeModifier; private int yFadeModifier; private float fade; @@ -48,11 +48,21 @@ public class PonderButton extends AbstractSimiWidget { this(x, y, ($, $$) -> onClick.run()); } + /** + * @param icon the icon to be rendered. assumed to be 16x16px in size. will be scaled to fit the button size + * + */ public PonderButton showing(IScreenRenderable icon) { this.icon = icon; return this; } + public PonderButton showingUnscaled(IScreenRenderable icon) { + this.icon = icon; + this.scaleIcon = false; + return this; + } + public PonderButton showing(ItemStack item) { this.item = item; return this; @@ -121,7 +131,9 @@ public class PonderButton extends AbstractSimiWidget { RenderSystem.color4f(1, 1, 1, fade); ms.push(); ms.translate(x + 2, y + 2, 0); - ms.scale((width - 4) / 16f, (height - 4) / 16f, 1); + if (this.scaleIcon) + ms.scale((width - 4) / 16f, (height - 4) / 16f, 1); + icon.draw(ms, this, 0, 0); ms.pop(); } @@ -141,10 +153,6 @@ public class PonderButton extends AbstractSimiWidget { ms.pop(); } - public void runCallback(double mouseX, double mouseY) { - onClick.accept((int) mouseX, (int) mouseY); - } - @Override public void onClick(double p_onClick_1_, double p_onClick_3_) { super.onClick(p_onClick_1_, p_onClick_3_);