Merge branch 'mc1.16/config-ui' into mc1.16/dev

# Conflicts:
#	src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java
#	src/main/java/com/simibubi/create/foundation/command/AllCommands.java
#	src/main/java/com/simibubi/create/foundation/command/FabulousWarningCommand.java
#	src/main/java/com/simibubi/create/foundation/command/OverlayConfigCommand.java
#	src/main/java/com/simibubi/create/foundation/command/PonderCommand.java
#	src/main/java/com/simibubi/create/foundation/command/ToggleDebugCommand.java
#	src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java
#	src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java
#	src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java
#	src/main/java/com/simibubi/create/foundation/gui/AllIcons.java
#	src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java
#	src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java
#	src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java
#	src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java
#	src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java
#	src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java
#	src/main/java/com/simibubi/create/foundation/ponder/ui/ChapterLabel.java
#	src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java
#	src/main/resources/create.mixins.json
This commit is contained in:
zelophed 2021-05-03 16:54:32 +02:00
commit c36346b97d
72 changed files with 3560 additions and 578 deletions

View file

@ -13,6 +13,7 @@ import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivit
import com.simibubi.create.content.schematics.ClientSchematicLoader;
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
import com.simibubi.create.content.schematics.client.SchematicHandler;
import com.simibubi.create.events.ClientEvents;
import com.simibubi.create.foundation.ResourceReloadHandler;
import com.simibubi.create.foundation.block.render.CustomBlockModels;
import com.simibubi.create.foundation.block.render.SpriteShifter;
@ -80,6 +81,7 @@ public class CreateClient {
modEventBus.addListener(CreateClient::onModelRegistry);
modEventBus.addListener(CreateClient::onTextureStitch);
modEventBus.addListener(AllParticleTypes::registerFactories);
modEventBus.addListener(ClientEvents::loadCompleted);
Backend.init();
OptifineHandler.init();
@ -110,11 +112,14 @@ public class CreateClient {
PonderIndex.registerTags();
UIRenderHelper.init();
UIRenderHelper.enableStencil();
IResourceManager resourceManager = Minecraft.getInstance()
.getResourceManager();
if (resourceManager instanceof IReloadableResourceManager)
((IReloadableResourceManager) resourceManager).addReloadListener(new ResourceReloadHandler());
}
public static void onTextureStitch(TextureStitchEvent.Pre event) {

View file

@ -88,7 +88,7 @@ public class BlockzapperUpgradeCategory extends CreateRecipeCategory<Blockzapper
font.drawWithShadow(matrixStack, textComponent, (BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(textComponent.getString())) / 2f, 57, 0x8B8B8B);
GuiGameElement.of(recipe.getRecipeOutput())
.at(90, 0)
.<GuiGameElement.GuiRenderBuilder>at(90, 0)
.scale(3.5)
.render(matrixStack);
}

View file

@ -73,7 +73,7 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
tag.put("Polishing", matchingStacks[0].serializeNBT());
tag.putBoolean("JEI", true);
GuiGameElement.of(renderedSandpaper)
.at(getBackground().getWidth() / 2 - 16, 0, 0)
.<GuiGameElement.GuiRenderBuilder>at(getBackground().getWidth() / 2 - 16, 0, 0)
.scale(2)
.render(matrixStack);
}

View file

@ -153,7 +153,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
0xffffff);
GuiGameElement.of(renderedItem)
.at(guiLeft + background.width + 10, guiTop + 100, -150)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + background.width + 10, guiTop + 100, -150)
.scale(5)
.render(matrixStack);
}

View file

@ -123,7 +123,7 @@ public class SymmetryWandScreen extends AbstractSimiScreen {
renderBlock(matrixStack);
GuiGameElement.of(wand)
.at(guiLeft + 190, guiTop + 420, -150)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 190, guiTop + 420, -150)
.scale(4)
.rotate(-70, 20, 20)
.render(matrixStack);

View file

@ -133,7 +133,7 @@ public class ZapperScreen extends AbstractSimiScreen {
protected void renderZapper(MatrixStack matrixStack) {
GuiGameElement.of(zapper)
.at((this.width - this.sWidth) / 2 + 200, this.height / 2 - this.sHeight / 4 + 25, -150)
.<GuiGameElement.GuiRenderBuilder>at((this.width - this.sWidth) / 2 + 200, this.height / 2 - this.sHeight / 4 + 25, -150)
.scale(4)
.render(matrixStack);
}

View file

@ -97,7 +97,7 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreen<Adjustabl
}
GuiGameElement.of(renderedItem)
.at(guiLeft + ADJUSTABLE_CRATE.width + 110, guiTop + 70, -150)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + ADJUSTABLE_CRATE.width + 110, guiTop + 70, -150)
.scale(5)
.render(matrixStack);
}

View file

@ -126,7 +126,7 @@ public class StockpileSwitchScreen extends AbstractSimiScreen {
matrixStack.push();
GuiGameElement.of(renderedItem)
.at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250)
.scale(5)
.render(matrixStack);
matrixStack.pop();

View file

@ -69,7 +69,7 @@ public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> ex
textRenderer.draw(ms, I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 3, 0xdedede);
GuiGameElement.of(container.filterItem)
.at(x + background.width, guiTop + background.height - 60)
.<GuiGameElement.GuiRenderBuilder>at(x + background.width, guiTop + background.height - 60)
.scale(5)
.render(ms);

View file

@ -122,7 +122,7 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen<SchematicT
textRenderer.drawWithShadow(matrixStack, noSchematics, mainLeft + 54, mainTop + 26, 0xd3d3d3);
GuiGameElement.of(renderedItem)
.at(mainLeft + 217, mainTop + 50, -150)
.<GuiGameElement.GuiRenderBuilder>at(mainLeft + 217, mainTop + 50, -150)
.scale(3)
.render(matrixStack);

View file

@ -262,7 +262,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
renderBlueprintHighlight(matrixStack);
GuiGameElement.of(renderedItem)
.at(guiLeft + 230, guiTop + 110, -200)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 230, guiTop + 110, -200)
.scale(5)
.render(matrixStack);
@ -274,7 +274,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
if (te.missingItem != null) {
stringWidth += 15;
GuiGameElement.of(te.missingItem)
.at(guiLeft + 150, guiTop + 46, 100)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 150, guiTop + 46, 100)
.scale(1)
.render(matrixStack);
}

View file

@ -152,7 +152,7 @@ public class SchematicEditScreen extends AbstractSimiScreen {
x + 93 - textRenderer.getStringWidth(handler.getCurrentSchematicName()) / 2, y + 3, 0xffffff);
GuiGameElement.of(AllItems.SCHEMATIC.asStack())
.at(guiLeft + 200, guiTop + 82, 0)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 200, guiTop + 82, 0)
.scale(3)
.render(matrixStack);
}

View file

@ -30,6 +30,7 @@ import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperR
import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler;
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.networking.AllPackets;
@ -78,7 +79,11 @@ import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
@EventBusSubscriber(value = Dist.CLIENT)
public class ClientEvents {
@ -310,4 +315,9 @@ public class ClientEvents {
}
}
public static void loadCompleted(FMLLoadCompleteEvent event) {
ModContainer createContainer = ModList.get().getModContainerById("create").orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted"));
createContainer.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, previousScreen) -> new BaseConfigScreen(previousScreen));
}
}

View file

@ -21,20 +21,22 @@ public class AllCommands {
LiteralCommandNode<CommandSource> util = buildUtilityCommands();
LiteralCommandNode<CommandSource> createRoot = dispatcher.register(Commands.literal("create")
.requires(cs -> cs.hasPermissionLevel(0))
// general purpose
.then(new ToggleExperimentalRenderingCommand().register())
.then(new ToggleDebugCommand().register())
.then(FabulousWarningCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(HighlightCommand.register())
.then(CouplingCommand.register())
.then(CloneCommand.register())
.then(PonderCommand.register())
.requires(cs -> cs.hasPermissionLevel(0))
// general purpose
.then(new ToggleExperimentalRenderingCommand().register())
.then(new ToggleDebugCommand().register())
.then(FabulousWarningCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(HighlightCommand.register())
.then(CouplingCommand.register())
.then(ConfigCommand.register())
.then(PonderCommand.register())
.then(CloneCommand.register())
// utility
.then(util));
// utility
.then(util)
);
createRoot.addChild(buildRedirect("u", util));
@ -50,12 +52,12 @@ public class AllCommands {
private static LiteralCommandNode<CommandSource> buildUtilityCommands() {
return Commands.literal("util")
.then(ReplaceInCommandBlocksCommand.register())
.then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register())
.then(FlySpeedCommand.register())
// .then(KillTPSCommand.register())
.build();
.then(ReplaceInCommandBlocksCommand.register())
.then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register())
.then(FlySpeedCommand.register())
//.then(KillTPSCommand.register())
.build();
}
@ -72,15 +74,15 @@ public class AllCommands {
*
* @return the built node
*/
public static LiteralCommandNode<CommandSource> buildRedirect(final String alias,
final LiteralCommandNode<CommandSource> destination) {
public static LiteralCommandNode<CommandSource> buildRedirect(final String alias, final LiteralCommandNode<CommandSource> destination) {
// Redirects only work for nodes with children, but break the top argument-less command.
// Manually adding the root command after setting the redirect doesn't fix it.
// See https://github.com/Mojang/brigadier/issues/46). Manually clone the node instead.
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder.<CommandSource>literal(alias)
.requires(destination.getRequirement())
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
.executes(destination.getCommand());
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder
.<CommandSource>literal(alias)
.requires(destination.getRequirement())
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
.executes(destination.getCommand());
for (CommandNode<CommandSource> child : destination.getChildren()) {
builder.then(child);
}

View file

@ -0,0 +1,27 @@
package com.simibubi.create.foundation.command;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraftforge.fml.network.PacketDistributor;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.simibubi.create.foundation.networking.AllPackets;
public class ConfigCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("config")
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource().asPlayer();
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.configScreen.name(), "")
);
return Command.SINGLE_SUCCESS;
});
}
}

View file

@ -13,16 +13,18 @@ public class FabulousWarningCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("dismissFabulousWarning")
.requires(AllCommands.sourceIsPlayer)
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource()
.asPlayer();
.requires(AllCommands.sourceIsPlayer)
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource()
.asPlayer();
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fabulousWarning.name(), ""));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fabulousWarning.name(), "")
);
return Command.SINGLE_SUCCESS;
});
return Command.SINGLE_SUCCESS;
});
}
}

View file

@ -17,7 +17,7 @@ public class FixLightingCommand {
.executes(ctx -> {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
ctx.getSource()
.sendFeedback(

View file

@ -15,35 +15,32 @@ public class OverlayConfigCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("overlay")
.requires(cs -> cs.hasPermissionLevel(0))
.then(Commands.literal("reset")
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> ConfigureConfigPacket.Actions.overlayReset.performAction(""));
.requires(cs -> cs.hasPermissionLevel(0))
.then(Commands.literal("reset")
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SConfigureConfigPacket.Actions.overlayReset.performAction(""));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER,
() -> () -> AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.overlayReset.name(), "")));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () ->
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.overlayReset.name(), "")));
ctx.getSource()
.sendFeedback(new StringTextComponent("reset overlay offset"), true);
return 1;
}))
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> ConfigureConfigPacket.Actions.overlayScreen.performAction(""));
return 1;
})
)
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SConfigureConfigPacket.Actions.overlayScreen.performAction(""));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER,
() -> () -> AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.overlayScreen.name(), "")));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () ->
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.overlayScreen.name(), "")));
ctx.getSource()
.sendFeedback(new StringTextComponent("window opened"), true);
ctx.getSource()
.sendFeedback(new StringTextComponent("window opened"), true);
return 1;
});

View file

@ -21,26 +21,20 @@ import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.network.PacketDistributor;
public class PonderCommand {
public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register(
new ResourceLocation("all_ponders"),
(iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet()
.stream(), builder));
public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register(new ResourceLocation("all_ponders"), (iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet().stream(), builder));
static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("ponder")
.requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> openScene("index", ctx.getSource()
.asPlayer()))
.then(Commands.argument("scene", ResourceLocationArgument.resourceLocation())
.suggests(ITEM_PONDERS)
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene")
.toString(),
ctx.getSource()
.asPlayer()))
.then(Commands.argument("targets", EntityArgument.players())
.requires(cs -> cs.hasPermissionLevel(2))
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene")
.toString(), EntityArgument.getPlayers(ctx, "targets")))));
.requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> openScene("index", ctx.getSource().asPlayer()))
.then(Commands.argument("scene", ResourceLocationArgument.resourceLocation())
.suggests(ITEM_PONDERS)
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), ctx.getSource().asPlayer()))
.then(Commands.argument("targets", EntityArgument.players())
.requires(cs -> cs.hasPermissionLevel(2))
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), EntityArgument.getPlayers(ctx, "targets")))
)
);
}
@ -53,8 +47,9 @@ public class PonderCommand {
if (player instanceof FakePlayer)
continue;
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.openPonder.name(), sceneId));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.openPonder.name(), sceneId));
}
return Command.SINGLE_SUCCESS;
}

View file

@ -8,6 +8,7 @@ import org.apache.logging.log4j.LogManager;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.ponder.PonderRegistry;
@ -31,17 +32,17 @@ import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent;
public class ConfigureConfigPacket extends SimplePacketBase {
public class SConfigureConfigPacket extends SimplePacketBase {
private final String option;
private final String value;
public ConfigureConfigPacket(String option, String value) {
public SConfigureConfigPacket(String option, String value) {
this.option = option;
this.value = value;
}
public ConfigureConfigPacket(PacketBuffer buffer) {
public SConfigureConfigPacket(PacketBuffer buffer) {
this.option = buffer.readString(32767);
this.value = buffer.readString(32767);
}
@ -69,7 +70,8 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.setPacketHandled(true);
}
enum Actions {
public enum Actions {
configScreen(() -> Actions::configScreen),
rainbowDebug(() -> Actions::rainbowDebug),
overlayScreen(() -> Actions::overlayScreen),
fixLighting(() -> Actions::experimentalLighting),
@ -91,6 +93,11 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.accept(value);
}
@OnlyIn(Dist.CLIENT)
private static void configScreen(String value) {
ScreenOpener.open(new BaseConfigScreen(null));
}
@OnlyIn(Dist.CLIENT)
private static void rainbowDebug(String value) {
ClientPlayerEntity player = Minecraft.getInstance().player;

View file

@ -13,7 +13,9 @@ public class ToggleDebugCommand extends ConfigureConfigCommand {
@Override
protected void sendPacket(ServerPlayerEntity player, String option) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.rainbowDebug.name(), option));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.rainbowDebug.name(), option)
);
}
}

View file

@ -13,7 +13,9 @@ public class ToggleExperimentalRenderingCommand extends ConfigureConfigCommand {
@Override
protected void sendPacket(ServerPlayerEntity player, String option) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.experimentalRendering.name(), option));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.experimentalRendering.name(), option)
);
}
}

View file

@ -107,8 +107,7 @@ public abstract class ConfigBase {
if (comment.length > 0) {
String[] comments = new String[comment.length + 1];
comments[0] = "";
for (int i = 0; i < comment.length; i++)
comments[i + 1] = comment[i];
System.arraycopy(comment, 0, comments, 1, comment.length);
builder.comment(comments);
} else
builder.comment("");

View file

@ -0,0 +1,59 @@
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.gui.widgets.BoxWidget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.config.ModConfig;
public class BaseConfigScreen extends ConfigScreen {
BoxWidget clientConfigWidget;
BoxWidget commonConfigWidget;
BoxWidget serverConfigWidget;
public BaseConfigScreen(Screen parent) {
super(parent);
}
@Override
protected void init() {
widgets.clear();
super.init();
TextStencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("Client Settings").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16)
.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("World Generation Settings").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16)
.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("Gameplay Settings").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16)
.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;
serverConfigWidget.updateColorsFromState();
text3.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE, true), Theme.i(Theme.Key.BUTTON_DISABLE, false) | 0x40_000000));
}
}
}

View file

