boxing elements

This commit is contained in:
zelophed 2021-04-25 19:54:18 +02:00
parent 33028e1087
commit c85870ea2d
31 changed files with 960 additions and 468 deletions

View file

@ -3,8 +3,9 @@ package com.simibubi.create.foundation.config.ui;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.TextStencilElement; 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.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.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
@ -14,9 +15,9 @@ import net.minecraftforge.fml.config.ModConfig;
public class BaseConfigScreen extends ConfigScreen { public class BaseConfigScreen extends ConfigScreen {
PonderButton clientConfigWidget; BoxWidget clientConfigWidget;
PonderButton commonConfigWidget; BoxWidget commonConfigWidget;
PonderButton serverConfigWidget; BoxWidget serverConfigWidget;
public BaseConfigScreen(Screen parent) { public BaseConfigScreen(Screen parent) {
super(parent); super(parent);
@ -28,30 +29,31 @@ public class BaseConfigScreen extends ConfigScreen {
super.init(); super.init();
TextStencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("CLIENT CONFIG").formatted(TextFormatting.BOLD)).centered(true, true); 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 BoxWidget(width / 2 - 100, height / 2 - 15 - 50, 200, 30)
widgets.add(clientConfigWidget = new PonderButton(width / 2 - 100, height / 2 - 15 - 50, (_$, _$$) -> { .showingElement(text)
ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification)); .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification)))
}, 200, 30).showingUnscaled(text)); );
clientConfigWidget.fade(1); text.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget));
TextStencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("COMMON CONFIG").formatted(TextFormatting.BOLD)).centered(true, true); 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 BoxWidget(width / 2 - 100, height / 2 - 15, 200, 30)
widgets.add(commonConfigWidget = new PonderButton(width / 2 - 100, height / 2 - 15, (_$, _$$) -> { .showingElement(text2)
ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification)); .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification)))
}, 200, 30).showingUnscaled(text2)); );
commonConfigWidget.fade(1); text2.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget));
TextStencilElement text3 = new TextStencilElement(client.fontRenderer, new StringTextComponent("SERVER CONFIG").formatted(TextFormatting.BOLD)).centered(true, true); 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 BoxWidget(width / 2 - 100, height / 2 - 15 + 50, 200, 30)
widgets.add(serverConfigWidget = new PonderButton(width / 2 - 100, height / 2 - 15 + 50, (_$, _$$) -> { .showingElement(text3)
}, 200, 30).showingUnscaled(text3)); );
serverConfigWidget.fade(1);
if (Minecraft.getInstance().world != null) { if (Minecraft.getInstance().world != null) {
serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification))); serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification)));
text3.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget));
} else { } else {
serverConfigWidget.active = false; 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));
} }
} }
} }

View file

@ -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;
}
}
}

View file

