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 36e75d18b..e613bfafd 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 @@ -3,8 +3,9 @@ package com.simibubi.create.foundation.config.ui; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.TextStencilElement; +import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; @@ -14,9 +15,9 @@ import net.minecraftforge.fml.config.ModConfig; public class BaseConfigScreen extends ConfigScreen { - PonderButton clientConfigWidget; - PonderButton commonConfigWidget; - PonderButton serverConfigWidget; + BoxWidget clientConfigWidget; + BoxWidget commonConfigWidget; + BoxWidget serverConfigWidget; public BaseConfigScreen(Screen parent) { super(parent); @@ -28,30 +29,31 @@ public class BaseConfigScreen extends ConfigScreen { super.init(); 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.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification)); - }, 200, 30).showingUnscaled(text)); - clientConfigWidget.fade(1); + widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 50, 200, 30) + .showingElement(text) + .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification))) + ); + text.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget)); 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.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification)); - }, 200, 30).showingUnscaled(text2)); - commonConfigWidget.fade(1); + widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 30) + .showingElement(text2) + .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification))) + ); + text2.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget)); TextStencilElement text3 = new TextStencilElement(client.fontRenderer, new StringTextComponent("SERVER CONFIG").formatted(TextFormatting.BOLD)).centered(true, true); - text3.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(serverConfigWidget = new PonderButton(width / 2 - 100, height / 2 - 15 + 50, (_$, _$$) -> { - }, 200, 30).showingUnscaled(text3)); - serverConfigWidget.fade(1); + widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 50, 200, 30) + .showingElement(text3) + ); if (Minecraft.getInstance().world != null) { serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification))); + text3.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget)); } 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)); + serverConfigWidget.updateColorsFromState(); + text3.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE_1), Theme.i(Theme.Key.BUTTON_DISABLE_2) | 0x40_000000)); } } } 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 deleted file mode 100644 index 768baab81..000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigButton.java +++ /dev/null @@ -1,163 +0,0 @@ -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; -import com.simibubi.create.foundation.gui.CombinedStencilElement; -import com.simibubi.create.foundation.gui.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.StencilElement; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.widgets.StencilWidget; -import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -public class ConfigButton extends StencilWidget { - - LerpedFloat colorAnimation = LerpedFloat.linear(); - protected int gradientColor1 = Palette.button_idle_1, gradientColor2 = Palette.button_idle_2; - private int colorTarget1, colorTarget2; - private int previousColor1, previousColor2; - - protected boolean wasHovered; - - 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, 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, height/2, height+2, width+2, button.gradientColor1, button.gradientColor2); - } - }; - button.stencilElement = CombinedStencilElement.of(box, text); - return button; - } - - public static ConfigButton createAndInjectElementRenderer(int x, int y, DelegatedStencilElement stencil) { - ConfigButton button = new ConfigButton(x, y); - button.stencilElement = stencil.withElementRenderer((ms, $width, $height) -> UIRenderHelper.angledGradient(ms, 0, 0, $height/2, $height+2, $width+2, button.gradientColor1, button.gradientColor2)); - 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); - } - - public ConfigButton(int x, int y, int width, int height, StencilElement stencilElement) { - 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); - } - - @Override - public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - //update hover status - //hovered = isMouseOver(mouseX, mouseY); - if (hovered != wasHovered) { - startGradientAnimation( - Palette.getColorForButtonState(true, active, hovered), - Palette.getColorForButtonState(false, active, hovered), - hovered - ); - } - - //update color animations - if (!colorAnimation.settled()) { - float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks)); - gradientColor1 = ColorHelper.mixAlphaColors(previousColor1, colorTarget1, animationValue); - gradientColor2 = ColorHelper.mixAlphaColors(previousColor2, colorTarget2, animationValue); - } - - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); - fill(ms, x, y, x + width, y + height, 0x10_ffffff); - RenderSystem.defaultBlendFunc(); - super.renderButton(ms, mouseX, mouseY, partialTicks); - wasHovered = hovered; - } - - public void updateColorsFromState() { - gradientColor1 = Palette.getColorForButtonState(true, active, hovered); - gradientColor2 = Palette.getColorForButtonState(false, active, hovered); - } - - public void animateGradientFromState() { - startGradientAnimation( - Palette.getColorForButtonState(true, active, hovered), - Palette.getColorForButtonState(false, active, hovered), - true - ); - } - - private void startGradientAnimation(int c1, int c2, boolean positive, double expSpeed) { - colorAnimation.startWithValue(positive ? 1 : -1); - colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP); - - previousColor1 = gradientColor1; - previousColor2 = gradientColor2; - - colorTarget1 = c1; - colorTarget2 = c2; - } - - private void startGradientAnimation(int c1, int c2, boolean positive) { - startGradientAnimation(c1, c2, positive, 0.3); - } - - public static class Palette { - public static int button_idle_1 = 0xff_c0c0ff; - public static int button_idle_2 = 0xff_7b7ba3; - - public static int button_hover_1 = 0xff_7b7ba3; - public static int button_hover_2 = 0xff_616192; - - public static int button_click_1 = 0xff_4b4bff; - public static int button_click_2 = 0xff_3b3bdd; - - public static int button_disable_1 = 0xff_909090; - public static int button_disable_2 = 0xff_606060; - - public static int getColorForButtonState(boolean first, boolean active, boolean hovered) { - if (!active) { - return first ? button_disable_1 : button_disable_2; - } - - if (!hovered) { - return first ? button_idle_1 : button_idle_2; - } - - return first ? button_hover_1 : button_hover_2; - } - - } -} 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 index 304ae9cce..f5dd5ea9e 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java @@ -9,6 +9,7 @@ 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.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; import net.minecraft.client.MainWindow; @@ -73,7 +74,14 @@ public class ConfigScreenList extends ExtendedList { } public void tick() { - children().forEach(Entry::tick); + //children().forEach(Entry::tick); + for(int i = 0; i < getItemCount(); ++i) { + int top = this.getRowTop(i); + int bot = top + itemHeight; + if (bot >= this.top && top <= this.bottom) + this.getEntry(i).tick(); + } + } public void bumpCog(float force) { @@ -126,7 +134,7 @@ public class ConfigScreenList extends ExtendedList { public LabeledEntry(String label) { this.label = new TextStencilElement(Minecraft.getInstance().fontRenderer, label); - this.label.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2)); + this.label.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.TEXT_ACCENT_1), Theme.i(Theme.Key.TEXT_ACCENT_2))); labelTooltip = new ArrayList<>(); } 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 index 408343255..2858ace02 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.config.ui; +import java.awt.Color; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -17,10 +19,10 @@ 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.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.gui.widgets.BoxWidget; 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; @@ -38,11 +40,11 @@ public class SubMenuConfigScreen extends ConfigScreen { protected UnmodifiableConfig configGroup; protected ConfigScreenList list; - protected PonderButton resetAll; - protected PonderButton saveChanges; - protected PonderButton discardChanges; - protected PonderButton goBack; - protected PonderButton serverLocked; + protected BoxWidget resetAll; + protected BoxWidget saveChanges; + protected BoxWidget discardChanges; + protected BoxWidget goBack; + protected BoxWidget serverLocked; protected int listWidth; protected String title; @@ -117,60 +119,65 @@ public class SubMenuConfigScreen extends ConfigScreen { 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 = new BoxWidget(listR + 10, yCenter - 25, 20, 20) + .withCallback((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) + ); + + resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll)) + .at(2, 2)); 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; + saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20) + .withCallback((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); + 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); + }); + saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges)) + .at(2, 2)); 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; + discardChanges = new BoxWidget(listL - 30, yCenter + 5, 20, 20) + .withCallback((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); + 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); + }); + discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges)) + .at(2, 2)); 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 = new BoxWidget(listL - 30, yCenter + 65, 20, 20) + .withCallback(this::attemptBackstep); + goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(goBack)) + .at(2, 2)); goBack.getToolTip().add(new StringTextComponent("Go Back")); widgets.add(resetAll); @@ -214,36 +221,35 @@ public class SubMenuConfigScreen extends ConfigScreen { } }); - //extras for sever configs + //extras for server 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; + Color colRed1 = Theme.c("button_fail_1"); + Color colRed2 = Theme.c("button_fail_2"); + Color colGreen1 = Theme.c("button_success_1"); + Color colGreen2 = Theme.c("button_success_2"); DelegatedStencilElement stencil = new DelegatedStencilElement(); - serverLocked = new PonderButton(listR + 10, yCenter + 5, () -> {}) - .showing(stencil); - serverLocked.fade(1); + serverLocked = new BoxWidget(listR + 10, yCenter + 5, 20, 20) + .showingElement(stencil.at(2, 2)); 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); + stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_LOCKED.draw(ms, 0, 0)); + stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colRed1.getRGB(), colRed2.getRGB())); + serverLocked.withBorderColors(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); + stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0)); + stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colGreen1.getRGB(), colGreen2.getRGB())); + serverLocked.withBorderColors(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)); } @@ -256,7 +262,7 @@ public class SubMenuConfigScreen extends ConfigScreen { super.renderWindow(ms, mouseX, mouseY, partialTicks); int x = width/2; - drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, 0xff_eaeaea); + drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, Theme.i(Theme.Key.TEXT_1)); list.render(ms, mouseX, mouseY, partialTicks); } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java index 2c9e37338..59ffdd120 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java @@ -3,7 +3,7 @@ package com.simibubi.create.foundation.config.ui.entries; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.TextStencilElement; import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.client.Minecraft; import net.minecraftforge.common.ForgeConfigSpec; @@ -12,22 +12,22 @@ public class BooleanEntry extends ValueEntry { TextStencilElement enabled; TextStencilElement disabled; - PonderButton button; + BoxWidget button; public BooleanEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { super(label, value, spec); enabled = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Enabled") .centered(true, true) - .withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height/2, height, width, 0xff_88f788, 0xff_20cc20)); + .withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height/2, height, width, 0xff_88f788, 0xff_20cc20)); disabled = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Disabled") .centered(true, true) - .withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0, 0, height/2, height, width, 0xff_f78888, 0xff_cc2020)); + .withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height/2, height, width, 0xff_f78888, 0xff_cc2020)); - button = new PonderButton(0, 0, () -> setValue(!getValue())) - .showingUnscaled(enabled); - button.fade(1); + button = new BoxWidget() + .showingElement(enabled) + .withCallback(() -> setValue(!getValue())); listeners.add(button); onReset(); @@ -42,6 +42,7 @@ public class BooleanEntry extends ValueEntry { @Override public void tick() { super.tick(); + button.tick(); } @Override @@ -58,7 +59,7 @@ public class BooleanEntry extends ValueEntry { @Override public void onValueChange(Boolean newValue) { super.onValueChange(newValue); - button.showingUnscaled(newValue ? enabled : disabled); + button.showingElement(newValue ? enabled : disabled); bumpCog(newValue ? 15f : -16f); } } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java index e4df547e3..e9aae833d 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java @@ -1,9 +1,10 @@ package com.simibubi.create.foundation.config.ui.entries; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.config.ui.ConfigButton; import com.simibubi.create.foundation.gui.TextStencilElement; +import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.client.Minecraft; import net.minecraftforge.common.ForgeConfigSpec; @@ -13,20 +14,22 @@ public class EnumEntry extends ValueEntry> { protected static final int cycleWidth = 34;//including 2px offset on either side protected TextStencilElement valueText; - protected ConfigButton cycleLeft; - protected ConfigButton cycleRight; + protected BoxWidget cycleLeft; + protected BoxWidget cycleRight; public EnumEntry(String label, ForgeConfigSpec.ConfigValue> value, ForgeConfigSpec.ValueSpec spec) { super(label, value, spec); valueText = new TextStencilElement(Minecraft.getInstance().fontRenderer, "YEP").centered(true, true); - valueText.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, ConfigButton.Palette.button_hover_1, ConfigButton.Palette.button_hover_2)); + valueText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.i(Theme.Key.TEXT_1), Theme.i(Theme.Key.TEXT_2))); TextStencilElement l = new TextStencilElement(Minecraft.getInstance().fontRenderer, "<").centered(true, true); - cycleLeft = ConfigButton.createAndInjectElementRenderer(0, 0, l).withBounds(30, 30).withCallback(() -> cycleValue(-1)); + cycleLeft = new BoxWidget(0, 0, 22, 22).showingElement(l).withCallback(() -> cycleValue(-1)); + l.withElementRenderer(BoxWidget.gradientFactory.apply(cycleLeft)); TextStencilElement r = new TextStencilElement(Minecraft.getInstance().fontRenderer, ">").centered(true, true); - cycleRight = ConfigButton.createAndInjectElementRenderer(0, 0, r).withBounds(30, 30).withCallback(() -> cycleValue(1)); + cycleRight = new BoxWidget(0, 0, 22, 22).showingElement(r).withCallback(() -> cycleValue(1)); + r.withElementRenderer(BoxWidget.gradientFactory.apply(cycleRight)); listeners.add(cycleLeft); listeners.add(cycleRight); diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java index f4a1b6115..7634edd0d 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java @@ -6,9 +6,9 @@ import java.util.function.Function; import javax.annotation.Nullable; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.config.ui.ConfigButton; import com.simibubi.create.foundation.config.ui.ConfigTextField; import com.simibubi.create.foundation.gui.TextStencilElement; +import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; import net.minecraft.client.Minecraft; @@ -54,13 +54,13 @@ public abstract class NumberEntry extends ValueEntry { if (!min.equals(getTypeMin())) { StringTextComponent t = new StringTextComponent(formatBound(min) + " < "); minText = new TextStencilElement(font, t).centered(true, false); - minText.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, ConfigButton.Palette.button_hover_1, ConfigButton.Palette.button_hover_2)); + minText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.c(Theme.Key.TEXT_ACCENT_1).darker().getRGB(), Theme.c(Theme.Key.TEXT_ACCENT_2).darker().getRGB())); minOffset = font.getWidth(t); } if (!max.equals(getTypeMax())) { StringTextComponent t = new StringTextComponent(" < " + formatBound(max)); maxText = new TextStencilElement(font, t).centered(true, false); - maxText.withElementRenderer((ms, width, height) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, ConfigButton.Palette.button_hover_1, ConfigButton.Palette.button_hover_2)); + maxText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.c(Theme.Key.TEXT_ACCENT_1).darker().getRGB(), Theme.c(Theme.Key.TEXT_ACCENT_2).darker().getRGB())); maxOffset = font.getWidth(t); } } catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) { 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 index 131ce5c48..0931587c7 100644 --- 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 @@ -2,28 +2,27 @@ 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 com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.client.Minecraft; import net.minecraftforge.common.ForgeConfigSpec; public class SubMenuEntry extends ConfigScreenList.LabeledEntry { - protected PonderButton button; + protected BoxWidget button; 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.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config))) - .showingUnscaled(text); - button.fade(1); + + button = new BoxWidget() + .showingElement(text) + .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config))); + text.withElementRenderer(BoxWidget.gradientFactory.apply(button)); listeners.add(button); } @@ -31,6 +30,7 @@ public class SubMenuEntry extends ConfigScreenList.LabeledEntry { @Override public void tick() { super.tick(); + button.tick(); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java index ff015c702..6c594cec3 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java @@ -11,13 +11,11 @@ import javax.annotation.Nonnull; import org.apache.commons.lang3.ArrayUtils; import com.mojang.blaze3d.matrix.MatrixStack; -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.AllIcons; import com.simibubi.create.foundation.gui.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.StringTextComponent; @@ -29,11 +27,10 @@ public class ValueEntry 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 value; protected ForgeConfigSpec.ValueSpec spec; - protected PonderButton resetButton; + protected BoxWidget resetButton; protected boolean editable = true; protected String unit = null; protected String path; @@ -44,12 +41,13 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { this.spec = spec; this.path = String.join(".", value.getPath()); - resetButton = new PonderButton(0, 0, (_$, _$$) -> { - setValue((T) spec.getDefault()); - this.onReset(); - }, resetWidth - 12, 16) - .showing(AllIcons.I_CONFIG_RESET.asStencil()/*.withElementRenderer(idle)*/); - resetButton.fade(1); + resetButton = new BoxWidget(0, 0, resetWidth - 12, 16) + .showingElement(AllIcons.I_CONFIG_RESET.asStencil()) + .withCallback(() -> { + setValue((T) spec.getDefault()); + this.onReset(); + }); + resetButton.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(resetButton))); listeners.add(resetButton); @@ -88,6 +86,13 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { protected void setEditable(boolean b) { editable = b; resetButton.active = editable && !isCurrentValueDefault(); + resetButton.animateGradientFromState(); + } + + @Override + public void tick() { + super.tick(); + resetButton.tick(); } @Override @@ -146,6 +151,7 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { } public void onValueChange(T newValue) { resetButton.active = editable && !isCurrentValueDefault(); + resetButton.animateGradientFromState(); } protected void bumpCog() {bumpCog(10f);} diff --git a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java index 7e3364131..1e889eb50 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java @@ -68,8 +68,6 @@ public abstract class AbstractSimiContainerScreen extends C RenderSystem.disableLighting(); RenderSystem.disableDepthTest(); renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks); - for (Widget widget : widgets) - widget.renderToolTip(matrixStack, mouseX, mouseY); } @Override @@ -151,8 +149,12 @@ public abstract class AbstractSimiContainerScreen extends C if (!widget.isHovered()) continue; - if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip().isEmpty()) { - renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + if (widget instanceof AbstractSimiWidget) { + if (!((AbstractSimiWidget) widget).getToolTip().isEmpty()) + renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + + } else { + widget.renderToolTip(matrixStack, mouseX, mouseY); } } } 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 066ff0993..b6faa7ba1 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java @@ -33,6 +33,13 @@ public abstract class AbstractSimiScreen extends Screen { guiTop = (this.height - sHeight) / 2; } + @Override + public void tick() { + super.tick(); + + widgets.stream().filter(w -> w instanceof AbstractSimiWidget).forEach(w -> ((AbstractSimiWidget) w).tick()); + } + @Override public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { partialTicks = partialTicks == 10 ? 0 @@ -46,8 +53,6 @@ public abstract class AbstractSimiScreen extends Screen { for (Widget widget : widgets) widget.render(ms, mouseX, mouseY, partialTicks); renderWindowForeground(ms, mouseX, mouseY, partialTicks); - for (Widget widget : widgets) - widget.renderToolTip(ms, mouseX, mouseY); ms.pop(); } @@ -131,8 +136,12 @@ public abstract class AbstractSimiScreen extends Screen { if (!widget.isHovered()) continue; - if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip().isEmpty()) { - renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + if (widget instanceof AbstractSimiWidget) { + if (!((AbstractSimiWidget) widget).getToolTip().isEmpty()) + renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + + } else { + widget.renderToolTip(ms, mouseX, mouseY); } } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java index f81cceb59..3a4b55d80 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java @@ -5,6 +5,7 @@ import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.Create; import com.simibubi.create.foundation.utility.ColorHelper; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -188,7 +189,7 @@ public class AllIcons implements IScreenRenderable { @OnlyIn(Dist.CLIENT) public DelegatedStencilElement asStencil() { - return new DelegatedStencilElement().withStencilRenderer((ms, w, h) -> this.draw(ms, 0, 0)).withBounds(16, 16); + return new DelegatedStencilElement().withStencilRenderer((ms, w, h, alpha) -> this.draw(ms, 0, 0)).withBounds(16, 16); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java b/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java new file mode 100644 index 000000000..334ef2490 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java @@ -0,0 +1,151 @@ +package com.simibubi.create.foundation.gui; + +import java.awt.Color; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.math.vector.Matrix4f; + +public class BoxElement extends RenderElement { + + protected Color background = new Color(0xff000000, true); + protected Color borderTop = new Color(0x40ffeedd, true); + protected Color borderBot = new Color(0x20ffeedd, true); + protected int borderOffset = 2; + + public T withBackground(Color color) { + this.background = color; + //noinspection unchecked + return (T) this; + } + + public T withBackground(int color) { + return withBackground(new Color(color, true)); + } + + public T flatBorder(Color color) { + this.borderTop = color; + this.borderBot = color; + //noinspection unchecked + return (T) this; + } + + public T flatBorder(int color) { + return flatBorder(new Color(color, true)); + } + + public T gradientBorder(Color top, Color bot) { + this.borderTop = top; + this.borderBot = bot; + //noinspection unchecked + return (T) this; + } + + public T gradientBorder(int top, int bot) { + return gradientBorder(new Color(top, true), new Color(bot, true)); + } + + public T withBorderOffset(int offset) { + this.borderOffset = offset; + //noinspection unchecked + return (T) this; + } + + @Override + public void render(MatrixStack ms) { + renderBox(ms); + } + + //total box width = 1 * 2 (outer border) + 1 * 2 (inner color border) + 2 * borderOffset + width + //defaults to 2 + 2 + 4 + 16 = 24px + //batch everything together to save a bunch of gl calls over GuiUtils + protected void renderBox(MatrixStack ms) { + /* + * _____________ + * _|_____________|_ + * | | ___________ | | + * | | | | | | | + * | | | | | | | + * | | |--* | | | | + * | | | h | | | + * | | | --w-+ | | | + * | | | | | | + * | | |_________| | | + * |_|_____________|_| + * |_____________| + * + * */ + RenderSystem.disableTexture(); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.shadeModel(GL11.GL_SMOOTH); + RenderSystem.color4f(1, 1, 1, alpha); + + int f = borderOffset; + Color c1 = background, c2 = borderTop, c3 = borderBot; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder b = tessellator.getBuffer(); + Matrix4f model = ms.peek().getModel(); + b.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + //outer top + b.vertex(model, x - f - 1 , y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + //outer left + b.vertex(model, x - f - 2 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x - f - 2 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + //outer bottom + b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + //outer right + b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 2 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 2 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + //inner background - also render behind the inner edges + b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); + tessellator.draw(); + b.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + //inner top - includes corners + b.vertex(model, x - f - 1 , y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + //inner left - excludes corners + b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x - f , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x - f , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + //inner bottom - includes corners + b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + //inner right - excludes corners + b.vertex(model, x + f + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + b.vertex(model, x + f + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); + b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); + + tessellator.draw(); + + RenderSystem.shadeModel(GL11.GL_FLAT); + RenderSystem.disableBlend(); + RenderSystem.enableTexture(); + RenderSystem.color4f(1, 1, 1, 1); + } +} 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 07789469f..374479c69 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java @@ -1,6 +1,7 @@ package com.simibubi.create.foundation.gui; import javax.annotation.Nonnull; + import com.mojang.blaze3d.matrix.MatrixStack; public class CombinedStencilElement extends StencilElement { @@ -45,21 +46,23 @@ public class CombinedStencilElement extends StencilElement { protected void renderStencil(MatrixStack ms) { ms.push(); element1.transform(ms); - element1.withBounds(width, height).renderStencil(ms); + element1.withBounds(width, height); + element1.renderStencil(ms); ms.pop(); ms.push(); element2.transform(ms); - element2.withBounds(width, height).renderStencil(ms); + element2.withBounds(width, height); + element2.renderStencil(ms); ms.pop(); } @Override protected void renderElement(MatrixStack ms) { if (mode.rendersFirst()) - element1.withBounds(width, height).renderElement(ms); + element1.withBounds(width, height).renderElement(ms); if (mode.rendersSecond()) - element2.withBounds(width, height).renderElement(ms); + element2.withBounds(width, height).renderElement(ms); } public enum ElementMode { diff --git a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java index 807dc91a0..c7e64981c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java @@ -10,8 +10,7 @@ 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 com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; @@ -29,8 +28,9 @@ public class ConfirmationScreen extends AbstractSimiScreen { private int textWidth; private int textHeight; - private PonderButton confirm; - private PonderButton cancel; + private BoxWidget confirm; + private BoxWidget cancel; + private BoxElement textBackground; /* * Removes text lines from the back of the list @@ -81,6 +81,13 @@ public class ConfirmationScreen extends AbstractSimiScreen { this.client.currentScreen = this; } + @Override + public void tick() { + super.tick(); + confirm.tick(); + cancel.tick(); + } + @Override protected void init() { widgets.clear(); @@ -106,18 +113,23 @@ public class ConfirmationScreen extends AbstractSimiScreen { } 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); + confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20) + .withCallback(() -> accept(true)); + confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm))); 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); + cancel = new BoxWidget(x + textWidth/2 + 6, y + textHeight + 2, textWidth/2 - 10, 20) + .withCallback(() -> accept(false)); + cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel))); widgets.add(confirm); widgets.add(cancel); + textBackground = new BoxElement() + .gradientBorder(Theme.c(Theme.Key.BUTTON_DISABLE_1), Theme.c(Theme.Key.BUTTON_DISABLE_2)) + .withBounds(textWidth, textHeight) + .at(x, y); + } @Override @@ -133,7 +145,7 @@ public class ConfirmationScreen extends AbstractSimiScreen { @Override protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - PonderUI.renderBox(ms, x, y, textWidth, textHeight, false); + textBackground.render(ms); int offset = client.fontRenderer.FONT_HEIGHT + 1; int lineY = y - offset; @@ -157,11 +169,12 @@ public class ConfirmationScreen extends AbstractSimiScreen { protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); - UIRenderHelper.prepFramebufferSize(); + //UIRenderHelper.prepFramebufferSize(); ms.push(); //ms.translate(0, 0, -50); //ms.scale(1, 1, 0.01f); + //todo wait for jozu's framebuffer capabilities on the other branch and use them here UIRenderHelper.framebuffer.bindFramebuffer(true); source.render(ms, mouseX, mouseY, partialTicks); UIRenderHelper.framebuffer.unbindFramebuffer(); diff --git a/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java index 2d0397065..4b45ace4f 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java @@ -1,11 +1,12 @@ package com.simibubi.create.foundation.gui; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.utility.ColorHelper; 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 static final ElementRenderer EMPTY_RENDERER = (ms, width, height, alpha) -> {}; + protected static final ElementRenderer DEFAULT_ELEMENT = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, -3, 5, height+4, width+6, ColorHelper.applyAlpha(0xff_10dd10, alpha), ColorHelper.applyAlpha(0xff_1010dd, alpha)); protected ElementRenderer stencil; protected ElementRenderer element; @@ -34,17 +35,17 @@ public class DelegatedStencilElement extends StencilElement { @Override protected void renderStencil(MatrixStack ms) { - stencil.render(ms, width, height); + stencil.render(ms, width, height, 1); } @Override protected void renderElement(MatrixStack ms) { - element.render(ms, width, height); + element.render(ms, width, height, alpha); } @FunctionalInterface public interface ElementRenderer { - void render(MatrixStack ms, int width, int height); + void render(MatrixStack ms, int width, int height, float alpha); } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/RenderElement.java b/src/main/java/com/simibubi/create/foundation/gui/RenderElement.java new file mode 100644 index 000000000..5300d8506 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/RenderElement.java @@ -0,0 +1,62 @@ +package com.simibubi.create.foundation.gui; + +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.client.gui.AbstractGui; + +public abstract class RenderElement implements IScreenRenderable { + + public static RenderElement EMPTY = new RenderElement() {@Override public void render(MatrixStack ms) {}}; + + protected int width = 16, height = 16; + protected float x = 0, y = 0, z = 0; + protected float alpha = 1f; + + public T at(float x, float y) { + this.x = x; + this.y = y; + //noinspection unchecked + return (T) this; + } + + public T at(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + //noinspection unchecked + return (T) this; + } + + public T withBounds(int width, int height) { + this.width = width; + this.height = height; + //noinspection unchecked + return (T) this; + } + + public T withAlpha(float alpha) { + this.alpha = alpha; + //noinspection unchecked + return (T) this; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public abstract void render(MatrixStack ms); + + @Override + public void draw(MatrixStack ms, AbstractGui screen, int x, int y) { + this.at(x, y).render(ms); + } + + @Override + public void draw(MatrixStack ms, int x, int y) { + this.at(x, y).render(ms); + } +} 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 220b5fa8c..26677e053 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java @@ -1,43 +1,15 @@ 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.systems.RenderSystem; -public abstract class StencilElement implements IScreenRenderable { +import net.minecraft.client.Minecraft; - protected int width = 0; - protected int height = 0; - float x, y , z; - - public T at(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - //noinspection unchecked - return (T) this; - } - - public T withBounds(int width, int height) { - this.width = width; - this.height = height; - //noinspection unchecked - return (T) this; - } +public abstract class StencilElement extends RenderElement { @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) { ms.push(); transform(ms); @@ -49,22 +21,6 @@ public abstract class StencilElement implements IScreenRenderable { 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 3fc0c4e24..f2d5ff943 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java @@ -1,11 +1,11 @@ package com.simibubi.create.foundation.gui; +import com.mojang.blaze3d.matrix.MatrixStack; + import net.minecraft.client.gui.FontRenderer; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.StringTextComponent; -import com.mojang.blaze3d.matrix.MatrixStack; - public class TextStencilElement extends DelegatedStencilElement { protected FontRenderer font; @@ -70,7 +70,7 @@ public class TextStencilElement extends DelegatedStencilElement { ms.push(); ms.translate(x, y, 0); - element.render(ms, font.getWidth(component), font.FONT_HEIGHT + 2); + element.render(ms, font.getWidth(component), font.FONT_HEIGHT + 2, alpha); ms.pop(); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/Theme.java b/src/main/java/com/simibubi/create/foundation/gui/Theme.java new file mode 100644 index 000000000..5733fe70a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/Theme.java @@ -0,0 +1,129 @@ +package com.simibubi.create.foundation.gui; + +import java.awt.Color; +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class Theme { + + private static final Theme base = new Theme(); + private static Theme custom = null; + + public static void setTheme(@Nullable Theme theme) { + custom = theme; + } + + @Nonnull public static Color c(String key) { + Color r = null; + + if (custom != null) + r = custom.get(key); + + if (r == null) + r = base.get(key); + + if (r == null) + r = Color.BLACK; + + return r; + } + + @Nonnull public static Color c(Key key) { + return c(key.get()); + } + + public static int i(String key) { + return c(key).getRGB(); + } + + public static int i(Key key) { + return i(key.get()); + } + + //-----------// + + protected final Map colors; + + protected Theme() { + colors = new HashMap<>(); + init(); + } + + protected void init() { + put(Key.BUTTON_IDLE_1, new Color(0x60_c0c0ff, true)); + put(Key.BUTTON_IDLE_2, new Color(0x30_c0c0ff, true)); + put(Key.BUTTON_HOVER_1, new Color(0xa0_c0c0ff, true)); + put(Key.BUTTON_HOVER_2, new Color(0x50_c0c0ff, true)); + put(Key.BUTTON_CLICK_1, new Color(0xff_4b4bff)); + put(Key.BUTTON_CLICK_2, new Color(0xff_3b3bdd)); + put(Key.BUTTON_DISABLE_1, new Color(0x80_909090, true)); + put(Key.BUTTON_DISABLE_2, new Color(0x20_909090, true)); + put("button_success_1", new Color(0xcc_88f788, true)); + put("button_success_2", new Color(0xcc_20cc20, true)); + put("button_fail_1", new Color(0xcc_f78888, true)); + put("button_fail_2", new Color(0xcc_cc2020, true)); + put(Key.TEXT_1, new Color(0xff_eeeeee)); + put(Key.TEXT_2, new Color(0xff_a3a3a3)); + put(Key.TEXT_ACCENT_1, new Color(0xff_7b7ba3)); + put(Key.TEXT_ACCENT_2, new Color(0xff_616192)); + //values from PonderUI & PonderButton + put(Key.PONDER_BACKGROUND, new Color(0xdd_000000, true)); + put(Key.PONDER_IDLE_1, new Color(0x40ffeedd, true)); + put(Key.PONDER_IDLE_2, new Color(0x20ffeedd, true)); + put(Key.PONDER_HOVER_1, new Color(0x70ffffff, true)); + put(Key.PONDER_HOVER_2, new Color(0x30ffffff, true)); + put(Key.PONDER_HIGHLIGHT_1, new Color(0xf0ffeedd, true)); + put(Key.PONDER_HIGHLIGHT_2, new Color(0x60ffeedd, true)); + } + + protected void put(String key, Color c) { + colors.put(key, c); + } + + protected void put(Key key, Color c) { + put(key.get(), c); + } + + @Nullable public Color get(String key) { + return colors.get(key); + } + + public enum Key { + BUTTON_IDLE_1("button_idle_1"), + BUTTON_IDLE_2("button_idle_2"), + BUTTON_HOVER_1("button_hover_1"), + BUTTON_HOVER_2("button_hover_2"), + BUTTON_CLICK_1("button_click_1"), + BUTTON_CLICK_2("button_click_2"), + BUTTON_DISABLE_1("button_disable_1"), + BUTTON_DISABLE_2("button_disable_2"), + + TEXT_1("text_1"), + TEXT_2("text_2"), + TEXT_ACCENT_1("text_accent_1"), + TEXT_ACCENT_2("text_accent_2"), + + PONDER_BACKGROUND("ponder_background"), + PONDER_IDLE_1("ponder_idle_1"), + PONDER_IDLE_2("ponder_idle_2"), + PONDER_HOVER_1("ponder_hover_1"), + PONDER_HOVER_2("ponder_hover_2"), + PONDER_HIGHLIGHT_1("ponder_highlight_1"), + PONDER_HIGHLIGHT_2("ponder_highlight_2"), + + ; + + String s; + + Key(String s) { + this.s = s; + } + + String get() { + return s; + } + } +} 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 e89d49797..96417860e 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java @@ -1,12 +1,12 @@ package com.simibubi.create.foundation.gui; -import com.mojang.blaze3d.matrix.MatrixStack; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; +import javax.annotation.Nonnull; + import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.KHRDebug; +import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.foundation.utility.ColorHelper; @@ -16,10 +16,10 @@ import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.shader.Framebuffer; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3f; import net.minecraftforge.fml.client.gui.GuiUtils; -import javax.annotation.Nonnull; - public class UIRenderHelper { public static void enableStencil() { @@ -39,12 +39,12 @@ public class UIRenderHelper { }); } - public static void prepFramebufferSize() {//TODO move this to a mixin + /*public static void prepFramebufferSize() { 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); } - } + }*/ public static void drawFramebuffer(float alpha) { MainWindow window = Minecraft.getInstance() 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 2826467bc..fe7323783 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 @@ -4,30 +4,30 @@ import java.util.LinkedList; import java.util.List; import java.util.function.BiConsumer; +import javax.annotation.Nonnull; + import com.mojang.blaze3d.matrix.MatrixStack; import net.minecraft.client.gui.widget.Widget; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; -import javax.annotation.Nonnull; - public abstract class AbstractSimiWidget extends Widget { - protected List toolTip; + protected boolean wasHovered = false; + protected List toolTip = new LinkedList<>(); protected BiConsumer onClick = (_$, _$$) -> {}; - public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) { - super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY); - toolTip = new LinkedList<>(); + protected AbstractSimiWidget() { + this(0, 0); } - - public List getToolTip() { - return toolTip; + + protected AbstractSimiWidget(int x, int y) { + this(x, y, 16, 16); } - - @Override - public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + + protected AbstractSimiWidget(int x, int y, int width, int height) { + super(x, y, width, height, StringTextComponent.EMPTY); } public T withCallback(BiConsumer cb) { @@ -40,6 +40,39 @@ public abstract class AbstractSimiWidget extends Widget { return withCallback((_$, _$$) -> cb.run()); } + public List getToolTip() { + return toolTip; + } + + public void tick() {} + + @Override + public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + if (visible) { + hovered = isMouseOver(mouseX, mouseY); + beforeRender(ms, mouseX, mouseY, partialTicks); + renderButton(ms, mouseX, mouseY, partialTicks); + afterRender(ms, mouseX, mouseY, partialTicks); + wasHovered = isHovered(); + } + } + + @Override + public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {} + + @Override + protected boolean clicked(double mouseX, double mouseY) { + return active && visible && isMouseOver(mouseX, mouseY); + } + + protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + ms.push(); + } + + protected void afterRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + ms.pop(); + } + 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/BoxWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/BoxWidget.java new file mode 100644 index 000000000..b9ad08fb9 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/BoxWidget.java @@ -0,0 +1,168 @@ +package com.simibubi.create.foundation.gui.widgets; + +import java.awt.Color; +import java.util.function.Function; + +import javax.annotation.Nonnull; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.gui.BoxElement; +import com.simibubi.create.foundation.gui.DelegatedStencilElement; +import com.simibubi.create.foundation.gui.Theme; +import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +public class BoxWidget extends ElementWidget { + + public static final Function gradientFactory = (box) -> (ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, w/2, -2, w + 4, h + 4, box.gradientColor1.getRGB(), box.gradientColor2.getRGB()); + + protected BoxElement box; + + protected Color customBorderTop; + protected Color customBorderBot; + protected boolean animateColors = true; + protected LerpedFloat colorAnimation = LerpedFloat.linear(); + protected Color gradientColor1 = Theme.c(Theme.Key.BUTTON_IDLE_1), gradientColor2 = Theme.c(Theme.Key.BUTTON_IDLE_2); + private Color colorTarget1, colorTarget2; + private Color previousColor1, previousColor2; + + public BoxWidget() { + this(0, 0); + } + + public BoxWidget(int x, int y) { + this(x, y, 16, 16); + } + public BoxWidget(int x, int y, int width, int height) { + super(x, y, width, height); + box = new BoxElement() + .at(x, y) + .withBounds(width, height); + } + + public BoxWidget withBounds(int width, int height) { + this.width = width; + this.height = height; + return this; + } + + public BoxWidget withBorderColors(Color top, Color bot) { + this.customBorderTop = top; + this.customBorderBot = bot; + updateColorsFromState(); + return this; + } + + @Override + public void tick() { + colorAnimation.tickChaser(); + } + + @Override + public void onClick(double x, double y) { + super.onClick(x, y); + + gradientColor1 = Theme.c(Theme.Key.BUTTON_CLICK_1); + gradientColor2 = Theme.c(Theme.Key.BUTTON_CLICK_2); + startGradientAnimation(getColorForState(true), getColorForState(false), true, 0.15); + } + + @Override + public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + float fadeValue = fade.getValue(partialTicks); + if (fadeValue < .1f) + return; + + box.withBackground(ColorHelper.applyAlpha(0xdd000000, fadeValue)) + .gradientBorder(gradientColor1, gradientColor2) + .at(x, y) + .withBounds(width, height) + .render(ms); + + super.renderButton(ms, mouseX, mouseY, partialTicks); + + wasHovered = hovered; + } + + @Override + protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + super.beforeRender(ms, mouseX, mouseY, partialTicks); + + if (hovered != wasHovered) { + startGradientAnimation( + getColorForState(true), + getColorForState(false), + hovered + ); + } + + if (!colorAnimation.settled()) { + float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks)); + gradientColor1 = ColorHelper.mixColors(previousColor1, colorTarget1, animationValue); + gradientColor2 = ColorHelper.mixColors(previousColor2, colorTarget2, animationValue); + } + + } + + @Override + public boolean isMouseOver(double mX, double mY) { + if (!active || !visible) + return false; + + return + x - 4 <= mX && + y - 4 <= mY && + mX <= x + 4 + width && + mY <= y + 4 + height; + } + + public BoxElement getBox() { + return box; + } + + public void updateColorsFromState() { + gradientColor1 = getColorForState(true); + gradientColor2 = getColorForState(false); + } + + public void animateGradientFromState() { + startGradientAnimation( + getColorForState(true), + getColorForState(false), + true + ); + } + + private void startGradientAnimation(Color c1, Color c2, boolean positive, double expSpeed) { + colorAnimation.startWithValue(positive ? 1 : -1); + colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP); + + previousColor1 = gradientColor1; + previousColor2 = gradientColor2; + + colorTarget1 = c1; + colorTarget2 = c2; + } + + private void startGradientAnimation(Color c1, Color c2, boolean positive) { + startGradientAnimation(c1, c2, positive, 0.3); + } + + private Color getColorForState(boolean first) { + if (!active) + return first ? Theme.c(Theme.Key.BUTTON_DISABLE_1) : Theme.c(Theme.Key.BUTTON_DISABLE_2); + + if (hovered) { + if (first) + return customBorderTop != null ? customBorderTop.darker() : Theme.c(Theme.Key.BUTTON_HOVER_1); + else + return customBorderBot != null ? customBorderBot.darker() : Theme.c(Theme.Key.BUTTON_HOVER_2); + } + + if (first) + return customBorderTop != null ? customBorderTop : Theme.c(Theme.Key.BUTTON_IDLE_1); + else + return customBorderBot != null ? customBorderBot : Theme.c(Theme.Key.BUTTON_IDLE_2); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/ElementWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/ElementWidget.java new file mode 100644 index 000000000..985b9216a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/ElementWidget.java @@ -0,0 +1,104 @@ +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.RenderElement; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +public class ElementWidget extends AbstractSimiWidget { + + protected RenderElement element = RenderElement.EMPTY; + + protected boolean usesFade = false; + protected int fadeModX; + protected int fadeModY; + protected LerpedFloat fade = LerpedFloat.linear().startWithValue(1); + + protected boolean rescaleElement = false; + protected float rescaleSizeX; + protected float rescaleSizeY; + + public ElementWidget(int x, int y) { + super(x, y); + } + + public ElementWidget(int x, int y, int width, int height) { + super(x, y, width, height); + } + + public T showingElement(RenderElement element) { + this.element = element; + //noinspection unchecked + return (T) this; + } + + public T modifyElement(Consumer consumer) { + if (element != null) + consumer.accept(element); + //noinspection unchecked + return (T) this; + } + + public T mapElement(UnaryOperator function) { + if (element != null) + element = function.apply(element); + //noinspection unchecked + return (T) this; + } + + public T enableFade(int fadeModifierX, int fadeModifierY) { + this.fade.startWithValue(0); + this.usesFade = true; + this.fadeModX = fadeModifierX; + this.fadeModY = fadeModifierY; + //noinspection unchecked + return (T) this; + } + + public T disableFade() { + this.fade.startWithValue(1); + this.usesFade = false; + //noinspection unchecked + return (T) this; + } + + public T rescaleElement(float rescaleSizeX, float rescaleSizeY) { + this.rescaleElement = true; + this.rescaleSizeX = rescaleSizeX; + this.rescaleSizeY = rescaleSizeY; + //noinspection unchecked + return (T) this; + } + + public T disableRescale() { + this.rescaleElement = false; + //noinspection unchecked + return (T) this; + } + + @Override + protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + super.beforeRender(ms, mouseX, mouseY, partialTicks); + + //todo fade + } + + @Override + public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + ms.push(); + ms.translate(x, y, 0); + if (rescaleElement) { + ms.scale(width / rescaleSizeX, height / rescaleSizeY, 1); + } + element.withBounds(width, height).render(ms); + ms.pop(); + } + + public RenderElement getRenderElement() { + return element; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java index 25df71cb1..627d6b017 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.gui.widgets; +import javax.annotation.Nonnull; + import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.AllGuiTextures; @@ -22,7 +24,7 @@ public class Indicator extends AbstractSimiWidget { } @Override - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks ) { + public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks ) { AllGuiTextures toDraw; switch(state) { case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break; diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java index 55e3ea767..3c7d904ca 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.gui.widgets; +import javax.annotation.Nonnull; + import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; @@ -69,7 +71,7 @@ public class Label extends AbstractSimiWidget { } @Override - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { if (!visible) return; if (text == null || text.getString().isEmpty()) 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 deleted file mode 100644 index 5e8a464af..000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/StencilWidget.java +++ /dev/null @@ -1,54 +0,0 @@ -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; - -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); - } - - public StencilWidget(int x, int y, int width, int height, StencilElement stencilElement) { - super(x, y, width, height); - this.stencilElement = stencilElement; - } - - @Override - public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - ms.push(); - - ms.translate(x, y, 0); - 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/mixin/WindowResizeMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java new file mode 100644 index 000000000..5008129b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java @@ -0,0 +1,29 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.simibubi.create.foundation.gui.UIRenderHelper; + +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(Minecraft.class) +public class WindowResizeMixin { + + @Shadow @Final private MainWindow mainWindow; + + @Inject(at = @At("TAIL"), method = "updateWindowSize") + private void updateWindowSize(CallbackInfo ci) { + if (UIRenderHelper.framebuffer != null) + UIRenderHelper.framebuffer.func_216491_a(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java index 73f354c44..b340cd8d8 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java @@ -1,5 +1,13 @@ package com.simibubi.create.foundation.ponder; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.mutable.MutableBoolean; +import org.apache.commons.lang3.mutable.MutableInt; +import org.lwjgl.glfw.GLFW; + import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.foundation.gui.AbstractSimiScreen; @@ -10,18 +18,12 @@ import com.simibubi.create.foundation.ponder.content.PonderTagScreen; import com.simibubi.create.foundation.ponder.ui.PonderButton; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.animation.LerpedFloat; + import net.minecraft.client.MainWindow; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; -import org.apache.commons.lang3.mutable.MutableBoolean; -import org.apache.commons.lang3.mutable.MutableInt; -import org.lwjgl.glfw.GLFW; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; public abstract class NavigatableSimiScreen extends AbstractSimiScreen { @@ -122,7 +124,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { if (lastScreen != null && lastScreen != this && !transition.settled()) { ms.push();// 1 UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); - UIRenderHelper.prepFramebufferSize(); + //UIRenderHelper.prepFramebufferSize(); ms.push();// 2 ms.translate(0, 0, -1000); UIRenderHelper.framebuffer.bindFramebuffer(true); diff --git a/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java b/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java index 51996fb3a..5c2544e77 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java @@ -1,7 +1,10 @@ package com.simibubi.create.foundation.utility; +import java.awt.Color; import java.util.UUID; +import javax.annotation.Nonnull; + import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.util.math.MathHelper; @@ -52,6 +55,18 @@ public class ColorHelper { return color; } + @Nonnull + public static Color mixColors(@Nonnull Color c1, @Nonnull Color c2, float w) { + float[] cmp1 = c1.getRGBComponents(null); + float[] cmp2 = c2.getRGBComponents(null); + return new Color( + cmp1[0] + (cmp2[0] - cmp1[0]) * w, + cmp1[1] + (cmp2[1] - cmp1[1]) * w, + cmp1[2] + (cmp2[2] - cmp1[2]) * w, + cmp1[3] + (cmp2[3] - cmp1[3]) * w + ); + } + public static int mixAlphaColors(int color1, int color2, float w) { int a1 = (color1 >> 24); int r1 = (color1 >> 16) & 0xFF; diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 81b7d6c55..c0a38f0c8 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -1,22 +1,23 @@ { - "required": true, - "priority": 1100, - "package": "com.simibubi.create.foundation.mixin", - "compatibilityLevel": "JAVA_8", - "refmap": "create.refmap.json", - "client": [ - "TileWorldHookMixin", - "CancelTileEntityRenderMixin", - "FogColorTrackerMixin", - "LightUpdateMixin", - "NetworkLightUpdateMixin", - "RenderHooksMixin", - "ShaderCloseMixin", - "TileRemoveMixin", - "EntityContraptionInteractionMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "minVersion": "0.8" + "required": true, + "priority": 1100, + "package": "com.simibubi.create.foundation.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "create.refmap.json", + "client": [ + "CancelTileEntityRenderMixin", + "EntityContraptionInteractionMixin", + "FogColorTrackerMixin", + "LightUpdateMixin", + "NetworkLightUpdateMixin", + "RenderHooksMixin", + "ShaderCloseMixin", + "TileRemoveMixin", + "TileWorldHookMixin", + "WindowResizeMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" } \ No newline at end of file