@ -0,0 +1,83 @@
package com.simibubi.create.foundation.config.ui;
import java.util.function.Supplier;
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.PacketDistributor;
public class CConfigureConfigPacket<T> extends SimplePacketBase {
private String path;
private String value;
public CConfigureConfigPacket(String path, T value) {
this.path = path;
this.value = serialize(value);
}
public CConfigureConfigPacket(PacketBuffer buffer) {
this.path = buffer.readString(32767);
this.value = buffer.readString(32767);
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeString(path);
buffer.writeString(value);
}
@Override
public void handle(Supplier<NetworkEvent.Context> context) {
ServerPlayerEntity sender = context.get().getSender();
if (sender == null || !sender.hasPermissionLevel(2))
return;
ForgeConfigSpec.ValueSpec valueSpec = AllConfigs.SERVER.specification.getRaw(path);
ForgeConfigSpec.ConfigValue<T> configValue = AllConfigs.SERVER.specification.getValues().get(path);
T v = (T) deserialize(configValue.get(), value);
if (!valueSpec.test(v))
return;
configValue.set(v);
}
public String serialize(T value) {
if (value instanceof Boolean)
return Boolean.toString((Boolean) value);
if (value instanceof Enum<?>)
return ((Enum<?>) value).name();
if (value instanceof Integer)
return Integer.toString((Integer) value);
if (value instanceof Float)
return Float.toString((Float) value);
if (value instanceof Double)
return Double.toString((Double) value);
throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName());
}
public Object deserialize(Object type, String sValue) {
if (type instanceof Boolean)
return Boolean.parseBoolean(sValue);
if (type instanceof Enum<?>)
return Enum.valueOf(((Enum<?>) type).getClass(), sValue);
if (type instanceof Integer)
return Integer.parseInt(sValue);
if (type instanceof Float)
return Float.parseFloat(sValue);
if (type instanceof Double)
return Double.parseDouble(sValue);
throw new IllegalArgumentException("unknown type " + type + ": " + type.getClass().getSimpleName());
}
}

View file

@ -0,0 +1,123 @@
package com.simibubi.create.foundation.config.ui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.StencilElement;
import com.simibubi.create.foundation.utility.animation.Force;
import com.simibubi.create.foundation.utility.animation.PhysicalFloat;
import net.minecraft.block.BlockState;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Direction;
public abstract class ConfigScreen extends AbstractSimiScreen {
/*
*
* zelo's list for configUI
* TODO
*
* replace java's awt color with something mutable
*
* FIXME
*
* tooltips are hidden underneath the scrollbar, if the bar is near the middle
* framebuffer blending is incorrect -> wait for jozu's changes to merge
*
* */
public static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f));
public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y);
public static final Map<String, Object> changes = new HashMap<>();
protected final Screen parent;
public ConfigScreen(Screen parent) {
this.parent = parent;
}
@Override
public void tick() {
super.tick();
cogSpin.tick();
}
@Override
public void renderBackground(@Nonnull MatrixStack ms) {
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.GuiScreenEvent.BackgroundDrawnEvent(this, ms));
}
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
//RenderSystem.disableDepthTest();
if (this.client != null && this.client.world != null) {
fill(ms, 0, 0, this.width, this.height, 0xb0_282c34);
} else {
fill(ms, 0, 0, this.width, this.height, 0xff_282c34);
}
new StencilElement() {
@Override
protected void renderStencil(MatrixStack ms) {
renderCog(ms, partialTicks);
}
@Override
protected void renderElement(MatrixStack ms) {
fill(ms, -200, -200, 200, 200, 0x60_000000);
}
}.at(width * 0.5f, height * 0.5f, 0).render(ms);
super.renderWindowBackground(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
int x = (int) (width * 0.5f);
int y = (int) (height * 0.5f);
//this.drawHorizontalLine(ms, x-25, x+25, y, 0xff_807060);
//this.drawVerticalLine(ms, x, y-25, y+25, 0xff_90a0b0);
//this.testStencil.render(ms);
//UIRenderHelper.streak(ms, 0, mouseX, mouseY, 16, 50, 0xaa_1e1e1e);
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
cogSpin.bump(3, -delta * 5);
return super.mouseScrolled(mouseX, mouseY, delta);
}
public static String toHumanReadable(String key) {
String s = key.replaceAll("_", " ");
s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(s)).map(StringUtils::capitalize).collect(Collectors.joining(" "));
s = s.replaceAll("\\s\\s+", " ");
return s;
}
protected void renderCog(MatrixStack ms, float partialTicks) {
ms.push();
ms.translate(-100, 100, -100);
ms.scale(200, 200, .1f);
GuiGameElement.of(cogwheelState)
.rotateBlock(22.5, cogSpin.getValue(partialTicks), 22.5)
.render(ms);
ms.pop();
}
}

View file

@ -0,0 +1,180 @@
package com.simibubi.create.foundation.config.ui;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.list.ExtendedList;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fml.client.gui.GuiUtils;
public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
public static TextFieldWidget currentText;
public boolean isForServer = false;
public ConfigScreenList(Minecraft client, int width, int height, int top, int bottom, int elementHeight) {
super(client, width, height, top, bottom, elementHeight);
func_244605_b(false);
func_244606_c(false);
setRenderSelection(false);
currentText = null;
headerHeight = 3;
}
@Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
//render tmp background
//fill(ms, left, top, left + width, top + height, 0x10_000000);
UIRenderHelper.angledGradient(ms, 90, left + width / 2, top, width, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, -90, left + width / 2, bottom, width, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, 0, left, top + height / 2, height, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, 180, right, top + height / 2, height, 5, 0x60_000000, 0x0);
super.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderList(MatrixStack p_238478_1_, int p_238478_2_, int p_238478_3_, int p_238478_4_, int p_238478_5_, float p_238478_6_) {
MainWindow window = Minecraft.getInstance().getWindow();
double d0 = window.getGuiScaleFactor();
RenderSystem.enableScissor((int) (this.left * d0), (int) (window.getFramebufferHeight() - (this.bottom * d0)), (int) (this.width * d0), (int) (this.height * d0));
super.renderList(p_238478_1_, p_238478_2_, p_238478_3_, p_238478_4_, p_238478_5_, p_238478_6_);
RenderSystem.disableScissor();
}
@Override
public boolean mouseClicked(double x, double y, int button) {
children().stream().filter(e -> e instanceof NumberEntry<?>).forEach(e -> e.mouseClicked(x, y, button));
return super.mouseClicked(x, y, button);
}
@Override
public int getRowWidth() {
return width - 16;
}
@Override
protected int getScrollbarPositionX() {
return left + this.width - 6;
}
public void 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) {
ConfigScreen.cogSpin.bump(3, force);
}
public static abstract class Entry extends ExtendedList.AbstractListEntry<Entry> {
protected List<IGuiEventListener> listeners;
protected Entry() {
listeners = new ArrayList<>();
}
@Override
public boolean mouseClicked(double x, double y, int button) {
return getGuiListeners().stream().anyMatch(l -> l.mouseClicked(x, y, button));
}
@Override
public boolean keyPressed(int code, int keyPressed_2_, int keyPressed_3_) {
return getGuiListeners().stream().anyMatch(l -> l.keyPressed(code, keyPressed_2_, keyPressed_3_));
}
@Override
public boolean charTyped(char ch, int code) {
return getGuiListeners().stream().anyMatch(l -> l.charTyped(ch, code));
}
public void tick() {}
public List<IGuiEventListener> getGuiListeners() {
return listeners;
}
protected void setEditable(boolean b) {}
}
public static class LabeledEntry extends Entry {
protected static final float labelWidthMult = 0.4f;
protected TextStencilElement label;
protected List<ITextComponent> labelTooltip;
protected String unit = null;
public LabeledEntry(String label) {
this.label = new TextStencilElement(Minecraft.getInstance().fontRenderer, label);
this.label.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.TEXT_ACCENT_STRONG)));
labelTooltip = new ArrayList<>();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 6, width, 0xdd_000000);
IFormattableTextComponent component = label.getComponent();
FontRenderer font = Minecraft.getInstance().fontRenderer;
if (font.getWidth(component) > getLabelWidth(width) - 10) {
label.withText(font.trimToWidth(component, getLabelWidth(width) - 15).getString() + "...");
}
if (unit != null) {
int unitWidth = font.getStringWidth(unit);
font.draw(ms, unit, x + getLabelWidth(width) - unitWidth - 5, y + height / 2 + 2, Theme.i(Theme.Key.TEXT_DARKER));
label.at(x + 10, y + height / 2 - 10, 0).render(ms);
} else {
label.at(x + 10, y + height / 2 - 4, 0).render(ms);
}
if (mouseX > x && mouseX < x + getLabelWidth(width) && mouseY > y + 5 && mouseY < y + height - 5) {
List<ITextComponent> tooltip = getLabelTooltip();
if (tooltip.isEmpty())
return;
GL11.glDisable(GL11.GL_SCISSOR_TEST);
Screen screen = Minecraft.getInstance().currentScreen;
ms.push();
ms.translate(0, 0, 400);
GuiUtils.drawHoveringText(ms, tooltip, mouseX, mouseY, screen.width, screen.height, 300, font);
ms.pop();
GL11.glEnable(GL11.GL_SCISSOR_TEST);
}
}
public List<ITextComponent> getLabelTooltip() {
return labelTooltip;
}
protected int getLabelWidth(int totalWidth) {
return totalWidth;
}
}
}

View file

@ -0,0 +1,34 @@
package com.simibubi.create.foundation.config.ui;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.text.StringTextComponent;
public class ConfigTextField extends TextFieldWidget {
protected FontRenderer font;
protected String unit;
public ConfigTextField(FontRenderer font, int x, int y, int width, int height, String unit) {
super(font, x, y, width, height, StringTextComponent.EMPTY);
this.font = font;
this.unit = unit;
}
@Override
public void setFocused2(boolean focus) {
super.setFocused2(focus);
if (!focus) {
if (ConfigScreenList.currentText == this)
ConfigScreenList.currentText = null;
return;
}
if (ConfigScreenList.currentText != null && ConfigScreenList.currentText != this)
ConfigScreenList.currentText.setFocused2(false);
ConfigScreenList.currentText = this;
}
}

View file

@ -0,0 +1,345 @@
package com.simibubi.create.foundation.config.ui;
import java.awt.Color;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.lwjgl.glfw.GLFW;
import com.electronwill.nightconfig.core.AbstractConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.entries.BooleanEntry;
import com.simibubi.create.foundation.config.ui.entries.EnumEntry;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry;
import com.simibubi.create.foundation.config.ui.entries.ValueEntry;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.ConfirmationScreen;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.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.networking.AllPackets;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
public class SubMenuConfigScreen extends ConfigScreen {
public final ModConfig.Type type;
protected ForgeConfigSpec spec;
protected UnmodifiableConfig configGroup;
protected ConfigScreenList list;
protected BoxWidget resetAll;
protected BoxWidget saveChanges;
protected BoxWidget discardChanges;
protected BoxWidget goBack;
protected BoxWidget serverLocked;
protected int listWidth;
protected String title;
public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
super(parent);
this.type = type;
this.spec = configSpec;
this.title = title;
this.configGroup = configGroup;
}
public SubMenuConfigScreen(Screen parent, ModConfig.Type type, ForgeConfigSpec configSpec) {
super(parent);
this.type = type;
this.spec = configSpec;
this.title = "root";
this.configGroup = configSpec.getValues();
}
protected void clearChanges() {
changes.clear();
list.children()
.stream()
.filter(e -> e instanceof ValueEntry)
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
}
protected void saveChanges() {
UnmodifiableConfig values = spec.getValues();
changes.forEach((path, value) -> {
ForgeConfigSpec.ConfigValue configValue = values.get(path);
configValue.set(value);
if (type == ModConfig.Type.SERVER) {
AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(path, value));
}
});
clearChanges();
}
protected void resetConfig(UnmodifiableConfig values) {
values.valueMap().forEach((key, obj) -> {
if (obj instanceof AbstractConfig) {
resetConfig((UnmodifiableConfig) obj);
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
if (!configValue.get().equals(valueSpec.getDefault()))
changes.put(String.join(".", configValue.getPath()), valueSpec.getDefault());
}
});
list.children()
.stream()
.filter(e -> e instanceof ValueEntry)
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
}
@Override
public void tick() {
super.tick();
list.tick();
}
@Override
protected void init() {
widgets.clear();
super.init();
listWidth = Math.min(width - 80, 300);
int yCenter = height / 2;
int listL = this.width / 2 - listWidth / 2;
int listR = this.width / 2 + listWidth / 2;
resetAll = new BoxWidget(listR + 10, yCenter - 25, 20, 20)
.withPadding(2, 2)
.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)));
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 BoxWidget(listL - 30, yCenter - 25, 20, 20)
.withPadding(2, 2)
.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);
});
saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges)));
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 BoxWidget(listL - 30, yCenter + 5, 20, 20)
.withPadding(2, 2)
.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);
});
discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges)));
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 BoxWidget(listL - 30, yCenter + 65, 20, 20)
.withPadding(2, 2)
.withCallback(this::attemptBackstep);
goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(goBack)));
goBack.getToolTip().add(new StringTextComponent("Go Back"));
widgets.add(resetAll);
widgets.add(saveChanges);
widgets.add(discardChanges);
widgets.add(goBack);
list = new ConfigScreenList(client, listWidth, height - 60, 45, height - 15, 40);
list.setLeftPos(this.width / 2 - list.getWidth() / 2);
children.add(list);
configGroup.valueMap().forEach((key, obj) -> {
String humanKey = toHumanReadable(key);
if (obj instanceof AbstractConfig) {
SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) obj);
list.children().add(entry);
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
Object value = configValue.get();
if (value instanceof Boolean) {
BooleanEntry entry = new BooleanEntry(humanKey, (ForgeConfigSpec.ConfigValue<Boolean>) configValue, valueSpec);
list.children().add(entry);
} else if (value instanceof Enum) {
EnumEntry entry = new EnumEntry(humanKey, (ForgeConfigSpec.ConfigValue<Enum<?>>) configValue, valueSpec);
list.children().add(entry);
} else if (value instanceof Number) {
NumberEntry<? extends Number> entry = NumberEntry.create(value, humanKey, configValue, valueSpec);
if (entry != null) {
list.children().add(entry);
} else {
list.children().add(new ConfigScreenList.LabeledEntry("n-" + obj.getClass().getSimpleName() + " " + humanKey + " : " + value));
}
} else {
list.children().add(new ConfigScreenList.LabeledEntry(humanKey + " : " + value));
}
}
});
//extras for server configs
if (type != ModConfig.Type.SERVER)
return;
list.isForServer = true;
boolean canEdit = client != null && client.player != null && client.player.hasPermissionLevel(2);
Couple<Color> red = Theme.p(Theme.Key.BUTTON_FAIL);
Couple<Color> green = Theme.p(Theme.Key.BUTTON_SUCCESS);
DelegatedStencilElement stencil = new DelegatedStencilElement();
serverLocked = new BoxWidget(listR + 10, yCenter + 5, 20, 20)
.withPadding(2, 2)
.showingElement(stencil);
if (!canEdit) {
list.children().forEach(e -> e.setEditable(false));
resetAll.active = false;
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, red));
serverLocked.withBorderColors(red);
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, alpha) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green));
serverLocked.withBorderColors(green);
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 when you save them.", TextFormatting.GRAY, TextFormatting.GRAY));
}
widgets.add(serverLocked);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderWindow(ms, mouseX, mouseY, partialTicks);
int x = width/2;
drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, Theme.i(Theme.Key.TEXT));
list.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderWindowForeground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderWindowForeground(ms, mouseX, mouseY, partialTicks);
}
@Override
public void resize(@Nonnull Minecraft client, int width, int height) {
double scroll = list.getScrollAmount();
init(client, width, height);
list.setScrollAmount(scroll);
}
@Nullable
@Override
public IGuiEventListener getFocused() {
if (ConfigScreenList.currentText != null)
return ConfigScreenList.currentText;
return super.getFocused();
}
@Override
public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) {
if (super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_))
return true;
if (code == GLFW.GLFW_KEY_BACKSPACE) {
attemptBackstep();
}
return false;
}
private void attemptBackstep() {
if (!changes.isEmpty() && parent instanceof BaseConfigScreen) {
new ConfirmationScreen()
.centered()
.addText(ITextProperties.plain("You still have " + changes.size() + " unsaved changes for this config."))
.addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?"))
.withAction(success -> {
if (!success)
return;
changes.clear();
ScreenOpener.open(parent);
})
.open(this);
} else {
ScreenOpener.open(parent);
}
}
@Override
public void onClose() {
if (changes.isEmpty()) {
super.onClose();
return;
}
new ConfirmationScreen()
.centered()
.addText(ITextProperties.plain("You still have " + changes.size() + " unsaved changes for this config."))
.addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?"))
.withAction(success -> {
if (!success)
return;
changes.clear();
super.onClose();
})
.open(this);
}
}

