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.ClientSchematicLoader;
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
import com.simibubi.create.content.schematics.client.SchematicHandler; 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.ResourceReloadHandler;
import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.CustomBlockModels;
import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.block.render.SpriteShifter;
@ -80,6 +81,7 @@ public class CreateClient {
modEventBus.addListener(CreateClient::onModelRegistry); modEventBus.addListener(CreateClient::onModelRegistry);
modEventBus.addListener(CreateClient::onTextureStitch); modEventBus.addListener(CreateClient::onTextureStitch);
modEventBus.addListener(AllParticleTypes::registerFactories); modEventBus.addListener(AllParticleTypes::registerFactories);
modEventBus.addListener(ClientEvents::loadCompleted);
Backend.init(); Backend.init();
OptifineHandler.init(); OptifineHandler.init();
@ -110,11 +112,14 @@ public class CreateClient {
PonderIndex.registerTags(); PonderIndex.registerTags();
UIRenderHelper.init(); UIRenderHelper.init();
UIRenderHelper.enableStencil();
IResourceManager resourceManager = Minecraft.getInstance() IResourceManager resourceManager = Minecraft.getInstance()
.getResourceManager(); .getResourceManager();
if (resourceManager instanceof IReloadableResourceManager) if (resourceManager instanceof IReloadableResourceManager)
((IReloadableResourceManager) resourceManager).addReloadListener(new ResourceReloadHandler()); ((IReloadableResourceManager) resourceManager).addReloadListener(new ResourceReloadHandler());
} }
public static void onTextureStitch(TextureStitchEvent.Pre event) { 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); font.drawWithShadow(matrixStack, textComponent, (BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(textComponent.getString())) / 2f, 57, 0x8B8B8B);
GuiGameElement.of(recipe.getRecipeOutput()) GuiGameElement.of(recipe.getRecipeOutput())
.at(90, 0) .<GuiGameElement.GuiRenderBuilder>at(90, 0)
.scale(3.5) .scale(3.5)
.render(matrixStack); .render(matrixStack);
} }

View file

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

View file

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

View file

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

View file

@ -133,7 +133,7 @@ public class ZapperScreen extends AbstractSimiScreen {
protected void renderZapper(MatrixStack matrixStack) { protected void renderZapper(MatrixStack matrixStack) {
GuiGameElement.of(zapper) 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) .scale(4)
.render(matrixStack); .render(matrixStack);
} }

View file

@ -97,7 +97,7 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreen<Adjustabl
} }
GuiGameElement.of(renderedItem) 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) .scale(5)
.render(matrixStack); .render(matrixStack);
} }

View file

@ -126,7 +126,7 @@ public class StockpileSwitchScreen extends AbstractSimiScreen {
matrixStack.push(); matrixStack.push();
GuiGameElement.of(renderedItem) GuiGameElement.of(renderedItem)
.at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250) .<GuiGameElement.GuiRenderBuilder>at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250)
.scale(5) .scale(5)
.render(matrixStack); .render(matrixStack);
matrixStack.pop(); 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); textRenderer.draw(ms, I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 3, 0xdedede);
GuiGameElement.of(container.filterItem) GuiGameElement.of(container.filterItem)
.at(x + background.width, guiTop + background.height - 60) .<GuiGameElement.GuiRenderBuilder>at(x + background.width, guiTop + background.height - 60)
.scale(5) .scale(5)
.render(ms); .render(ms);

View file

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

View file

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

View file