@ -9,6 +9,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry; import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.gui.TextStencilElement; 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.UIRenderHelper;
import net.minecraft.client.MainWindow; import net.minecraft.client.MainWindow;
@ -73,7 +74,14 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
} }
public void tick() { 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) { public void bumpCog(float force) {
@ -126,7 +134,7 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
public LabeledEntry(String label) { public LabeledEntry(String label) {
this.label = new TextStencilElement(Minecraft.getInstance().fontRenderer, 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<>(); labelTooltip = new ArrayList<>();
} }

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.config.ui; package com.simibubi.create.foundation.config.ui;
import java.awt.Color;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; 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.ConfirmationScreen;
import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.ScreenOpener; 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.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener; import net.minecraft.client.gui.IGuiEventListener;
@ -38,11 +40,11 @@ public class SubMenuConfigScreen extends ConfigScreen {
protected UnmodifiableConfig configGroup; protected UnmodifiableConfig configGroup;
protected ConfigScreenList list; protected ConfigScreenList list;
protected PonderButton resetAll; protected BoxWidget resetAll;
protected PonderButton saveChanges; protected BoxWidget saveChanges;
protected PonderButton discardChanges; protected BoxWidget discardChanges;
protected PonderButton goBack; protected BoxWidget goBack;
protected PonderButton serverLocked; protected BoxWidget serverLocked;
protected int listWidth; protected int listWidth;
protected String title; protected String title;
@ -117,60 +119,65 @@ public class SubMenuConfigScreen extends ConfigScreen {
int listL = this.width / 2 - listWidth / 2; int listL = this.width / 2 - listWidth / 2;
int listR = this.width / 2 + listWidth / 2; int listR = this.width / 2 + listWidth / 2;
resetAll = new PonderButton(listR + 10, yCenter - 25, (x, y) -> { resetAll = new BoxWidget(listR + 10, yCenter - 25, 20, 20)
new ConfirmationScreen() .withCallback((x, y) ->
.at(x, y) new ConfirmationScreen()
.withText(ITextProperties.plain("You are about to reset all settings for the " + type.toString() + " config. Are you sure?")) .at(x, y)
.withAction(success -> { .withText(ITextProperties.plain("You are about to reset all settings for the " + type.toString() + " config. Are you sure?"))
if (success) .withAction(success -> {
resetConfig(spec.getValues()); if (success)
}) resetConfig(spec.getValues());
.open(this); })
}) .open(this)
.showing(AllIcons.I_CONFIG_RESET.asStencil()); );
resetAll.fade(1);
resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll))
.at(2, 2));
resetAll.getToolTip().add(new StringTextComponent("Reset All")); 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)); 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) -> { saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20)
if (changes.isEmpty()) .withCallback((x, y) -> {
return; if (changes.isEmpty())
return;
new ConfirmationScreen() new ConfirmationScreen()
.at(x, y) .at(x, y)
.withText(ITextProperties.plain("You are about to change " + changes.size() + " values. Are you sure?")) .withText(ITextProperties.plain("You are about to change " + changes.size() + " values. Are you sure?"))
.withAction(success -> { .withAction(success -> {
if (success) if (success)
saveChanges(); saveChanges();
}) })
.open(this); .open(this);
}) });
.showing(AllIcons.I_CONFIG_SAVE.asStencil()); saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges))
saveChanges.fade(1); .at(2, 2));
saveChanges.getToolTip().add(new StringTextComponent("Save Changes")); saveChanges.getToolTip().add(new StringTextComponent("Save Changes"));
saveChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to save your current changes.", TextFormatting.GRAY, TextFormatting.GRAY)); 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) -> { discardChanges = new BoxWidget(listL - 30, yCenter + 5, 20, 20)
if (changes.isEmpty()) .withCallback((x, y) -> {
return; if (changes.isEmpty())
return;
new ConfirmationScreen() new ConfirmationScreen()
.at(x, y) .at(x, y)
.withText(ITextProperties.plain("You are about to discard " + changes.size() + " unsaved changes. Are you sure?")) .withText(ITextProperties.plain("You are about to discard " + changes.size() + " unsaved changes. Are you sure?"))
.withAction(success -> { .withAction(success -> {
if (success) if (success)
clearChanges(); clearChanges();
}) })
.open(this); .open(this);
}) });
.showing(AllIcons.I_CONFIG_DISCARD.asStencil()); discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges))
discardChanges.fade(1); .at(2, 2));
discardChanges.getToolTip().add(new StringTextComponent("Discard Changes")); 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)); 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) goBack = new BoxWidget(listL - 30, yCenter + 65, 20, 20)
.showing(AllIcons.I_CONFIG_BACK); .withCallback(this::attemptBackstep);
goBack.fade(1); goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(goBack))
.at(2, 2));
goBack.getToolTip().add(new StringTextComponent("Go Back")); goBack.getToolTip().add(new StringTextComponent("Go Back"));
widgets.add(resetAll); 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) if (type != ModConfig.Type.SERVER)
return; return;
list.isForServer = true; list.isForServer = true;
boolean canEdit = client != null && client.player != null && client.player.hasPermissionLevel(2); boolean canEdit = client != null && client.player != null && client.player.hasPermissionLevel(2);
int colRed1 = 0xff_f78888; Color colRed1 = Theme.c("button_fail_1");
int colRed2 = 0xff_cc2020; Color colRed2 = Theme.c("button_fail_2");
int colGreen1 = 0xff_88f788; Color colGreen1 = Theme.c("button_success_1");
int colGreen2 = 0xff_20cc20; Color colGreen2 = Theme.c("button_success_2");
DelegatedStencilElement stencil = new DelegatedStencilElement(); DelegatedStencilElement stencil = new DelegatedStencilElement();
serverLocked = new PonderButton(listR + 10, yCenter + 5, () -> {}) serverLocked = new BoxWidget(listR + 10, yCenter + 5, 20, 20)
.showing(stencil); .showingElement(stencil.at(2, 2));
serverLocked.fade(1);
if (!canEdit) { if (!canEdit) {
list.children().forEach(e -> e.setEditable(false)); list.children().forEach(e -> e.setEditable(false));
resetAll.active = false; resetAll.active = false;
stencil.withStencilRenderer((ms, w, h) -> AllIcons.I_CONFIG_LOCKED.draw(ms, 0, 0)); stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_LOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colRed1, colRed2)); stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colRed1.getRGB(), colRed2.getRGB()));
serverLocked.customColors(colRed1, colRed2); serverLocked.withBorderColors(colRed1, colRed2);
serverLocked.getToolTip().add(new StringTextComponent("Locked").formatted(TextFormatting.BOLD)); 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)); 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 { } else {
stencil.withStencilRenderer((ms, w, h) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0)); stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colGreen1, colGreen2)); stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, colGreen1.getRGB(), colGreen2.getRGB()));
serverLocked.customColors(colGreen1, colGreen2); serverLocked.withBorderColors(colGreen1, colGreen2);
serverLocked.getToolTip().add(new StringTextComponent("Unlocked").formatted(TextFormatting.BOLD)); 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)); 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); super.renderWindow(ms, mouseX, mouseY, partialTicks);
int x = width/2; 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); list.render(ms, mouseX, mouseY, partialTicks);
} }