View file

@ -0,0 +1,74 @@
package com.simibubi.create.foundation.config.ui.entries;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraftforge.common.ForgeConfigSpec;
public class BooleanEntry extends ValueEntry<Boolean> {
RenderElement enabled;
RenderElement disabled;
BoxWidget button;
public BooleanEntry(String label, ForgeConfigSpec.ConfigValue<Boolean> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
// enabled = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Enabled")
// .centered(true, true)
// .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, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height/2, height, width, 0xff_f78888, 0xff_cc2020));
enabled = AllIcons.I_CONFIRM.asStencil()
.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_SUCCESS)))
.at(10, 0);
disabled = AllIcons.I_DISABLE.asStencil()
.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_FAIL)))
.at(10, 0);
button = new BoxWidget().showingElement(enabled)
.withCallback(() -> setValue(!getValue()));
listeners.add(button);
onReset();
}
@Override
protected void setEditable(boolean b) {
super.setEditable(b);
button.active = b;
}
@Override
public void tick() {
super.tick();
button.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY,
boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
button.x = x + width - 80 - resetWidth;
button.y = y + 10;
button.setWidth(35);
button.setHeight(height - 20);
button.render(ms, mouseX, mouseY, partialTicks);
}
@Override
public void onValueChange(Boolean newValue) {
super.onValueChange(newValue);
button.showingElement(newValue ? enabled : disabled);
bumpCog(newValue ? 15f : -16f);
}
}

View file

@ -0,0 +1,102 @@
package com.simibubi.create.foundation.config.ui.entries;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
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;
public class EnumEntry extends ValueEntry<Enum<?>> {
protected static final int cycleWidth = 34;
protected TextStencilElement valueText;
protected BoxWidget cycleLeft;
protected BoxWidget cycleRight;
public EnumEntry(String label, ForgeConfigSpec.ConfigValue<Enum<?>> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
valueText = new TextStencilElement(Minecraft.getInstance().fontRenderer, "YEP").centered(true, true);
valueText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2,
height, width, Theme.p(Theme.Key.TEXT)));
DelegatedStencilElement l = AllIcons.I_CONFIG_PREV.asStencil();
cycleLeft = new BoxWidget(0, 0, cycleWidth + 8, 16).showingElement(l)
.withCallback(() -> cycleValue(-1));
l.withElementRenderer(BoxWidget.gradientFactory.apply(cycleLeft));
DelegatedStencilElement r = AllIcons.I_CONFIG_NEXT.asStencil();
cycleRight = new BoxWidget(0, 0, cycleWidth + 8, 16).showingElement(r)
.withCallback(() -> cycleValue(1));
r.at(cycleWidth - 8, 0);
r.withElementRenderer(BoxWidget.gradientFactory.apply(cycleRight));
listeners.add(cycleLeft);
listeners.add(cycleRight);
onReset();
}
protected void cycleValue(int direction) {
Enum<?> e = getValue();
Enum<?>[] options = e.getDeclaringClass()
.getEnumConstants();
e = options[Math.floorMod(e.ordinal() + direction, options.length)];
setValue(e);
bumpCog(direction * 15f);
}
@Override
protected void setEditable(boolean b) {
super.setEditable(b);
cycleLeft.active = b;
cycleLeft.animateGradientFromState();
cycleRight.active = b;
cycleRight.animateGradientFromState();
}
@Override
public void tick() {
super.tick();
cycleLeft.tick();
cycleRight.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY,
boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
cycleLeft.x = x + getLabelWidth(width) + 4;
cycleLeft.y = y + 10;
cycleLeft.render(ms, mouseX, mouseY, partialTicks);
valueText.at(cycleLeft.x + cycleWidth - 8, y + 10, 200)
.withBounds(width - getLabelWidth(width) - 2 * cycleWidth - resetWidth - 4, 16)
.render(ms);
cycleRight.x = x + width - cycleWidth * 2 - resetWidth + 10;
cycleRight.y = y + 10;
cycleRight.render(ms, mouseX, mouseY, partialTicks);
new BoxElement()
.withBackground(0)
.flatBorder(0)
.withBounds(10, 10)
.at(cycleLeft.x + cycleWidth + 4, cycleLeft.y + 3)
.render(ms);
}
@Override
public void onValueChange(Enum<?> newValue) {
super.onValueChange(newValue);
valueText.withText(newValue.name());
}
}

View file

@ -0,0 +1,211 @@
package com.simibubi.create.foundation.config.ui.entries;
import java.lang.reflect.Field;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
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;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.common.ForgeConfigSpec;
public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
protected int minOffset = 0, maxOffset = 0;
protected TextStencilElement minText = null, maxText = null;
protected TextFieldWidget textField;
@Nullable
public static NumberEntry<? extends Number> create(Object type, String label, ForgeConfigSpec.ConfigValue<?> value, ForgeConfigSpec.ValueSpec spec) {
if (type instanceof Integer) {
return new IntegerEntry(label, (ForgeConfigSpec.ConfigValue<Integer>) value, spec);
} else if (type instanceof Float) {
return new FloatEntry(label, (ForgeConfigSpec.ConfigValue<Float>) value, spec);
} else if (type instanceof Double) {
return new DoubleEntry(label, (ForgeConfigSpec.ConfigValue<Double>) value, spec);
}
return null;
}
public NumberEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
textField = new ConfigTextField(Minecraft.getInstance().fontRenderer, 0, 0, 200, 20, unit);
textField.setText(String.valueOf(getValue()));
textField.setTextColor(Theme.i(Theme.Key.TEXT));
Object range = spec.getRange();
try {
Field minField = range.getClass().getDeclaredField("min");
Field maxField = range.getClass().getDeclaredField("max");
minField.setAccessible(true);
maxField.setAccessible(true);
T min = (T) minField.get(range);
T max = (T) maxField.get(range);
FontRenderer font = Minecraft.getInstance().fontRenderer;
if (min.doubleValue() > getTypeMin().doubleValue()) {
StringTextComponent t = new StringTextComponent(formatBound(min) + " < ");
minText = new TextStencilElement(font, t).centered(true, false);
minText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.p(Theme.Key.TEXT_DARKER)));
minOffset = font.getWidth(t);
}
if (max.doubleValue() < getTypeMax().doubleValue()) {
StringTextComponent t = new StringTextComponent(" < " + formatBound(max));
maxText = new TextStencilElement(font, t).centered(true, false);
maxText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.p(Theme.Key.TEXT_DARKER)));
maxOffset = font.getWidth(t);
}
} catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) {
}
textField.setResponder(s -> {
try {
T number = getParser().apply(s);
if (!spec.test(number))
throw new IllegalArgumentException();
textField.setTextColor(Theme.i(Theme.Key.TEXT));
setValue(number);
} catch (IllegalArgumentException ignored) {
textField.setTextColor(Theme.i(Theme.Key.BUTTON_FAIL));
}
});
listeners.add(textField);
onReset();
}
protected String formatBound(T bound) {
String sci = String.format("%.2E", bound.doubleValue());
String str = String.valueOf(bound);
return sci.length() < str.length() ? sci : str;
}
protected abstract T getTypeMin();
protected abstract T getTypeMax();
protected abstract Function<String, T> getParser();
@Override
protected void setEditable(boolean b) {
super.setEditable(b);
textField.setEnabled(b);
}
@Override
public void onValueChange(T newValue) {
super.onValueChange(newValue);
String newText = String.valueOf(newValue);
if (textField.getText().equals(newText))
return;
textField.setText(newText);
}
@Override
public void tick() {
super.tick();
textField.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
textField.x = x + width - 82 - resetWidth;
textField.y = y + 8;
textField.setWidth(Math.min(width - getLabelWidth(width) - resetWidth - minOffset - maxOffset, 40));
textField.setHeight(20);
textField.render(ms, mouseX, mouseY, partialTicks);
if (minText != null)
minText
.at(textField.x - minOffset, textField.y, 0)
.withBounds(minOffset, textField.unusedGetHeight())
.render(ms);
if (maxText != null)
maxText
.at(textField.x + textField.getWidth(), textField.y, 0)
.withBounds(maxOffset, textField.unusedGetHeight())
.render(ms);
}
public static class IntegerEntry extends NumberEntry<Integer> {
public IntegerEntry(String label, ForgeConfigSpec.ConfigValue<Integer> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Integer getTypeMin() {
return Integer.MIN_VALUE;
}
@Override
protected Integer getTypeMax() {
return Integer.MAX_VALUE;
}
@Override
protected Function<String, Integer> getParser() {
return Integer::parseInt;
}
}
public static class FloatEntry extends NumberEntry<Float> {
public FloatEntry(String label, ForgeConfigSpec.ConfigValue<Float> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Float getTypeMin() {
return -Float.MAX_VALUE;
}
@Override
protected Float getTypeMax() {
return Float.MAX_VALUE;
}
@Override
protected Function<String, Float> getParser() {
return Float::parseFloat;
}
}
public static class DoubleEntry extends NumberEntry<Double> {
public DoubleEntry(String label, ForgeConfigSpec.ConfigValue<Double> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Double getTypeMin() {
return (double) -Float.MAX_VALUE;
}
@Override
protected Double getTypeMax() {
return (double) Float.MAX_VALUE;
}
@Override
protected Function<String, Double> getParser() {
return Double::parseDouble;
}
}
}

View file

@ -0,0 +1,49 @@
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.ConfigScreenList;
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraftforge.common.ForgeConfigSpec;
public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
protected BoxWidget button;
public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) {
super(label);
button = new BoxWidget(0, 0, 35, 16)
.showingElement(AllIcons.I_CONFIG_OPEN.asStencil().at(10, 0))
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config)));
button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(button)));
listeners.add(button);
}
@Override
public void tick() {
super.tick();
button.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
button.x = x + width - 108;
button.y = y + 10;
button.setHeight(height - 20);
button.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected int getLabelWidth(int totalWidth) {
return (int) (totalWidth * labelWidthMult) + 30;
}
}

View file

@ -0,0 +1,159 @@
package com.simibubi.create.foundation.config.ui.entries;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.ArrayUtils;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.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.widgets.BoxWidget;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
protected static final IFormattableTextComponent modComponent = new StringTextComponent("* ").formatted(TextFormatting.BOLD, TextFormatting.DARK_BLUE).append(StringTextComponent.EMPTY.copy().formatted(TextFormatting.RESET));
protected static final int resetWidth = 28;//including 6px offset on either side
public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]");
protected ForgeConfigSpec.ConfigValue<T> value;
protected ForgeConfigSpec.ValueSpec spec;
protected BoxWidget resetButton;
protected boolean editable = true;
protected String path;
public ValueEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label);
this.value = value;
this.spec = spec;
this.path = String.join(".", value.getPath());
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);
List<String> path = value.getPath();
labelTooltip.add(new StringTextComponent(path.get(path.size()-1)).formatted(TextFormatting.GRAY));
String comment = spec.getComment();
if (comment == null || comment.isEmpty())
return;
String[] commentLines = comment.split("\n");
//find unit in the comment
for (int i = 0; i < commentLines.length; i++) {
if (commentLines[i].isEmpty()) {
commentLines = ArrayUtils.remove(commentLines, i);
i--;
continue;
}
Matcher matcher = unitPattern.matcher(commentLines[i]);
if (!matcher.matches())
continue;
String u = matcher.group(1);
if (u.equals("in Revolutions per Minute"))
u = "in RPM";
if (u.equals("in Stress Units"))
u = "in SU";
unit = u;
}
//add comment to tooltip
labelTooltip.addAll(Arrays.stream(commentLines).map(StringTextComponent::new).collect(Collectors.toList()));
}
@Override
protected void setEditable(boolean b) {
editable = b;
resetButton.active = editable && !isCurrentValueDefault();
resetButton.animateGradientFromState();
}
@Override
public void tick() {
super.tick();
resetButton.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
if (isCurrentValueChanged()) {
IFormattableTextComponent original = label.getComponent();
IFormattableTextComponent changed = modComponent.copy().append(original);
label.withText(changed);
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
label.withText(original);
} else {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
}
resetButton.x = x + width - resetWidth + 6;
resetButton.y = y + 10;
resetButton.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected int getLabelWidth(int totalWidth) {
return (int) (totalWidth * labelWidthMult) + 30;
}
public void setValue(@Nonnull T value) {
if (value.equals(this.value.get())) {
ConfigScreen.changes.remove(path);
onValueChange(value);
return;
}
ConfigScreen.changes.put(path, value);
onValueChange(value);
}
@Nonnull
public T getValue() {
//noinspection unchecked
return (T) ConfigScreen.changes.getOrDefault(path, this.value.get());
}
protected boolean isCurrentValueChanged() {
return ConfigScreen.changes.containsKey(path);
}
protected boolean isCurrentValueDefault() {
return spec.getDefault().equals(getValue());
}
public void onReset() {
onValueChange(getValue());
}
public void onValueChange() {
onValueChange(getValue());
}
public void onValueChange(T newValue) {
resetButton.active = editable && !isCurrentValueDefault();
resetButton.animateGradientFromState();
}
protected void bumpCog() {bumpCog(10f);}
protected void bumpCog(float force) {
if (list != null && list instanceof ConfigScreenList)
((ConfigScreenList) list).bumpCog(force);
}
}

View file

@ -69,8 +69,6 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
RenderSystem.disableLighting();
RenderSystem.disableDepthTest();
renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(matrixStack, mouseX, mouseY);
}
@Override
@ -152,9 +150,12 @@ public abstract class AbstractSimiContainerScreen<T extends Container> 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);
}
}
}

View file

@ -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();
}
@ -62,6 +67,10 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets)
if (widget.mouseClicked(x, y, button))
result = true;
if (!result) {
result = super.mouseClicked(x, y, button);
}
return result;
}
@ -127,9 +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);
}
}
}

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui;
import java.awt.Color;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create;
@ -80,8 +82,8 @@ public enum AllGuiTextures implements IScreenRenderable {
INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6),
INDICATOR_RED("widgets.png", 72, 18, 18, 6),
SPEECH_TOOLTIP("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_HIGHLIGHT("widgets.png", 8, 24, 8, 8),
SPEECH_TOOLTIP_BACKGROUND("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_COLOR("widgets.png", 8, 24, 8, 8),
// PlacementIndicator
PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256);
@ -123,4 +125,9 @@ public enum AllGuiTextures implements IScreenRenderable {
bind();
screen.drawTexture(ms, x, y, startX, startY, width, height);
}
public void draw(MatrixStack ms, int x, int y, Color c) {
bind();
UIRenderHelper.drawColoredTexture(ms, c, x, y, startX, startY, width, height);
}
}

View file