@ -152,7 +152,7 @@ public class SchematicEditScreen extends AbstractSimiScreen {
x + 93 - textRenderer.getStringWidth(handler.getCurrentSchematicName()) / 2, y + 3, 0xffffff); x + 93 - textRenderer.getStringWidth(handler.getCurrentSchematicName()) / 2, y + 3, 0xffffff);
GuiGameElement.of(AllItems.SCHEMATIC.asStack()) GuiGameElement.of(AllItems.SCHEMATIC.asStack())
.at(guiLeft + 200, guiTop + 82, 0) .<GuiGameElement.GuiRenderBuilder>at(guiLeft + 200, guiTop + 82, 0)
.scale(3) .scale(3)
.render(matrixStack); .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.depot.EjectorTargetHandler;
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
import com.simibubi.create.foundation.config.AllConfigs; 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.ItemDescription;
import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.networking.AllPackets; 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.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; 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.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class ClientEvents { 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

@ -30,11 +30,13 @@ public class AllCommands {
.then(FixLightingCommand.register()) .then(FixLightingCommand.register())
.then(HighlightCommand.register()) .then(HighlightCommand.register())
.then(CouplingCommand.register()) .then(CouplingCommand.register())
.then(CloneCommand.register()) .then(ConfigCommand.register())
.then(PonderCommand.register()) .then(PonderCommand.register())
.then(CloneCommand.register())
// utility // utility
.then(util)); .then(util)
);
createRoot.addChild(buildRedirect("u", util)); createRoot.addChild(buildRedirect("u", util));
@ -54,7 +56,7 @@ public class AllCommands {
.then(ClearBufferCacheCommand.register()) .then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register()) .then(ChunkUtilCommand.register())
.then(FlySpeedCommand.register()) .then(FlySpeedCommand.register())
// .then(KillTPSCommand.register()) //.then(KillTPSCommand.register())
.build(); .build();
} }
@ -72,12 +74,12 @@ public class AllCommands {
* *
* @return the built node * @return the built node
*/ */
public static LiteralCommandNode<CommandSource> buildRedirect(final String alias, public static LiteralCommandNode<CommandSource> buildRedirect(final String alias, final LiteralCommandNode<CommandSource> destination) {
final LiteralCommandNode<CommandSource> destination) {
// Redirects only work for nodes with children, but break the top argument-less command. // 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. // 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. // See https://github.com/Mojang/brigadier/issues/46). Manually clone the node instead.
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder.<CommandSource>literal(alias) LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder
.<CommandSource>literal(alias)
.requires(destination.getRequirement()) .requires(destination.getRequirement())
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork()) .forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
.executes(destination.getCommand()); .executes(destination.getCommand());

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

@ -18,8 +18,10 @@ public class FabulousWarningCommand {
ServerPlayerEntity player = ctx.getSource() ServerPlayerEntity player = ctx.getSource()
.asPlayer(); .asPlayer();
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), AllPackets.channel.send(
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fabulousWarning.name(), "")); 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 -> { .executes(ctx -> {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource() AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()), .getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true))); new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
ctx.getSource() ctx.getSource()
.sendFeedback( .sendFeedback(

View file

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

View file

@ -21,26 +21,20 @@ import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
public class PonderCommand { public class PonderCommand {
public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register( public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register(new ResourceLocation("all_ponders"), (iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet().stream(), builder));
new ResourceLocation("all_ponders"),
(iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet()
.stream(), builder));
static ArgumentBuilder<CommandSource, ?> register() { static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("ponder") return Commands.literal("ponder")
.requires(cs -> cs.hasPermissionLevel(0)) .requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> openScene("index", ctx.getSource() .executes(ctx -> openScene("index", ctx.getSource().asPlayer()))
.asPlayer()))
.then(Commands.argument("scene", ResourceLocationArgument.resourceLocation()) .then(Commands.argument("scene", ResourceLocationArgument.resourceLocation())
.suggests(ITEM_PONDERS) .suggests(ITEM_PONDERS)
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene") .executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), ctx.getSource().asPlayer()))
.toString(),
ctx.getSource()
.asPlayer()))
.then(Commands.argument("targets", EntityArgument.players()) .then(Commands.argument("targets", EntityArgument.players())
.requires(cs -> cs.hasPermissionLevel(2)) .requires(cs -> cs.hasPermissionLevel(2))
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene") .executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), EntityArgument.getPlayers(ctx, "targets")))
.toString(), EntityArgument.getPlayers(ctx, "targets"))))); )
);
} }
@ -53,8 +47,9 @@ public class PonderCommand {
if (player instanceof FakePlayer) if (player instanceof FakePlayer)
continue; continue;
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), AllPackets.channel.send(
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.openPonder.name(), sceneId)); PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.openPonder.name(), sceneId));
} }
return Command.SINGLE_SUCCESS; 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.Create;
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen; import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
import com.simibubi.create.foundation.config.AllConfigs; 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.gui.ScreenOpener;
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.ponder.PonderRegistry; 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.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
public class ConfigureConfigPacket extends SimplePacketBase { public class SConfigureConfigPacket extends SimplePacketBase {
private final String option; private final String option;
private final String value; private final String value;
public ConfigureConfigPacket(String option, String value) { public SConfigureConfigPacket(String option, String value) {
this.option = option; this.option = option;
this.value = value; this.value = value;
} }
public ConfigureConfigPacket(PacketBuffer buffer) { public SConfigureConfigPacket(PacketBuffer buffer) {
this.option = buffer.readString(32767); this.option = buffer.readString(32767);
this.value = buffer.readString(32767); this.value = buffer.readString(32767);
} }
@ -69,7 +70,8 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.setPacketHandled(true); .setPacketHandled(true);
} }
enum Actions { public enum Actions {
configScreen(() -> Actions::configScreen),
rainbowDebug(() -> Actions::rainbowDebug), rainbowDebug(() -> Actions::rainbowDebug),
overlayScreen(() -> Actions::overlayScreen), overlayScreen(() -> Actions::overlayScreen),
fixLighting(() -> Actions::experimentalLighting), fixLighting(() -> Actions::experimentalLighting),
@ -91,6 +93,11 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.accept(value); .accept(value);
} }
@OnlyIn(Dist.CLIENT)
private static void configScreen(String value) {
ScreenOpener.open(new BaseConfigScreen(null));
}
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private static void rainbowDebug(String value) { private static void rainbowDebug(String value) {
ClientPlayerEntity player = Minecraft.getInstance().player; ClientPlayerEntity player = Minecraft.getInstance().player;

View file

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

View file

@ -13,7 +13,9 @@ public class ToggleExperimentalRenderingCommand extends ConfigureConfigCommand {
@Override @Override
protected void sendPacket(ServerPlayerEntity player, String option) { protected void sendPacket(ServerPlayerEntity player, String option) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), AllPackets.channel.send(
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.experimentalRendering.name(), option)); 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) { if (comment.length > 0) {
String[] comments = new String[comment.length + 1]; String[] comments = new String[comment.length + 1];
comments[0] = ""; comments[0] = "";
for (int i = 0; i < comment.length; i++) System.arraycopy(comment, 0, comments, 1, comment.length);
comments[i + 1] = comment[i];
builder.comment(comments); builder.comment(comments);
} else } else
builder.comment(""); 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.disableLighting();
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks); renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(matrixStack, mouseX, mouseY);
} }
@Override @Override
@ -152,9 +150,12 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
if (!widget.isHovered()) if (!widget.isHovered())
continue; continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip() if (widget instanceof AbstractSimiWidget) {
.isEmpty()) { if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
} else {
widget.renderToolTip(matrixStack, mouseX, mouseY);
} }
} }
} }