View file

@ -3,7 +3,7 @@ package com.simibubi.create.foundation.config.ui.entries;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.TextStencilElement; import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper; 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.Minecraft;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
@ -12,22 +12,22 @@ public class BooleanEntry extends ValueEntry<Boolean> {
TextStencilElement enabled; TextStencilElement enabled;
TextStencilElement disabled; TextStencilElement disabled;
PonderButton button; BoxWidget button;
public BooleanEntry(String label, ForgeConfigSpec.ConfigValue<Boolean> value, ForgeConfigSpec.ValueSpec spec) { public BooleanEntry(String label, ForgeConfigSpec.ConfigValue<Boolean> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec); super(label, value, spec);
enabled = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Enabled") enabled = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Enabled")
.centered(true, true) .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") disabled = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Disabled")
.centered(true, true) .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())) button = new BoxWidget()
.showingUnscaled(enabled); .showingElement(enabled)
button.fade(1); .withCallback(() -> setValue(!getValue()));
listeners.add(button); listeners.add(button);
onReset(); onReset();
@ -42,6 +42,7 @@ public class BooleanEntry extends ValueEntry<Boolean> {
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
button.tick();
} }
@Override @Override
@ -58,7 +59,7 @@ public class BooleanEntry extends ValueEntry<Boolean> {
@Override @Override
public void onValueChange(Boolean newValue) { public void onValueChange(Boolean newValue) {
super.onValueChange(newValue); super.onValueChange(newValue);
button.showingUnscaled(newValue ? enabled : disabled); button.showingElement(newValue ? enabled : disabled);
bumpCog(newValue ? 15f : -16f); bumpCog(newValue ? 15f : -16f);
} }
} }

View file

@ -1,9 +1,10 @@
package com.simibubi.create.foundation.config.ui.entries; package com.simibubi.create.foundation.config.ui.entries;
import com.mojang.blaze3d.matrix.MatrixStack; 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.TextStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
@ -13,20 +14,22 @@ public class EnumEntry extends ValueEntry<Enum<?>> {
protected static final int cycleWidth = 34;//including 2px offset on either side protected static final int cycleWidth = 34;//including 2px offset on either side
protected TextStencilElement valueText; protected TextStencilElement valueText;
protected ConfigButton cycleLeft; protected BoxWidget cycleLeft;
protected ConfigButton cycleRight; protected BoxWidget cycleRight;
public EnumEntry(String label, ForgeConfigSpec.ConfigValue<Enum<?>> value, ForgeConfigSpec.ValueSpec spec) { public EnumEntry(String label, ForgeConfigSpec.ConfigValue<Enum<?>> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec); super(label, value, spec);
valueText = new TextStencilElement(Minecraft.getInstance().fontRenderer, "YEP").centered(true, true); 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); 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); 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(cycleLeft);
listeners.add(cycleRight); listeners.add(cycleRight);