@ -22,45 +22,121 @@ public class AllIcons implements IScreenRenderable {
private int iconX;
private int iconY;
public static final AllIcons I_ADD = newRow(), I_TRASH = next(), I_3x3 = next(), I_TARGET = next(),
I_PRIORITY_VERY_LOW = next(), I_PRIORITY_LOW = next(), I_PRIORITY_HIGH = next(), I_PRIORITY_VERY_HIGH = next(),
I_BLACKLIST = next(), I_WHITELIST = next(), I_WHITELIST_OR = next(), I_WHITELIST_AND = next(),
I_WHITELIST_NOT = next(), I_RESPECT_NBT = next(), I_IGNORE_NBT = next();
public static final AllIcons
I_ADD = newRow(),
I_TRASH = next(),
I_3x3 = next(),
I_TARGET = next(),
I_PRIORITY_VERY_LOW = next(),
I_PRIORITY_LOW = next(),
I_PRIORITY_HIGH = next(),
I_PRIORITY_VERY_HIGH = next(),
I_BLACKLIST = next(),
I_WHITELIST = next(),
I_WHITELIST_OR = next(),
I_WHITELIST_AND = next(),
I_WHITELIST_NOT = next(),
I_RESPECT_NBT = next(),
I_IGNORE_NBT = next();
public static final AllIcons I_CONFIRM = newRow(), I_NONE = next(), I_OPEN_FOLDER = next(), I_REFRESH = next(),
I_ACTIVE = next(), I_PASSIVE = next(), I_ROTATE_PLACE = next(), I_ROTATE_PLACE_RETURNED = next(),
I_ROTATE_NEVER_PLACE = next(), I_MOVE_PLACE = next(), I_MOVE_PLACE_RETURNED = next(),
I_MOVE_NEVER_PLACE = next(), I_CART_ROTATE = next(), I_CART_ROTATE_PAUSED = next(),
public static final AllIcons
I_CONFIRM = newRow(),
I_NONE = next(),
I_OPEN_FOLDER = next(),
I_REFRESH = next(),
I_ACTIVE = next(),
I_PASSIVE = next(),
I_ROTATE_PLACE = next(),
I_ROTATE_PLACE_RETURNED = next(),
I_ROTATE_NEVER_PLACE = next(),
I_MOVE_PLACE = next(),
I_MOVE_PLACE_RETURNED = next(),
I_MOVE_NEVER_PLACE = next(),
I_CART_ROTATE = next(),
I_CART_ROTATE_PAUSED = next(),
I_CART_ROTATE_LOCKED = next();
public static final AllIcons I_DONT_REPLACE = newRow(), I_REPLACE_SOLID = next(), I_REPLACE_ANY = next(),
I_REPLACE_EMPTY = next(), I_CENTERED = next(), I_ATTACHED = next(), I_INSERTED = next(), I_FILL = next(),
I_PLACE = next(), I_REPLACE = next(), I_CLEAR = next(), I_OVERLAY = next(), I_FLATTEN = next(), I_LMB = next(),
I_SCROLL = next(), I_RMB = next();
public static final AllIcons I_TOOL_DEPLOY = newRow(), I_SKIP_MISSING = next(), I_SKIP_TILES = next(),
I_DICE = next(), I_TUNNEL_SPLIT = next(), I_TUNNEL_FORCED_SPLIT = next(), I_TUNNEL_ROUND_ROBIN = next(),
I_TUNNEL_FORCED_ROUND_ROBIN = next(), I_TUNNEL_PREFER_NEAREST = next(), I_TUNNEL_RANDOMIZE = next(),
public static final AllIcons
I_DONT_REPLACE = newRow(),
I_REPLACE_SOLID = next(),
I_REPLACE_ANY = next(),
I_REPLACE_EMPTY = next(),
I_CENTERED = next(),
I_ATTACHED = next(),
I_INSERTED = next(),
I_FILL = next(),
I_PLACE = next(),
I_REPLACE = next(),
I_CLEAR = next(),
I_OVERLAY = next(),
I_FLATTEN = next(),
I_LMB = next(),
I_SCROLL = next(),
I_RMB = next();
public static final AllIcons
I_TOOL_DEPLOY = newRow(),
I_SKIP_MISSING = next(),
I_SKIP_TILES = next(),
I_DICE = next(),
I_TUNNEL_SPLIT = next(),
I_TUNNEL_FORCED_SPLIT = next(),
I_TUNNEL_ROUND_ROBIN = next(),
I_TUNNEL_FORCED_ROUND_ROBIN = next(),
I_TUNNEL_PREFER_NEAREST = next(),
I_TUNNEL_RANDOMIZE = next(),
I_TUNNEL_SYNCHRONIZE = next(),
I_TOOL_MOVE_XZ = newRow(), I_TOOL_MOVE_Y = next(), I_TOOL_ROTATE = next(), I_TOOL_MIRROR = next(),
I_ARM_ROUND_ROBIN = next(), I_ARM_FORCED_ROUND_ROBIN = next(), I_ARM_PREFER_FIRST = next(),
I_ADD_INVERTED_ATTRIBUTE = next(), I_FLIP = next(),
I_PLAY = newRow(), I_PAUSE = next(), I_STOP = next(), I_PLACEMENT_SETTINGS = next(), I_ROTATE_CCW = next(),
I_HOUR_HAND_FIRST = next(), I_MINUTE_HAND_FIRST = next(), I_HOUR_HAND_FIRST_24 = next(),
I_PATTERN_SOLID = newRow(), I_PATTERN_CHECKERED = next(), I_PATTERN_CHECKERED_INVERSED = next(),
I_TOOL_MOVE_XZ = newRow(),
I_TOOL_MOVE_Y = next(),
I_TOOL_ROTATE = next(),
I_TOOL_MIRROR = next(),
I_ARM_ROUND_ROBIN = next(),
I_ARM_FORCED_ROUND_ROBIN = next(),
I_ARM_PREFER_FIRST = next(),
I_ADD_INVERTED_ATTRIBUTE = next(),
I_FLIP = next(),
I_PLAY = newRow(),
I_PAUSE = next(),
I_STOP = next(),
I_PLACEMENT_SETTINGS = next(),
I_ROTATE_CCW = next(),
I_HOUR_HAND_FIRST = next(),
I_MINUTE_HAND_FIRST = next(),
I_HOUR_HAND_FIRST_24 = next(),
I_PATTERN_SOLID = newRow(),
I_PATTERN_CHECKERED = next(),
I_PATTERN_CHECKERED_INVERSED = next(),
I_PATTERN_CHANCE_25 = next(),
I_PATTERN_CHANCE_50 = newRow(), I_PATTERN_CHANCE_75 = next(), I_FOLLOW_DIAGONAL = next(),
I_PATTERN_CHANCE_50 = newRow(),
I_PATTERN_CHANCE_75 = next(),
I_FOLLOW_DIAGONAL = next(),
I_FOLLOW_MATERIAL = next(),
I_SCHEMATIC = newRow(),
I_MTD_LEFT = newRow(), I_MTD_CLOSE = next(), I_MTD_RIGHT = next(), I_MTD_SCAN = next(), I_MTD_REPLAY = next(),
I_MTD_USER_MODE = next(), I_MTD_SLOW_MODE = next();
I_MTD_LEFT = newRow(),
I_MTD_CLOSE = next(),
I_MTD_RIGHT = next(),
I_MTD_SCAN = next(),
I_MTD_REPLAY = next(),
I_MTD_USER_MODE = next(),
I_MTD_SLOW_MODE = next(),
I_CONFIG_UNLOCKED = newRow(),
I_CONFIG_LOCKED = next(),
I_CONFIG_DISCARD = next(),
I_CONFIG_SAVE = next(),
I_CONFIG_RESET = next(),
I_CONFIG_BACK = next(),
I_CONFIG_PREV = next(),
I_CONFIG_NEXT = next(),
I_DISABLE = next(),
I_CONFIG_OPEN = next();
public AllIcons(int x, int y) {
iconX = x * 16;
@ -116,8 +192,12 @@ public class AllIcons implements IScreenRenderable {
}
@OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u,
float v) {
public DelegatedStencilElement asStencil() {
return new DelegatedStencilElement().withStencilRenderer((ms, w, h, alpha) -> this.draw(ms, 0, 0)).withBounds(16, 16);
}
@OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u, float v) {
builder.vertex(peek.getModel(), (float) vec.x, (float) vec.y, (float) vec.z)
.color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1)
.texture(u, v)

View file

@ -0,0 +1,160 @@
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 com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
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(Couple<Color> colors) {
this.borderTop = colors.getFirst();
this.borderBot = colors.getSecond();
//noinspection unchecked
return (T) this;
}
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);
int f = borderOffset;
Color c1 = ColorHelper.applyAlpha(background, alpha);
Color c2 = ColorHelper.applyAlpha(borderTop, alpha);
Color c3 = ColorHelper.applyAlpha(borderBot, alpha);
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();
}
}

View file

@ -0,0 +1,79 @@
package com.simibubi.create.foundation.gui;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
public class CombinedStencilElement extends StencilElement {
private StencilElement element1;
private StencilElement element2;
private ElementMode mode;
private CombinedStencilElement() {}
public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2) {
return of(element1, element2, ElementMode.FIRST);
}
public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2, ElementMode mode) {
CombinedStencilElement e = new CombinedStencilElement();
e.element1 = element1;
e.element2 = element2;
e.mode = mode;
return e;
}
public <T extends CombinedStencilElement> T withFirst(StencilElement element) {
this.element1 = element;
//noinspection unchecked
return (T) this;
}
public <T extends CombinedStencilElement> T withSecond(StencilElement element) {
this.element2 = element;
//noinspection unchecked
return (T) this;
}
public <T extends CombinedStencilElement> T withMode(ElementMode mode) {
this.mode = mode;
//noinspection unchecked
return (T) this;
}
@Override
protected void renderStencil(MatrixStack ms) {
ms.push();
element1.transform(ms);
element1.withBounds(width, height);
element1.renderStencil(ms);
ms.pop();
ms.push();
element2.transform(ms);
element2.withBounds(width, height);
element2.renderStencil(ms);
ms.pop();
}
@Override
protected void renderElement(MatrixStack ms) {
if (mode.rendersFirst())
element1.<StencilElement>withBounds(width, height).renderElement(ms);
if (mode.rendersSecond())
element2.<StencilElement>withBounds(width, height).renderElement(ms);
}
public enum ElementMode {
FIRST, SECOND, BOTH;
boolean rendersFirst() {
return this == FIRST || this == BOTH;
}
boolean rendersSecond() {
return this == SECOND || this == BOTH;
}
}
}

View file

@ -0,0 +1,198 @@
package com.simibubi.create.foundation.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL30;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.Style;
public class ConfirmationScreen extends AbstractSimiScreen {
private Screen source;
private Consumer<Boolean> action = _success -> {};
private List<ITextProperties> text = new ArrayList<>();
private boolean centered = false;
private int x;
private int y;
private int textWidth;
private int textHeight;
private BoxWidget confirm;
private BoxWidget cancel;
private BoxElement textBackground;
/*
* Removes text lines from the back of the list
* */
public ConfirmationScreen removeTextLines(int amount) {
if (amount > text.size())
return clearText();
text.subList(text.size() - amount, text.size()).clear();
return this;
}
public ConfirmationScreen clearText() {
this.text.clear();
return this;
}
public ConfirmationScreen addText(ITextProperties text) {
this.text.add(text);
return this;
}
public ConfirmationScreen withText(ITextProperties text) {
return clearText().addText(text);
}
public ConfirmationScreen at(int x, int y) {
this.x = Math.max(x, 0);
this.y = Math.max(y, 0);
this.centered = false;
return this;
}
public ConfirmationScreen centered() {
this.centered = true;
return this;
}
public ConfirmationScreen withAction(Consumer<Boolean> action) {
this.action = action;
return this;
}
public void open(@Nonnull Screen source) {
this.source = source;
Minecraft client = source.getMinecraft();
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
this.client.currentScreen = this;
}
@Override
public void tick() {
super.tick();
confirm.tick();
cancel.tick();
}
@Override
protected void init() {
widgets.clear();
ArrayList<ITextProperties> copy = new ArrayList<>(text);
text.clear();
copy.forEach(t -> text.addAll(client.fontRenderer.getTextHandler().wrapLines(t, 300, Style.EMPTY)));
textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4;
textWidth = 300;
if (x + textWidth > width) {
x = width - textWidth;
}
if (y + textHeight + 30 > height) {
y = height - textHeight - 30;
}
if (centered) {
x = width/2 - textWidth/2 - 2;
y = height/2 - textHeight/2 - 16;
}
TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true);
confirm = new 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 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.p(Theme.Key.BUTTON_DISABLE))
.withBounds(textWidth, textHeight)
.at(x, y);
}
@Override
public void onClose() {
accept(false);
}
private void accept(boolean success) {
client.currentScreen = source;
action.accept(success);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
textBackground.render(ms);
int offset = client.fontRenderer.FONT_HEIGHT + 1;
int lineY = y - offset;
ms.push();
ms.translate(0, 0, 200);
for (ITextProperties line : text) {
lineY = lineY + offset;
if (line == null)
continue;
client.fontRenderer.draw(ms, line.getString(), x, lineY, 0xeaeaea);
}
ms.pop();
}
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
//UIRenderHelper.prepFramebufferSize();
ms.push();
//ms.translate(0, 0, -50);
//ms.scale(1, 1, 0.01f);
//todo wait for jozu's framebuffer capabilities on the other branch and use them here
UIRenderHelper.framebuffer.bindFramebuffer(true);
source.render(ms, mouseX, mouseY, 10);
UIRenderHelper.framebuffer.unbindFramebuffer();
Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer();
ms.pop();
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, UIRenderHelper.framebuffer.framebufferObject);
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject);
GL30.glBlitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL30.GL_LINEAR);
mainBuffer.bindFramebuffer(true);
this.fillGradient(ms, 0, 0, this.width, this.height, 0x70101010, 0x80101010);
//RenderSystem.enableAlphaTest();
}
@Override
public void resize(@Nonnull Minecraft client, int width, int height) {
super.resize(client, width, height);
source.resize(client, width, height);
}
}

View file

@ -0,0 +1,51 @@
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, 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;
public DelegatedStencilElement() {
stencil = EMPTY_RENDERER;
element = DEFAULT_ELEMENT;
}
public DelegatedStencilElement(ElementRenderer stencil, ElementRenderer element) {
this.stencil = stencil;
this.element = element;
}
public <T extends DelegatedStencilElement> T withStencilRenderer(ElementRenderer renderer) {
stencil = renderer;
//noinspection unchecked
return (T) this;
}
public <T extends DelegatedStencilElement> T withElementRenderer(ElementRenderer renderer) {
element = renderer;
//noinspection unchecked
return (T) this;
}
@Override
protected void renderStencil(MatrixStack ms) {
stencil.render(ms, width, height, 1);
}
@Override
protected void renderElement(MatrixStack ms) {
element.render(ms, width, height, alpha);
}
@FunctionalInterface
public interface ElementRenderer {
void render(MatrixStack ms, int width, int height, float alpha);
}
}

View file

@ -63,22 +63,22 @@ public class GuiGameElement {
.with(FlowingFluidBlock.LEVEL, 0));
}
public static abstract class GuiRenderBuilder {
double xBeforeScale, yBeforeScale, zBeforeScale = 0;
double x, y, z;
public static abstract class GuiRenderBuilder extends RenderElement {
//double xBeforeScale, yBeforeScale, zBeforeScale = 0;
double xLocal, yLocal, zLocal;
double xRot, yRot, zRot;
double scale = 1;
int color = 0xFFFFFF;
Vector3d rotationOffset = Vector3d.ZERO;
public GuiRenderBuilder atLocal(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
this.xLocal = x;
this.yLocal = y;
this.zLocal = z;
return this;
}
public GuiRenderBuilder at(double x, double y) {
/*public GuiRenderBuilder at(double x, double y) {
this.xBeforeScale = x;
this.yBeforeScale = y;
return this;
@ -89,7 +89,7 @@ public class GuiGameElement {
this.yBeforeScale = y;
this.zBeforeScale = z;
return this;
}
}*/
public GuiRenderBuilder rotate(double xRot, double yRot, double zRot) {
this.xRot = xRot;
@ -136,9 +136,9 @@ public class GuiGameElement {
@Deprecated
protected void transform() {
RenderSystem.translated(xBeforeScale, yBeforeScale, 0);
RenderSystem.translated(x, y, 0);
RenderSystem.scaled(scale, scale, scale);
RenderSystem.translated(x, y, z);
RenderSystem.translated(xLocal, yLocal, zLocal);
RenderSystem.scaled(1, -1, 1);
RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z);
RenderSystem.rotatef((float) zRot, 0, 0, 1);
@ -148,9 +148,9 @@ public class GuiGameElement {
}
protected void transformMatrix(MatrixStack matrixStack) {
matrixStack.translate(xBeforeScale, yBeforeScale, zBeforeScale);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(x, y, z);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(xLocal, yLocal, zLocal);
matrixStack.scale(1, -1, 1);
matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z);
matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion((float) zRot));

View file

@ -0,0 +1,92 @@
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) {}};
public static RenderElement of(IScreenRenderable renderable) {
return new SimpleRenderElement(renderable);
}
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 float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
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);
}
public static class SimpleRenderElement extends RenderElement {
private IScreenRenderable renderable;
public SimpleRenderElement(IScreenRenderable renderable) {
this.renderable = renderable;
}
@Override
public void render(MatrixStack ms) {
renderable.draw(ms, (int) x, (int) y);
}
}
}