View file

@ -33,6 +33,13 @@ public abstract class AbstractSimiScreen extends Screen {
guiTop = (this.height - sHeight) / 2; guiTop = (this.height - sHeight) / 2;
} }
@Override
public void tick() {
super.tick();
widgets.stream().filter(w -> w instanceof AbstractSimiWidget).forEach(w -> ((AbstractSimiWidget) w).tick());
}
@Override @Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
partialTicks = partialTicks == 10 ? 0 partialTicks = partialTicks == 10 ? 0
@ -46,8 +53,6 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets) for (Widget widget : widgets)
widget.render(ms, mouseX, mouseY, partialTicks); widget.render(ms, mouseX, mouseY, partialTicks);
renderWindowForeground(ms, mouseX, mouseY, partialTicks); renderWindowForeground(ms, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(ms, mouseX, mouseY);
ms.pop(); ms.pop();
} }
@ -62,6 +67,10 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets) for (Widget widget : widgets)
if (widget.mouseClicked(x, y, button)) if (widget.mouseClicked(x, y, button))
result = true; result = true;
if (!result) {
result = super.mouseClicked(x, y, button);
}
return result; return result;
} }
@ -127,9 +136,12 @@ public abstract class AbstractSimiScreen extends Screen {
if (!widget.isHovered()) if (!widget.isHovered())
continue; continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip() if (widget instanceof AbstractSimiWidget) {
.isEmpty()) { if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); 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; package com.simibubi.create.foundation.gui;
import java.awt.Color;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -80,8 +82,8 @@ public enum AllGuiTextures implements IScreenRenderable {
INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6), INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6),
INDICATOR_RED("widgets.png", 72, 18, 18, 6), INDICATOR_RED("widgets.png", 72, 18, 18, 6),
SPEECH_TOOLTIP("widgets.png", 0, 24, 8, 8), SPEECH_TOOLTIP_BACKGROUND("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_HIGHLIGHT("widgets.png", 8, 24, 8, 8), SPEECH_TOOLTIP_COLOR("widgets.png", 8, 24, 8, 8),
// PlacementIndicator // PlacementIndicator
PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256); PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256);
@ -123,4 +125,9 @@ public enum AllGuiTextures implements IScreenRenderable {
bind(); bind();
screen.drawTexture(ms, x, y, startX, startY, width, height); 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 iconX;
private int iconY; private int iconY;
public static final AllIcons I_ADD = newRow(), I_TRASH = next(), I_3x3 = next(), I_TARGET = next(), public static final AllIcons
I_PRIORITY_VERY_LOW = next(), I_PRIORITY_LOW = next(), I_PRIORITY_HIGH = next(), I_PRIORITY_VERY_HIGH = next(), I_ADD = newRow(),
I_BLACKLIST = next(), I_WHITELIST = next(), I_WHITELIST_OR = next(), I_WHITELIST_AND = next(), I_TRASH = next(),
I_WHITELIST_NOT = next(), I_RESPECT_NBT = next(), I_IGNORE_NBT = 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(), public static final AllIcons
I_ACTIVE = next(), I_PASSIVE = next(), I_ROTATE_PLACE = next(), I_ROTATE_PLACE_RETURNED = next(), I_CONFIRM = newRow(),
I_ROTATE_NEVER_PLACE = next(), I_MOVE_PLACE = next(), I_MOVE_PLACE_RETURNED = next(), I_NONE = next(),
I_MOVE_NEVER_PLACE = next(), I_CART_ROTATE = next(), I_CART_ROTATE_PAUSED = 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(); I_CART_ROTATE_LOCKED = next();
public static final AllIcons I_DONT_REPLACE = newRow(), I_REPLACE_SOLID = next(), I_REPLACE_ANY = next(), public static final AllIcons
I_REPLACE_EMPTY = next(), I_CENTERED = next(), I_ATTACHED = next(), I_INSERTED = next(), I_FILL = next(), I_DONT_REPLACE = newRow(),
I_PLACE = next(), I_REPLACE = next(), I_CLEAR = next(), I_OVERLAY = next(), I_FLATTEN = next(), I_LMB = next(), I_REPLACE_SOLID = next(),
I_SCROLL = next(), I_RMB = 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(), public static final AllIcons
I_DICE = next(), I_TUNNEL_SPLIT = next(), I_TUNNEL_FORCED_SPLIT = next(), I_TUNNEL_ROUND_ROBIN = next(), I_TOOL_DEPLOY = newRow(),
I_TUNNEL_FORCED_ROUND_ROBIN = next(), I_TUNNEL_PREFER_NEAREST = next(), I_TUNNEL_RANDOMIZE = next(), 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_TUNNEL_SYNCHRONIZE = next(),
I_TOOL_MOVE_XZ = newRow(), I_TOOL_MOVE_Y = next(), I_TOOL_ROTATE = next(), I_TOOL_MIRROR = next(), I_TOOL_MOVE_XZ = newRow(),
I_ARM_ROUND_ROBIN = next(), I_ARM_FORCED_ROUND_ROBIN = next(), I_ARM_PREFER_FIRST = next(), 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_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_PLAY = newRow(),
I_HOUR_HAND_FIRST = next(), I_MINUTE_HAND_FIRST = next(), I_HOUR_HAND_FIRST_24 = next(), 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_SOLID = newRow(),
I_PATTERN_CHECKERED = next(),
I_PATTERN_CHECKERED_INVERSED = next(),
I_PATTERN_CHANCE_25 = 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_FOLLOW_MATERIAL = next(),
I_SCHEMATIC = newRow(), 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_LEFT = newRow(),
I_MTD_USER_MODE = next(), I_MTD_SLOW_MODE = next(); 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) { public AllIcons(int x, int y) {
iconX = x * 16; iconX = x * 16;
@ -116,8 +192,12 @@ public class AllIcons implements IScreenRenderable {
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u, public DelegatedStencilElement asStencil() {
float v) { 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) builder.vertex(peek.getModel(), (float) vec.x, (float) vec.y, (float) vec.z)
.color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1) .color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1)
.texture(u, v) .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)); .with(FlowingFluidBlock.LEVEL, 0));
} }
public static abstract class GuiRenderBuilder { public static abstract class GuiRenderBuilder extends RenderElement {
double xBeforeScale, yBeforeScale, zBeforeScale = 0; //double xBeforeScale, yBeforeScale, zBeforeScale = 0;
double x, y, z; double xLocal, yLocal, zLocal;
double xRot, yRot, zRot; double xRot, yRot, zRot;
double scale = 1; double scale = 1;
int color = 0xFFFFFF; int color = 0xFFFFFF;
Vector3d rotationOffset = Vector3d.ZERO; Vector3d rotationOffset = Vector3d.ZERO;
public GuiRenderBuilder atLocal(double x, double y, double z) { public GuiRenderBuilder atLocal(double x, double y, double z) {
this.x = x; this.xLocal = x;
this.y = y; this.yLocal = y;
this.z = z; this.zLocal = z;
return this; return this;
} }
public GuiRenderBuilder at(double x, double y) { /*public GuiRenderBuilder at(double x, double y) {
this.xBeforeScale = x; this.xBeforeScale = x;
this.yBeforeScale = y; this.yBeforeScale = y;
return this; return this;
@ -89,7 +89,7 @@ public class GuiGameElement {
this.yBeforeScale = y; this.yBeforeScale = y;
this.zBeforeScale = z; this.zBeforeScale = z;
return this; return this;
} }*/
public GuiRenderBuilder rotate(double xRot, double yRot, double zRot) { public GuiRenderBuilder rotate(double xRot, double yRot, double zRot) {
this.xRot = xRot; this.xRot = xRot;
@ -136,9 +136,9 @@ public class GuiGameElement {
@Deprecated @Deprecated
protected void transform() { protected void transform() {
RenderSystem.translated(xBeforeScale, yBeforeScale, 0); RenderSystem.translated(x, y, 0);
RenderSystem.scaled(scale, scale, scale); RenderSystem.scaled(scale, scale, scale);
RenderSystem.translated(x, y, z); RenderSystem.translated(xLocal, yLocal, zLocal);
RenderSystem.scaled(1, -1, 1); RenderSystem.scaled(1, -1, 1);
RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z); RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z);
RenderSystem.rotatef((float) zRot, 0, 0, 1); RenderSystem.rotatef((float) zRot, 0, 0, 1);
@ -148,9 +148,9 @@ public class GuiGameElement {
} }
protected void transformMatrix(MatrixStack matrixStack) { protected void transformMatrix(MatrixStack matrixStack) {
matrixStack.translate(xBeforeScale, yBeforeScale, zBeforeScale);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(x, y, z); matrixStack.translate(x, y, z);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(xLocal, yLocal, zLocal);
matrixStack.scale(1, -1, 1); matrixStack.scale(1, -1, 1);
matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z); matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z);
matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion((float) zRot)); 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()) if (screenHistory.isEmpty())
return false; return false;
Screen previouslyRenderedScreen = screenHistory.get(0); Screen previouslyRenderedScreen = screenHistory.get(0);
if (!(previouslyRenderedScreen instanceof AbstractSimiScreen)) if (!(previouslyRenderedScreen instanceof NavigatableSimiScreen))
return false; return false;
if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen)) if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen))
return false; 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; package com.simibubi.create.foundation.gui;
import java.awt.Color;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.MainWindow; import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.shader.Framebuffer; import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
@ -18,6 +24,10 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class UIRenderHelper { public class UIRenderHelper {
public static void enableStencil() {
RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil());
}
public static Framebuffer framebuffer; public static Framebuffer framebuffer;
public static void init() { public static void init() {
@ -27,19 +37,17 @@ public class UIRenderHelper {
framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true, framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true,
Minecraft.IS_RUNNING_ON_MAC); Minecraft.IS_RUNNING_ON_MAC);
framebuffer.setFramebufferColor(0, 0, 0, 0); framebuffer.setFramebufferColor(0, 0, 0, 0);
framebuffer.enableStencil();
// framebuffer.deleteFramebuffer(); // framebuffer.deleteFramebuffer();
}); });
} }
public static void prepFramebufferSize() { /*public static void prepFramebufferSize() {
MainWindow window = Minecraft.getInstance() MainWindow window = Minecraft.getInstance().getWindow();
.getWindow(); if (framebuffer.framebufferWidth != window.getFramebufferWidth() || framebuffer.framebufferHeight != window.getFramebufferHeight()) {
if (framebuffer.framebufferWidth != window.getFramebufferWidth() framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC);
|| framebuffer.framebufferHeight != window.getFramebufferHeight()) {
framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(),
Minecraft.IS_RUNNING_ON_MAC);
}
} }
}*/
public static void drawFramebuffer(float alpha) { public static void drawFramebuffer(float alpha) {
MainWindow window = Minecraft.getInstance() MainWindow window = Minecraft.getInstance()
@ -51,10 +59,6 @@ public class UIRenderHelper {
float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight; float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight;
RenderSystem.enableTexture(); RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.disableLighting();
RenderSystem.disableAlphaTest();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
framebuffer.bindFramebufferTexture(); framebuffer.bindFramebufferTexture();
@ -82,14 +86,14 @@ public class UIRenderHelper {
tessellator.draw(); tessellator.draw();
framebuffer.unbindFramebufferTexture(); 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 // angle in degrees; 0° -> fading to the right
// x and y specify the middle point of the starting edge // x and y specify the middle point of the starting edge
// width is the total width of the streak // breadth 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) { public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, int color) {
int a1 = 0xa0 << 24; int a1 = 0xa0 << 24;
int a2 = 0x80 << 24; int a2 = 0x80 << 24;
int a3 = 0x10 << 24; int a3 = 0x10 << 24;
@ -105,7 +109,7 @@ public class UIRenderHelper {
ms.translate(x, y, 0); ms.translate(x, y, 0);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90)); 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(); ms.pop();
} }
@ -120,9 +124,49 @@ public class UIRenderHelper {
GuiUtils.drawGradientRect(model, 0, -width, (int) (split2 * height), width, height, c3, c4); 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 // 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, public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, int startColor, int endColor) {
int startColor, int endColor) {
matrixStack.push(); matrixStack.push();
matrixStack.translate(x - indent, y, z); matrixStack.translate(x - indent, y, z);
@ -241,4 +285,30 @@ public class UIRenderHelper {
RenderSystem.enableAlphaTest(); RenderSystem.enableAlphaTest();
RenderSystem.enableTexture(); 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.LinkedList;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
@ -11,19 +14,78 @@ import net.minecraft.util.text.StringTextComponent;
public abstract class AbstractSimiWidget extends Widget { public abstract class AbstractSimiWidget extends Widget {
protected List<ITextComponent> toolTip; protected float z;
protected boolean wasHovered = false;
protected List<ITextComponent> toolTip = new LinkedList<>();
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) { protected AbstractSimiWidget() {
super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY); this(0, 0);
toolTip = new LinkedList<>(); }
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() { public List<ITextComponent> getToolTip() {
return toolTip; return toolTip;
} }
public void tick() {}
@Override @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 net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
public class IconButton extends AbstractSimiWidget { public class IconButton extends AbstractSimiWidget {
private AllIcons icon; private AllIcons icon;
@ -18,7 +20,7 @@ public class IconButton extends AbstractSimiWidget {
} }
@Override @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) { if (this.visible) {
this.hovered = this.hovered =
mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; 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; package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
@ -22,7 +24,7 @@ public class Indicator extends AbstractSimiWidget {
} }
@Override @Override
public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks ) { public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks ) {
AllGuiTextures toDraw; AllGuiTextures toDraw;
switch(state) { switch(state) {
case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break; case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break;

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui.widgets; package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@ -69,7 +71,7 @@ public class Label extends AbstractSimiWidget {
} }
@Override @Override
public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
if (!visible) if (!visible)
return; return;
if (text == null || text.getString().isEmpty()) if (text == null || text.getString().isEmpty())

View file

@ -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.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; 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.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.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
@ -80,12 +81,13 @@ public enum AllPackets {
PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER), PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER),
TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER), TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER),
EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::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 // Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT), SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::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_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT), CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::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 org.lwjgl.glfw.GLFW;
import com.mojang.blaze3d.matrix.MatrixStack; 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.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.ScreenOpener; 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.UIRenderHelper;
import com.simibubi.create.foundation.ponder.content.PonderTagScreen; import com.simibubi.create.foundation.ponder.content.PonderTagScreen;
import com.simibubi.create.foundation.ponder.ui.PonderButton; import com.simibubi.create.foundation.ponder.ui.PonderButton;
@ -76,9 +78,9 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
if (screen instanceof PonderTagScreen) if (screen instanceof PonderTagScreen)
icon = ((PonderTagScreen) screen).getTag(); icon = ((PonderTagScreen) screen).getTag();
widgets.add(backTrack = new PonderButton(31, height - 31 - PonderButton.SIZE, () -> { widgets.add(backTrack = new PonderButton(31, height - 31 - 20)
ScreenOpener.openPreviousScreen(this, Optional.empty()); .enableFade(0, 5)
}).fade(0, -1)); .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty())));
backTrack.fade(1); backTrack.fade(1);
if (icon != null) if (icon != null)
@ -97,7 +99,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.push(); ms.push();
ms.translate(0, 0, 500); ms.translate(0, 0, 500);
if (backTrack.isHovered()) { 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())) { if (MathHelper.epsilonEquals(arrowAnimation.getValue(), arrowAnimation.getChaseTarget())) {
arrowAnimation.setValue(1); arrowAnimation.setValue(1);
arrowAnimation.setValue(1);// called twice to also set the previous value to 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 @Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { 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); renderBackground(ms);
return; return;
} }
@ -123,11 +136,11 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
if (lastScreen != null && lastScreen != this && !transition.settled()) { if (lastScreen != null && lastScreen != this && !transition.settled()) {
ms.push();// 1 ms.push();// 1
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
UIRenderHelper.prepFramebufferSize(); //UIRenderHelper.prepFramebufferSize();
ms.push();// 2 ms.push();// 2
ms.translate(0, 0, -1000); ms.translate(0, 0, -1000);
UIRenderHelper.framebuffer.bindFramebuffer(true); UIRenderHelper.framebuffer.bindFramebuffer(true);
lastScreen.render(ms, mouseX, mouseY, 10); lastScreen.render(ms, mouseX, mouseY, partialTicks);
ms.pop();// 2 ms.pop();// 2
// use the buffer texture // use the buffer texture
@ -149,7 +162,12 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.translate(dpx, dpy, 0); ms.translate(dpx, dpy, 0);
ms.scale((float) scale, (float) scale, 1); ms.scale((float) scale, (float) scale, 1);
ms.translate(-dpx, -dpy, 0); ms.translate(-dpx, -dpy, 0);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.disableAlphaTest();
UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue)); UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue));
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
ms.pop();// 1 ms.pop();// 1
} }
@ -158,18 +176,6 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.translate(depthPointX, depthPointY, 0); ms.translate(depthPointX, depthPointY, 0);
ms.scale((float) scale, (float) scale, 1); ms.scale((float) scale, (float) scale, 1);
ms.translate(-depthPointX, -depthPointY, 0); 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 @Override