View file

@ -6,9 +6,9 @@ import java.util.function.Function;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack; 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.config.ui.ConfigTextField;
import com.simibubi.create.foundation.gui.TextStencilElement; 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.UIRenderHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -54,13 +54,13 @@ public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
if (!min.equals(getTypeMin())) { if (!min.equals(getTypeMin())) {
StringTextComponent t = new StringTextComponent(formatBound(min) + " < "); StringTextComponent t = new StringTextComponent(formatBound(min) + " < ");
minText = new TextStencilElement(font, t).centered(true, false); 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); minOffset = font.getWidth(t);
} }
if (!max.equals(getTypeMax())) { if (!max.equals(getTypeMax())) {
StringTextComponent t = new StringTextComponent(" < " + formatBound(max)); StringTextComponent t = new StringTextComponent(" < " + formatBound(max));
maxText = new TextStencilElement(font, t).centered(true, false); 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); maxOffset = font.getWidth(t);
} }
} catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) { } catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) {

View file

@ -2,28 +2,27 @@ package com.simibubi.create.foundation.config.ui.entries;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.mojang.blaze3d.matrix.MatrixStack; 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.ConfigScreenList;
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen; import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.TextStencilElement; import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
public class SubMenuEntry extends ConfigScreenList.LabeledEntry { public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
protected PonderButton button; protected BoxWidget button;
public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) { public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) {
super(label); super(label);
TextStencilElement text = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Click to open").centered(true, true); 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))) button = new BoxWidget()
.showingUnscaled(text); .showingElement(text)
button.fade(1); .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config)));
text.withElementRenderer(BoxWidget.gradientFactory.apply(button));
listeners.add(button); listeners.add(button);
} }
@ -31,6 +30,7 @@ public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
button.tick();
} }
@Override @Override

View file

@ -11,13 +11,11 @@ import javax.annotation.Nonnull;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import com.mojang.blaze3d.matrix.MatrixStack; 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.ConfigScreen;
import com.simibubi.create.foundation.config.ui.ConfigScreenList; import com.simibubi.create.foundation.config.ui.ConfigScreenList;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
@ -29,11 +27,10 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
protected static final IFormattableTextComponent modComponent = new StringTextComponent("* ").formatted(TextFormatting.BOLD, TextFormatting.DARK_BLUE).append(StringTextComponent.EMPTY.copy().formatted(TextFormatting.RESET)); protected static final 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 protected static final int resetWidth = 28;//including 6px offset on either side
public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]"); public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]");
//public static DelegatedStencilElement.ElementRenderer idle = (ms, w, h) -> UIRenderHelper.angledGradient(ms, 0, 0, h / 2, h, w, ConfigButton.Palette.button_idle_1, ConfigButton.Palette.button_idle_2);
protected ForgeConfigSpec.ConfigValue<T> value; protected ForgeConfigSpec.ConfigValue<T> value;
protected ForgeConfigSpec.ValueSpec spec; protected ForgeConfigSpec.ValueSpec spec;
protected PonderButton resetButton; protected BoxWidget resetButton;
protected boolean editable = true; protected boolean editable = true;
protected String unit = null; protected String unit = null;
protected String path; protected String path;
@ -44,12 +41,13 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
this.spec = spec; this.spec = spec;
this.path = String.join(".", value.getPath()); this.path = String.join(".", value.getPath());
resetButton = new PonderButton(0, 0, (_$, _$$) -> { resetButton = new BoxWidget(0, 0, resetWidth - 12, 16)
setValue((T) spec.getDefault()); .showingElement(AllIcons.I_CONFIG_RESET.asStencil())
this.onReset(); .withCallback(() -> {
}, resetWidth - 12, 16) setValue((T) spec.getDefault());
.showing(AllIcons.I_CONFIG_RESET.asStencil()/*.withElementRenderer(idle)*/); this.onReset();
resetButton.fade(1); });
resetButton.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(resetButton)));
listeners.add(resetButton); listeners.add(resetButton);
@ -88,6 +86,13 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
protected void setEditable(boolean b) { protected void setEditable(boolean b) {
editable = b; editable = b;
resetButton.active = editable && !isCurrentValueDefault(); resetButton.active = editable && !isCurrentValueDefault();
resetButton.animateGradientFromState();
}
@Override
public void tick() {
super.tick();
resetButton.tick();
} }
@Override @Override
@ -146,6 +151,7 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
} }
public void onValueChange(T newValue) { public void onValueChange(T newValue) {
resetButton.active = editable && !isCurrentValueDefault(); resetButton.active = editable && !isCurrentValueDefault();
resetButton.animateGradientFromState();
} }
protected void bumpCog() {bumpCog(10f);} protected void bumpCog() {bumpCog(10f);}