View file

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

View file

@ -0,0 +1,51 @@
package com.simibubi.create.foundation.gui;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
public abstract class StencilElement extends RenderElement {
@Override
public void render(MatrixStack ms) {
ms.push();
transform(ms);
prepareStencil(ms);
renderStencil(ms);
prepareElement(ms);
renderElement(ms);
cleanUp(ms);
ms.pop();
}
protected abstract void renderStencil(MatrixStack ms);
protected abstract void renderElement(MatrixStack ms);
protected void transform(MatrixStack ms) {
ms.translate(x, y, z);
}
protected void prepareStencil(MatrixStack ms) {
GL11.glDisable(GL11.GL_STENCIL_TEST);
RenderSystem.stencilMask(~0);
RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC);
GL11.glEnable(GL11.GL_STENCIL_TEST);
RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP);
RenderSystem.stencilMask(0xFF);
RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF);
}
protected void prepareElement(MatrixStack ms) {
GL11.glEnable(GL11.GL_STENCIL_TEST);
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
}
protected void cleanUp(MatrixStack ms) {
GL11.glDisable(GL11.GL_STENCIL_TEST);
}
}

View file

@ -0,0 +1,80 @@
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;
public class TextStencilElement extends DelegatedStencilElement {
protected FontRenderer font;
protected IFormattableTextComponent component;
protected boolean centerVertically = false;
protected boolean centerHorizontally = false;
public TextStencilElement(FontRenderer font) {
super();
this.font = font;
height = 10;
}
public TextStencilElement(FontRenderer font, String text) {
this(font);
component = new StringTextComponent(text);
}
public TextStencilElement(FontRenderer font, IFormattableTextComponent component) {
this(font);
this.component = component;
}
public TextStencilElement withText(String text) {
component = new StringTextComponent(text);
return this;
}
public TextStencilElement withText(IFormattableTextComponent component) {
this.component = component;
return this;
}
public TextStencilElement centered(boolean vertical, boolean horizontal) {
this.centerVertically = vertical;
this.centerHorizontally = horizontal;
return this;
}
@Override
protected void renderStencil(MatrixStack ms) {
float x = 0, y = 0;
if (centerHorizontally)
x = width / 2f - font.getWidth(component) / 2f;
if (centerVertically)
y = height / 2f - font.FONT_HEIGHT / 2f;
font.draw(ms, component, x, y, 0xff_000000);
//font.draw(ms, component, 0, 0, 0xff_000000);
}
@Override
protected void renderElement(MatrixStack ms) {
float x = 0, y = 0;
if (centerHorizontally)
x = width / 2f - font.getWidth(component) / 2f;
if (centerVertically)
y = height / 2f - font.FONT_HEIGHT / 2f;
ms.push();
ms.translate(x, y, 0);
element.render(ms, font.getWidth(component), font.FONT_HEIGHT + 2, alpha);
ms.pop();
}
public IFormattableTextComponent getComponent() {
return component;
}
}

View file

@ -0,0 +1,177 @@
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;
import com.simibubi.create.foundation.utility.Couple;
public class Theme {
private static final Theme base = new Theme();
private static Theme custom = null;
public static void setTheme(@Nullable Theme theme) {
custom = theme;
}
private static ColorHolder resolve(String key) {
ColorHolder h = null;
if (custom != null)
h = custom.get(key);
if (h == null)
h = base.get(key);
if (h == null)
h = ColorHolder.missing;
return h;
}
@Nonnull public static Couple<Color> p(@Nonnull Key key) {return p(key.get());}
@Nonnull public static Couple<Color> p(String key) {return resolve(key).asPair();}
@Nonnull public static Color c(@Nonnull Key key, boolean first) {return c(key.get(), first);}
@Nonnull public static Color c(String key, boolean first) {return p(key).get(first);}
public static int i(@Nonnull Key key, boolean first) {return i(key.get(), first);}
public static int i(String key, boolean first) {return p(key).get(first).getRGB();}
@Nonnull public static Color c(@Nonnull Key key) {return c(key.get());}
@Nonnull public static Color c(String key) {return resolve(key).get();}
public static int i(@Nonnull Key key) {return i(key.get());}
public static int i(String key) {return resolve(key).get().getRGB();}
//-----------//
protected final Map<String, ColorHolder> colors;
protected Theme() {
colors = new HashMap<>();
init();
}
protected void init() {
put(Key.BUTTON_IDLE, new Color(0x60_c0c0ff, true), new Color(0x30_c0c0ff, true));
put(Key.BUTTON_HOVER, new Color(0xa0_c0c0ff, true), new Color(0x50_c0c0ff, true));
put(Key.BUTTON_CLICK, new Color(0xff_4b4bff), new Color(0xff_3b3bdd));
put(Key.BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x20_909090, true));
put(Key.BUTTON_SUCCESS, new Color(0xcc_88f788, true), new Color(0xcc_20cc20, true));
put(Key.BUTTON_FAIL, new Color(0xcc_f78888, true), new Color(0xcc_cc2020, true));
put(Key.TEXT, new Color(0xff_eeeeee), new Color(0xff_a3a3a3));
put(Key.TEXT_DARKER, new Color(0xff_a3a3a3), new Color(0xff_808080));
put(Key.TEXT_ACCENT_STRONG, new Color(0xff_7b7ba3), new Color(0xff_616192));
put(Key.TEXT_ACCENT_SLIGHT, new Color(0xff_ddeeff), new Color(0xff_a0b0c0));
put(Key.STREAK, new Color(0x101010, false));
put(Key.PONDER_BACKGROUND_TRANSPARENT, new Color(0xdd_000000, true));
put(Key.PONDER_BACKGROUND_FLAT, new Color(0xff_000000, false));
put(Key.PONDER_IDLE, new Color(0x40ffeedd, true), new Color(0x20ffeedd, true));
put(Key.PONDER_HOVER, new Color(0x70ffffff, true), new Color(0x30ffffff, true));
put(Key.PONDER_HIGHLIGHT, new Color(0xf0ffeedd, true), new Color(0x60ffeedd, true));
put(Key.TEXT_WINDOW_BORDER, new Color(0x607a6000, true), new Color(0x207a6000, true));
put(Key.PONDER_BACK_ARROW, new Color(0x70aa9999, true), new Color(0x30aa9999, true));
put(Key.PONDER_PROGRESSBAR, new Color(0x80ffeedd, true), new Color(0x50ffeedd, true));
put(Key.PONDER_MISSING_CREATE, new Color(0x70_984500, true), new Color(0x70_692400, true));
put(Key.PONDER_MISSING_VANILLA, new Color(0x50_5000ff, true), new Color(0x50_300077, true));
//put(Key., new Color(0x, true), new Color(0x, true));
}
protected void put(String key, Color c) {
colors.put(key, ColorHolder.single(c));
}
protected void put(Key key, Color c) {
put(key.get(), c);
}
protected void put(String key, Color c1, Color c2) {
colors.put(key, ColorHolder.pair(c1, c2));
}
protected void put(Key key, Color c1, Color c2) {
put(key.get(), c1 , c2);
}
@Nullable protected ColorHolder get(String key) {
return colors.get(key);
}
public static class Key {
public static Key BUTTON_IDLE = new Key();
public static Key BUTTON_HOVER = new Key();
public static Key BUTTON_CLICK = new Key();
public static Key BUTTON_DISABLE = new Key();
public static Key BUTTON_SUCCESS = new Key();
public static Key BUTTON_FAIL = new Key();
public static Key TEXT = new Key();
public static Key TEXT_DARKER = new Key();
public static Key TEXT_ACCENT_STRONG = new Key();
public static Key TEXT_ACCENT_SLIGHT = new Key();
public static Key STREAK = new Key();
public static Key PONDER_BACKGROUND_TRANSPARENT = new Key();
public static Key PONDER_BACKGROUND_FLAT = new Key();
public static Key PONDER_IDLE = new Key();
public static Key PONDER_HOVER = new Key();
public static Key PONDER_HIGHLIGHT = new Key();
public static Key TEXT_WINDOW_BORDER = new Key();
public static Key PONDER_BACK_ARROW = new Key();
public static Key PONDER_PROGRESSBAR = new Key();
public static Key PONDER_MISSING_CREATE = new Key();
public static Key PONDER_MISSING_VANILLA = new Key();
private static int index = 0;
private final String s;
protected Key() {
this.s = "_" + index++;
}
protected Key(String s) {
this.s = s;
}
public String get() {
return s;
}
}
private static class ColorHolder {
private static final ColorHolder missing = ColorHolder.single(Color.BLACK);
private Couple<Color> colors;
private static ColorHolder single(Color c) {
ColorHolder h = new ColorHolder();
h.colors = Couple.create(c, c);
return h;
}
private static ColorHolder pair(Color first, Color second) {
ColorHolder h = new ColorHolder();
h.colors = Couple.create(first, second);
return h;
}
private Color get() {
return colors.getFirst();
}
private Couple<Color> asPair() {
return colors;
}
}
}

View file