View file

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

View file

@ -10,6 +10,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock;
import com.simibubi.create.foundation.gui.ScreenOpener; 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.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderRegistry; import com.simibubi.create.foundation.ponder.PonderRegistry;
@ -106,17 +107,17 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
int itemCenterY = (int) (height * itemYmult); int itemCenterY = (int) (height * itemYmult);
for (Item item : items) { for (Item item : items) {
PonderButton button = PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> { .showing(new ItemStack(item))
.withCallback((x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName())) if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return; return;
centerScalingOn(x, y); centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item))); ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
}).showing(new ItemStack(item)); });
button.fade(1); widgets.add(b);
widgets.add(button);
layout.next(); layout.next();
} }
@ -158,8 +159,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(x, y, 0); ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010); 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, 0xffddeeff); textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop(); ms.pop();
} }
@ -170,8 +171,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(x, y, 0); ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220, 0x101010); UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, 0xffddeeff); textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop(); ms.pop();
} }
@ -189,7 +190,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.pop(); ms.pop();
} }
@Override /*@Override
public boolean mouseClicked(double x, double y, int button) { public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false); MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> { widgets.forEach(w -> {
@ -207,7 +208,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
if (handled.booleanValue()) if (handled.booleanValue())
return true; return true;
return super.mouseClicked(x, y, button); return super.mouseClicked(x, y, button);
} }*/
@Override @Override
public boolean isEquivalentTo(NavigatableSimiScreen other) { 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.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.Create; 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.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderLocalization; import com.simibubi.create.foundation.ponder.PonderLocalization;
@ -84,24 +86,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int itemCenterY = getItemsY(); int itemCenterY = getItemsY();
for (Item i : items) { for (Item i : items) {
final boolean canClick = PonderRegistry.all.containsKey(i.getRegistryName()); PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
PonderButton button = .showing(new ItemStack(i));
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (mouseX, mouseY) -> {
if (!canClick) if (PonderRegistry.all.containsKey(i.getRegistryName())) {
return; b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY); centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag)); ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag));
}).showing(new ItemStack(i)); });
if (!canClick) } else {
if (i.getRegistryName() if (i.getRegistryName()
.getNamespace() .getNamespace()
.equals(Create.ID)) .equals(Create.ID))
button.customColors(0x70984500, 0x70692400); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else else
button.customColors(0x505000FF, 0x50300077); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1); widgets.add(b);
widgets.add(button);
layout.next(); layout.next();
} }
@ -109,23 +113,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ResourceLocation registryName = tag.getMainItem() ResourceLocation registryName = tag.getMainItem()
.getItem() .getItem()
.getRegistryName(); .getRegistryName();
final boolean canClick = PonderRegistry.all.containsKey(registryName);
PonderButton button = PonderButton b = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10)
new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> { .showing(tag.getMainItem());
if (!canClick)
return; if (PonderRegistry.all.containsKey(registryName)) {
b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY); centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag)); ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
}).showing(tag.getMainItem()); });
if (!canClick) } else {
if (registryName.getNamespace() if (registryName.getNamespace()
.equals(Create.ID)) .equals(Create.ID))
button.customColors(0x70984500, 0x70692400); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else else
button.customColors(0x505000FF, 0x50300077); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1); widgets.add(b);
widgets.add(button);
} }
// chapters // chapters
@ -187,15 +194,21 @@ public class PonderTagScreen extends NavigatableSimiScreen {
String title = tag.getTitle(); String title = tag.getTitle();
int streakHeight = 35; int streakHeight = 35;
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240, 0x101010); UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240);
PonderUI.renderBox(ms, 21, 21, 30, 30, false); //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; y += 8;
x += 0; x += 0;
ms.translate(x, y, 0); ms.translate(x, y, 0);
ms.translate(0, 0, 5); 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.pop();
ms.push(); ms.push();
@ -214,9 +227,16 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int h = textRenderer.getWordWrappedHeight(desc, w); 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); 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(); ms.pop();
} }
@ -232,16 +252,23 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(x, y, 0); 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); ms.translate(0, 0, 200);
// UIRenderHelper.streak(0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 180, 0x101010); // 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); ms.translate(0,0, -200);
UIRenderHelper.streak(ms, 0, 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, 0x101010); UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75);
ms.pop(); ms.pop();
@ -261,8 +288,8 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(chapterX, chapterY, 0); ms.translate(chapterX, chapterY, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010); 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, 0xffddeeff); textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
ms.pop(); ms.pop();
} }
@ -291,7 +318,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
return hoveredItem; return hoveredItem;
} }
@Override /*@Override
public boolean mouseClicked(double x, double y, int button) { public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false); MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> { widgets.forEach(w -> {
@ -310,7 +337,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
if (handled.booleanValue()) if (handled.booleanValue())
return true; return true;
return super.mouseClicked(x, y, button); return super.mouseClicked(x, y, button);
} }*/
@Override @Override
public boolean isEquivalentTo(NavigatableSimiScreen other) { public boolean isEquivalentTo(NavigatableSimiScreen other) {

View file

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

View file

@ -4,6 +4,8 @@ import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.mojang.blaze3d.matrix.MatrixStack; 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.PonderLocalization;
import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.PonderUI;
@ -110,7 +112,14 @@ public class TextWindowElement extends AnimatedOverlayElement {
ms.push(); ms.push();
ms.translate(0, sceneToScreen.y, 400); 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); int brighterColor = ColorHelper.mixAlphaColors(color, 0xFFffffdd, 1 / 2f);
if (vec != null) { if (vec != null) {

View file

@ -5,6 +5,7 @@ import java.util.function.BiConsumer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; 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.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.content.PonderChapter; 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) { public ChapterLabel(PonderChapter chapter, int x, int y, BiConsumer<Integer, Integer> onClick) {
super(x, y, 175, 38); super(x, y, 175, 38);
this.button = new PonderButton(x + 4, y + 4, onClick, 30, 30).showing(chapter); this.button = new PonderButton(x + 4, y + 4, 30, 30)
this.button.fade(1); .showing(chapter)
.withCallback(onClick);
this.chapter = chapter; this.chapter = chapter;
} }
@Override @Override
public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { 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, 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); button.renderButton(ms, mouseX, mouseY, partialTicks);
super.render(ms, mouseX, mouseY, partialTicks); super.render(ms, mouseX, mouseY, partialTicks);

View file

@ -1,175 +1,105 @@
package com.simibubi.create.foundation.ponder.ui; 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.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.ponder.PonderUI; 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.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
public class PonderButton extends AbstractSimiWidget { public class PonderButton extends BoxWidget {
private IScreenRenderable icon; protected ItemStack item;
private ItemStack item; protected KeyBinding shortcut;
protected boolean pressed; protected LerpedFloat flash = LerpedFloat.linear().startWithValue(0).chase(0, 0.1f, LerpedFloat.Chaser.EXP);
private BiConsumer<Integer, Integer> onClick;
private int xFadeModifier;
private int yFadeModifier;
private float fade;
private KeyBinding shortcut;
private LerpedFloat flash;
private Couple<Integer> customPassiveBorder;
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); super(x, y, width, height);
this.onClick = onClick; z = 400;
flash = LerpedFloat.linear() paddingX = 2;
.startWithValue(0); paddingY = 2;
} }
public PonderButton(int x, int y, BiConsumer<Integer, Integer> onClick) { public <T extends PonderButton> T withShortcut(KeyBinding key) {
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) {
this.shortcut = key; this.shortcut = key;
return this; //noinspection unchecked
return (T) this;
} }
public PonderButton fade(int xModifier, int yModifier) { public <T extends PonderButton> T showing(ItemStack item) {
this.xFadeModifier = xModifier; this.item = item;
this.yFadeModifier = yModifier; return super.showingElement(GuiGameElement.of(item)
return this; .scale(1.5f)
.at(-4, -4));
} }
public void fade(float fade) { @Override
this.fade = fade; public <T extends ElementWidget> T showingElement(RenderElement element) {
return super.showingElement(element);
} }
public void flash() { public void flash() {
float value = flash.getValue(); flash.updateChaseTarget(1);
flash.setValue(value + (1 - value) * .2f);
} }
public void dim() { public void dim() {
float value = flash.getValue(); flash.updateChaseTarget(0);
flash.setValue(value * .5f);
} }
@Override @Override
public void renderButton(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { public void tick() {
if (!visible) super.tick();
return; flash.tickChaser();
if (fade < .1f) }
return;
hovered = isMouseOver(mouseX, mouseY) && fade > .75f; @Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
ms.push(); super.beforeRender(ms, mouseX, mouseY, partialTicks);
RenderSystem.disableDepthTest();
if (fade < 1)
ms.translate((1 - fade) * -5 * xFadeModifier, (1 - fade) * -5 * yFadeModifier, 0);
float flashValue = flash.getValue(partialTicks); float flashValue = flash.getValue(partialTicks);
if (flashValue > .1f) if (flashValue > .1f) {
fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6); float sin = 0.5f + 0.5f * MathHelper.sin((AnimationTickHolder.getTicks(true) + partialTicks) / 6f);
sin *= flashValue;
int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade); Color c1 = gradientColor1;
int borderColorStart = customPassiveBorder != null ? customPassiveBorder.getFirst() : hovered ? 0x70ffffff : 0x40aa9999; Color c2 = gradientColor2;
int borderColorEnd = customPassiveBorder != null ? customPassiveBorder.getSecond() : hovered ? 0x30ffffff : 0x20aa9999; Color nc1 = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), MathHelper.clamp(c1.getAlpha() + 50, 0, 255));
borderColorStart = ColorHelper.applyAlpha(borderColorStart, fade); Color nc2 = new Color(c2.getRed(), c2.getGreen(), c2.getBlue(), MathHelper.clamp(c2.getAlpha() + 50, 0, 255));
borderColorEnd = ColorHelper.applyAlpha(borderColorEnd, fade); gradientColor1 = ColorHelper.mixColors(c1, nc1, sin);
gradientColor2 = ColorHelper.mixColors(c2, nc2, sin);
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 (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 @Override
public void onClick(double p_onClick_1_, double p_onClick_3_) { public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.onClick(p_onClick_1_, p_onClick_3_); super.renderButton(ms, mouseX, mouseY, partialTicks);
this.pressed = true; float fadeValue = fade.getValue();
}
@Override if (fadeValue < .1f)
public void onRelease(double p_onRelease_1_, double p_onRelease_3_) { return;
super.onRelease(p_onRelease_1_, p_onRelease_3_);
this.pressed = false;
}
/*public void setToolTip(String text) { if (shortcut != null) {
toolTip.clear(); ms.translate(0, 0, z+50);
toolTip.add(text); 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() { public ItemStack getItem() {
return item; 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 { public class AnimationTickHolder {
private static int ticks; private static int ticks;
private static int paused_ticks;
public static void reset() { public static void reset() {
ticks = 0; ticks = 0;
paused_ticks = 0;
} }
public static void tick() { public static void tick() {
if (!Minecraft.getInstance() if (!Minecraft.getInstance()
.isGamePaused()) { .isGamePaused()) {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision 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() { 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() { public static float getRenderTime() {

View file

@ -1,7 +1,10 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import java.awt.Color;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -39,6 +42,10 @@ public class ColorHelper {
return (color & 0xFFFFFF) | alphaChannel << 24; 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) { public static int mixColors(int color1, int color2, float w) {
int r1 = (color1 >> 16); int r1 = (color1 >> 16);
int g1 = (color1 >> 8) & 0xFF; int g1 = (color1 >> 8) & 0xFF;
@ -52,6 +59,23 @@ public class ColorHelper {
return color; return color;
} }
@Nonnull
public static Color mixColors(@Nonnull Color c1, @Nonnull Color c2, float w) {
float[] cmp1 = c1.getRGBComponents(null);
float[] cmp2 = c2.getRGBComponents(null);
return new Color(
cmp1[0] + (cmp2[0] - cmp1[0]) * w,
cmp1[1] + (cmp2[1] - cmp1[1]) * w,
cmp1[2] + (cmp2[2] - cmp1[2]) * w,
cmp1[3] + (cmp2[3] - cmp1[3]) * w
);
}
@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) { public static int mixAlphaColors(int color1, int color2, float w) {
int a1 = (color1 >> 24); int a1 = (color1 >> 24);
int r1 = (color1 >> 16) & 0xFF; int r1 = (color1 >> 16) & 0xFF;

View file

@ -81,4 +81,22 @@ public interface Force {
return timeRemaining <= 0; 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

@ -5,16 +5,17 @@
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_8",
"refmap": "create.refmap.json", "refmap": "create.refmap.json",
"client": [ "client": [
"TileWorldHookMixin",
"CancelTileEntityRenderMixin", "CancelTileEntityRenderMixin",
"EntityContraptionInteractionMixin",
"FogColorTrackerMixin", "FogColorTrackerMixin",
"LightUpdateMixin", "LightUpdateMixin",
"NetworkLightUpdateMixin", "NetworkLightUpdateMixin",
"RenderHooksMixin", "RenderHooksMixin",
"ShaderCloseMixin", "ShaderCloseMixin",
"StoreProjectionMatrixMixin",
"TileRemoveMixin", "TileRemoveMixin",
"EntityContraptionInteractionMixin", "TileWorldHookMixin",
"StoreProjectionMatrixMixin" "WindowResizeMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1