View file

@ -68,8 +68,6 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
RenderSystem.disableLighting(); RenderSystem.disableLighting();
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks); renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(matrixStack, mouseX, mouseY);
} }
@Override @Override
@ -151,8 +149,12 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
if (!widget.isHovered()) if (!widget.isHovered())
continue; continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip().isEmpty()) { if (widget instanceof AbstractSimiWidget) {
renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
} else {
widget.renderToolTip(matrixStack, mouseX, mouseY);
} }
} }
} }

View file

@ -33,6 +33,13 @@ public abstract class AbstractSimiScreen extends Screen {
guiTop = (this.height - sHeight) / 2; guiTop = (this.height - sHeight) / 2;
} }
@Override
public void tick() {
super.tick();
widgets.stream().filter(w -> w instanceof AbstractSimiWidget).forEach(w -> ((AbstractSimiWidget) w).tick());
}
@Override @Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
partialTicks = partialTicks == 10 ? 0 partialTicks = partialTicks == 10 ? 0
@ -46,8 +53,6 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets) for (Widget widget : widgets)
widget.render(ms, mouseX, mouseY, partialTicks); widget.render(ms, mouseX, mouseY, partialTicks);
renderWindowForeground(ms, mouseX, mouseY, partialTicks); renderWindowForeground(ms, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(ms, mouseX, mouseY);
ms.pop(); ms.pop();
} }
@ -131,8 +136,12 @@ public abstract class AbstractSimiScreen extends Screen {
if (!widget.isHovered()) if (!widget.isHovered())
continue; continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip().isEmpty()) { if (widget instanceof AbstractSimiWidget) {
renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
} else {
widget.renderToolTip(ms, mouseX, mouseY);
} }
} }
} }

View file