@ -1,15 +1,21 @@
package com.simibubi.create.foundation.gui;
import java.awt.Color;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.math.vector.Matrix4f;
@ -18,6 +24,10 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class UIRenderHelper {
public static void enableStencil() {
RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil());
}
public static Framebuffer framebuffer;
public static void init() {
@ -27,19 +37,17 @@ public class UIRenderHelper {
framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true,
Minecraft.IS_RUNNING_ON_MAC);
framebuffer.setFramebufferColor(0, 0, 0, 0);
framebuffer.enableStencil();
// framebuffer.deleteFramebuffer();
});
}
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 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()
@ -51,10 +59,6 @@ public class UIRenderHelper {
float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight;
RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.disableLighting();
RenderSystem.disableAlphaTest();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
framebuffer.bindFramebufferTexture();
@ -82,14 +86,14 @@ public class UIRenderHelper {
tessellator.draw();
framebuffer.unbindFramebufferTexture();
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
}
public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length) {streak(ms, angle, x, y, breadth, length, Theme.i(Theme.Key.STREAK));}
// angle in degrees; 0° -> fading to the right
// x and y specify the middle point of the starting edge
// width is the total width of the streak
public static void streak(MatrixStack ms, float angle, int x, int y, int width, int length, int color) {
// breadth is the total width of the streak
public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, int color) {
int a1 = 0xa0 << 24;
int a2 = 0x80 << 24;
int a3 = 0x10 << 24;
@ -105,7 +109,7 @@ public class UIRenderHelper {
ms.translate(x, y, 0);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90));
streak(ms, width / 2, length, c1, c2, c3, c4);
streak(ms, breadth / 2, length, c1, c2, c3, c4);
ms.pop();
}
@ -120,9 +124,49 @@ public class UIRenderHelper {
GuiUtils.drawGradientRect(model, 0, -width, (int) (split2 * height), width, height, c3, c4);
}
/**
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int)
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, Couple<Color> c) {
angledGradient(ms, angle, x, y, 0, breadth, length, c);
}
/**
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int)
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, Couple<Color> c) {
angledGradient(ms, angle, x, y, z, breadth, length, c.getFirst().getRGB(), c.getSecond().getRGB());
}
/**
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int)
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, int color1, int color2) {
angledGradient(ms, angle, x, y, 0, breadth, length, color1, color2);
}
/**
* x and y specify the middle point of the starting edge
*
* @param angle the angle of the gradient in degrees; 0° means from left to right
* @param color1 the color at the starting edge
* @param color2 the color at the ending edge
* @param breadth the total width of the gradient
*
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, int color1, int color2) {
ms.push();
ms.translate(x, y, z);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90));
Matrix4f model = ms.peek().getModel();
int w = breadth / 2;
GuiUtils.drawGradientRect(model, 0, -w, 0, w, length, color1, color2);
ms.pop();
}
public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, Couple<Color> colors) {breadcrumbArrow(matrixStack, x, y, z, width, height, indent, colors.getFirst().getRGB(), colors.getSecond().getRGB());}
// draws a wide chevron-style breadcrumb arrow pointing left
public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent,
int startColor, int endColor) {
public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, int startColor, int endColor) {
matrixStack.push();
matrixStack.translate(x - indent, y, z);
@ -241,4 +285,30 @@ public class UIRenderHelper {
RenderSystem.enableAlphaTest();
RenderSystem.enableTexture();
}
//just like AbstractGui#drawTexture, but with a color at every vertex
public static void drawColoredTexture(MatrixStack ms, Color c, int x, int y, int tex_left, int tex_top, int width, int height) {
drawColoredTexture(ms, c, x, y, 0, (float)tex_left, (float)tex_top, width, height, 256, 256);
}
public static void drawColoredTexture(MatrixStack ms, Color c, int x, int y, int z, float tex_left, float tex_top, int width, int height, int sheet_width, int sheet_height) {
drawColoredTexture(ms, c, x, x + width, y, y + height, z, width, height, tex_left, tex_top, sheet_width, sheet_height);
}
private static void drawColoredTexture(MatrixStack ms, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) {
drawTexturedQuad(ms.peek().getModel(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float)sheet_width, (tex_left + (float)tex_width) / (float)sheet_width, (tex_top + 0.0F) / (float)sheet_height, (tex_top + (float)tex_height) / (float)sheet_height);
}
private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) {
RenderSystem.enableBlend();
BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR_TEXTURE);
bufferbuilder.vertex(m, (float)left , (float)bot, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u1, v2).endVertex();
bufferbuilder.vertex(m, (float)right, (float)bot, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u2, v2).endVertex();
bufferbuilder.vertex(m, (float)right, (float)top, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u2, v1).endVertex();
bufferbuilder.vertex(m, (float)left , (float)top, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u1, v1).endVertex();
bufferbuilder.finishDrawing();
RenderSystem.enableAlphaTest();
WorldVertexBufferUploader.draw(bufferbuilder);
}
}

View file

@ -2,6 +2,9 @@ package com.simibubi.create.foundation.gui.widgets;
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
@ -11,19 +14,78 @@ import net.minecraft.util.text.StringTextComponent;
public abstract class AbstractSimiWidget extends Widget {
protected List<ITextComponent> toolTip;
public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) {
super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY);
toolTip = new LinkedList<>();
protected float z;
protected boolean wasHovered = false;
protected List<ITextComponent> toolTip = new LinkedList<>();
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
protected AbstractSimiWidget() {
this(0, 0);
}
protected AbstractSimiWidget(int x, int y) {
this(x, y, 16, 16);
}
protected AbstractSimiWidget(int x, int y, int width, int height) {
super(x, y, width, height, StringTextComponent.EMPTY);
}
public <T extends AbstractSimiWidget> T withCallback(BiConsumer<Integer, Integer> cb) {
this.onClick = cb;
//noinspection unchecked
return (T) this;
}
public <T extends AbstractSimiWidget> T withCallback(Runnable cb) {
return withCallback((_$, _$$) -> cb.run());
}
public <T extends AbstractSimiWidget> T atZLevel(float z) {
this.z = z;
//noinspection unchecked
return (T) this;
}
public List<ITextComponent> getToolTip() {
return toolTip;
}
public void tick() {}
@Override
public void renderButton(MatrixStack matrixStack, int p_renderButton_1_, int p_renderButton_2_, float p_renderButton_3_) {
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);
}
@Override
public void onClick(double mouseX, double mouseY) {
runCallback(mouseX, mouseY);
}
}

View file

@ -0,0 +1,197 @@
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.Couple;
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, gradientColor2;
private Color colorTarget1 = Theme.c(Theme.Key.BUTTON_IDLE, true), colorTarget2 = Theme.c(Theme.Key.BUTTON_IDLE, false);
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);
gradientColor1 = colorTarget1;
gradientColor2 = colorTarget2;
}
public <T extends BoxWidget> T withBounds(int width, int height) {
this.width = width;
this.height = height;
//noinspection unchecked
return (T) this;
}
public <T extends BoxWidget> T withBorderColors(Couple<Color> colors) {
this.customBorderTop = colors.getFirst();
this.customBorderBot = colors.getSecond();
updateColorsFromState();
//noinspection unchecked
return (T) this;
}
public <T extends BoxWidget> T withBorderColors(Color top, Color bot) {
this.customBorderTop = top;
this.customBorderBot = bot;
updateColorsFromState();
//noinspection unchecked
return (T) this;
}
public <T extends BoxWidget> T animateColors(boolean b) {
this.animateColors = b;
//noinspection unchecked
return (T) this;
}
@Override
public void tick() {
super.tick();
colorAnimation.tickChaser();
}
@Override
public void onClick(double x, double y) {
super.onClick(x, y);
gradientColor1 = Theme.c(Theme.Key.BUTTON_CLICK, true);
gradientColor2 = Theme.c(Theme.Key.BUTTON_CLICK, true);
startGradientAnimation(getColorForState(true), getColorForState(false), true, 0.15);
}
@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()) {
gradientColor1 = colorTarget1;
gradientColor2 = colorTarget2;
} else {
float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks));
gradientColor1 = ColorHelper.mixColors(previousColor1, colorTarget1, animationValue);
gradientColor2 = ColorHelper.mixColors(previousColor2, colorTarget2, animationValue);
}
}
@Override
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
float fadeValue = fade.getValue(partialTicks);
if (fadeValue < .1f)
return;
box.withAlpha(fadeValue);
box.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_TRANSPARENT))
.gradientBorder(gradientColor1, gradientColor2)
.at(x, y, z)
.withBounds(width, height)
.render(ms);
super.renderButton(ms, mouseX, mouseY, partialTicks);
wasHovered = hovered;
}
@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() {
colorTarget1 = getColorForState(true);
colorTarget2 = getColorForState(false);
}
public void animateGradientFromState() {
startGradientAnimation(
getColorForState(true),
getColorForState(false),
true
);
}
private void startGradientAnimation(Color c1, Color c2, boolean positive, double expSpeed) {
if (!animateColors)
return;
colorAnimation.startWithValue(positive ? 1 : -1);
colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP);
colorAnimation.tickChaser();
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 Theme.p(Theme.Key.BUTTON_DISABLE).get(first);
if (hovered) {
if (first)
return customBorderTop != null ? customBorderTop.darker() : Theme.c(Theme.Key.BUTTON_HOVER, true);
else
return customBorderBot != null ? customBorderBot.darker() : Theme.c(Theme.Key.BUTTON_HOVER, false);
}
if (first)
return customBorderTop != null ? customBorderTop : Theme.c(Theme.Key.BUTTON_IDLE, true);
else
return customBorderBot != null ? customBorderBot : Theme.c(Theme.Key.BUTTON_IDLE, false);
}
}

View file

@ -0,0 +1,144 @@
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.IScreenRenderable;
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;
protected float paddingX = 0;
protected float paddingY = 0;
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 showing(IScreenRenderable renderable) {
return this.showingElement(RenderElement.of(renderable));
}
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 withPadding(float paddingX, float paddingY) {
this.paddingX = paddingX;
this.paddingY = paddingY;
//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 LerpedFloat fade() {
return fade;
}
public <T extends ElementWidget> T fade(float target) {
fade.chase(target, 0.1, LerpedFloat.Chaser.EXP);
//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
public void tick() {
super.tick();
fade.tickChaser();
}
@Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.beforeRender(ms, mouseX, mouseY, partialTicks);
float fadeValue = fade.getValue(partialTicks);
element.withAlpha(fadeValue);
if (fadeValue < 1) {
ms.translate((1 - fadeValue) * fadeModX, (1 - fadeValue) * fadeModY, 0);
}
}
@Override
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
ms.push();
ms.translate(x + paddingX, y + paddingY, z);
float innerWidth = width - 2 * paddingX;
float innerHeight = height - 2 * paddingY;
if (rescaleElement) {
float xScale = innerWidth / rescaleSizeX;
float yScale = innerHeight / rescaleSizeY;
ms.scale(xScale, yScale, 1);
element.at(element.getX() / xScale, element.getY() / yScale);
}
element.withBounds((int) innerWidth, (int) innerHeight).render(ms);
ms.pop();
}
public RenderElement getRenderElement() {
return element;
}
}

View file

@ -7,6 +7,8 @@ import com.simibubi.create.foundation.gui.AllIcons;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
public class IconButton extends AbstractSimiWidget {
private AllIcons icon;
@ -18,7 +20,7 @@ public class IconButton extends AbstractSimiWidget {
}
@Override
public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
public void renderButton(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
if (this.visible) {
this.hovered =
mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;

View file

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

View file

@ -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())

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

@ -38,8 +38,9 @@ import com.simibubi.create.content.schematics.packet.InstantSchematicPacket;
import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
import com.simibubi.create.foundation.command.ConfigureConfigPacket;
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
import com.simibubi.create.foundation.command.HighlightPacket;
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
@ -80,12 +81,13 @@ public enum AllPackets {
PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER),
TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER),
EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::new, PLAY_TO_SERVER),
C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT),
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new, PLAY_TO_CLIENT),
S_CONFIGURE_CONFIG(SConfigureConfigPacket.class, SConfigureConfigPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT),

View file

@ -9,9 +9,11 @@ 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;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.content.PonderTagScreen;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
@ -76,9 +78,9 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
if (screen instanceof PonderTagScreen)
icon = ((PonderTagScreen) screen).getTag();
widgets.add(backTrack = new PonderButton(31, height - 31 - PonderButton.SIZE, () -> {
ScreenOpener.openPreviousScreen(this, Optional.empty());
}).fade(0, -1));
widgets.add(backTrack = new PonderButton(31, height - 31 - 20)
.enableFade(0, 5)
.withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty())));
backTrack.fade(1);
if (icon != null)
@ -97,7 +99,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.push();
ms.translate(0, 0, 500);
if (backTrack.isHovered()) {
textRenderer.draw(ms, Lang.translate(THINK_BACK), 15, height - 16, 0xffa3a3a3);
textRenderer.draw(ms, Lang.translate(THINK_BACK), 15, height - 16, Theme.i(Theme.Key.TEXT_DARKER));
if (MathHelper.epsilonEquals(arrowAnimation.getValue(), arrowAnimation.getChaseTarget())) {
arrowAnimation.setValue(1);
arrowAnimation.setValue(1);// called twice to also set the previous value to 1
@ -108,7 +110,18 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (transition.getChaseTarget() == 0) {
if (backTrack != null) {
int x = (int) MathHelper.lerp(arrowAnimation.getValue(partialTicks), -9, 21);
int maxX = backTrack.x + backTrack.getWidth();
if (x + 30 < backTrack.x)
UIRenderHelper.breadcrumbArrow(ms, x + 30, height - 51, 0, maxX - (x + 30), 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW));
UIRenderHelper.breadcrumbArrow(ms, x, height - 51, 0, 30, 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW));
UIRenderHelper.breadcrumbArrow(ms, x - 30, height - 51, 0, 30, 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW));
}
if (transition.getChaseTarget() == 0 || transition.settled()) {
renderBackground(ms);
return;
}
@ -123,11 +136,11 @@ 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);
lastScreen.render(ms, mouseX, mouseY, 10);
lastScreen.render(ms, mouseX, mouseY, partialTicks);
ms.pop();// 2
// use the buffer texture
@ -149,7 +162,12 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.translate(dpx, dpy, 0);
ms.scale((float) scale, (float) scale, 1);
ms.translate(-dpx, -dpy, 0);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.disableAlphaTest();
UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue));
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
ms.pop();// 1
}
@ -158,18 +176,6 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.translate(depthPointX, depthPointY, 0);
ms.scale((float) scale, (float) scale, 1);
ms.translate(-depthPointX, -depthPointY, 0);
if (backTrack != null) {
int x = (int) MathHelper.lerp(arrowAnimation.getValue(partialTicks), -9, 21);
int maxX = backTrack.x + backTrack.getWidth();
if (x + 30 < backTrack.x)
UIRenderHelper.breadcrumbArrow(ms, x + 30, height - 51, 0, maxX - (x + 30), 20, 5, 0x40aa9999,
0x10aa9999);
UIRenderHelper.breadcrumbArrow(ms, x, height - 51, 0, 30, 20, 5, 0x40aa9999, 0x10aa9999);
UIRenderHelper.breadcrumbArrow(ms, x - 30, height - 51, 0, 30, 20, 5, 0x40aa9999, 0x10aa9999);
}
}
@Override

View file

@ -1,9 +1,13 @@
package com.simibubi.create.foundation.ponder;
import javax.annotation.Nonnull;
import org.antlr.v4.runtime.misc.IntegerList;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import it.unimi.dsi.fastutil.ints.IntList;
@ -15,7 +19,6 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class PonderProgressBar extends AbstractSimiWidget {
LerpedFloat progress;
LerpedFloat flash;
PonderUI ponder;
@ -25,27 +28,12 @@ public class PonderProgressBar extends AbstractSimiWidget {
this.ponder = ponder;
progress = LerpedFloat.linear()
.startWithValue(0);
flash = LerpedFloat.linear()
.startWithValue(0);
}
public void tick() {
progress.chase(ponder.getActiveScene()
.getSceneProgress(), .5f, LerpedFloat.Chaser.EXP);
progress.tickChaser();
if (hovered)
flash();
}
public void flash() {
float value = flash.getValue();
flash.setValue(value + (1 - value) * .2f);
}
public void dim() {
float value = flash.getValue();
flash.setValue(value * .5f);
}
@Override
@ -102,58 +90,47 @@ public class PonderProgressBar extends AbstractSimiWidget {
}
@Override
public void renderButton(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
hovered = clicked(mouseX, mouseY);
ms.push();
ms.translate(0, 0, 250);
/*
* ponderButtons are at z+400
* renderBox is at z+100
* gradients have to be in front of the box so z>+100
*/
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(x, y, 250)
.withBounds(width, height)
.render(ms);
ms.push();
PonderUI.renderBox(ms, x, y, width, height, false);
ms.pop();
ms.push();
ms.translate(x - 2, y - 2, 0);
ms.translate(x - 2, y - 2, 150);
ms.push();
ms.scale((width + 4) * progress.getValue(partialTicks), 1, 1);
GuiUtils.drawGradientRect(ms.peek()
.getModel(), 110, 0, 3, 1, 4, 0x80ffeedd, 0x80ffeedd);
GuiUtils.drawGradientRect(ms.peek()
.getModel(), 110, 0, 4, 1, 5, 0x50ffeedd, 0x50ffeedd);
int c1 = Theme.i(Theme.Key.PONDER_PROGRESSBAR, true);
int c2 = Theme.i(Theme.Key.PONDER_PROGRESSBAR, false);
GuiUtils.drawGradientRect(ms.peek().getModel(), 110, 0, 3, 1, 4, c1, c1);
GuiUtils.drawGradientRect(ms.peek().getModel(), 110, 0, 4, 1, 5, c2, c2);
ms.pop();
renderKeyframes(ms, mouseX, partialTicks);
ms.pop();
ms.pop();
}
private void renderKeyframes(MatrixStack ms, int mouseX, float partialTicks) {
PonderScene activeScene = ponder.getActiveScene();
int hoverStartColor;
int hoverEndColor;
int hoverStartColor = Theme.i(Theme.Key.PONDER_HOVER, true) | 0xa0_000000;
int hoverEndColor = Theme.i(Theme.Key.PONDER_HOVER, false) | 0xa0_000000;
int idleStartColor = Theme.i(Theme.Key.PONDER_IDLE, true) | 0x40_000000;
int idleEndColor = Theme.i(Theme.Key.PONDER_IDLE, false) | 0x40_000000;
int hoverIndex;
if (hovered) {
hoverIndex = getHoveredKeyframeIndex(activeScene, mouseX);
float flashValue = flash.getValue(partialTicks) * 3
+ (float) Math.sin((AnimationTickHolder.getTicks() + partialTicks) / 6);
hoverEndColor = ColorHelper.applyAlpha(0x70ffffff, flashValue);
hoverStartColor = ColorHelper.applyAlpha(0x30ffffff, flashValue);
} else {
hoverIndex = -2;
hoverEndColor = 0;
hoverStartColor = 0;
}
IntList keyframeTimes = activeScene.keyframeTimes;
@ -167,8 +144,8 @@ public class PonderProgressBar extends AbstractSimiWidget {
int keyframePos = (int) (((float) keyframeTime) / ((float) activeScene.totalTime) * (width + 4));
boolean selected = i == hoverIndex;
int startColor = selected ? hoverStartColor : 0x30ffeedd;
int endColor = selected ? hoverEndColor : 0x60ffeedd;
int startColor = selected ? hoverStartColor : idleStartColor;
int endColor = selected ? hoverEndColor : idleEndColor;
int height = selected ? 8 : 4;
drawKeyframe(ms, activeScene, selected, keyframeTime, keyframePos, startColor, endColor, height);
@ -176,8 +153,7 @@ public class PonderProgressBar extends AbstractSimiWidget {
}
}
private void drawKeyframe(MatrixStack ms, PonderScene activeScene, boolean selected, int keyframeTime,
int keyframePos, int startColor, int endColor, int height) {
private void drawKeyframe(MatrixStack ms, PonderScene activeScene, boolean selected, int keyframeTime, int keyframePos, int startColor, int endColor, int height) {
if (selected) {
FontRenderer font = Minecraft.getInstance().fontRenderer;
GuiUtils.drawGradientRect(ms.peek()

View file

@ -2,13 +2,13 @@ package com.simibubi.create.foundation.ponder;
import static com.simibubi.create.foundation.ponder.PonderLocalization.LANG_PREFIX;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
@ -16,8 +16,10 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.PonderScene.SceneTransform;
import com.simibubi.create.foundation.ponder.content.DebugScenes;
@ -29,6 +31,7 @@ import com.simibubi.create.foundation.ponder.elements.TextWindowElement;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.FontHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -43,14 +46,12 @@ import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.util.text.IFormattableTextComponent;
@ -166,13 +167,16 @@ public class PonderUI extends NavigatableSimiScreen {
int i = tagButtons.size();
int x = 31;
int y = 81 + i * 30;
PonderButton b = new PonderButton(x, y, (mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(new PonderTagScreen(t));
}).showing(t);
widgets.add(b);
tagButtons.add(b);
PonderButton b2 = new PonderButton(x, y)
.showing(t)
.withCallback((mX, mY) -> {
centerScalingOn(mX, mY);
ScreenOpener.transitionTo(new PonderTagScreen(t));
});
widgets.add(b2);
tagButtons.add(b2);
LerpedFloat chase = LerpedFloat.linear()
.startWithValue(0)
@ -181,10 +185,10 @@ public class PonderUI extends NavigatableSimiScreen {
});
if (chapter != null) {
/*if (chapter != null) {
widgets.add(chap = new PonderButton(width - 31 - 24, 31, () -> {
}).showing(chapter));
}
}*/
GameSettings bindings = client.gameSettings;
int spacing = 8;
@ -193,53 +197,63 @@ public class PonderUI extends NavigatableSimiScreen {
{
int pX = (width / 2) - 110;
int pY = bY + PonderButton.SIZE + 4;
int pY = bY + 20 + 4;
int pW = width - 2 * pX;
widgets.add(progressBar = new PonderProgressBar(this, pX, pY, pW, 1));
}
widgets.add(scan = new PonderButton(bX, bY, () -> {
identifyMode = !identifyMode;
if (!identifyMode)
scenes.get(index)
.deselect();
else
ponderPartialTicksPaused = client.getRenderPartialTicks();
}).showing(AllIcons.I_MTD_SCAN)
.shortcut(bindings.keyBindDrop)
.fade(0, -1));
widgets.add(slowMode = new PonderButton(width - 20 - 31, bY, () -> {
setComfyReadingEnabled(!isComfyReadingEnabled());
}).showing(AllIcons.I_MTD_SLOW_MODE)
.fade(0, -1));
widgets.add(scan = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindDrop)
.showing(AllIcons.I_MTD_SCAN)
.enableFade(0, 5)
.withCallback(() -> {
identifyMode = !identifyMode;
if (!identifyMode)
scenes.get(index)
.deselect();
else
ponderPartialTicksPaused = client.getRenderPartialTicks();
}));
widgets.add(slowMode = new PonderButton(width - 20 - 31, bY)
.showing(AllIcons.I_MTD_SLOW_MODE)
.enableFade(0, 5)
.withCallback(() -> setComfyReadingEnabled(!isComfyReadingEnabled())));
if (PonderIndex.EDITOR_MODE) {
widgets.add(userMode = new PonderButton(width - 50 - 31, bY, () -> {
userViewMode = !userViewMode;
}).showing(AllIcons.I_MTD_USER_MODE)
.fade(0, -1));
widgets.add(userMode = new PonderButton(width - 50 - 31, bY)
.showing(AllIcons.I_MTD_USER_MODE)
.enableFade(0, 5)
.withCallback(() -> userViewMode = !userViewMode));
}
bX += 50 + spacing;
widgets.add(left = new PonderButton(bX, bY, () -> this.scroll(false)).showing(AllIcons.I_MTD_LEFT)
.shortcut(bindings.keyBindLeft)
.fade(0, -1));
widgets.add(left = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindLeft)
.showing(AllIcons.I_MTD_LEFT)
.enableFade(0, 5)
.withCallback(() -> this.scroll(false)));
bX += 20 + spacing;
widgets.add(close = new PonderButton(bX, bY, this::onClose).showing(AllIcons.I_MTD_CLOSE)
.shortcut(bindings.keyBindInventory)
.fade(0, -1));
widgets.add(close = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindInventory)
.showing(AllIcons.I_MTD_CLOSE)
.enableFade(0, 5)
.withCallback(this::onClose));
bX += 20 + spacing;
widgets.add(right = new PonderButton(bX, bY, () -> this.scroll(true)).showing(AllIcons.I_MTD_RIGHT)
.shortcut(bindings.keyBindRight)
.fade(0, -1));
widgets.add(right = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindRight)
.showing(AllIcons.I_MTD_RIGHT)
.enableFade(0, 5)
.withCallback(() -> this.scroll(true)));
bX += 50 + spacing;
widgets.add(replay = new PonderButton(bX, bY, this::replay).showing(AllIcons.I_MTD_REPLAY)
.shortcut(bindings.keyBindBack)
.fade(0, -1));
widgets.add(replay = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindBack)
.showing(AllIcons.I_MTD_REPLAY)
.enableFade(0, 5)
.withCallback(this::replay));
}
@Override
@ -527,17 +541,16 @@ public class PonderUI extends NavigatableSimiScreen {
float lazyIndexValue = lazyIndex.getValue(partialTicks);
float indexDiff = Math.abs(lazyIndexValue - index);
PonderScene activeScene = scenes.get(index);
int textColor = 0xeeeeee;
boolean noWidgetsHovered = true;
for (Widget widget : widgets)
noWidgetsHovered &= !widget.isMouseOver(mouseX, mouseY);
int tooltipColor = 0xffa3a3a3;
int tooltipColor = Theme.i(Theme.Key.TEXT_DARKER);
{
// Chapter title
ms.push();
ms.translate(0, 0, 300);
ms.translate(0, 0, 100);
int x = 31 + 20 + 8;
int y = 31;
@ -545,14 +558,21 @@ public class PonderUI extends NavigatableSimiScreen {
int wordWrappedHeight = textRenderer.getWordWrappedHeight(title, left.x - 51);
int streakHeight = 35 - 9 + wordWrappedHeight;
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade), 0x101010);
UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * fade), 0x101010);
renderBox(ms, 21, 21, 30, 30, false);
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade));
UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * fade));
//renderBox(ms, 21, 21, 30, 30, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(21, 21, 100)
.withBounds(30, 30)
.render(ms);
GuiGameElement.of(stack)
.at(x - 39, y - 11)
.scale(2)
.render(ms);
.scale(2)
.at(x - 39, y - 11)
.render(ms);
textRenderer.draw(ms, Lang.translate(PONDERING), x, y - 6, tooltipColor);
y += 8;
@ -562,19 +582,18 @@ public class PonderUI extends NavigatableSimiScreen {
ms.multiply(Vector3f.NEGATIVE_X.getDegreesQuaternion(indexDiff * -75));
ms.translate(0, 0, 5);
FontHelper.drawSplitString(ms, textRenderer, title, 0, 0, left.x - 51,
ColorHelper.applyAlpha(textColor, 1 - indexDiff));
ColorHelper.applyAlpha(Theme.i(Theme.Key.TEXT), 1 - indexDiff));
ms.pop();
if (chapter != null) {
ms.push();
ms.translate(chap.x - 4 - 4, chap.y, 0);
UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade), 0x101010);
UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade));
drawRightAlignedString(textRenderer, ms, Lang.translate(IN_CHAPTER)
.getString(), 0, 0, tooltipColor);
drawRightAlignedString(textRenderer, ms, Lang.translate(LANG_PREFIX + "chapter." + chapter.getId())
.getString(), 0, 12, 0xffeeeeee);
drawRightAlignedString(textRenderer, ms, Lang.translate(IN_CHAPTER).getString(), 0, 0, tooltipColor);
drawRightAlignedString(textRenderer, ms,
Lang.translate(LANG_PREFIX + "chapter." + chapter.getId()).getString(), 0, 12, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -590,29 +609,24 @@ public class PonderUI extends NavigatableSimiScreen {
ms.push();
ms.translate(mouseX, mouseY, 100);
if (hoveredTooltipItem.isEmpty()) {
IFormattableTextComponent text = Lang
.translate(IDENTIFY_MODE,
((IFormattableTextComponent) client.gameSettings.keyBindDrop.getBoundKeyLocalizedText())
.formatted(TextFormatting.WHITE))
.formatted(TextFormatting.GRAY);
IFormattableTextComponent text = Lang.translate(
IDENTIFY_MODE,
((IFormattableTextComponent) client.gameSettings.keyBindDrop.getBoundKeyLocalizedText()).formatted(TextFormatting.WHITE)
).formatted(TextFormatting.GRAY);
// renderOrderedTooltip(ms, textRenderer.wrapLines(text, width / 3), 0, 0);
renderWrappedToolTip(ms, textRenderer.getTextHandler()
.wrapLines(text, width / 3, Style.EMPTY), 0, 0, textRenderer);
/*
* String tooltip = Lang
* .createTranslationTextComponent(IDENTIFY_MODE, client.gameSettings.keyBindDrop.getBoundKeyLocalizedText().applyTextStyle(TextFormatting.WHITE))
* .applyTextStyle(TextFormatting.GRAY)
* .getFormattedText();
* renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0);
*/
//renderOrderedTooltip(ms, textRenderer.wrapLines(text, width / 3), 0, 0);
renderWrappedToolTip(ms, textRenderer.getTextHandler().wrapLines(text, width / 3, Style.EMPTY), 0, 0, textRenderer);
/*String tooltip = Lang
.createTranslationTextComponent(IDENTIFY_MODE, client.gameSettings.keyBindDrop.getBoundKeyLocalizedText().applyTextStyle(TextFormatting.WHITE))
.applyTextStyle(TextFormatting.GRAY)
.getFormattedText();
renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0);*/
} else
renderTooltip(ms, hoveredTooltipItem, 0, 0);
if (hoveredBlockPos != null && PonderIndex.EDITOR_MODE && !userViewMode) {
ms.translate(0, -15, 0);
boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos);
IFormattableTextComponent coords = new StringTextComponent(
hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ())
IFormattableTextComponent coords = new StringTextComponent(hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ())
.formatted(copied ? TextFormatting.GREEN : TextFormatting.GOLD);
renderTooltip(ms, coords, 0, 0);
}
@ -649,15 +663,14 @@ public class PonderUI extends NavigatableSimiScreen {
// Widgets
widgets.forEach(w -> {
if (w instanceof PonderButton) {
PonderButton mtdButton = (PonderButton) w;
mtdButton.fade(fade);
((PonderButton) w).fade().startWithValue(fade);
}
});
if (index == 0 || index == 1 && lazyIndexValue < index)
left.fade(lazyIndexValue);
left.fade().startWithValue(lazyIndexValue);
if (index == scenes.size() - 1 || index == scenes.size() - 2 && lazyIndexValue > index)
right.fade(scenes.size() - lazyIndexValue - 1);
right.fade().startWithValue(scenes.size() - lazyIndexValue - 1);
boolean finished = activeScene.isFinished();
if (finished)
@ -693,14 +706,14 @@ public class PonderUI extends NavigatableSimiScreen {
ms.translate(x, y + 5 * (1 - fade), 800);
float fadedWidth = 200 * chase.getValue(partialTicks);
UIRenderHelper.streak(ms, 0, 0, 12, 26, (int) fadedWidth, 0x101010);
UIRenderHelper.streak(ms, 0, 0, 12, 26, (int) fadedWidth);
GL11.glScissor((int) (x * s), 0, (int) (fadedWidth * s), (int) (height * s));
GL11.glEnable(GL11.GL_SCISSOR_TEST);
String tagName = this.tags.get(i)
.getTitle();
textRenderer.draw(ms, tagName, 3, 8, 0xffeedd);
textRenderer.draw(ms, tagName, 3, 8, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
GL11.glDisable(GL11.GL_SCISSOR_TEST);
@ -727,8 +740,7 @@ public class PonderUI extends NavigatableSimiScreen {
ms.pop();
}
protected void lowerButtonGroup(MatrixStack ms, int index, int mouseX, int mouseY, float fade, AllIcons icon,
KeyBinding key) {
/*protected void lowerButtonGroup(MatrixStack ms, int index, int mouseX, int mouseY, float fade, AllIcons icon, KeyBinding key) {
int bWidth = 20;
int bHeight = 20;
int bX = (width - bWidth) / 2 + (index - 1) * (bWidth + 8);
@ -740,10 +752,9 @@ public class PonderUI extends NavigatableSimiScreen {
boolean hovered = isMouseOver(mouseX, mouseY, bX, bY, bWidth, bHeight);
renderBox(ms, bX, bY, bWidth, bHeight, hovered);
icon.draw(ms, bX + 2, bY + 2);
drawCenteredText(ms, textRenderer, key.getBoundKeyLocalizedText(), bX + bWidth / 2 + 8, bY + bHeight - 6,
0xff606060);
drawCenteredText(ms, textRenderer, key.getBoundKeyLocalizedText(), bX + bWidth / 2 + 8, bY + bHeight - 6, 0xff606060);
ms.pop();
}
}*/
private void renderOverlay(MatrixStack ms, int i, float partialTicks) {
if (identifyMode)
@ -756,7 +767,7 @@ public class PonderUI extends NavigatableSimiScreen {
@Override
public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false);
/*MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> {
if (handled.booleanValue())
return;
@ -771,7 +782,7 @@ public class PonderUI extends NavigatableSimiScreen {
});
if (handled.booleanValue())
return true;
return true;*/
if (identifyMode && hoveredBlockPos != null && PonderIndex.EDITOR_MODE) {
long handle = client.getWindow()
@ -843,8 +854,8 @@ public class PonderUI extends NavigatableSimiScreen {
.getString();
return stack.getItem()
.getName()
.getString();
.getName()
.getString();
}
public FontRenderer getFontRenderer() {
@ -857,13 +868,8 @@ public class PonderUI extends NavigatableSimiScreen {
return hovered;
}
public static void renderBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted) {
renderBox(ms, x, y, w, h, 0xff000000, highlighted ? 0xf0ffeedd : 0x40ffeedd,
highlighted ? 0x60ffeedd : 0x20ffeedd);
}
public static void renderSpeechBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted,
Pointing pointing, boolean returnWithLocalTransform) {
public static void renderSpeechBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted, Pointing pointing,
boolean returnWithLocalTransform) {
if (!returnWithLocalTransform)
ms.push();
@ -875,6 +881,8 @@ public class PonderUI extends NavigatableSimiScreen {
int divotSize = 8;
int distance = 1;
int divotRadius = divotSize / 2;
Couple<Color> borderColors = Theme.p(highlighted ? Theme.Key.PONDER_HIGHLIGHT : Theme.Key.PONDER_IDLE);
Color c;
switch (pointing) {
default:
@ -884,6 +892,7 @@ public class PonderUI extends NavigatableSimiScreen {
boxY -= h + divotSize + 1 + distance;
divotX -= divotRadius;
divotY -= divotSize + distance;
c = borderColors.getSecond();
break;
case LEFT:
divotRotation = 90;
@ -891,6 +900,7 @@ public class PonderUI extends NavigatableSimiScreen {
boxY -= h / 2;
divotX += distance;
divotY -= divotRadius;
c = ColorHelper.mixColors(borderColors, 0.5f);
break;
case RIGHT:
divotRotation = 270;
@ -898,6 +908,7 @@ public class PonderUI extends NavigatableSimiScreen {
boxY -= h / 2;
divotX -= divotSize + distance;
divotY -= divotRadius;
c = ColorHelper.mixColors(borderColors, 0.5f);
break;
case UP:
divotRotation = 180;
@ -905,17 +916,24 @@ public class PonderUI extends NavigatableSimiScreen {
boxY += divotSize + 1 + distance;
divotX -= divotRadius;
divotY += distance;
c = borderColors.getFirst();
break;
}
renderBox(ms, boxX, boxY, w, h, highlighted);
//renderBox(ms, boxX, boxY, w, h, highlighted);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(borderColors)
.at(boxX, boxY, 100)
.withBounds(w, h)
.render(ms);
ms.push();
AllGuiTextures toRender = highlighted ? AllGuiTextures.SPEECH_TOOLTIP_HIGHLIGHT : AllGuiTextures.SPEECH_TOOLTIP;
ms.translate(divotX + divotRadius, divotY + divotRadius, 10);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(divotRotation));
ms.translate(-divotRadius, -divotRadius, 0);
toRender.draw(ms, 0, 0);
AllGuiTextures.SPEECH_TOOLTIP_BACKGROUND.draw(ms, 0, 0);
AllGuiTextures.SPEECH_TOOLTIP_COLOR.draw(ms, 0, 0, c);
ms.pop();
if (returnWithLocalTransform) {
@ -927,23 +945,20 @@ public class PonderUI extends NavigatableSimiScreen {
}
public static void renderBox(MatrixStack ms, int x, int y, int w, int h, int backgroundColor, int borderColorStart,
/*public static void renderBox(MatrixStack ms, int x, int y, int w, int h, int backgroundColor, int borderColorStart,
int borderColorEnd) {
int z = 100;
Matrix4f model = ms.peek()
.getModel();
Matrix4f model = ms.peek().getModel();
GuiUtils.drawGradientRect(model, z, x - 3, y - 4, x + w + 3, y - 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 3, y + h + 3, x + w + 3, y + h + 4, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3, x + w + 3, y + h + 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 4, y - 3, x - 3, y + h + 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x + w + 3, y - 3, x + w + 4, y + h + 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3 + 1, x - 3 + 1, y + h + 3 - 1, borderColorStart,
borderColorEnd);
GuiUtils.drawGradientRect(model, z, x + w + 2, y - 3 + 1, x + w + 3, y + h + 3 - 1, borderColorStart,
borderColorEnd);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3 + 1, x - 3 + 1, y + h + 3 - 1, borderColorStart, borderColorEnd);
GuiUtils.drawGradientRect(model, z, x + w + 2, y - 3 + 1, x + w + 3, y + h + 3 - 1, borderColorStart, borderColorEnd);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3, x + w + 3, y - 3 + 1, borderColorStart, borderColorStart);
GuiUtils.drawGradientRect(model, z, x - 3, y + h + 2, x + w + 3, y + h + 3, borderColorEnd, borderColorEnd);
}
}*/
public ItemStack getHoveredTooltipItem() {
return hoveredTooltipItem;

View file

@ -10,6 +10,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderRegistry;
@ -106,17 +107,17 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
int itemCenterY = (int) (height * itemYmult);
for (Item item : items) {
PonderButton button =
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return;
PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
.showing(new ItemStack(item))
.withCallback((x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return;
centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
}).showing(new ItemStack(item));
centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
});
button.fade(1);
widgets.add(button);
widgets.add(b);
layout.next();
}
@ -158,8 +159,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010);
textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, 0xffddeeff);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -170,8 +171,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220, 0x101010);
textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, 0xffddeeff);
UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -189,7 +190,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.pop();
}
@Override
/*@Override
public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> {
@ -207,7 +208,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
if (handled.booleanValue())
return true;
return super.mouseClicked(x, y, button);
}
}*/
@Override
public boolean isEquivalentTo(NavigatableSimiScreen other) {

View file

@ -9,7 +9,9 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderLocalization;
@ -84,24 +86,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int itemCenterY = getItemsY();
for (Item i : items) {
final boolean canClick = PonderRegistry.all.containsKey(i.getRegistryName());
PonderButton button =
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (mouseX, mouseY) -> {
if (!canClick)
return;
PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
.showing(new ItemStack(i));
if (PonderRegistry.all.containsKey(i.getRegistryName())) {
b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag));
}).showing(new ItemStack(i));
if (!canClick)
});
} else {
if (i.getRegistryName()
.getNamespace()
.equals(Create.ID))
button.customColors(0x70984500, 0x70692400);
.getNamespace()
.equals(Create.ID))
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else
button.customColors(0x505000FF, 0x50300077);
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1);
widgets.add(button);
widgets.add(b);
layout.next();
}
@ -109,23 +113,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ResourceLocation registryName = tag.getMainItem()
.getItem()
.getRegistryName();
final boolean canClick = PonderRegistry.all.containsKey(registryName);
PonderButton button =
new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> {
if (!canClick)
return;
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
}).showing(tag.getMainItem());
if (!canClick)
PonderButton b = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10)
.showing(tag.getMainItem());
if (PonderRegistry.all.containsKey(registryName)) {
b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
});
} else {
if (registryName.getNamespace()
.equals(Create.ID))
button.customColors(0x70984500, 0x70692400);
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else
button.customColors(0x505000FF, 0x50300077);
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1);
widgets.add(button);
widgets.add(b);
}
// chapters
@ -187,15 +194,21 @@ public class PonderTagScreen extends NavigatableSimiScreen {
String title = tag.getTitle();
int streakHeight = 35;
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240, 0x101010);
PonderUI.renderBox(ms, 21, 21, 30, 30, false);
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240);
//PonderUI.renderBox(ms, 21, 21, 30, 30, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(21, 21, 100)
.withBounds(30, 30)
.render(ms);
textRenderer.draw(ms, Lang.translate(PonderUI.PONDERING), x, y - 6, 0xffa3a3a3);
textRenderer.draw(ms, Lang.translate(PonderUI.PONDERING), x, y - 6, Theme.i(Theme.Key.TEXT_DARKER));
y += 8;
x += 0;
ms.translate(x, y, 0);
ms.translate(0, 0, 5);
textRenderer.draw(ms, title, 0, 0, 0xeeeeee);
textRenderer.draw(ms, title, 0, 0, Theme.i(Theme.Key.TEXT));
ms.pop();
ms.push();
@ -214,9 +227,16 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int h = textRenderer.getWordWrappedHeight(desc, w);
PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false);
//PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(x - 3, y - 3, 90)
.withBounds(w + 6, h + 6)
.render(ms);
ms.translate(0, 0, 100);
FontHelper.drawSplitString(ms, textRenderer, desc, x, y, w, 0xeeeeee);
FontHelper.drawSplitString(ms, textRenderer, desc, x, y, w, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -232,16 +252,23 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(x, y, 0);
PonderUI.renderBox(ms, (sWidth - stringWidth) / 2 - 5, itemArea.getY() - 21, stringWidth + 10, 10, false);
//PonderUI.renderBox(ms, (sWidth - stringWidth) / 2 - 5, itemArea.getY() - 21, stringWidth + 10, 10, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at((sWidth - stringWidth) / 2f - 5, itemArea.getY() - 21, 100)
.withBounds(stringWidth + 10, 10)
.render(ms);
ms.translate(0, 0, 200);
// UIRenderHelper.streak(0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 180, 0x101010);
drawCenteredString(ms, textRenderer, relatedTitle, sWidth / 2, itemArea.getY() - 20, 0xeeeeee);
drawCenteredString(ms, textRenderer, relatedTitle, sWidth / 2, itemArea.getY() - 20, Theme.i(Theme.Key.TEXT));
ms.translate(0,0, -200);
UIRenderHelper.streak(ms, 0, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75, 0x101010);
UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75, 0x101010);
UIRenderHelper.streak(ms, 0, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75);
UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75);
ms.pop();
@ -261,8 +288,8 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(chapterX, chapterY, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010);
textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, 0xffddeeff);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
ms.pop();
}
@ -291,7 +318,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
return hoveredItem;
}
@Override
/*@Override
public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> {
@ -310,7 +337,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
if (handled.booleanValue())
return true;
return super.mouseClicked(x, y, button);
}
}*/
@Override
public boolean isEquivalentTo(NavigatableSimiScreen other) {

View file

@ -136,7 +136,7 @@ public class InputWindowElement extends AnimatedOverlayElement {
if (hasItem) {
GuiGameElement.of(item)
.at(keyWidth + (hasIcon ? 24 : 0), 0)
.<GuiGameElement.GuiRenderBuilder>at(keyWidth + (hasIcon ? 24 : 0), 0)
.scale(1.5)
.render(ms);
RenderSystem.disableDepthTest();

View file

@ -4,6 +4,8 @@ import java.util.List;
import java.util.function.Supplier;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.ponder.PonderLocalization;
import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderUI;
@ -110,7 +112,14 @@ public class TextWindowElement extends AnimatedOverlayElement {
ms.push();
ms.translate(0, sceneToScreen.y, 400);
PonderUI.renderBox(ms, targetX - 10, 3, boxWidth, boxHeight - 1, 0xaa000000, 0x30eebb00, 0x10eebb00);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.TEXT_WINDOW_BORDER))
.at(targetX - 10, 3, 100)
.withBounds(boxWidth, boxHeight - 1)
.render(ms);
//PonderUI.renderBox(ms, targetX - 10, 3, boxWidth, boxHeight - 1, 0xaa000000, 0x30eebb00, 0x10eebb00);
int brighterColor = ColorHelper.mixAlphaColors(color, 0xFFffffdd, 1 / 2f);
if (vec != null) {

View file

@ -5,6 +5,7 @@ import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.content.PonderChapter;
@ -20,17 +21,18 @@ public class ChapterLabel extends AbstractSimiWidget {
public ChapterLabel(PonderChapter chapter, int x, int y, BiConsumer<Integer, Integer> onClick) {
super(x, y, 175, 38);
this.button = new PonderButton(x + 4, y + 4, onClick, 30, 30).showing(chapter);
this.button.fade(1);
this.button = new PonderButton(x + 4, y + 4, 30, 30)
.showing(chapter)
.withCallback(onClick);
this.chapter = chapter;
}
@Override
public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 2, width, 0x101010);
UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 2, width);
Minecraft.getInstance().fontRenderer.draw(ms, Lang.translate("ponder.chapter." + chapter.getId()), x + 50,
y + 20, 0xffddeeff);
y + 20, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
button.renderButton(ms, mouseX, mouseY, partialTicks);
super.render(ms, mouseX, mouseY, partialTicks);

View file

@ -1,175 +1,105 @@
package com.simibubi.create.foundation.ponder.ui;
import java.util.function.BiConsumer;
import java.awt.Color;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.gui.widgets.ElementWidget;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
public class PonderButton extends AbstractSimiWidget {
public class PonderButton extends BoxWidget {
private IScreenRenderable icon;
private ItemStack item;
protected boolean pressed;
private BiConsumer<Integer, Integer> onClick;
private int xFadeModifier;
private int yFadeModifier;
private float fade;
private KeyBinding shortcut;
private LerpedFloat flash;
private Couple<Integer> customPassiveBorder;
protected ItemStack item;
protected KeyBinding shortcut;
protected LerpedFloat flash = LerpedFloat.linear().startWithValue(0).chase(0, 0.1f, LerpedFloat.Chaser.EXP);
public static final int SIZE = 20;
public PonderButton(int x, int y) {
this(x, y, 20, 20);
}
public PonderButton(int x, int y, BiConsumer<Integer, Integer> onClick, int width, int height) {
public PonderButton(int x, int y, int width, int height) {
super(x, y, width, height);
this.onClick = onClick;
flash = LerpedFloat.linear()
.startWithValue(0);
z = 400;
paddingX = 2;
paddingY = 2;
}
public PonderButton(int x, int y, BiConsumer<Integer, Integer> onClick) {
this(x, y, onClick, SIZE, SIZE);
}
public PonderButton(int x, int y, Runnable onClick) {
this(x, y, ($, $$) -> onClick.run());
}
public PonderButton showing(IScreenRenderable icon) {
this.icon = icon;
return this;
}
public PonderButton showing(ItemStack item) {
this.item = item;
return this;
}
public PonderButton customColors(int start, int end) {
this.customPassiveBorder = Couple.create(start, end);
return this;
}
public PonderButton shortcut(KeyBinding key) {
public <T extends PonderButton> T withShortcut(KeyBinding key) {
this.shortcut = key;
return this;
//noinspection unchecked
return (T) this;
}
public PonderButton fade(int xModifier, int yModifier) {
this.xFadeModifier = xModifier;
this.yFadeModifier = yModifier;
return this;
public <T extends PonderButton> T showing(ItemStack item) {
this.item = item;
return super.showingElement(GuiGameElement.of(item)
.scale(1.5f)
.at(-4, -4));
}
public void fade(float fade) {
this.fade = fade;
@Override
public <T extends ElementWidget> T showingElement(RenderElement element) {
return super.showingElement(element);
}
public void flash() {
float value = flash.getValue();
flash.setValue(value + (1 - value) * .2f);
flash.updateChaseTarget(1);
}
public void dim() {
float value = flash.getValue();
flash.setValue(value * .5f);
flash.updateChaseTarget(0);
}
@Override
public void renderButton(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (!visible)
return;
if (fade < .1f)
return;
public void tick() {
super.tick();
flash.tickChaser();
}
hovered = isMouseOver(mouseX, mouseY) && fade > .75f;
ms.push();
RenderSystem.disableDepthTest();
if (fade < 1)
ms.translate((1 - fade) * -5 * xFadeModifier, (1 - fade) * -5 * yFadeModifier, 0);
@Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.beforeRender(ms, mouseX, mouseY, partialTicks);
float flashValue = flash.getValue(partialTicks);
if (flashValue > .1f)
fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6);
int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade);
int borderColorStart = customPassiveBorder != null ? customPassiveBorder.getFirst() : hovered ? 0x70ffffff : 0x40aa9999;
int borderColorEnd = customPassiveBorder != null ? customPassiveBorder.getSecond() : hovered ? 0x30ffffff : 0x20aa9999;
borderColorStart = ColorHelper.applyAlpha(borderColorStart, fade);
borderColorEnd = ColorHelper.applyAlpha(borderColorEnd, fade);
ms.translate(0, 0, 400);
PonderUI.renderBox(ms, x, y, width, height, backgroundColor, borderColorStart, borderColorEnd);
ms.translate(0, 0, 100);
if (icon != null) {
RenderSystem.enableBlend();
RenderSystem.color4f(1, 1, 1, fade);
ms.push();
ms.translate(x + 2, y + 2, 0);
ms.scale((width - 4) / 16f, (height - 4) / 16f, 1);
icon.draw(ms, this, 0, 0);
ms.pop();
if (flashValue > .1f) {
float sin = 0.5f + 0.5f * MathHelper.sin((AnimationTickHolder.getTicks(true) + partialTicks) / 6f);
sin *= flashValue;
Color c1 = gradientColor1;
Color c2 = gradientColor2;
Color nc1 = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), MathHelper.clamp(c1.getAlpha() + 50, 0, 255));
Color nc2 = new Color(c2.getRed(), c2.getGreen(), c2.getBlue(), MathHelper.clamp(c2.getAlpha() + 50, 0, 255));
gradientColor1 = ColorHelper.mixColors(c1, nc1, sin);
gradientColor2 = ColorHelper.mixColors(c2, nc2, sin);
}
if (item != null) {
ms.push();
ms.translate(0, 0, -100);
GuiGameElement.of(item)
.at(x - 2, y - 2)
.scale(1.5f)
.render(ms);
ms.pop();
}
if (shortcut != null)
drawCenteredText(ms, Minecraft.getInstance().fontRenderer, shortcut.getBoundKeyLocalizedText(), x + width / 2 + 8,
y + height - 6, ColorHelper.applyAlpha(0xff606060, fade));
ms.pop();
}
public void runCallback(double mouseX, double mouseY) {
onClick.accept((int) mouseX, (int) mouseY);
}
@Override
public void onClick(double p_onClick_1_, double p_onClick_3_) {
super.onClick(p_onClick_1_, p_onClick_3_);
this.pressed = true;
}
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderButton(ms, mouseX, mouseY, partialTicks);
float fadeValue = fade.getValue();
@Override
public void onRelease(double p_onRelease_1_, double p_onRelease_3_) {
super.onRelease(p_onRelease_1_, p_onRelease_3_);
this.pressed = false;
}
if (fadeValue < .1f)
return;
/*public void setToolTip(String text) {
toolTip.clear();
toolTip.add(text);
}*/
if (shortcut != null) {
ms.translate(0, 0, z+50);
drawCenteredText(ms, Minecraft.getInstance().fontRenderer, shortcut.getBoundKeyLocalizedText(), x + width / 2 + 8, y + height - 6, ColorHelper.applyAlpha(Theme.i(Theme.Key.TEXT_DARKER), fadeValue));
}
}
public ItemStack getItem() {
return item;
}
@Override
public boolean isMouseOver(double x, double y) {
double m = 4;
x = Math.floor(x);
y = Math.floor(y);
return active && visible
&& !(x < this.x - m || x > this.x + width + m - 1 || y < this.y - m || y > this.y + height + m - 1);
}
}

View file

@ -10,20 +10,28 @@ import net.minecraft.world.IWorld;
public class AnimationTickHolder {
private static int ticks;
private static int paused_ticks;
public static void reset() {
ticks = 0;
paused_ticks = 0;
}
public static void tick() {
if (!Minecraft.getInstance()
.isGamePaused()) {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision
} else {
paused_ticks = (paused_ticks + 1) % 1_728_000;
}
}
public static int getTicks() {
return ticks;
return getTicks(false);
}
public static int getTicks(boolean includePaused) {
return includePaused ? ticks + paused_ticks : ticks;
}
public static float getRenderTime() {

View file

@ -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;
@ -39,6 +42,10 @@ public class ColorHelper {
return (color & 0xFFFFFF) | alphaChannel << 24;
}
public static Color applyAlpha(Color c, float alpha) {
return new Color(applyAlpha(c.getRGB(), alpha), true);
}
public static int mixColors(int color1, int color2, float w) {
int r1 = (color1 >> 16);
int g1 = (color1 >> 8) & 0xFF;
@ -52,6 +59,23 @@ 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
);
}
@Nonnull
public static Color mixColors(@Nonnull Couple<Color> colors, float w) {
return mixColors(colors.getFirst(), colors.getSecond(), w);
}
public static int mixAlphaColors(int color1, int color2, float w) {
int a1 = (color1 >> 24);
int r1 = (color1 >> 16) & 0xFF;

View file

@ -81,4 +81,22 @@ public interface Force {
return timeRemaining <= 0;
}
}
class Static implements Force {
float force;
public Static(float force) {
this.force = force;
}
@Override
public float get(float mass, float value, float speed) {
return force;
}
@Override
public boolean finished() {
return false;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,23 +1,24 @@
{
"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",
"StoreProjectionMatrixMixin"
],
"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",
"StoreProjectionMatrixMixin",
"TileRemoveMixin",
"TileWorldHookMixin",
"WindowResizeMixin"
],
"injectors": {
"defaultRequire": 1
},
"minVersion": "0.8"
}