@ -5,6 +5,7 @@ import com.mojang.blaze3d.matrix.MatrixStack.Entry;
import com.mojang.blaze3d.vertex.IVertexBuilder; import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.gui.AbstractGui;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -188,7 +189,7 @@ public class AllIcons implements IScreenRenderable {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public DelegatedStencilElement asStencil() { 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) @OnlyIn(Dist.CLIENT)

View file

@ -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 extends BoxElement> T withBackground(Color color) {
this.background = color;
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T withBackground(int color) {
return withBackground(new Color(color, true));
}
public <T extends BoxElement> T flatBorder(Color color) {
this.borderTop = color;
this.borderBot = color;
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T flatBorder(int color) {
return flatBorder(new Color(color, true));
}
public <T extends BoxElement> T gradientBorder(Color top, Color bot) {
this.borderTop = top;
this.borderBot = bot;
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T gradientBorder(int top, int bot) {
return gradientBorder(new Color(top, true), new Color(bot, true));
}
public <T extends BoxElement> 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);
}
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.gui; package com.simibubi.create.foundation.gui;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
public class CombinedStencilElement extends StencilElement { public class CombinedStencilElement extends StencilElement {
@ -45,21 +46,23 @@ public class CombinedStencilElement extends StencilElement {
protected void renderStencil(MatrixStack ms) { protected void renderStencil(MatrixStack ms) {
ms.push(); ms.push();
element1.transform(ms); element1.transform(ms);
element1.withBounds(width, height).renderStencil(ms); element1.withBounds(width, height);
element1.renderStencil(ms);
ms.pop(); ms.pop();
ms.push(); ms.push();
element2.transform(ms); element2.transform(ms);
element2.withBounds(width, height).renderStencil(ms); element2.withBounds(width, height);
element2.renderStencil(ms);
ms.pop(); ms.pop();
} }
@Override @Override
protected void renderElement(MatrixStack ms) { protected void renderElement(MatrixStack ms) {
if (mode.rendersFirst()) if (mode.rendersFirst())
element1.withBounds(width, height).renderElement(ms); element1.<StencilElement>withBounds(width, height).renderElement(ms);
if (mode.rendersSecond()) if (mode.rendersSecond())
element2.withBounds(width, height).renderElement(ms); element2.<StencilElement>withBounds(width, height).renderElement(ms);
} }
public enum ElementMode { public enum ElementMode {

View file

@ -10,8 +10,7 @@ import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
@ -29,8 +28,9 @@ public class ConfirmationScreen extends AbstractSimiScreen {
private int textWidth; private int textWidth;
private int textHeight; private int textHeight;
private PonderButton confirm; private BoxWidget confirm;
private PonderButton cancel; private BoxWidget cancel;
private BoxElement textBackground;
/* /*
* Removes text lines from the back of the list * Removes text lines from the back of the list
@ -81,6 +81,13 @@ public class ConfirmationScreen extends AbstractSimiScreen {
this.client.currentScreen = this; this.client.currentScreen = this;
} }
@Override
public void tick() {
super.tick();
confirm.tick();
cancel.tick();
}
@Override @Override
protected void init() { protected void init() {
widgets.clear(); widgets.clear();
@ -106,18 +113,23 @@ public class ConfirmationScreen extends AbstractSimiScreen {
} }
TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true); TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true);
confirm = new PonderButton(x + 4, y + textHeight + 2, (_$, _$$) -> accept(true), textWidth/2 - 10, 20) confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20)
.showingUnscaled(confirmText); .withCallback(() -> accept(true));
confirm.fade(1); confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm)));
TextStencilElement cancelText = new TextStencilElement(client.fontRenderer, "Cancel").centered(true, true); 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) cancel = new BoxWidget(x + textWidth/2 + 6, y + textHeight + 2, textWidth/2 - 10, 20)
.showingUnscaled(cancelText); .withCallback(() -> accept(false));
cancel.fade(1); cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel)));
widgets.add(confirm); widgets.add(confirm);
widgets.add(cancel); 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 @Override
@ -133,7 +145,7 @@ public class ConfirmationScreen extends AbstractSimiScreen {
@Override @Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { 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 offset = client.fontRenderer.FONT_HEIGHT + 1;
int lineY = y - offset; int lineY = y - offset;
@ -157,11 +169,12 @@ public class ConfirmationScreen extends AbstractSimiScreen {
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
UIRenderHelper.prepFramebufferSize(); //UIRenderHelper.prepFramebufferSize();
ms.push(); ms.push();
//ms.translate(0, 0, -50); //ms.translate(0, 0, -50);
//ms.scale(1, 1, 0.01f); //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); UIRenderHelper.framebuffer.bindFramebuffer(true);
source.render(ms, mouseX, mouseY, partialTicks); source.render(ms, mouseX, mouseY, partialTicks);
UIRenderHelper.framebuffer.unbindFramebuffer(); UIRenderHelper.framebuffer.unbindFramebuffer();

View file

@ -1,11 +1,12 @@
package com.simibubi.create.foundation.gui; package com.simibubi.create.foundation.gui;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.utility.ColorHelper;
public class DelegatedStencilElement extends StencilElement { public class DelegatedStencilElement extends StencilElement {
protected static final ElementRenderer EMPTY_RENDERER = (ms, width, height) -> {}; protected static final ElementRenderer EMPTY_RENDERER = (ms, width, height, alpha) -> {};
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 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 stencil;
protected ElementRenderer element; protected ElementRenderer element;
@ -34,17 +35,17 @@ public class DelegatedStencilElement extends StencilElement {
@Override @Override
protected void renderStencil(MatrixStack ms) { protected void renderStencil(MatrixStack ms) {
stencil.render(ms, width, height); stencil.render(ms, width, height, 1);
} }
@Override @Override
protected void renderElement(MatrixStack ms) { protected void renderElement(MatrixStack ms) {
element.render(ms, width, height); element.render(ms, width, height, alpha);
} }
@FunctionalInterface @FunctionalInterface
public interface ElementRenderer { public interface ElementRenderer {
void render(MatrixStack ms, int width, int height); void render(MatrixStack ms, int width, int height, float alpha);
} }
} }

View file

@ -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 extends RenderElement> T at(float x, float y) {
this.x = x;
this.y = y;
//noinspection unchecked
return (T) this;
}
public <T extends RenderElement> T at(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
//noinspection unchecked
return (T) this;
}
public <T extends RenderElement> T withBounds(int width, int height) {
this.width = width;
this.height = height;
//noinspection unchecked
return (T) this;
}
public <T extends RenderElement> 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);
}
}

View file

@ -1,43 +1,15 @@
package com.simibubi.create.foundation.gui; package com.simibubi.create.foundation.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.AbstractGui;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
public abstract class StencilElement implements IScreenRenderable { import net.minecraft.client.Minecraft;
protected int width = 0; public abstract class StencilElement extends RenderElement {
protected int height = 0;
float x, y , z;
public <T extends StencilElement> T at(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
//noinspection unchecked
return (T) this;
}
public <T extends StencilElement> T withBounds(int width, int height) {
this.width = width;
this.height = height;
//noinspection unchecked
return (T) this;
}
@Override @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) { public void render(MatrixStack ms) {
ms.push(); ms.push();
transform(ms); transform(ms);
@ -49,22 +21,6 @@ public abstract class StencilElement implements IScreenRenderable {
ms.pop(); 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 renderStencil(MatrixStack ms);
protected abstract void renderElement(MatrixStack ms); protected abstract void renderElement(MatrixStack ms);

View file

@ -1,11 +1,11 @@
package com.simibubi.create.foundation.gui; package com.simibubi.create.foundation.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import com.mojang.blaze3d.matrix.MatrixStack;
public class TextStencilElement extends DelegatedStencilElement { public class TextStencilElement extends DelegatedStencilElement {
protected FontRenderer font; protected FontRenderer font;
@ -70,7 +70,7 @@ public class TextStencilElement extends DelegatedStencilElement {
ms.push(); ms.push();
ms.translate(x, y, 0); 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(); ms.pop();
} }

View file

@ -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<String, Color> 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;
}
}
}

View file

@ -1,12 +1,12 @@
package com.simibubi.create.foundation.gui; package com.simibubi.create.foundation.gui;
import com.mojang.blaze3d.matrix.MatrixStack; import javax.annotation.Nonnull;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3f;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.KHRDebug; import org.lwjgl.opengl.KHRDebug;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper; 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.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.shader.Framebuffer; 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 net.minecraftforge.fml.client.gui.GuiUtils;
import javax.annotation.Nonnull;
public class UIRenderHelper { public class UIRenderHelper {
public static void enableStencil() { 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(); MainWindow window = Minecraft.getInstance().getWindow();
if (framebuffer.framebufferWidth != window.getFramebufferWidth() || framebuffer.framebufferHeight != window.getFramebufferHeight()) { if (framebuffer.framebufferWidth != window.getFramebufferWidth() || framebuffer.framebufferHeight != window.getFramebufferHeight()) {
framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC); framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC);
} }
} }*/
public static void drawFramebuffer(float alpha) { public static void drawFramebuffer(float alpha) {
MainWindow window = Minecraft.getInstance() MainWindow window = Minecraft.getInstance()

View file

@ -4,30 +4,30 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import javax.annotation.Nonnull;
public abstract class AbstractSimiWidget extends Widget { public abstract class AbstractSimiWidget extends Widget {
protected List<ITextComponent> toolTip; protected boolean wasHovered = false;
protected List<ITextComponent> toolTip = new LinkedList<>();
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {}; protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) { protected AbstractSimiWidget() {
super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY); this(0, 0);
toolTip = new LinkedList<>();
} }
public List<ITextComponent> getToolTip() { protected AbstractSimiWidget(int x, int y) {
return toolTip; this(x, y, 16, 16);
} }
@Override protected AbstractSimiWidget(int x, int y, int width, int height) {
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { super(x, y, width, height, StringTextComponent.EMPTY);
} }
public <T extends AbstractSimiWidget> T withCallback(BiConsumer<Integer, Integer> cb) { public <T extends AbstractSimiWidget> T withCallback(BiConsumer<Integer, Integer> cb) {
@ -40,6 +40,39 @@ public abstract class AbstractSimiWidget extends Widget {
return withCallback((_$, _$$) -> cb.run()); return withCallback((_$, _$$) -> cb.run());
} }
public List<ITextComponent> 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) { public void runCallback(double mouseX, double mouseY) {
onClick.accept((int) mouseX, (int) mouseY); onClick.accept((int) mouseX, (int) mouseY);
} }

View file

@ -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<BoxWidget, DelegatedStencilElement.ElementRenderer> 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);
}
}

View file

@ -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 extends ElementWidget> T showingElement(RenderElement element) {
this.element = element;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T modifyElement(Consumer<RenderElement> consumer) {
if (element != null)
consumer.accept(element);
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T mapElement(UnaryOperator<RenderElement> function) {
if (element != null)
element = function.apply(element);
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> 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 extends ElementWidget> T disableFade() {
this.fade.startWithValue(1);
this.usesFade = false;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T rescaleElement(float rescaleSizeX, float rescaleSizeY) {
this.rescaleElement = true;
this.rescaleSizeX = rescaleSizeX;
this.rescaleSizeY = rescaleSizeY;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> 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;
}
}

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui.widgets; package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
@ -22,7 +24,7 @@ public class Indicator extends AbstractSimiWidget {
} }
@Override @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; AllGuiTextures toDraw;
switch(state) { switch(state) {
case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break; case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break;

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui.widgets; package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@ -69,7 +71,7 @@ public class Label extends AbstractSimiWidget {
} }
@Override @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) if (!visible)
return; return;
if (text == null || text.getString().isEmpty()) if (text == null || text.getString().isEmpty())

View file

@ -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 extends StencilWidget> T modifyElement(Consumer<StencilElement> consumer) {
if (stencilElement != null)
consumer.accept(stencilElement);
//noinspection unchecked
return (T) this;
}
public <T extends StencilWidget> T mapElement(UnaryOperator<StencilElement> function) {
if (stencilElement != null)
stencilElement = function.apply(stencilElement);
//noinspection unchecked
return (T) this;
}
public StencilElement getStencilElement() {
return stencilElement;
}
}

View file

@ -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);
}
}

View file

@ -1,5 +1,13 @@
package com.simibubi.create.foundation.ponder; 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.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.AbstractSimiScreen; 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.ponder.ui.PonderButton;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.MainWindow; import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper; 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 { public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
@ -122,7 +124,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
if (lastScreen != null && lastScreen != this && !transition.settled()) { if (lastScreen != null && lastScreen != this && !transition.settled()) {
ms.push();// 1 ms.push();// 1
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
UIRenderHelper.prepFramebufferSize(); //UIRenderHelper.prepFramebufferSize();
ms.push();// 2 ms.push();// 2
ms.translate(0, 0, -1000); ms.translate(0, 0, -1000);
UIRenderHelper.framebuffer.bindFramebuffer(true); UIRenderHelper.framebuffer.bindFramebuffer(true);

View file

@ -1,7 +1,10 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import java.awt.Color;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -52,6 +55,18 @@ public class ColorHelper {
return color; 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) { public static int mixAlphaColors(int color1, int color2, float w) {
int a1 = (color1 >> 24); int a1 = (color1 >> 24);
int r1 = (color1 >> 16) & 0xFF; int r1 = (color1 >> 16) & 0xFF;

View file

@ -1,22 +1,23 @@
{ {
"required": true, "required": true,
"priority": 1100, "priority": 1100,
"package": "com.simibubi.create.foundation.mixin", "package": "com.simibubi.create.foundation.mixin",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_8",
"refmap": "create.refmap.json", "refmap": "create.refmap.json",
"client": [ "client": [
"TileWorldHookMixin", "CancelTileEntityRenderMixin",
"CancelTileEntityRenderMixin", "EntityContraptionInteractionMixin",
"FogColorTrackerMixin", "FogColorTrackerMixin",
"LightUpdateMixin", "LightUpdateMixin",
"NetworkLightUpdateMixin", "NetworkLightUpdateMixin",
"RenderHooksMixin", "RenderHooksMixin",
"ShaderCloseMixin", "ShaderCloseMixin",
"TileRemoveMixin", "TileRemoveMixin",
"EntityContraptionInteractionMixin" "TileWorldHookMixin",
], "WindowResizeMixin"
"injectors": { ],
"defaultRequire": 1 "injectors": {
}, "defaultRequire": 1
"minVersion": "0.8" },
"minVersion": "0.8"
} }