From fbf63125647bbefd66842308fe90fa8a35901665 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Sun, 6 Oct 2024 00:01:01 -0400 Subject: [PATCH 01/17] gui, can load backgrounds from files in config/terminal/backgrounds extracting from the jar -> config/terminal has not yet been reimplemented --- .../java/gregtech/api/mui/GTGuiTextures.java | 2 + .../gregtech/api/terminal2/Terminal2.java | 22 ++++ .../api/terminal2/Terminal2Settings.java | 32 ++++++ .../java/gregtech/common/items/MetaItem1.java | 2 + .../items/behaviors/Terminal2Behavior.java | 96 ++++++++++++++++++ .../common/mui/widget/FileTexture.java | 82 +++++++++++++++ .../wallpaper_Kumquat.png | Bin .../wallpaper_Zalgo.png | Bin .../wallpaper_celeryman.png | Bin .../{image => backgrounds}/wallpaper_moth.png | Bin .../textures/gui/terminal/terminal_frame.png | Bin 0 -> 14246 bytes 11 files changed, 236 insertions(+) create mode 100644 src/main/java/gregtech/api/terminal2/Terminal2.java create mode 100644 src/main/java/gregtech/api/terminal2/Terminal2Settings.java create mode 100644 src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java create mode 100644 src/main/java/gregtech/common/mui/widget/FileTexture.java rename src/main/resources/assets/gregtech/terminal/{image => backgrounds}/wallpaper_Kumquat.png (100%) rename src/main/resources/assets/gregtech/terminal/{image => backgrounds}/wallpaper_Zalgo.png (100%) rename src/main/resources/assets/gregtech/terminal/{image => backgrounds}/wallpaper_celeryman.png (100%) rename src/main/resources/assets/gregtech/terminal/{image => backgrounds}/wallpaper_moth.png (100%) create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index 998ad9c1d03..adebcb6d46b 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -290,6 +290,8 @@ private static String id(String path) { public static final UITexture FLUID_LOCK_OVERLAY = fullImage("textures/gui/widget/button_lock.png", ColorType.DEFAULT); + public static final UITexture TERMINAL_FRAME = fullImage("textures/gui/terminal/terminal_frame.png"); + // todo bronze/steel/primitive fluid slots? // SLOT OVERLAYS diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java new file mode 100644 index 00000000000..cd2b4d93eb9 --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -0,0 +1,22 @@ +package gregtech.api.terminal2; + +import gregtech.common.ConfigHolder; + +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.io.File; + +public class Terminal2 { + + @SideOnly(Side.CLIENT) + public static File TERMINAL_PATH; + + static { + if (FMLCommonHandler.instance().getSide().isClient()) { + TERMINAL_PATH = new File(Loader.instance().getConfigDir(), ConfigHolder.client.terminalRootPath); + } + } +} diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Settings.java b/src/main/java/gregtech/api/terminal2/Terminal2Settings.java new file mode 100644 index 00000000000..3ee2ef3b33c --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/Terminal2Settings.java @@ -0,0 +1,32 @@ +package gregtech.api.terminal2; + +import gregtech.api.util.GTUtility; +import gregtech.common.mui.widget.FileTexture; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.drawable.UITexture; + +import java.io.File; + +public class Terminal2Settings { + + private static String currentBackground = null; + public static File backgroundsDir = new File(Terminal2.TERMINAL_PATH, "backgrounds"); + private static final UITexture defaultBackground = UITexture + .fullImage(GTUtility.gregtechId("textures/gui/terminal/terminal_background.png")); + + public static IDrawable getBackgroundDrawable() { + if (currentBackground == null) { + return defaultBackground; + } + return new FileTexture(new File(backgroundsDir, currentBackground)); + } + + public static void setBackground(String file) { + if (file.equals("default")) { + currentBackground = null; + } else { + currentBackground = file; + } + } +} diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index b528f3c1041..bfe4ce48567 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -48,6 +48,7 @@ import gregtech.common.items.behaviors.MultiblockBuilderBehavior; import gregtech.common.items.behaviors.NanoSaberBehavior; import gregtech.common.items.behaviors.ProspectorScannerBehavior; +import gregtech.common.items.behaviors.Terminal2Behavior; import gregtech.common.items.behaviors.TooltipBehavior; import gregtech.common.items.behaviors.TricorderBehavior; import gregtech.common.items.behaviors.TurbineRotorBehavior; @@ -832,6 +833,7 @@ public void registerSubItems() { .setMaxStackSize(1) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); TERMINAL = addItem(465, "terminal") + .addComponents(new Terminal2Behavior()) .setMaxStackSize(1) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); PROSPECTOR_LV = addItem(466, "prospector.lv") diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java new file mode 100644 index 00000000000..98be73b934f --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -0,0 +1,96 @@ +package gregtech.common.items.behaviors; + +import gregtech.api.items.gui.ItemUIFactory; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; +import gregtech.api.mui.factory.MetaItemGuiFactory; +import gregtech.api.terminal2.Terminal2Settings; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.PanelSyncHandler; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.ListWidget; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +public class Terminal2Behavior implements IItemBehaviour, ItemUIFactory { + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack heldItem = player.getHeldItem(hand); + if (!world.isRemote) { + MetaItemGuiFactory.open(player, hand); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + } + + @Override + public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { + var backgroundSelectPanel = (PanelSyncHandler) guiSyncManager.panel("terminal_background_select", + backgroundSelectWidget(), true); + return GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248) + .background(GTGuiTextures.TERMINAL_FRAME) + .child(new DynamicDrawable(Terminal2Settings::getBackgroundDrawable).asWidget().size(340, 240).pos(4, + 4)) + .child(new ButtonWidget<>() + .overlay(GuiTextures.GEAR) + // TODO lang + .addTooltipLine("Change Background") + .posRel(0.1F, 0.1F) + .onMousePressed(i -> { + if (backgroundSelectPanel.isPanelOpen()) { + backgroundSelectPanel.closePanel(); + } else { + backgroundSelectPanel.openPanel(); + } + return true; + })); + } + + private PanelSyncHandler.IPanelBuilder backgroundSelectWidget() { + return (syncManager, syncHandler) -> { + String[] files = Terminal2Settings.backgroundsDir.list(); + List options; + if (files == null) { + options = new ArrayList<>(); + } else { + options = new ArrayList<>(Arrays.asList(files)); + } + options.sort(Comparator.naturalOrder()); + options.add(0, "default"); + + var list = ListWidget.builder(options, (st) -> new ButtonWidget<>() + .overlay(IKey.str(st)) + .size(140, 18) + .leftRel(0.2F) + .onMousePressed(i -> { + Terminal2Settings.setBackground(st); + return true; + })) + .size(150, 90).pos(9, 16); + + return GTGuis.createPopupPanel("terminal_background_select", 168, 112) + // TODO lang + .child(IKey.str("Background Select").asWidget() + .leftRel(0.5F) + .top(6)) + .child(list); + }; + } +} diff --git a/src/main/java/gregtech/common/mui/widget/FileTexture.java b/src/main/java/gregtech/common/mui/widget/FileTexture.java new file mode 100644 index 00000000000..93a6c520ee7 --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/FileTexture.java @@ -0,0 +1,82 @@ +package gregtech.common.mui.widget; + +import gregtech.api.util.GTLog; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.TextureUtil; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.drawable.GuiDraw; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.ImageIO; + +public class FileTexture implements IDrawable { + + private static final Map pathLookup = new HashMap<>(); + private int texID; + + public FileTexture(File file) { + String fullPath = file.getAbsolutePath(); + if (pathLookup.containsKey(fullPath)) { + texID = pathLookup.get(fullPath); + return; + } + + try { + BufferedImage image = ImageIO.read(file); + if (image == null) { + throw new IOException("Read null image from " + file.getName()); + } + int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth()); + ByteBuffer buffer = ByteBuffer.allocateDirect(pixels.length * 4); + for (int pixel : pixels) { + buffer.put((byte) ((pixel >> 16) & 0xFF)); + buffer.put((byte) ((pixel >> 8) & 0xFF)); + buffer.put((byte) (pixel & 0xFF)); + buffer.put((byte) ((pixel >> 24) & 0xFF)); + } + buffer.flip(); + + int texID = GL11.glGenTextures(); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, + GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); + + this.texID = texID; + pathLookup.put(fullPath, texID); + } catch (IOException e) { + GTLog.logger.error("Could not create FileTexture for {}", file.getName(), e); + this.texID = TextureUtil.MISSING_TEXTURE.getGlTextureId(); + pathLookup.put(fullPath, this.texID); + } + } + + @Override + public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { + GlStateManager.disableAlpha(); + GlStateManager.enableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.bindTexture(texID); + GuiDraw.drawTexture(x, y, 0, 0, width, height, width, height); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + } +} diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_Kumquat.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Kumquat.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_Kumquat.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Kumquat.png diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_Zalgo.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Zalgo.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_Zalgo.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Zalgo.png diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_celeryman.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_celeryman.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_celeryman.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_celeryman.png diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_moth.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_moth.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_moth.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_moth.png diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png b/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png new file mode 100644 index 0000000000000000000000000000000000000000..ae470d611ec28b184f586b6b5b824ff55a0fa0b5 GIT binary patch literal 14246 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 c#4wNgUtb~Dco(1`)!A~M2df;xWx3yX-7JOBUy literal 0 HcmV?d00001 From 6c80ece92e3218b8b0d6afdb540a8e4aeb106c87 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:09:41 -0400 Subject: [PATCH 02/17] app framework, settings app --- .../java/gregtech/api/mui/GTGuiTextures.java | 2 + .../java/gregtech/api/mui/GTGuiTheme.java | 5 + .../gregtech/api/terminal2/ITerminalApp.java | 17 ++ .../gregtech/api/terminal2/Terminal2.java | 31 ++- .../api/terminal2/Terminal2Settings.java | 32 --- .../api/terminal2/Terminal2Theme.java | 126 ++++++++++ .../items/behaviors/Terminal2Behavior.java | 90 +++---- .../mui/{widget => drawable}/FileTexture.java | 2 +- .../mui/widget/GTColorPickerDialog.java | 213 ++++++++++++++++ .../gregtech/common/terminal2/HomeApp.java | 45 ++++ .../common/terminal2/SettingsApp.java | 146 +++++++++++ .../gregtech/common/terminal2/TestApp.java | 17 ++ src/main/java/gregtech/core/CoreModule.java | 3 + .../resources/assets/gregtech/lang/en_us.lang | 231 ++---------------- .../gregtech/terminal/config/theme.json | 1 - .../textures/gui/terminal/home_button.png | Bin 0 -> 10056 bytes .../gui/terminal/home_button_hover.png | Bin 0 -> 10057 bytes .../textures/gui/terminal/terminal_frame.png | Bin 14246 -> 12682 bytes 18 files changed, 654 insertions(+), 307 deletions(-) create mode 100644 src/main/java/gregtech/api/terminal2/ITerminalApp.java delete mode 100644 src/main/java/gregtech/api/terminal2/Terminal2Settings.java create mode 100644 src/main/java/gregtech/api/terminal2/Terminal2Theme.java rename src/main/java/gregtech/common/mui/{widget => drawable}/FileTexture.java (98%) create mode 100644 src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java create mode 100644 src/main/java/gregtech/common/terminal2/HomeApp.java create mode 100644 src/main/java/gregtech/common/terminal2/SettingsApp.java create mode 100644 src/main/java/gregtech/common/terminal2/TestApp.java delete mode 100644 src/main/resources/assets/gregtech/terminal/config/theme.json create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/home_button.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/home_button_hover.png diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index adebcb6d46b..499166b5c66 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -291,6 +291,8 @@ private static String id(String path) { ColorType.DEFAULT); public static final UITexture TERMINAL_FRAME = fullImage("textures/gui/terminal/terminal_frame.png"); + public static final UITexture HOME_BUTTON = fullImage("textures/gui/terminal/home_button.png"); + public static final UITexture HOME_BUTTON_HOVER = fullImage("textures/gui/terminal/home_button_hover.png"); // todo bronze/steel/primitive fluid slots? diff --git a/src/main/java/gregtech/api/mui/GTGuiTheme.java b/src/main/java/gregtech/api/mui/GTGuiTheme.java index 01b5084ec2c..429dff24c73 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTheme.java +++ b/src/main/java/gregtech/api/mui/GTGuiTheme.java @@ -99,6 +99,11 @@ private static String gregtech(String s) { .itemSlot(GTGuiTextures.IDs.PRIMITIVE_SLOT) .build(); + public static final GTGuiTheme TERMINAL = templateBuilder("gregtech_terminal") + .parent("gregtech_standard") + .textColor(0xFFFDFDFD) + .build(); + protected final String themeId; protected final List> elementBuilder; diff --git a/src/main/java/gregtech/api/terminal2/ITerminalApp.java b/src/main/java/gregtech/api/terminal2/ITerminalApp.java new file mode 100644 index 00000000000..1fb40d6e216 --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/ITerminalApp.java @@ -0,0 +1,17 @@ +package gregtech.api.terminal2; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; + +public interface ITerminalApp { + + IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel); + + default IDrawable getIcon() { + return GuiTextures.IMAGE; + } +} diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java index cd2b4d93eb9..9684684f70a 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -1,22 +1,51 @@ package gregtech.api.terminal2; +import gregtech.api.util.FileUtility; +import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; +import gregtech.common.terminal2.HomeApp; +import gregtech.common.terminal2.SettingsApp; +import gregtech.common.terminal2.TestApp; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class Terminal2 { + // we want both ordered id -> int and unordered id -> app + // todo this could probably be a better data structure + public static final List idList = new ArrayList<>(); + public static final Map appMap = new HashMap<>(); + public static final ResourceLocation HOME_ID = GTUtility.gregtechId("home"); + @SideOnly(Side.CLIENT) public static File TERMINAL_PATH; - static { + public static void init() { if (FMLCommonHandler.instance().getSide().isClient()) { TERMINAL_PATH = new File(Loader.instance().getConfigDir(), ConfigHolder.client.terminalRootPath); + FileUtility.extractJarFiles("/assets/gregtech/terminal", TERMINAL_PATH, false); + Terminal2Theme.init(); + } + registerApp(HOME_ID, new HomeApp()); + registerApp(GTUtility.gregtechId("settings"), new SettingsApp()); + registerApp(GTUtility.gregtechId("test"), new TestApp()); + } + + public static void registerApp(ResourceLocation id, ITerminalApp app) { + if (idList.contains(id)) { + throw new AssertionError("A terminal app with id " + id + " already exists!"); } + idList.add(id); + appMap.put(id, app); } } diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Settings.java b/src/main/java/gregtech/api/terminal2/Terminal2Settings.java deleted file mode 100644 index 3ee2ef3b33c..00000000000 --- a/src/main/java/gregtech/api/terminal2/Terminal2Settings.java +++ /dev/null @@ -1,32 +0,0 @@ -package gregtech.api.terminal2; - -import gregtech.api.util.GTUtility; -import gregtech.common.mui.widget.FileTexture; - -import com.cleanroommc.modularui.api.drawable.IDrawable; -import com.cleanroommc.modularui.drawable.UITexture; - -import java.io.File; - -public class Terminal2Settings { - - private static String currentBackground = null; - public static File backgroundsDir = new File(Terminal2.TERMINAL_PATH, "backgrounds"); - private static final UITexture defaultBackground = UITexture - .fullImage(GTUtility.gregtechId("textures/gui/terminal/terminal_background.png")); - - public static IDrawable getBackgroundDrawable() { - if (currentBackground == null) { - return defaultBackground; - } - return new FileTexture(new File(backgroundsDir, currentBackground)); - } - - public static void setBackground(String file) { - if (file.equals("default")) { - currentBackground = null; - } else { - currentBackground = file; - } - } -} diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java new file mode 100644 index 00000000000..1a32d026597 --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -0,0 +1,126 @@ +package gregtech.api.terminal2; + +import gregtech.api.util.FileUtility; +import gregtech.api.util.GTUtility; +import gregtech.common.mui.drawable.FileTexture; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.drawable.UITexture; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import java.awt.Color; +import java.io.File; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@SuppressWarnings("unused") +public class Terminal2Theme { + + private static final String CONFIG_PATH = "config/theme.json"; + private static IDrawable currentBackgroundDrawable = null; + private static final UITexture defaultBackground = UITexture + .fullImage(GTUtility.gregtechId("textures/gui/terminal/terminal_background.png")); + public static File backgroundsDir; + private static final Map defaultColors = new Object2IntOpenHashMap<>(); + + public static String currentBackground = "default"; + // theres enough colors here to make specifying stuff for all of them annoying + // therefore, we use reflection for its intended purpose + public static final List colors = Arrays.stream(Terminal2Theme.class.getFields()) + .map(Field::getName).filter(name -> name.startsWith("COLOR_")).collect(Collectors.toList()); + + public static Rectangle COLOR_BRIGHT_1 = new Rectangle().setColor(new Color(144, 243, 116).getRGB()); + public static Rectangle COLOR_BRIGHT_2 = new Rectangle().setColor(new Color(243, 208, 116).getRGB()); + public static Rectangle COLOR_BRIGHT_3 = new Rectangle().setColor(new Color(231, 95, 95).getRGB()); + public static Rectangle COLOR_BRIGHT_4 = new Rectangle().setColor(new Color(230, 230, 230).getRGB()); + + public static Rectangle COLOR_DARK_1 = new Rectangle().setColor(new Color(0, 115, 255).getRGB()); + public static Rectangle COLOR_DARK_2 = new Rectangle().setColor(new Color(113, 27, 217).getRGB()); + public static Rectangle COLOR_DARK_3 = new Rectangle().setColor(new Color(30, 80, 30).getRGB()); + public static Rectangle COLOR_DARK_4 = new Rectangle().setColor(new Color(30, 30, 30).getRGB()); + + public static Rectangle COLOR_FOREGROUND_BRIGHT = new Rectangle().setColor(new Color(148, 226, 193).getRGB()); + public static Rectangle COLOR_FOREGROUND_DARK = new Rectangle().setColor(new Color(175, 0, 0, 131).getRGB()); + + public static Rectangle COLOR_BACKGROUND_1 = new Rectangle().setColor(new Color(0, 0, 0, 80).getRGB()); + public static Rectangle COLOR_BACKGROUND_2 = new Rectangle().setColor(new Color(0, 0, 0, 160).getRGB()); + public static Rectangle COLOR_BACKGROUND_3 = new Rectangle().setColor(new Color(246, 120, 120, 160).getRGB()); + + public static void init() { + backgroundsDir = new File(Terminal2.TERMINAL_PATH, "backgrounds"); + + JsonElement element = FileUtility.loadJson(new File(Terminal2.TERMINAL_PATH, CONFIG_PATH)); + if (element == null || !element.isJsonObject()) { + saveConfig(); + return; + } + + JsonObject config = element.getAsJsonObject(); + + for (String color : colors) { + defaultColors.put(color, getColorRect(color).getColor()); + if (config.has(color)) { + setColor(color, config.get(color).getAsInt()); + } + } + + if (config.has("BACKGROUND_FILE")) { + setBackground(config.get("BACKGROUND_FILE").getAsString()); + } + } + + public static boolean saveConfig() { + JsonObject config = new JsonObject(); + + for (String color : colors) { + config.addProperty(color, getColorRect(color).getColor()); + } + + config.addProperty("BACKGROUND_FILE", currentBackground); + + return FileUtility.saveJson(new File(Terminal2.TERMINAL_PATH, CONFIG_PATH), config); + } + + public static IDrawable getBackgroundDrawable() { + // noinspection ReplaceNullCheck + if (currentBackgroundDrawable == null) { + return defaultBackground; + } + return currentBackgroundDrawable; + } + + public static void setBackground(String file) { + currentBackground = file; + if (file.equals("default")) { + currentBackgroundDrawable = null; + } else { + currentBackgroundDrawable = new FileTexture(new File(backgroundsDir, file)); + } + } + + public static Rectangle getColorRect(String color) { + try { + return (Rectangle) Terminal2Theme.class.getField(color).get(null); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException("Failed to get color rect " + color, e); + } + } + + public static void setColor(String color, int i) { + try { + ((Rectangle) Terminal2Theme.class.getField(color).get(null)).setColor(i); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException("Failed to set color " + color + " to " + i, e); + } + } + + public static void resetToDefaultColor(String color) { + setColor(color, defaultColors.get(color)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index 98be73b934f..5209c19abe9 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -3,31 +3,29 @@ import gregtech.api.items.gui.ItemUIFactory; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuiTheme; import gregtech.api.mui.GTGuis; import gregtech.api.mui.factory.MetaItemGuiFactory; -import gregtech.api.terminal2.Terminal2Settings; +import gregtech.api.terminal2.Terminal2; +import gregtech.api.terminal2.Terminal2Theme; +import gregtech.common.terminal2.HomeApp; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; +import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.drawable.DynamicDrawable; -import com.cleanroommc.modularui.drawable.GuiTextures; import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; -import com.cleanroommc.modularui.value.sync.PanelSyncHandler; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widgets.ButtonWidget; -import com.cleanroommc.modularui.widgets.ListWidget; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; +import com.cleanroommc.modularui.widgets.PagedWidget; public class Terminal2Behavior implements IItemBehaviour, ItemUIFactory { @@ -40,57 +38,39 @@ public ActionResult onItemRightClick(World world, EntityPlayer player return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); } + @Override + public GTGuiTheme getUITheme() { + return GTGuiTheme.TERMINAL; + } + @Override public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { - var backgroundSelectPanel = (PanelSyncHandler) guiSyncManager.panel("terminal_background_select", - backgroundSelectWidget(), true); - return GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248) - .background(GTGuiTextures.TERMINAL_FRAME) - .child(new DynamicDrawable(Terminal2Settings::getBackgroundDrawable).asWidget().size(340, 240).pos(4, - 4)) + ModularPanel panel = GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248); + PagedWidget appPages = new PagedWidget<>(); + ((HomeApp) Terminal2.appMap.get(Terminal2.HOME_ID)).setPageWidget(appPages); + for (ResourceLocation appID : Terminal2.idList) { + appPages.addPage(Terminal2.appMap.get(appID).buildWidgets(guiData, guiSyncManager, panel)); + } + appPages.setPage(Terminal2.idList.indexOf(Terminal2.HOME_ID)); + appPages.size(340, 240).pos(4, 4); + + return panel.background(GTGuiTextures.TERMINAL_FRAME) + .child(new DynamicDrawable(Terminal2Theme::getBackgroundDrawable).asWidget() + .size(340, 240) + .pos(4, 4)) + .child(appPages) .child(new ButtonWidget<>() - .overlay(GuiTextures.GEAR) - // TODO lang - .addTooltipLine("Change Background") - .posRel(0.1F, 0.1F) + .overlay(GTGuiTextures.HOME_BUTTON) + .hoverOverlay(GTGuiTextures.HOME_BUTTON_HOVER) + .background(IDrawable.NONE) + .disableHoverBackground() + .addTooltipLine(IKey.lang("terminal.app.gregtech.home.name")) + .size(16, 16) + .left(346) + .topRelAnchor(0.5F, 0.5F) .onMousePressed(i -> { - if (backgroundSelectPanel.isPanelOpen()) { - backgroundSelectPanel.closePanel(); - } else { - backgroundSelectPanel.openPanel(); - } + appPages.setPage(Terminal2.idList.indexOf(Terminal2.HOME_ID)); return true; })); } - - private PanelSyncHandler.IPanelBuilder backgroundSelectWidget() { - return (syncManager, syncHandler) -> { - String[] files = Terminal2Settings.backgroundsDir.list(); - List options; - if (files == null) { - options = new ArrayList<>(); - } else { - options = new ArrayList<>(Arrays.asList(files)); - } - options.sort(Comparator.naturalOrder()); - options.add(0, "default"); - - var list = ListWidget.builder(options, (st) -> new ButtonWidget<>() - .overlay(IKey.str(st)) - .size(140, 18) - .leftRel(0.2F) - .onMousePressed(i -> { - Terminal2Settings.setBackground(st); - return true; - })) - .size(150, 90).pos(9, 16); - - return GTGuis.createPopupPanel("terminal_background_select", 168, 112) - // TODO lang - .child(IKey.str("Background Select").asWidget() - .leftRel(0.5F) - .top(6)) - .child(list); - }; - } } diff --git a/src/main/java/gregtech/common/mui/widget/FileTexture.java b/src/main/java/gregtech/common/mui/drawable/FileTexture.java similarity index 98% rename from src/main/java/gregtech/common/mui/widget/FileTexture.java rename to src/main/java/gregtech/common/mui/drawable/FileTexture.java index 93a6c520ee7..4f3d6221ea9 100644 --- a/src/main/java/gregtech/common/mui/widget/FileTexture.java +++ b/src/main/java/gregtech/common/mui/drawable/FileTexture.java @@ -1,4 +1,4 @@ -package gregtech.common.mui.widget; +package gregtech.common.mui.drawable; import gregtech.api.util.GTLog; diff --git a/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java new file mode 100644 index 00000000000..3b7b5d6c4e3 --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java @@ -0,0 +1,213 @@ +package gregtech.common.mui.widget; + +import gregtech.api.mui.GTGuiTextures; + +import com.cleanroommc.modularui.api.GuiAxis; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.drawable.HueBar; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.DoubleValue; +import com.cleanroommc.modularui.value.StringValue; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.Dialog; +import com.cleanroommc.modularui.widgets.PageButton; +import com.cleanroommc.modularui.widgets.PagedWidget; +import com.cleanroommc.modularui.widgets.SliderWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; + +import java.util.function.Consumer; + +// TODO remove this class when MUI2 page buttons stop having inverted backgrounds and MUI2 color picker obeys theming +// for its page buttons +public class GTColorPickerDialog extends Dialog { + + private static final IDrawable handleBackground = new Rectangle().setColor(Color.WHITE.main); + + private int color; + private final int alpha; + private final boolean controlAlpha; + + private final Rectangle preview = new Rectangle(); + private final Rectangle sliderBackgroundR = new Rectangle(); + private final Rectangle sliderBackgroundG = new Rectangle(); + private final Rectangle sliderBackgroundB = new Rectangle(); + private final Rectangle sliderBackgroundA = new Rectangle(); + private final Rectangle sliderBackgroundS = new Rectangle(); + private final Rectangle sliderBackgroundV = new Rectangle(); + + public GTColorPickerDialog(Consumer resultConsumer, int startColor, boolean controlAlpha) { + this("color_picker", resultConsumer, startColor, controlAlpha); + } + + public GTColorPickerDialog(String name, Consumer resultConsumer, int startColor, boolean controlAlpha) { + super(name, resultConsumer); + this.alpha = Color.getAlpha(startColor); + updateColor(startColor); + this.controlAlpha = controlAlpha; + size(140, controlAlpha ? 106 : 94).background(GuiTextures.MC_BACKGROUND); + IWidget alphaSlider = controlAlpha ? new Row() + .widthRel(1f).height(12) + .child(IKey.str("A: ").asWidget().heightRel(1f)) + .child(createSlider(this.sliderBackgroundA) + .bounds(0, 255) + .value(new DoubleValue.Dynamic(() -> Color.getAlpha(this.color), + val -> updateColor(Color.withAlpha(this.color, (int) val))))) : + null; + + PagedWidget.Controller controller = new PagedWidget.Controller(); + child(new Column() + .left(5).right(5).top(5).bottom(5) + .child(new Row() + .left(5).right(5).height(14) + .child(new PageButton(0, controller) + .sizeRel(0.5f, 1f) + .background(true, GTGuiTextures.SLOT) + .background(false, GTGuiTextures.BUTTON) + .overlay(IKey.str("RGB"))) + .child(new PageButton(1, controller) + .sizeRel(0.5f, 1f) + .background(true, GTGuiTextures.SLOT) + .background(false, GTGuiTextures.BUTTON) + .overlay(IKey.str("HSV")))) + .child(new Row().widthRel(1f).height(12).marginTop(4) + .child(IKey.str("Hex: ").asWidget().heightRel(1f)) + .child(new TextFieldWidget() + .height(12) + .expanded() + .setValidator(this::validateRawColor) + .value(new StringValue.Dynamic(() -> { + if (controlAlpha) { + return "#" + Integer.toHexString(this.color); + } + return "#" + Integer.toHexString(Color.withAlpha(this.color, 0)); + }, val -> { + try { + updateColor(Integer.decode(val)); + } catch (NumberFormatException ignored) {} + }))) + .child(this.preview.asWidget().background(GuiTextures.CHECKBOARD).size(10, 10).margin(1))) + .child(new PagedWidget<>() + .left(5).right(5) + .expanded() + .controller(controller) + .addPage(createRGBPage(alphaSlider)) + .addPage(createHSVPage(alphaSlider))) + .child(new Row() + .left(10).right(10).height(14) + .mainAxisAlignment(Alignment.MainAxis.SPACE_BETWEEN) + .child(new ButtonWidget<>() + .heightRel(1f).width(50) + .overlay(IKey.str("Cancel")) + .onMousePressed(button -> { + animateClose(); + return true; + })) + .child(new ButtonWidget<>() + .heightRel(1f).width(50) + .overlay(IKey.str("Confirm")) + .onMousePressed(button -> { + closeWith(this.color); + return true; + })))); + } + + private IWidget createRGBPage(IWidget alphaSlider) { + return new Column() + .sizeRel(1f, 1f) + .child(new Row() + .widthRel(1f).height(12) + .child(IKey.str("R: ").asWidget().heightRel(1f)) + .child(createSlider(this.sliderBackgroundR) + .bounds(0, 255) + .value(new DoubleValue.Dynamic(() -> Color.getRed(this.color), + val -> updateColor(Color.withRed(this.color, (int) val)))))) + .child(new Row() + .widthRel(1f).height(12) + .child(IKey.str("G: ").asWidget().heightRel(1f)) + .child(createSlider(this.sliderBackgroundG) + .bounds(0, 255) + .value(new DoubleValue.Dynamic(() -> Color.getGreen(this.color), + val -> updateColor(Color.withGreen(this.color, (int) val)))))) + .child(new Row() + .widthRel(1f).height(12) + .child(IKey.str("B: ").asWidget().heightRel(1f)) + .child(createSlider(this.sliderBackgroundB) + .bounds(0, 255) + .value(new DoubleValue.Dynamic(() -> Color.getBlue(this.color), + val -> updateColor(Color.withBlue(this.color, (int) val)))))) + .childIf(alphaSlider != null, alphaSlider); + } + + private IWidget createHSVPage(IWidget alphaSlider) { + return new Column() + .sizeRel(1f, 1f) + .child(new Row() + .widthRel(1f).height(12) + .child(IKey.str("H: ").asWidget().heightRel(1f)) + .child(createSlider(new HueBar(GuiAxis.X)) + .bounds(0, 360) + .value(new DoubleValue.Dynamic(() -> Color.getHue(this.color), + val -> updateColor(Color.withHSVHue(this.color, (float) val)))))) + .child(new Row() + .widthRel(1f).height(12) + .child(IKey.str("S: ").asWidget().heightRel(1f)) + .child(createSlider(this.sliderBackgroundS) + .bounds(0, 1) + .value(new DoubleValue.Dynamic(() -> Color.getHSVSaturation(this.color), + val -> updateColor(Color.withHSVSaturation(this.color, (float) val)))))) + .child(new Row() + .widthRel(1f).height(12) + .child(IKey.str("V: ").asWidget().heightRel(1f)) + .child(createSlider(this.sliderBackgroundV) + .bounds(0, 1) + .value(new DoubleValue.Dynamic(() -> Color.getValue(this.color), + val -> updateColor(Color.withValue(this.color, (float) val)))))) + .childIf(alphaSlider != null, alphaSlider); + } + + private static SliderWidget createSlider(IDrawable background) { + return new SliderWidget() + .expanded() + .heightRel(1f) + .background(background.asIcon().size(0, 4)) + .sliderTexture(handleBackground) + .sliderSize(2, 8); + } + + private String validateRawColor(String raw) { + if (!raw.startsWith("#")) { + if (raw.startsWith("0x") || raw.startsWith("0X")) { + raw = raw.substring(2); + } + return "#" + raw; + } + return raw; + } + + public void updateColor(int color) { + this.color = color; + if (!this.controlAlpha) { + this.color = Color.withAlpha(this.color, this.alpha); + } + color = Color.withAlpha(color, 255); + int rs = Color.withRed(color, 0), re = Color.withRed(color, 255); + int gs = Color.withGreen(color, 0), ge = Color.withGreen(color, 255); + int bs = Color.withBlue(color, 0), be = Color.withBlue(color, 255); + int as = Color.withAlpha(color, 0), ae = Color.withAlpha(color, 255); + this.sliderBackgroundR.setHorizontalGradient(rs, re); + this.sliderBackgroundG.setHorizontalGradient(gs, ge); + this.sliderBackgroundB.setHorizontalGradient(bs, be); + this.sliderBackgroundA.setHorizontalGradient(as, ae); + this.sliderBackgroundS.setHorizontalGradient(Color.withHSVSaturation(color, 0f), + Color.withHSVSaturation(color, 1f)); + this.sliderBackgroundV.setHorizontalGradient(Color.withValue(color, 0f), Color.withValue(color, 1f)); + this.preview.setColor(this.color); + } +} diff --git a/src/main/java/gregtech/common/terminal2/HomeApp.java b/src/main/java/gregtech/common/terminal2/HomeApp.java new file mode 100644 index 00000000000..a9810c588bb --- /dev/null +++ b/src/main/java/gregtech/common/terminal2/HomeApp.java @@ -0,0 +1,45 @@ +package gregtech.common.terminal2; + +import gregtech.api.terminal2.ITerminalApp; +import gregtech.api.terminal2.Terminal2; + +import net.minecraft.util.ResourceLocation; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.PagedWidget; +import com.cleanroommc.modularui.widgets.layout.Grid; + +public class HomeApp implements ITerminalApp { + + private final PagedWidget.Controller pageController = new PagedWidget.Controller(); + + public void setPageWidget(PagedWidget widget) { + widget.controller(pageController); + } + + @Override + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { + Grid appGrid = new Grid() + .size(340, 240) + .nextRow(); + + for (ResourceLocation appID : Terminal2.idList) { + if (appID == Terminal2.HOME_ID) continue; + + appGrid.child(new ButtonWidget<>() + .overlay(Terminal2.appMap.get(appID).getIcon()) + .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) + .onMousePressed(i -> { + pageController.setPage(Terminal2.idList.indexOf(appID)); + return true; + })); + } + + return appGrid; + } +} diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java new file mode 100644 index 00000000000..f5e22b8f9cb --- /dev/null +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -0,0 +1,146 @@ +package gregtech.common.terminal2; + +import gregtech.api.mui.GTGuis; +import gregtech.api.terminal2.ITerminalApp; +import gregtech.api.terminal2.Terminal2Theme; +import gregtech.common.mui.widget.GTColorPickerDialog; + +import com.cleanroommc.modularui.api.IPanelHandler; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.PanelSyncHandler; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.ScrollWidget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.ListWidget; +import com.cleanroommc.modularui.widgets.layout.Flow; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +public class SettingsApp implements ITerminalApp { + + @Override + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { + var backgroundSelectPanel = (PanelSyncHandler) guiSyncManager.panel("terminal_background_select", + backgroundSelectWidget(), true); + + int rows = Terminal2Theme.colors.size() + 1; + + var column = Flow.column() + .crossAxisAlignment(Alignment.CrossAxis.START) + .widthRel(0.95F) + .height(rows * 24) + .leftRel(0.4F); + + column.child(Flow.row() + .widthRel(1.0F) + .height(24) + .child(IKey.lang("terminal.settings.background").asWidget()) + .child(new ButtonWidget<>() + .overlay(IKey.dynamic(() -> Terminal2Theme.currentBackground)) + .size(140, 18) + .align(Alignment.CenterRight) + .onMousePressed(i -> { + if (backgroundSelectPanel.isPanelOpen()) { + backgroundSelectPanel.closePanel(); + } else { + backgroundSelectPanel.openPanel(); + } + return true; + }))); + + for (String color : Terminal2Theme.colors) { + IPanelHandler colorPanel = IPanelHandler.simple(panel, + (mainPanel, player) -> new GTColorPickerDialog("color_select_" + color, i -> { + Terminal2Theme.setColor(color, i); + Terminal2Theme.saveConfig(); + }, Terminal2Theme.getColorRect(color).getColor(), true), + true); + + column.child(Flow.row() + .widthRel(1.0F) + .height(24) + .child(IKey.lang("terminal.settings.color", color.substring(6)).asWidget()) + .child(new ButtonWidget<>() + .overlay(GuiTextures.REFRESH) + .left(276) + .topRelAnchor(0.5F, 0.5F) + .addTooltipLine(IKey.lang("terminal.settings.reset_color")) + .onMousePressed(i -> { + Terminal2Theme.resetToDefaultColor(color); + Terminal2Theme.saveConfig(); + // force reset color picker state + colorPanel.deleteCachedPanel(); + return true; + })) + .child(new ButtonWidget<>() + .overlay(Terminal2Theme.getColorRect(color)) + .background(GuiTextures.CHECKBOARD) + .disableHoverOverlay() + .disableHoverBackground() + .align(Alignment.CenterRight) + .onMousePressed(i -> { + colorPanel.openPanel(); + return true; + }))); + } + + var scroll = new ScrollWidget<>(new VerticalScrollData()) + .child(column) + .sizeRel(1.0F); + + scroll.getScrollArea().getScrollY().setScrollSize(rows * 24); + + return new ParentWidget<>() + .sizeRel(0.98F) + .posRel(0.5F, 0.5F) + .background(Terminal2Theme.COLOR_BACKGROUND_1) + .child(scroll); + } + + @Override + public IDrawable getIcon() { + return GuiTextures.GEAR; + } + + private PanelSyncHandler.IPanelBuilder backgroundSelectWidget() { + return (syncManager, syncHandler) -> { + String[] files = Terminal2Theme.backgroundsDir.list(); + List options; + if (files == null) { + options = new ArrayList<>(); + } else { + options = new ArrayList<>(Arrays.asList(files)); + } + options.sort(Comparator.naturalOrder()); + options.add(0, "default"); + + var list = ListWidget.builder(options, (st) -> new ButtonWidget<>() + .overlay(IKey.str(st)) + .size(140, 18) + .leftRel(0.2F) + .onMousePressed(i -> { + Terminal2Theme.setBackground(st); + Terminal2Theme.saveConfig(); + return true; + })) + .size(150, 90).pos(9, 16); + + return GTGuis.createPopupPanel("terminal_background_select", 168, 112) + .child(IKey.lang("terminal.settings.background_select").asWidget() + .leftRel(0.5F) + .top(6)) + .child(list); + }; + } +} diff --git a/src/main/java/gregtech/common/terminal2/TestApp.java b/src/main/java/gregtech/common/terminal2/TestApp.java new file mode 100644 index 00000000000..58b2a557baf --- /dev/null +++ b/src/main/java/gregtech/common/terminal2/TestApp.java @@ -0,0 +1,17 @@ +package gregtech.common.terminal2; + +import gregtech.api.terminal2.ITerminalApp; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; + +public class TestApp implements ITerminalApp { + + @Override + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { + return IKey.str("test app").color(0xFFFFFF).shadow(true).asWidget(); + } +} diff --git a/src/main/java/gregtech/core/CoreModule.java b/src/main/java/gregtech/core/CoreModule.java index f4121bb3ecb..df51a0704b4 100644 --- a/src/main/java/gregtech/core/CoreModule.java +++ b/src/main/java/gregtech/core/CoreModule.java @@ -22,6 +22,7 @@ import gregtech.api.recipes.ModHandler; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.properties.impl.TemperatureProperty; +import gregtech.api.terminal2.Terminal2; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.event.MaterialEvent; @@ -291,6 +292,8 @@ public void init(FMLInitializationEvent event) { DungeonLootLoader.init(); MetaBlocks.registerWalkingSpeedBonus(); + + Terminal2.init(); } @Override diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 2eddc0b2147..ee4badcdb14 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -6050,230 +6050,27 @@ gregtech.creative.energy.source=Source gregtech.creative.activity.on=Active gregtech.creative.activity.off=Not active -gregtech.terminal.app_name.items=Item Guides -gregtech.terminal.app_name.machines=Machine Guides -gregtech.terminal.app_name.multiblocks=Multiblock Guides -gregtech.terminal.app_name.tutorials=Tutorials -gregtech.terminal.app_name.settings=System Settings -gregtech.terminal.app_name.guide_editor=Guide Editor -gregtech.terminal.app_name.recipe_chart=Recipe Chart -gregtech.terminal.app_name.ore_prospector=Ore Prospector -gregtech.terminal.app_name.fluid_prospector=Fluid Prospector -gregtech.terminal.app_name.pong=Pong -gregtech.terminal.app_name.minesweeper=Minesweeper -gregtech.terminal.app_name.maze=Theseus's Escape -gregtech.terminal.app_name.console=GT Console -gregtech.terminal.app_name.battery=Battery Manager -gregtech.terminal.app_name.hardware=Hardware Manager -gregtech.terminal.app_name.store=App Store -gregtech.terminal.app_name.multiblock_ar=Multiblock Helper -gregtech.terminal.app_name.world_prospector=World Prospector -gregtech.terminal.app_name.vtank_viewer=Virtual Tank Viewer -gregtech.terminal.app_name.cape_selector=Cape Selector -gregtech.terminal.app_name.teleport=Teleporter - - -terminal.app_name.description=No description. -terminal.app_name.tier=Tier %d -terminal.app_name.maximize.unsupported=This App does not support maximize. -terminal.items.description=A guide book about items. -terminal.machines.description=A guide book about gt machines. -terminal.multiblocks.description=A guide book about multi-blocks. -terminal.tutorials.description=Introduces all kinds of things, CT integration, tips, tutorials and more. -terminal.pong.description=A classic pong game, if you're really that bored of waiting for that tungstensteel. -terminal.minesweeper.description=A classic minesweeper game, if you're in class. -terminal.maze.description=A GTOS exclusive game finding you racing through an endless labyrinth to survive the Minotaur! -terminal.cape_selector.description=An app that allows you to equip GT capes that you've unlocked through advancements. -terminal.teleport.description=Open portals to any coordinate in any dimension. Be careful not to teleport into a wall! - -texture.modify_gui_texture.missing=Missing Texture -texture.url_texture.fail=Load Failed - -terminal.hw.battery=Battery -terminal.hw.device=Device - -terminal.os.shutdown_confirm=Confirm shutdown? (Press ESC again to see ok) -terminal.os.hw_demand=Missing mounting hardware: - -terminal.system_call.null=NULL -terminal.system_call.call_menu=Call Menu -terminal.system_call.full_screen=Full Screen -terminal.system_call.minimize_focus_app=Back to Desktop -terminal.system_call.close_focus_app=Close App -terminal.system_call.shutdown=Shutdown -terminal.system_call.open_app=Open App - -terminal.menu.close=Close App -terminal.menu.minimize=Minimize App -terminal.menu.maximize=Full Screen/Recover - -terminal.component.new_page=New Page -terminal.component.page_name=Page Name -terminal.component.load_file=Load File -terminal.component.load_file.error=An error occurred while loading the file. -terminal.component.save_file=Save File -terminal.component.save_file.error=An error occurred while saving the file. -terminal.component.confirm=Are you sure? -terminal.component.error=ERROR -terminal.component.warning=WARNING +# new terminal +terminal.app.gregtech.home.name=Home +terminal.app.gregtech.settings.name=Theme Settings +terminal.app.gregtech.test.name=test app + +terminal.settings.background=Background +terminal.settings.background_select=Select Background +terminal.settings.color=Set color %s +terminal.settings.reset_color=Reset to default color + +# old terminal +# currently indirectly used in alarm terminal.component.searching=searching -terminal.component.reload=reload resource - -terminal.dialog.notice=NOTICE -terminal.dialog.error_path=error file path: -terminal.dialog.no_file_selected=No file selected. -terminal.dialog.folder=Open Folder - -terminal.guide_editor.description=An interactive guide page editor that allows you to create guide pages easily. -terminal.guide_editor.up=Up -terminal.guide_editor.down=Down -terminal.guide_editor.remove=Remove -terminal.guide_editor.add_stream=Add to stream -terminal.guide_editor.add_fixed=Add to fixed -terminal.guide_editor.update=Update -terminal.guide_editor.add_slot=Add Slot -terminal.guide_editor.default=Default Value -terminal.guide_editor.page_config=Page Config -terminal.guide_editor.widgets_box=Widgets Box -terminal.guide_editor.widget_config=Widget Config -terminal.guide_editor.error_type=Item types do not match and will still be saved, but will not be seen in app. - -terminal.settings.description=The system settings for GTOS. -terminal.settings.theme=Theme -terminal.settings.theme.color=Theme Color Settings -terminal.settings.theme.wallpaper=Wallpaper Settings -terminal.settings.theme.wallpaper.resource=resource -terminal.settings.theme.wallpaper.url=url -terminal.settings.theme.wallpaper.color=color -terminal.settings.theme.wallpaper.file=file -terminal.settings.theme.select=Select -terminal.settings.theme.image=Image File -terminal.settings.home=Home Button -terminal.settings.home.double=Double -terminal.settings.home.action=Click Action -terminal.settings.home.args=Args -terminal.settings.home.click=click -terminal.settings.home.double_click=double Click -terminal.settings.os=Os settings -terminal.settings.os.double_check=Double Check -terminal.settings.os.double_check.desc=Should Double Check when shutdown. - - -terminal.recipe_chart.description=A tool for analyzing recipe chains, with which you can easily build a recipe graph and even calculate the ingredients needed like JEC. -terminal.recipe_chart.limit=Page limit. -terminal.recipe_chart.delete=Delete Page -terminal.recipe_chart.add_slot=Add Root Slot -terminal.recipe_chart.demand=Demand -terminal.recipe_chart.calculator=Calculator -terminal.recipe_chart.add=Set the item from inventory -terminal.recipe_chart.drag=Drag ingredients here. -terminal.recipe_chart.visible=Visible -terminal.recipe_chart.jei=JEI Focus -terminal.recipe_chart.tier=Tier: -terminal.recipe_chart.ratio=Weight -terminal.recipe_chart.tier.0=cache of 5 pages -terminal.recipe_chart.tier.1=cache of 6 pages -terminal.recipe_chart.tier.2=cache of 7 pages -terminal.recipe_chart.tier.3=cache of 8 pages - -terminal.prospector.vis_mode=Switch color mode + +# currently used in prospector terminal.prospector.list=All Resources terminal.prospector.ore=Ore Data terminal.prospector.fluid=Fluid Deposit Data terminal.prospector.fluid.info=%s %s - %s%% terminal.prospector.waypoint.add=[Double §7Left click§r] to add waypoint -terminal.ore_prospector.description=Hate the scanner toy? Don't want to run around looking for ores? Come and look at it. -terminal.ore_prospector.tier.0=radius size 1 -terminal.ore_prospector.tier.1=radius size 2 -terminal.ore_prospector.tier.2=radius size 3 -terminal.ore_prospector.tier.3=radius size 4 -terminal.ore_prospector.tier.4=radius size 5 -terminal.ore_prospector.tier.5=radius size 6 -terminal.ore_prospector.tier.6=radius size 7 - -terminal.fluid_prospector.description=You know, there's gold in bedrocks. -terminal.fluid_prospector.tier.0=radius size 1 -terminal.fluid_prospector.tier.1=radius size 2 -terminal.fluid_prospector.tier.2=radius size 3 -terminal.fluid_prospector.tier.3=radius size 4 -terminal.fluid_prospector.tier.4=radius size 5 -terminal.fluid_prospector.tier.5=radius size 6 -terminal.fluid_prospector.tier.6=radius size 7 - -terminal.console.description=A tool to help you free your inventory, it's time to say goodbye to wrench, screwdriver, hammer, and crowbar. -terminal.console.notice=Please shift-right-click a machine when opening the terminal. -terminal.console.front=Set as front -terminal.console.items=set as items output -terminal.console.fluids=set as fluids output -terminal.console.auto_output=allow auto output -terminal.console.input=allow input from output -terminal.console.cover_rs=signal: %s -terminal.console.cover_gui=Gui -terminal.console.gui=Open machine gui -terminal.console.maintenance=Fix all problems -terminal.console.venting=set as venting -terminal.console.controllable=set working enable - -terminal.hardware.description=Hardware Manager, masterpieces of elegance and precision. How can a tablet be without hardware? -terminal.hardware.select=Mounting hardware -terminal.hardware.remove=Remove hardware -terminal.hardware.remove.full=There are no empty slots in inventory -terminal.hardware.tip.remove=§4right-click remove the hardware - -terminal.battery.description=Battery manager, visually analyze your app's energy consumption. -terminal.battery.hover=%s: Usage %d eu/s -terminal.battery.low_energy=Low power! Plz recharge the terminal. - -terminal.store.description=App store, check out what you got? Install and upgrade the app. -terminal.store.match=Detected required item in inventory, install/upgrade App? -terminal.store.miss=Requires %s (%d). -terminal.store.close=Close - -terminal.ar.open=Open AR - -terminal.multiblock_ar.description=Remember the §cFreedom Wrench§r? Unfortunately, it it's gone. It doesn't matter, we have a new technology now. This app can also help you build your multi-block machine. -terminal.multiblock_ar.tier.0=AR Camera -terminal.multiblock_ar.tier.1=3D Builder -terminal.multiblock_ar.unlock=Unlock this mode after the upgrade -terminal.multiblock_ar.builder.hover=3D Builder -terminal.multiblock_ar.builder.auto=Automatic Build -terminal.multiblock_ar.builder.place=Place block -terminal.multiblock_ar.builder.debug=Debug - -terminal.world_prospector.description="I wish I had X-ray vision."\n"Sir, I'm sorry, but we don't sell superpowers. You should trust the science." -terminal.world_prospector.tier.0=Radius 15m (1 slot) -terminal.world_prospector.tier.1=Radius 30m (2 slot) -terminal.world_prospector.tier.2=Radius 60m (4 slot) -terminal.world_prospector.radius=Radius %sm -terminal.world_prospector.reference=Select a reference -terminal.world_prospector.color=Select box color - -terminal.vtank_viewer.description=Never lose any fluids to changing ender link frequencies again! Here's a scrollable list of every virtual tank that you have access to in your world. -terminal.vtank_viewer.title=Virtual Tank Viewer -terminal.vtank_viewer.refresh=Refresh tank index - -terminal.teleporter.dimension=Dimension: -terminal.teleporter.spawn_portal=Engage - -terminal.maze.title=Theseus's Escape -terminal.maze.play=Play -terminal.maze.continue=Continue -terminal.maze.pause=Game Paused -terminal.maze.death.1=Oh no! You were eaten by the Minotaur! -terminal.maze.death.2=You got through %s mazes before losing. -terminal.maze.death.3=Try again? -terminal.maze.retry=Retry - -terminal.minesweeper.time=%s seconds elapsed -terminal.minesweeper.lose=You lost. Game will restart in %s seconds. -terminal.minesweeper.win.1=You won in %s seconds! -terminal.minesweeper.win.2=Game will restart in %s - -terminal.cape_selector.empty=It looks like you haven't unlocked any capes yet! -terminal.cape_selector.select=Click on an unlocked cape to select it! -terminal.cape_selector.tip=You can get these from high-level advancements. - metaitem.cover.digital.title.mode=Mode: metaitem.cover.digital.title.spin=Spin: metaitem.cover.digital.wireless.tooltip.1=§fWirelessly§7 connects machines to the §fCentral Monitor§7 as §fCover§7. diff --git a/src/main/resources/assets/gregtech/terminal/config/theme.json b/src/main/resources/assets/gregtech/terminal/config/theme.json deleted file mode 100644 index ac33fcf5bdf..00000000000 --- a/src/main/resources/assets/gregtech/terminal/config/theme.json +++ /dev/null @@ -1 +0,0 @@ -{"COLOR_1":-7277708,"COLOR_2":-798604,"COLOR_3":-1613985,"COLOR_4":-16747521,"COLOR_5":-9364519,"COLOR_6":-14803426,"COLOR_7":-1644826,"COLOR_F_1":-7019839,"COLOR_F_2":-2085683200,"COLOR_B_1":1342177280,"COLOR_B_2":-1610612736,"COLOR_B_3":-1594460040,"WALL_PAPER":{"type":"resource","resource":"gregtech:textures/gui/terminal/terminal_background.png"}} \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/home_button.png b/src/main/resources/assets/gregtech/textures/gui/terminal/home_button.png new file mode 100644 index 0000000000000000000000000000000000000000..f78a813adda5d72636d9b2bb0082f50ad236ab33 GIT binary patch literal 10056 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png b/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png index ae470d611ec28b184f586b6b5b824ff55a0fa0b5..fcd89e52fd89f53650f3a3b076f83febaacdfdb4 100644 GIT binary patch delta 1221 zcmYjQe^gR;9DTB_TB}?ugOStJDVnY{(Ma7~PUx^>aS+p~EG4$WRKzn&!5?^BrGi-7 zbN(1P>wRKK^y?gKbywCUE_uiEz37B;> zN4~WKIe33q+JIqjfBcp>jM~&Cj@4fd&x^J0&1uAa&YRjYUh$o&3C&1yJo6m=C;EKQ z=6gqGcM4?KJVrYq!B#g`IY`!QAGw52t=*X4eZOcq$il@;H8d05uK zsnlnNx_2K^+`PFb!MEXPoZEH@zI(``<409LIEswvs=kLHXt98b2u@_yJfI@JyZkSW zDdkTlj*9~Bjmc!V!<{D!^@fsj{^hM6NojFvRsTR!MDcKQMq(nPk2R0Bf*`sTGUOR= zXSXTz>p6R)@z(NHjyxw>vcBWGd0}CYs$y4xGa|fp2p!|?Y%{K)ruN&M=i|I{U;JY* zi0beC5%JTA8Nf#|f)SZXX(JdJ_xHLQpf_i>psadV8wxo;A zlle^gz0#*mGpPx@cOXc;n13*(CUYTW2<}YTg^gJAuvSQdpzM9y4q{4nk({#7g^JA@ zv`n_LMMX&T!J2~jghC4S+nAR40O0L3tDSYHb_g>Um(slva80li$-U!6)P?Ijo@Lf_ zMXMZFnn->vf$7I`z-{mOY4fyp**sCZF}J@Yi|=IyAbp& z7xr><^rI^{kN2(ty7ZBdL-$$PDE&snq2pg80Y@$d`5{`LlWqJ60P3wi%~fFIc?1>u!E99^UcN$#7{HC#mPE6n;RzN+?WNZQ`gc?l9@?ACi z@&LiEY}KqSk-#opMF|6kZNPW3{|I()cHnb4 zp$|{xp`%bJ1t4NJc}(?$jFt3xtp`&s`Nu*!4YSlXM7y# zxebV##wGLdNxcv)d|@F-i;NEiZDByh2uTIuwtJcU46d@-a*NBEY-Is?oikH=W%O%bM* z|M{X8a}bl5wls>6cW0?oDypwI{l`=KzgC`6&;Q#O@O04^D?7_fYe10DV*ao`BlDH< z%8|W9kj~xp6h$QBJpZ+0S|-zMEgVHn9kDq-F@+#!sFjS>LOEb^Z_Bx9guH0>1w)13 z4AQXF8&R%l6S3#W)gJ!DYsj7ir2b9i({-Tnp~%?sa3-j%GB&LG_bA1_yP)yAMeX&r xF)i+oUe46>YEwf`(npnpS!U(^k9(%hE~8uy5kIlk^UeX+5Se%=xF#qz=Rc!zE9C$H delta 3046 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 From 31745b30f476997e48dd96e4bb0e9b5ba792988f Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Sun, 10 Nov 2024 16:54:05 -0500 Subject: [PATCH 03/17] clean up some stuff --- .../gregtech/api/terminal2/Terminal2.java | 10 +-- .../api/terminal2/Terminal2Theme.java | 6 +- .../items/behaviors/Terminal2Behavior.java | 31 +++++--- .../mui/widget/GTColorPickerDialog.java | 21 +++++- .../common/mui/widget/IDPagedWidget.java | 70 +++++++++++++++++++ .../gregtech/common/terminal2/HomeApp.java | 45 ------------ 6 files changed, 113 insertions(+), 70 deletions(-) create mode 100644 src/main/java/gregtech/common/mui/widget/IDPagedWidget.java delete mode 100644 src/main/java/gregtech/common/terminal2/HomeApp.java diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java index 9684684f70a..873fba5c77c 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -3,7 +3,6 @@ import gregtech.api.util.FileUtility; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; -import gregtech.common.terminal2.HomeApp; import gregtech.common.terminal2.SettingsApp; import gregtech.common.terminal2.TestApp; @@ -14,16 +13,11 @@ import net.minecraftforge.fml.relauncher.SideOnly; import java.io.File; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; public class Terminal2 { - // we want both ordered id -> int and unordered id -> app - // todo this could probably be a better data structure - public static final List idList = new ArrayList<>(); public static final Map appMap = new HashMap<>(); public static final ResourceLocation HOME_ID = GTUtility.gregtechId("home"); @@ -36,16 +30,14 @@ public static void init() { FileUtility.extractJarFiles("/assets/gregtech/terminal", TERMINAL_PATH, false); Terminal2Theme.init(); } - registerApp(HOME_ID, new HomeApp()); registerApp(GTUtility.gregtechId("settings"), new SettingsApp()); registerApp(GTUtility.gregtechId("test"), new TestApp()); } public static void registerApp(ResourceLocation id, ITerminalApp app) { - if (idList.contains(id)) { + if (appMap.containsKey(id) || HOME_ID.equals(id)) { throw new AssertionError("A terminal app with id " + id + " already exists!"); } - idList.add(id); appMap.put(id, app); } } diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java index 1a32d026597..48f194543b3 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -113,11 +113,7 @@ public static Rectangle getColorRect(String color) { } public static void setColor(String color, int i) { - try { - ((Rectangle) Terminal2Theme.class.getField(color).get(null)).setColor(i); - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException("Failed to set color " + color + " to " + i, e); - } + getColorRect(color).setColor(i); } public static void resetToDefaultColor(String color) { diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index 5209c19abe9..1852ba85f3b 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -8,7 +8,7 @@ import gregtech.api.mui.factory.MetaItemGuiFactory; import gregtech.api.terminal2.Terminal2; import gregtech.api.terminal2.Terminal2Theme; -import gregtech.common.terminal2.HomeApp; +import gregtech.common.mui.widget.IDPagedWidget; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -25,7 +25,7 @@ import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widgets.ButtonWidget; -import com.cleanroommc.modularui.widgets.PagedWidget; +import com.cleanroommc.modularui.widgets.layout.Grid; public class Terminal2Behavior implements IItemBehaviour, ItemUIFactory { @@ -46,14 +46,29 @@ public GTGuiTheme getUITheme() { @Override public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { ModularPanel panel = GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248); - PagedWidget appPages = new PagedWidget<>(); - ((HomeApp) Terminal2.appMap.get(Terminal2.HOME_ID)).setPageWidget(appPages); - for (ResourceLocation appID : Terminal2.idList) { - appPages.addPage(Terminal2.appMap.get(appID).buildWidgets(guiData, guiSyncManager, panel)); + IDPagedWidget appPages = new IDPagedWidget<>(); + for (var app : Terminal2.appMap.entrySet()) { + appPages.addPage(app.getKey(), app.getValue().buildWidgets(guiData, guiSyncManager, panel)); } - appPages.setPage(Terminal2.idList.indexOf(Terminal2.HOME_ID)); appPages.size(340, 240).pos(4, 4); + Grid appGrid = new Grid() + .size(340, 240) + .nextRow(); + + for (ResourceLocation appID : Terminal2.appMap.keySet()) { + if (appID == Terminal2.HOME_ID) continue; + + appGrid.child(new ButtonWidget<>() + .overlay(Terminal2.appMap.get(appID).getIcon()) + .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) + .onMousePressed(i -> { + appPages.setPage(appID); + return true; + })); + } + appPages.addPage(Terminal2.HOME_ID, appGrid).setDefaultPage(Terminal2.HOME_ID); + return panel.background(GTGuiTextures.TERMINAL_FRAME) .child(new DynamicDrawable(Terminal2Theme::getBackgroundDrawable).asWidget() .size(340, 240) @@ -69,7 +84,7 @@ public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager .left(346) .topRelAnchor(0.5F, 0.5F) .onMousePressed(i -> { - appPages.setPage(Terminal2.idList.indexOf(Terminal2.HOME_ID)); + appPages.setPage(Terminal2.HOME_ID); return true; })); } diff --git a/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java index 3b7b5d6c4e3..68766fc13cc 100644 --- a/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java +++ b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java @@ -22,10 +22,12 @@ import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; // TODO remove this class when MUI2 page buttons stop having inverted backgrounds and MUI2 color picker obeys theming -// for its page buttons +// for its page buttons, and the weird resizing bugs are fixed public class GTColorPickerDialog extends Dialog { private static final IDrawable handleBackground = new Rectangle().setColor(Color.WHITE.main); @@ -42,6 +44,8 @@ public class GTColorPickerDialog extends Dialog { private final Rectangle sliderBackgroundS = new Rectangle(); private final Rectangle sliderBackgroundV = new Rectangle(); + private final List sliders = new ArrayList<>(); + public GTColorPickerDialog(Consumer resultConsumer, int startColor, boolean controlAlpha) { this("color_picker", resultConsumer, startColor, controlAlpha); } @@ -172,13 +176,24 @@ private IWidget createHSVPage(IWidget alphaSlider) { .childIf(alphaSlider != null, alphaSlider); } - private static SliderWidget createSlider(IDrawable background) { - return new SliderWidget() + private SliderWidget createSlider(IDrawable background) { + var result = new SliderWidget() .expanded() .heightRel(1f) .background(background.asIcon().size(0, 4)) .sliderTexture(handleBackground) .sliderSize(2, 8); + sliders.add(result); + return result; + } + + @Override + public void onResized() { + super.onResized(); + // HACK: work around this not getting called by MUI2 in some situations + for (var slider : sliders) { + slider.onResized(); + } } private String validateRawColor(String raw) { diff --git a/src/main/java/gregtech/common/mui/widget/IDPagedWidget.java b/src/main/java/gregtech/common/mui/widget/IDPagedWidget.java new file mode 100644 index 00000000000..22f98f78162 --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/IDPagedWidget.java @@ -0,0 +1,70 @@ +package gregtech.common.mui.widget; + +import net.minecraft.util.ResourceLocation; + +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.widget.Widget; +import com.google.common.collect.ImmutableList; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class IDPagedWidget> extends Widget { + + private final Map pages = new Object2ObjectOpenHashMap<>(); + private IWidget currentPage; + private ResourceLocation currentPageID = null; + private ResourceLocation defaultPageID = null; + + @Override + public void afterInit() { + if (defaultPageID == null) { + throw new IllegalStateException("IDPagedWidget has no default page!"); + } + setPage(defaultPageID); + } + + public void setPage(ResourceLocation page) { + if (!pages.containsKey(page)) { + throw new IndexOutOfBoundsException(); + } + this.currentPageID = page; + if (this.currentPage != null) { + this.currentPage.setEnabled(false); + } + this.currentPage = this.pages.get(this.currentPageID); + this.currentPage.setEnabled(true); + } + + public Collection getPages() { + return this.pages.values(); + } + + public IWidget getCurrentPage() { + return this.currentPage; + } + + public ResourceLocation getCurrentPageID() { + return this.currentPageID; + } + + @Override + public @Unmodifiable @NotNull List getChildren() { + return ImmutableList.copyOf(this.pages.values()); + } + + public W addPage(ResourceLocation id, IWidget widget) { + this.pages.put(id, widget); + widget.setEnabled(false); + return getThis(); + } + + public W setDefaultPage(ResourceLocation id) { + defaultPageID = id; + return getThis(); + } +} diff --git a/src/main/java/gregtech/common/terminal2/HomeApp.java b/src/main/java/gregtech/common/terminal2/HomeApp.java deleted file mode 100644 index a9810c588bb..00000000000 --- a/src/main/java/gregtech/common/terminal2/HomeApp.java +++ /dev/null @@ -1,45 +0,0 @@ -package gregtech.common.terminal2; - -import gregtech.api.terminal2.ITerminalApp; -import gregtech.api.terminal2.Terminal2; - -import net.minecraft.util.ResourceLocation; - -import com.cleanroommc.modularui.api.drawable.IKey; -import com.cleanroommc.modularui.api.widget.IWidget; -import com.cleanroommc.modularui.factory.HandGuiData; -import com.cleanroommc.modularui.screen.ModularPanel; -import com.cleanroommc.modularui.value.sync.PanelSyncManager; -import com.cleanroommc.modularui.widgets.ButtonWidget; -import com.cleanroommc.modularui.widgets.PagedWidget; -import com.cleanroommc.modularui.widgets.layout.Grid; - -public class HomeApp implements ITerminalApp { - - private final PagedWidget.Controller pageController = new PagedWidget.Controller(); - - public void setPageWidget(PagedWidget widget) { - widget.controller(pageController); - } - - @Override - public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { - Grid appGrid = new Grid() - .size(340, 240) - .nextRow(); - - for (ResourceLocation appID : Terminal2.idList) { - if (appID == Terminal2.HOME_ID) continue; - - appGrid.child(new ButtonWidget<>() - .overlay(Terminal2.appMap.get(appID).getIcon()) - .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) - .onMousePressed(i -> { - pageController.setPage(Terminal2.idList.indexOf(appID)); - return true; - })); - } - - return appGrid; - } -} From f303af0f68feaf4195f95d1be8b3d2ce6580b3a8 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:45:18 -0500 Subject: [PATCH 04/17] better home screen --- .../gregtech/api/terminal2/Terminal2.java | 8 +-- .../api/terminal2/Terminal2Theme.java | 49 ++++++++++++------- .../items/behaviors/Terminal2Behavior.java | 11 ++++- .../mui/drawable/RectangleWithCircle.java | 21 ++++++++ .../gregtech/common/terminal2/TestApp.java | 8 ++- 5 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java index 873fba5c77c..c4acbbcda54 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -13,12 +13,12 @@ import net.minecraftforge.fml.relauncher.SideOnly; import java.io.File; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; public class Terminal2 { - public static final Map appMap = new HashMap<>(); + public static final Map appMap = new LinkedHashMap<>(); public static final ResourceLocation HOME_ID = GTUtility.gregtechId("home"); @SideOnly(Side.CLIENT) @@ -31,7 +31,9 @@ public static void init() { Terminal2Theme.init(); } registerApp(GTUtility.gregtechId("settings"), new SettingsApp()); - registerApp(GTUtility.gregtechId("test"), new TestApp()); + for (int i = 0; i < 18; i++) { + registerApp(GTUtility.gregtechId("test" + i), new TestApp(i)); + } } public static void registerApp(ResourceLocation id, ITerminalApp app) { diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java index 48f194543b3..4a72a63c78b 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -3,9 +3,9 @@ import gregtech.api.util.FileUtility; import gregtech.api.util.GTUtility; import gregtech.common.mui.drawable.FileTexture; +import gregtech.common.mui.drawable.RectangleWithCircle; import com.cleanroommc.modularui.api.drawable.IDrawable; -import com.cleanroommc.modularui.drawable.Rectangle; import com.cleanroommc.modularui.drawable.UITexture; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -35,22 +35,33 @@ public class Terminal2Theme { public static final List colors = Arrays.stream(Terminal2Theme.class.getFields()) .map(Field::getName).filter(name -> name.startsWith("COLOR_")).collect(Collectors.toList()); - public static Rectangle COLOR_BRIGHT_1 = new Rectangle().setColor(new Color(144, 243, 116).getRGB()); - public static Rectangle COLOR_BRIGHT_2 = new Rectangle().setColor(new Color(243, 208, 116).getRGB()); - public static Rectangle COLOR_BRIGHT_3 = new Rectangle().setColor(new Color(231, 95, 95).getRGB()); - public static Rectangle COLOR_BRIGHT_4 = new Rectangle().setColor(new Color(230, 230, 230).getRGB()); - - public static Rectangle COLOR_DARK_1 = new Rectangle().setColor(new Color(0, 115, 255).getRGB()); - public static Rectangle COLOR_DARK_2 = new Rectangle().setColor(new Color(113, 27, 217).getRGB()); - public static Rectangle COLOR_DARK_3 = new Rectangle().setColor(new Color(30, 80, 30).getRGB()); - public static Rectangle COLOR_DARK_4 = new Rectangle().setColor(new Color(30, 30, 30).getRGB()); - - public static Rectangle COLOR_FOREGROUND_BRIGHT = new Rectangle().setColor(new Color(148, 226, 193).getRGB()); - public static Rectangle COLOR_FOREGROUND_DARK = new Rectangle().setColor(new Color(175, 0, 0, 131).getRGB()); - - public static Rectangle COLOR_BACKGROUND_1 = new Rectangle().setColor(new Color(0, 0, 0, 80).getRGB()); - public static Rectangle COLOR_BACKGROUND_2 = new Rectangle().setColor(new Color(0, 0, 0, 160).getRGB()); - public static Rectangle COLOR_BACKGROUND_3 = new Rectangle().setColor(new Color(246, 120, 120, 160).getRGB()); + public static RectangleWithCircle COLOR_BRIGHT_1 = new RectangleWithCircle() + .setColor(new Color(144, 243, 116).getRGB()); + public static RectangleWithCircle COLOR_BRIGHT_2 = new RectangleWithCircle() + .setColor(new Color(243, 208, 116).getRGB()); + public static RectangleWithCircle COLOR_BRIGHT_3 = new RectangleWithCircle() + .setColor(new Color(231, 95, 95).getRGB()); + public static RectangleWithCircle COLOR_BRIGHT_4 = new RectangleWithCircle() + .setColor(new Color(230, 230, 230).getRGB()); + + public static RectangleWithCircle COLOR_DARK_1 = new RectangleWithCircle() + .setColor(new Color(0, 115, 255).getRGB()); + public static RectangleWithCircle COLOR_DARK_2 = new RectangleWithCircle() + .setColor(new Color(113, 27, 217).getRGB()); + public static RectangleWithCircle COLOR_DARK_3 = new RectangleWithCircle().setColor(new Color(30, 80, 30).getRGB()); + public static RectangleWithCircle COLOR_DARK_4 = new RectangleWithCircle().setColor(new Color(30, 30, 30).getRGB()); + + public static RectangleWithCircle COLOR_FOREGROUND_BRIGHT = new RectangleWithCircle() + .setColor(new Color(148, 226, 193).getRGB()); + public static RectangleWithCircle COLOR_FOREGROUND_DARK = new RectangleWithCircle() + .setColor(new Color(175, 0, 0, 131).getRGB()); + + public static RectangleWithCircle COLOR_BACKGROUND_1 = new RectangleWithCircle() + .setColor(new Color(0, 0, 0, 80).getRGB()); + public static RectangleWithCircle COLOR_BACKGROUND_2 = new RectangleWithCircle() + .setColor(new Color(0, 0, 0, 160).getRGB()); + public static RectangleWithCircle COLOR_BACKGROUND_3 = new RectangleWithCircle() + .setColor(new Color(246, 120, 120, 160).getRGB()); public static void init() { backgroundsDir = new File(Terminal2.TERMINAL_PATH, "backgrounds"); @@ -104,9 +115,9 @@ public static void setBackground(String file) { } } - public static Rectangle getColorRect(String color) { + public static RectangleWithCircle getColorRect(String color) { try { - return (Rectangle) Terminal2Theme.class.getField(color).get(null); + return (RectangleWithCircle) Terminal2Theme.class.getField(color).get(null); } catch (IllegalAccessException | NoSuchFieldException e) { throw new RuntimeException("Failed to get color rect " + color, e); } diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index 1852ba85f3b..bc991e9555d 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -53,7 +53,9 @@ public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager appPages.size(340, 240).pos(4, 4); Grid appGrid = new Grid() - .size(340, 240) + .pos(44, 22) + .size(340 - 44 * 2, 240 - 22 * 2) + .margin(6) .nextRow(); for (ResourceLocation appID : Terminal2.appMap.keySet()) { @@ -61,11 +63,18 @@ public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager appGrid.child(new ButtonWidget<>() .overlay(Terminal2.appMap.get(appID).getIcon()) + .background(Terminal2Theme.COLOR_BACKGROUND_2.getCircle()) + .hoverBackground(Terminal2Theme.COLOR_BACKGROUND_2.getCircle()) + .size(24, 24) .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) .onMousePressed(i -> { appPages.setPage(appID); return true; })); + + if (appGrid.getChildren().size() % 7 == 0) { + appGrid.nextRow(); + } } appPages.addPage(Terminal2.HOME_ID, appGrid).setDefaultPage(Terminal2.HOME_ID); diff --git a/src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java b/src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java new file mode 100644 index 00000000000..9d06ab914dc --- /dev/null +++ b/src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java @@ -0,0 +1,21 @@ +package gregtech.common.mui.drawable; + +import com.cleanroommc.modularui.drawable.Circle; +import com.cleanroommc.modularui.drawable.Rectangle; + +public class RectangleWithCircle extends Rectangle { + + private Circle circle; + + @Override + public RectangleWithCircle setColor(int color) { + getCircle().setColor(color, color); + super.setColor(color); + return this; + } + + public Circle getCircle() { + // circle needs to be initialized during the super constructor somehow, and this is the simplest way + return circle == null ? circle = new Circle() : circle; + } +} diff --git a/src/main/java/gregtech/common/terminal2/TestApp.java b/src/main/java/gregtech/common/terminal2/TestApp.java index 58b2a557baf..8532efc61af 100644 --- a/src/main/java/gregtech/common/terminal2/TestApp.java +++ b/src/main/java/gregtech/common/terminal2/TestApp.java @@ -10,8 +10,14 @@ public class TestApp implements ITerminalApp { + private final int n; + + public TestApp(int n) { + this.n = n; + } + @Override public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { - return IKey.str("test app").color(0xFFFFFF).shadow(true).asWidget(); + return IKey.str("test app " + n).color(0xFFFFFF).shadow(true).asWidget(); } } From 3f18ffa042ac1446fd7c38fa8f9b47f409fbb847 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:23:33 -0500 Subject: [PATCH 05/17] home screen hover overlays, theme-colored scroll bars --- .../api/terminal2/Terminal2Theme.java | 32 +++---- .../items/behaviors/Terminal2Behavior.java | 3 +- .../common/mui/drawable/BoundRectangle.java | 72 +++++++++++++++ .../mui/drawable/RectangleWithCircle.java | 21 ----- .../gregtech/common/mui/drawable/Ring.java | 90 +++++++++++++++++++ .../mui/widget/ColorableHScrollData.java | 42 +++++++++ .../mui/widget/ColorableVScrollData.java | 42 +++++++++ .../mui/widget/IColorableScrollData.java | 6 ++ .../common/terminal2/SettingsApp.java | 11 ++- 9 files changed, 279 insertions(+), 40 deletions(-) create mode 100644 src/main/java/gregtech/common/mui/drawable/BoundRectangle.java delete mode 100644 src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java create mode 100644 src/main/java/gregtech/common/mui/drawable/Ring.java create mode 100644 src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java create mode 100644 src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java create mode 100644 src/main/java/gregtech/common/mui/widget/IColorableScrollData.java diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java index 4a72a63c78b..e24941fa5b3 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -2,8 +2,8 @@ import gregtech.api.util.FileUtility; import gregtech.api.util.GTUtility; +import gregtech.common.mui.drawable.BoundRectangle; import gregtech.common.mui.drawable.FileTexture; -import gregtech.common.mui.drawable.RectangleWithCircle; import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.drawable.UITexture; @@ -35,32 +35,32 @@ public class Terminal2Theme { public static final List colors = Arrays.stream(Terminal2Theme.class.getFields()) .map(Field::getName).filter(name -> name.startsWith("COLOR_")).collect(Collectors.toList()); - public static RectangleWithCircle COLOR_BRIGHT_1 = new RectangleWithCircle() + public static BoundRectangle COLOR_BRIGHT_1 = new BoundRectangle() .setColor(new Color(144, 243, 116).getRGB()); - public static RectangleWithCircle COLOR_BRIGHT_2 = new RectangleWithCircle() + public static BoundRectangle COLOR_BRIGHT_2 = new BoundRectangle() .setColor(new Color(243, 208, 116).getRGB()); - public static RectangleWithCircle COLOR_BRIGHT_3 = new RectangleWithCircle() + public static BoundRectangle COLOR_BRIGHT_3 = new BoundRectangle() .setColor(new Color(231, 95, 95).getRGB()); - public static RectangleWithCircle COLOR_BRIGHT_4 = new RectangleWithCircle() + public static BoundRectangle COLOR_BRIGHT_4 = new BoundRectangle() .setColor(new Color(230, 230, 230).getRGB()); - public static RectangleWithCircle COLOR_DARK_1 = new RectangleWithCircle() + public static BoundRectangle COLOR_DARK_1 = new BoundRectangle() .setColor(new Color(0, 115, 255).getRGB()); - public static RectangleWithCircle COLOR_DARK_2 = new RectangleWithCircle() + public static BoundRectangle COLOR_DARK_2 = new BoundRectangle() .setColor(new Color(113, 27, 217).getRGB()); - public static RectangleWithCircle COLOR_DARK_3 = new RectangleWithCircle().setColor(new Color(30, 80, 30).getRGB()); - public static RectangleWithCircle COLOR_DARK_4 = new RectangleWithCircle().setColor(new Color(30, 30, 30).getRGB()); + public static BoundRectangle COLOR_DARK_3 = new BoundRectangle().setColor(new Color(30, 80, 30).getRGB()); + public static BoundRectangle COLOR_DARK_4 = new BoundRectangle().setColor(new Color(30, 30, 30).getRGB()); - public static RectangleWithCircle COLOR_FOREGROUND_BRIGHT = new RectangleWithCircle() + public static BoundRectangle COLOR_FOREGROUND_BRIGHT = new BoundRectangle() .setColor(new Color(148, 226, 193).getRGB()); - public static RectangleWithCircle COLOR_FOREGROUND_DARK = new RectangleWithCircle() + public static BoundRectangle COLOR_FOREGROUND_DARK = new BoundRectangle() .setColor(new Color(175, 0, 0, 131).getRGB()); - public static RectangleWithCircle COLOR_BACKGROUND_1 = new RectangleWithCircle() + public static BoundRectangle COLOR_BACKGROUND_1 = new BoundRectangle() .setColor(new Color(0, 0, 0, 80).getRGB()); - public static RectangleWithCircle COLOR_BACKGROUND_2 = new RectangleWithCircle() + public static BoundRectangle COLOR_BACKGROUND_2 = new BoundRectangle() .setColor(new Color(0, 0, 0, 160).getRGB()); - public static RectangleWithCircle COLOR_BACKGROUND_3 = new RectangleWithCircle() + public static BoundRectangle COLOR_BACKGROUND_3 = new BoundRectangle() .setColor(new Color(246, 120, 120, 160).getRGB()); public static void init() { @@ -115,9 +115,9 @@ public static void setBackground(String file) { } } - public static RectangleWithCircle getColorRect(String color) { + public static BoundRectangle getColorRect(String color) { try { - return (RectangleWithCircle) Terminal2Theme.class.getField(color).get(null); + return (BoundRectangle) Terminal2Theme.class.getField(color).get(null); } catch (IllegalAccessException | NoSuchFieldException e) { throw new RuntimeException("Failed to get color rect " + color, e); } diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index bc991e9555d..ae642535604 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -64,7 +64,8 @@ public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager appGrid.child(new ButtonWidget<>() .overlay(Terminal2.appMap.get(appID).getIcon()) .background(Terminal2Theme.COLOR_BACKGROUND_2.getCircle()) - .hoverBackground(Terminal2Theme.COLOR_BACKGROUND_2.getCircle()) + .hoverBackground(Terminal2Theme.COLOR_BACKGROUND_2.getCircle(), + Terminal2Theme.COLOR_BRIGHT_2.getRing()) .size(24, 24) .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) .onMousePressed(i -> { diff --git a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java new file mode 100644 index 00000000000..d505f6ef632 --- /dev/null +++ b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java @@ -0,0 +1,72 @@ +package gregtech.common.mui.drawable; + +import gregtech.common.mui.widget.IColorableScrollData; + +import com.cleanroommc.modularui.drawable.Circle; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.widget.ScrollWidget; +import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BooleanSupplier; +import java.util.function.IntConsumer; + +public class BoundRectangle extends Rectangle { + + private Circle circle; + private Ring ring; + private final List> colorSetters = new ArrayList<>(); + + @Override + public BoundRectangle setColor(int color) { + getCircle().setColor(color, color); + getRing().setColor(color); + super.setColor(color); + if (colorSetters != null) { + for (int i = 0; i < colorSetters.size(); i++) { + var setterPair = colorSetters.get(i); + if (setterPair.getRight().getAsBoolean()) { + colorSetters.remove(i); + i--; + continue; + } + setterPair.getLeft().accept(color); + } + } + return this; + } + + public Circle getCircle() { + // circle needs to be initialized during the super constructor somehow, and this is the simplest way + return circle == null ? circle = new Circle() : circle; + } + + public Ring getRing() { + return ring == null ? ring = new Ring() : ring; + } + + public BoundRectangle bind(IntConsumer colorSetter, BooleanSupplier removeCondition) { + colorSetters.add(Pair.of(colorSetter, removeCondition)); + colorSetter.accept(this.getColor()); + return this; + } + + public BoundRectangle bindScrollFG(ScrollWidget widget) { + HorizontalScrollData scrollX = widget.getScrollArea().getScrollX(); + VerticalScrollData scrollY = widget.getScrollArea().getScrollY(); + if (scrollX instanceof IColorableScrollData scroll) { + bind(scroll::setColor, () -> !widget.isValid()); + } + if (scrollY instanceof IColorableScrollData scroll) { + bind(scroll::setColor, () -> !widget.isValid()); + } + return this; + } + + public BoundRectangle bindScrollBG(ScrollWidget widget) { + return bind(widget.getScrollArea()::setScrollBarBackgroundColor, () -> !widget.isValid()); + } +} diff --git a/src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java b/src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java deleted file mode 100644 index 9d06ab914dc..00000000000 --- a/src/main/java/gregtech/common/mui/drawable/RectangleWithCircle.java +++ /dev/null @@ -1,21 +0,0 @@ -package gregtech.common.mui.drawable; - -import com.cleanroommc.modularui.drawable.Circle; -import com.cleanroommc.modularui.drawable.Rectangle; - -public class RectangleWithCircle extends Rectangle { - - private Circle circle; - - @Override - public RectangleWithCircle setColor(int color) { - getCircle().setColor(color, color); - super.setColor(color); - return this; - } - - public Circle getCircle() { - // circle needs to be initialized during the super constructor somehow, and this is the simplest way - return circle == null ? circle = new Circle() : circle; - } -} diff --git a/src/main/java/gregtech/common/mui/drawable/Ring.java b/src/main/java/gregtech/common/mui/drawable/Ring.java new file mode 100644 index 00000000000..ac7c75626c3 --- /dev/null +++ b/src/main/java/gregtech/common/mui/drawable/Ring.java @@ -0,0 +1,90 @@ +package gregtech.common.mui.drawable; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.utils.Color; +import org.lwjgl.opengl.GL11; + +public class Ring implements IDrawable { + + private int color; + private float ringWidth; + private int segments, start, end; + + public Ring() { + this.color = 0; + this.ringWidth = 0.2f; + this.segments = 40; + this.start = 0; + this.end = this.segments; + } + + public Ring setColor(int color) { + this.color = color; + return this; + } + + public Ring setWidth(float ringWidth) { + if (ringWidth < 0 || ringWidth > 1) { + throw new IllegalArgumentException("ringWidth must be between 0 and 1"); + } + this.ringWidth = ringWidth; + return this; + } + + /** + * This will reset end to segments, call {@link this#setProgress} after this! + */ + public Ring setSegments(int segments) { + this.segments = segments; + this.end = this.segments; + return this; + } + + public Ring setProgress(int start, int end) { + this.start = start; + this.end = end; + return this; + } + + public Ring setProgress(int end) { + this.end = end; + return this; + } + + @Override + public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { + drawRing(x, y, width, height, ringWidth, color, segments, start, end); + } + + // modified from mui0 Widget#drawTorus to + private static void drawRing(float x, float y, float w, float h, float ringWidth, int color, int segments, int from, + int to) { + float cx = x + w / 2f, cy = y + h / 2f; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ZERO); + GlStateManager.color(Color.getRedF(color), Color.getGreenF(color), Color.getBlueF(color), + Color.getAlphaF(color)); + bufferbuilder.begin(GL11.GL_QUAD_STRIP, DefaultVertexFormats.POSITION); + for (int i = from; i <= to; i++) { + float angle = (i / (float) segments) * 3.14159f * 2.0f; + bufferbuilder.pos(cx + (w / 2) * (1 - ringWidth) * Math.cos(-angle), + cy + (h / 2) * (1 - ringWidth) * Math.sin(-angle), 0).endVertex(); + bufferbuilder.pos(cx + (w / 2) * Math.cos(-angle), cy + (h / 2) * Math.sin(-angle), 0).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1, 1, 1, 1); + } +} diff --git a/src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java b/src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java new file mode 100644 index 00000000000..1353a40670d --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java @@ -0,0 +1,42 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.drawable.GuiDraw; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; + +public class ColorableHScrollData extends HorizontalScrollData implements IColorableScrollData { + + private int color; + + public ColorableHScrollData() { + this(0xFFFFFFFF); + } + + public ColorableHScrollData(int color) { + super(); + this.color = color; + } + + public ColorableHScrollData(int color, boolean topAlignment) { + super(topAlignment); + this.color = color; + } + + public ColorableHScrollData(int color, boolean topAlignment, int thickness) { + super(topAlignment, thickness); + this.color = color; + } + + @Override + public IColorableScrollData setColor(int color) { + this.color = color; + return this; + } + + @Override + protected void drawScrollBar(int x, int y, int w, int h) { + GuiDraw.drawRect(x, y, w, h, Color.multiply(color, 14f / 15f, false)); + GuiDraw.drawRect(x + 1, y + 1, w - 1, h - 1, Color.multiply(color, 6f / 15f, false)); + GuiDraw.drawRect(x + 1, y + 1, w - 2, h - 2, Color.multiply(color, 10f / 15f, false)); + } +} diff --git a/src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java b/src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java new file mode 100644 index 00000000000..604865c07fb --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java @@ -0,0 +1,42 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.drawable.GuiDraw; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; + +public class ColorableVScrollData extends VerticalScrollData implements IColorableScrollData { + + private int color; + + public ColorableVScrollData() { + this(0xFFFFFFFF); + } + + public ColorableVScrollData(int color) { + super(); + this.color = color; + } + + public ColorableVScrollData(int color, boolean leftAlignment) { + super(leftAlignment); + this.color = color; + } + + public ColorableVScrollData(int color, boolean leftAlignment, int thickness) { + super(leftAlignment, thickness); + this.color = color; + } + + @Override + public IColorableScrollData setColor(int color) { + this.color = color; + return this; + } + + @Override + protected void drawScrollBar(int x, int y, int w, int h) { + GuiDraw.drawRect(x, y, w, h, Color.multiply(color, 14f / 15f, false)); + GuiDraw.drawRect(x + 1, y + 1, w - 1, h - 1, Color.multiply(color, 6f / 15f, false)); + GuiDraw.drawRect(x + 1, y + 1, w - 2, h - 2, Color.multiply(color, 10f / 15f, false)); + } +} diff --git a/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java b/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java new file mode 100644 index 00000000000..76afa9b5477 --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java @@ -0,0 +1,6 @@ +package gregtech.common.mui.widget; + +public interface IColorableScrollData { + + IColorableScrollData setColor(int color); +} diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java index f5e22b8f9cb..8740789b4c3 100644 --- a/src/main/java/gregtech/common/terminal2/SettingsApp.java +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -3,6 +3,7 @@ import gregtech.api.mui.GTGuis; import gregtech.api.terminal2.ITerminalApp; import gregtech.api.terminal2.Terminal2Theme; +import gregtech.common.mui.widget.ColorableVScrollData; import gregtech.common.mui.widget.GTColorPickerDialog; import com.cleanroommc.modularui.api.IPanelHandler; @@ -17,7 +18,7 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widget.ScrollWidget; -import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; import com.cleanroommc.modularui.widgets.ButtonWidget; import com.cleanroommc.modularui.widgets.ListWidget; import com.cleanroommc.modularui.widgets.layout.Flow; @@ -95,11 +96,12 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager }))); } - var scroll = new ScrollWidget<>(new VerticalScrollData()) + var scroll = new ScrollWidget<>(new ColorableVScrollData()) .child(column) .sizeRel(1.0F); scroll.getScrollArea().getScrollY().setScrollSize(rows * 24); + Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(scroll); return new ParentWidget<>() .sizeRel(0.98F) @@ -134,8 +136,13 @@ private PanelSyncHandler.IPanelBuilder backgroundSelectWidget() { Terminal2Theme.saveConfig(); return true; })) + // convince it to accept the colorable scroll data by giving it one with a different axis first + .scrollDirection(new HorizontalScrollData()) + .scrollDirection(new ColorableVScrollData()) .size(150, 90).pos(9, 16); + Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(list); + return GTGuis.createPopupPanel("terminal_background_select", 168, 112) .child(IKey.lang("terminal.settings.background_select").asWidget() .leftRel(0.5F) From e13b8ea8ff25d4237884672bb5d2388901b6a762 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:50:56 -0500 Subject: [PATCH 06/17] gc bound rect setters on terminal close as well --- .../java/gregtech/api/terminal2/Terminal2Theme.java | 6 ++++++ .../common/items/behaviors/Terminal2Behavior.java | 11 ++++++++++- .../gregtech/common/mui/drawable/BoundRectangle.java | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java index e24941fa5b3..9ff0026f015 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -130,4 +130,10 @@ public static void setColor(String color, int i) { public static void resetToDefaultColor(String color) { setColor(color, defaultColors.get(color)); } + + public static void gcBoundRects() { + for (String color : colors) { + getColorRect(color).gc(); + } + } } diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index ae642535604..997ee024585 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -46,7 +46,16 @@ public GTGuiTheme getUITheme() { @Override public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { ModularPanel panel = GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248); - IDPagedWidget appPages = new IDPagedWidget<>(); + + // to avoid tying the terminal bound rect gc logic to IDPagedWidget itself + @SuppressWarnings("rawtypes") + IDPagedWidget appPages = new IDPagedWidget() { + @Override + public void dispose() { + super.dispose(); + Terminal2Theme.gcBoundRects(); + } + }; for (var app : Terminal2.appMap.entrySet()) { appPages.addPage(app.getKey(), app.getValue().buildWidgets(guiData, guiSyncManager, panel)); } diff --git a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java index d505f6ef632..a04c91d726a 100644 --- a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java +++ b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java @@ -69,4 +69,8 @@ public BoundRectangle bindScrollFG(ScrollWidget widget) { public BoundRectangle bindScrollBG(ScrollWidget widget) { return bind(widget.getScrollArea()::setScrollBarBackgroundColor, () -> !widget.isValid()); } + + public void gc() { + colorSetters.removeIf((e) -> e.getRight().getAsBoolean()); + } } From 1ad1ab2f8cf8a7240f454e2202042f447f639cd2 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Sun, 29 Dec 2024 14:17:26 -0500 Subject: [PATCH 07/17] constants for terminal screen size --- src/main/java/gregtech/api/terminal2/Terminal2.java | 2 +- .../gregtech/common/items/behaviors/Terminal2Behavior.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java index c4acbbcda54..70e7dbd120e 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -17,7 +17,7 @@ import java.util.Map; public class Terminal2 { - + public static final int SCREEN_WIDTH = 340, SCREEN_HEIGHT = 240; public static final Map appMap = new LinkedHashMap<>(); public static final ResourceLocation HOME_ID = GTUtility.gregtechId("home"); diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index 997ee024585..2d9108cabeb 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -59,11 +59,11 @@ public void dispose() { for (var app : Terminal2.appMap.entrySet()) { appPages.addPage(app.getKey(), app.getValue().buildWidgets(guiData, guiSyncManager, panel)); } - appPages.size(340, 240).pos(4, 4); + appPages.size(Terminal2.SCREEN_WIDTH, Terminal2.SCREEN_HEIGHT).pos(4, 4); Grid appGrid = new Grid() .pos(44, 22) - .size(340 - 44 * 2, 240 - 22 * 2) + .size(Terminal2.SCREEN_WIDTH - 44 * 2, Terminal2.SCREEN_HEIGHT - 22 * 2) .margin(6) .nextRow(); @@ -90,7 +90,7 @@ public void dispose() { return panel.background(GTGuiTextures.TERMINAL_FRAME) .child(new DynamicDrawable(Terminal2Theme::getBackgroundDrawable).asWidget() - .size(340, 240) + .size(Terminal2.SCREEN_WIDTH, Terminal2.SCREEN_HEIGHT) .pos(4, 4)) .child(appPages) .child(new ButtonWidget<>() From 99dad6c16827345be96549cfc522af50dc60e39e Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Tue, 7 Jan 2025 16:26:19 -0500 Subject: [PATCH 08/17] cape selector part 1 done: select cape from list todo: sync unlocked/worn capes, test on server, polish --- .../gregtech/api/terminal2/ITerminalApp.java | 2 + .../gregtech/api/terminal2/Terminal2.java | 3 + .../java/gregtech/api/util/CapesRegistry.java | 15 ++- .../items/behaviors/Terminal2Behavior.java | 4 + .../common/terminal2/CapeSelectorApp.java | 119 ++++++++++++++++++ .../resources/assets/gregtech/lang/en_us.lang | 1 + 6 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 src/main/java/gregtech/common/terminal2/CapeSelectorApp.java diff --git a/src/main/java/gregtech/api/terminal2/ITerminalApp.java b/src/main/java/gregtech/api/terminal2/ITerminalApp.java index 1fb40d6e216..e43eea88241 100644 --- a/src/main/java/gregtech/api/terminal2/ITerminalApp.java +++ b/src/main/java/gregtech/api/terminal2/ITerminalApp.java @@ -14,4 +14,6 @@ public interface ITerminalApp { default IDrawable getIcon() { return GuiTextures.IMAGE; } + + default void dispose() {} } diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java index 70e7dbd120e..31626319c86 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -3,6 +3,7 @@ import gregtech.api.util.FileUtility; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; +import gregtech.common.terminal2.CapeSelectorApp; import gregtech.common.terminal2.SettingsApp; import gregtech.common.terminal2.TestApp; @@ -17,6 +18,7 @@ import java.util.Map; public class Terminal2 { + public static final int SCREEN_WIDTH = 340, SCREEN_HEIGHT = 240; public static final Map appMap = new LinkedHashMap<>(); public static final ResourceLocation HOME_ID = GTUtility.gregtechId("home"); @@ -31,6 +33,7 @@ public static void init() { Terminal2Theme.init(); } registerApp(GTUtility.gregtechId("settings"), new SettingsApp()); + registerApp(GTUtility.gregtechId("capes"), new CapeSelectorApp()); for (int i = 0; i < 18; i++) { registerApp(GTUtility.gregtechId("test" + i), new TestApp(i)); } diff --git a/src/main/java/gregtech/api/util/CapesRegistry.java b/src/main/java/gregtech/api/util/CapesRegistry.java index 7d0acaa0ba6..899c1a2cde4 100644 --- a/src/main/java/gregtech/api/util/CapesRegistry.java +++ b/src/main/java/gregtech/api/util/CapesRegistry.java @@ -36,8 +36,8 @@ public class CapesRegistry { private static final Map> UNLOCKED_CAPES = new HashMap<>(); private static final Map WORN_CAPES = new HashMap<>(); - private static final Map CAPE_ADVANCEMENTS = new HashMap<>(); - private static final Set FREE_CAPES = new HashSet<>(); + private static final Map CAPE_ADVANCEMENTS = new LinkedHashMap<>(); + private static final Set FREE_CAPES = new LinkedHashSet<>(); public static void registerDevCapes() { unlockCape(UUID.fromString("a24a9108-23d2-43fc-8db7-43f809d017db"), Textures.GREGTECH_CAPE_TEXTURE); // ALongStringOfNumbers @@ -250,6 +250,17 @@ public static void unlockCapeOnAdvancement(EntityPlayer player, Advancement adva } } + /** + * @return A list of all registered capes, with advancement capes sorted before free capes. + * This currently does not count capes that are manually unlocked by other mods. + */ + public static List allCapes() { + List result = new ArrayList<>(); + result.addAll(CAPE_ADVANCEMENTS.values()); + result.addAll(FREE_CAPES); + return result; + } + public static void clearMaps() { UNLOCKED_CAPES.clear(); WORN_CAPES.clear(); diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index 2d9108cabeb..c6c2c4b682b 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -50,10 +50,14 @@ public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager // to avoid tying the terminal bound rect gc logic to IDPagedWidget itself @SuppressWarnings("rawtypes") IDPagedWidget appPages = new IDPagedWidget() { + @Override public void dispose() { super.dispose(); Terminal2Theme.gcBoundRects(); + for (var app : Terminal2.appMap.values()) { + app.dispose(); + } } }; for (var app : Terminal2.appMap.entrySet()) { diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java new file mode 100644 index 00000000000..1de63f588a2 --- /dev/null +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -0,0 +1,119 @@ +package gregtech.common.terminal2; + +import gregtech.api.terminal2.ITerminalApp; +import gregtech.api.terminal2.Terminal2Theme; +import gregtech.api.util.CapesRegistry; +import gregtech.api.util.GTLog; +import gregtech.client.renderer.texture.Textures; +import gregtech.common.mui.widget.ColorableVScrollData; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.value.sync.SyncHandler; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Grid; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +// todo: this needs testing on dedicated server once that no longer crashes (mui rc3) +public class CapeSelectorApp implements ITerminalApp { + + private static final int SYNC_UNLOCKED_CAPES = 1; + private static final int SELECT_CAPE = 2; + + @Override + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { + UUID uuid = guiData.getPlayer().getPersistentID(); + var syncHandler = new CapeSelectorSyncHandler(uuid); + guiSyncManager.syncValue("cape_handler", syncHandler); + + var capeGrid = new Grid() + .sizeRel(1f) + .posRel(0.5f, 0.5f) + .margin(21) + .scrollable(new ColorableVScrollData()) + .nextRow(); + Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(capeGrid); + + for (ResourceLocation cape : CapesRegistry.allCapes()) { + if (capeGrid.getChildren().size() % 4 == 0 && !capeGrid.getChildren().isEmpty()) { + capeGrid.nextRow(); + } + + capeGrid.child(new ButtonWidget<>() + .size(40, 72) + .overlay(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, false)) + .background(Terminal2Theme.COLOR_BACKGROUND_2) + .disableHoverOverlay() + .hoverBackground(Terminal2Theme.COLOR_DARK_4) + .onMousePressed(b -> { + GTLog.logger.info("set {}", cape.toString()); + syncHandler.syncToServer(SELECT_CAPE, buf -> buf.writeString(cape.toString())); + return true; + })); + } + + return new ParentWidget<>() + .sizeRel(0.98f) + .posRel(0.5f, 0.5f) + .background(Terminal2Theme.COLOR_BACKGROUND_1) + .child(capeGrid); + } + + @Override + public IDrawable getIcon() { + return new UITexture(Textures.GREGTECH_CAPE_TEXTURE, 32f / 64, 0, 46f / 64, 22f / 32, false); + } + + private static final class CapeSelectorSyncHandler extends SyncHandler { + + private final UUID uuid; + private List unlockedCapes; + + public CapeSelectorSyncHandler(UUID uuid) { + this.uuid = uuid; + } + +// @Override +// public void init(String key, PanelSyncManager syncManager) { +// super.init(key, syncManager); +// if (!getSyncManager().isClient()) { +// unlockedCapes = CapesRegistry.getUnlockedCapes(uuid); +// syncToClient(SYNC_UNLOCKED_CAPES, buf -> { +// buf.writeVarInt(unlockedCapes.size()); +// for (ResourceLocation cape : unlockedCapes) { +// buf.writeString(cape.toString()); +// } +// }); +// } +// } + + @Override + public void readOnClient(int id, PacketBuffer buf) { + if (id == SYNC_UNLOCKED_CAPES) { + int len = buf.readVarInt(); + unlockedCapes = new ArrayList<>(len); + for (int i = 0; i < len; i++) { + unlockedCapes.add(new ResourceLocation(buf.readString(Short.MAX_VALUE))); + } + } + } + + @Override + public void readOnServer(int id, PacketBuffer buf) { + if (id == SELECT_CAPE) { + CapesRegistry.giveCape(uuid, new ResourceLocation(buf.readString(Short.MAX_VALUE))); + } + } + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index ee4badcdb14..114916d5e57 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -6053,6 +6053,7 @@ gregtech.creative.activity.off=Not active # new terminal terminal.app.gregtech.home.name=Home terminal.app.gregtech.settings.name=Theme Settings +terminal.app.gregtech.capes.name=Cape Selector terminal.app.gregtech.test.name=test app terminal.settings.background=Background From 50999cb969d46a87dc1b60504c16d0304486b752 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:02:03 -0500 Subject: [PATCH 09/17] mui rc3 fixes and simplifications --- .../items/behaviors/Terminal2Behavior.java | 2 +- .../common/mui/drawable/BoundRectangle.java | 6 +- .../mui/widget/GTColorPickerDialog.java | 224 +----------------- .../common/terminal2/CapeSelectorApp.java | 2 +- .../common/terminal2/SettingsApp.java | 14 +- 5 files changed, 24 insertions(+), 224 deletions(-) diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index c6c2c4b682b..4de2b92c8d5 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -68,7 +68,7 @@ public void dispose() { Grid appGrid = new Grid() .pos(44, 22) .size(Terminal2.SCREEN_WIDTH - 44 * 2, Terminal2.SCREEN_HEIGHT - 22 * 2) - .margin(6) + .minElementMargin(6) .nextRow(); for (ResourceLocation appID : Terminal2.appMap.keySet()) { diff --git a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java index a04c91d726a..be21767f71b 100644 --- a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java +++ b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java @@ -4,7 +4,7 @@ import com.cleanroommc.modularui.drawable.Circle; import com.cleanroommc.modularui.drawable.Rectangle; -import com.cleanroommc.modularui.widget.ScrollWidget; +import com.cleanroommc.modularui.widget.AbstractScrollWidget; import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; import org.apache.commons.lang3.tuple.Pair; @@ -54,7 +54,7 @@ public BoundRectangle bind(IntConsumer colorSetter, BooleanSupplier removeCondit return this; } - public BoundRectangle bindScrollFG(ScrollWidget widget) { + public BoundRectangle bindScrollFG(AbstractScrollWidget widget) { HorizontalScrollData scrollX = widget.getScrollArea().getScrollX(); VerticalScrollData scrollY = widget.getScrollArea().getScrollY(); if (scrollX instanceof IColorableScrollData scroll) { @@ -66,7 +66,7 @@ public BoundRectangle bindScrollFG(ScrollWidget widget) { return this; } - public BoundRectangle bindScrollBG(ScrollWidget widget) { + public BoundRectangle bindScrollBG(AbstractScrollWidget widget) { return bind(widget.getScrollArea()::setScrollBarBackgroundColor, () -> !widget.isValid()); } diff --git a/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java index 68766fc13cc..a021234e211 100644 --- a/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java +++ b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java @@ -1,228 +1,28 @@ package gregtech.common.mui.widget; -import gregtech.api.mui.GTGuiTextures; - -import com.cleanroommc.modularui.api.GuiAxis; -import com.cleanroommc.modularui.api.drawable.IDrawable; -import com.cleanroommc.modularui.api.drawable.IKey; -import com.cleanroommc.modularui.api.widget.IWidget; -import com.cleanroommc.modularui.drawable.GuiTextures; -import com.cleanroommc.modularui.drawable.HueBar; -import com.cleanroommc.modularui.drawable.Rectangle; -import com.cleanroommc.modularui.utils.Alignment; -import com.cleanroommc.modularui.utils.Color; -import com.cleanroommc.modularui.value.DoubleValue; -import com.cleanroommc.modularui.value.StringValue; -import com.cleanroommc.modularui.widgets.ButtonWidget; -import com.cleanroommc.modularui.widgets.Dialog; -import com.cleanroommc.modularui.widgets.PageButton; -import com.cleanroommc.modularui.widgets.PagedWidget; +import com.cleanroommc.modularui.widget.WidgetTree; +import com.cleanroommc.modularui.widgets.ColorPickerDialog; import com.cleanroommc.modularui.widgets.SliderWidget; -import com.cleanroommc.modularui.widgets.layout.Column; -import com.cleanroommc.modularui.widgets.layout.Row; -import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; -import java.util.ArrayList; -import java.util.List; import java.util.function.Consumer; -// TODO remove this class when MUI2 page buttons stop having inverted backgrounds and MUI2 color picker obeys theming -// for its page buttons, and the weird resizing bugs are fixed -public class GTColorPickerDialog extends Dialog { - - private static final IDrawable handleBackground = new Rectangle().setColor(Color.WHITE.main); - - private int color; - private final int alpha; - private final boolean controlAlpha; - - private final Rectangle preview = new Rectangle(); - private final Rectangle sliderBackgroundR = new Rectangle(); - private final Rectangle sliderBackgroundG = new Rectangle(); - private final Rectangle sliderBackgroundB = new Rectangle(); - private final Rectangle sliderBackgroundA = new Rectangle(); - private final Rectangle sliderBackgroundS = new Rectangle(); - private final Rectangle sliderBackgroundV = new Rectangle(); - - private final List sliders = new ArrayList<>(); - - public GTColorPickerDialog(Consumer resultConsumer, int startColor, boolean controlAlpha) { - this("color_picker", resultConsumer, startColor, controlAlpha); - } +// TODO remove this class when the weird resizing bugs are fixed +public class GTColorPickerDialog extends ColorPickerDialog { public GTColorPickerDialog(String name, Consumer resultConsumer, int startColor, boolean controlAlpha) { - super(name, resultConsumer); - this.alpha = Color.getAlpha(startColor); - updateColor(startColor); - this.controlAlpha = controlAlpha; - size(140, controlAlpha ? 106 : 94).background(GuiTextures.MC_BACKGROUND); - IWidget alphaSlider = controlAlpha ? new Row() - .widthRel(1f).height(12) - .child(IKey.str("A: ").asWidget().heightRel(1f)) - .child(createSlider(this.sliderBackgroundA) - .bounds(0, 255) - .value(new DoubleValue.Dynamic(() -> Color.getAlpha(this.color), - val -> updateColor(Color.withAlpha(this.color, (int) val))))) : - null; - - PagedWidget.Controller controller = new PagedWidget.Controller(); - child(new Column() - .left(5).right(5).top(5).bottom(5) - .child(new Row() - .left(5).right(5).height(14) - .child(new PageButton(0, controller) - .sizeRel(0.5f, 1f) - .background(true, GTGuiTextures.SLOT) - .background(false, GTGuiTextures.BUTTON) - .overlay(IKey.str("RGB"))) - .child(new PageButton(1, controller) - .sizeRel(0.5f, 1f) - .background(true, GTGuiTextures.SLOT) - .background(false, GTGuiTextures.BUTTON) - .overlay(IKey.str("HSV")))) - .child(new Row().widthRel(1f).height(12).marginTop(4) - .child(IKey.str("Hex: ").asWidget().heightRel(1f)) - .child(new TextFieldWidget() - .height(12) - .expanded() - .setValidator(this::validateRawColor) - .value(new StringValue.Dynamic(() -> { - if (controlAlpha) { - return "#" + Integer.toHexString(this.color); - } - return "#" + Integer.toHexString(Color.withAlpha(this.color, 0)); - }, val -> { - try { - updateColor(Integer.decode(val)); - } catch (NumberFormatException ignored) {} - }))) - .child(this.preview.asWidget().background(GuiTextures.CHECKBOARD).size(10, 10).margin(1))) - .child(new PagedWidget<>() - .left(5).right(5) - .expanded() - .controller(controller) - .addPage(createRGBPage(alphaSlider)) - .addPage(createHSVPage(alphaSlider))) - .child(new Row() - .left(10).right(10).height(14) - .mainAxisAlignment(Alignment.MainAxis.SPACE_BETWEEN) - .child(new ButtonWidget<>() - .heightRel(1f).width(50) - .overlay(IKey.str("Cancel")) - .onMousePressed(button -> { - animateClose(); - return true; - })) - .child(new ButtonWidget<>() - .heightRel(1f).width(50) - .overlay(IKey.str("Confirm")) - .onMousePressed(button -> { - closeWith(this.color); - return true; - })))); - } - - private IWidget createRGBPage(IWidget alphaSlider) { - return new Column() - .sizeRel(1f, 1f) - .child(new Row() - .widthRel(1f).height(12) - .child(IKey.str("R: ").asWidget().heightRel(1f)) - .child(createSlider(this.sliderBackgroundR) - .bounds(0, 255) - .value(new DoubleValue.Dynamic(() -> Color.getRed(this.color), - val -> updateColor(Color.withRed(this.color, (int) val)))))) - .child(new Row() - .widthRel(1f).height(12) - .child(IKey.str("G: ").asWidget().heightRel(1f)) - .child(createSlider(this.sliderBackgroundG) - .bounds(0, 255) - .value(new DoubleValue.Dynamic(() -> Color.getGreen(this.color), - val -> updateColor(Color.withGreen(this.color, (int) val)))))) - .child(new Row() - .widthRel(1f).height(12) - .child(IKey.str("B: ").asWidget().heightRel(1f)) - .child(createSlider(this.sliderBackgroundB) - .bounds(0, 255) - .value(new DoubleValue.Dynamic(() -> Color.getBlue(this.color), - val -> updateColor(Color.withBlue(this.color, (int) val)))))) - .childIf(alphaSlider != null, alphaSlider); - } - - private IWidget createHSVPage(IWidget alphaSlider) { - return new Column() - .sizeRel(1f, 1f) - .child(new Row() - .widthRel(1f).height(12) - .child(IKey.str("H: ").asWidget().heightRel(1f)) - .child(createSlider(new HueBar(GuiAxis.X)) - .bounds(0, 360) - .value(new DoubleValue.Dynamic(() -> Color.getHue(this.color), - val -> updateColor(Color.withHSVHue(this.color, (float) val)))))) - .child(new Row() - .widthRel(1f).height(12) - .child(IKey.str("S: ").asWidget().heightRel(1f)) - .child(createSlider(this.sliderBackgroundS) - .bounds(0, 1) - .value(new DoubleValue.Dynamic(() -> Color.getHSVSaturation(this.color), - val -> updateColor(Color.withHSVSaturation(this.color, (float) val)))))) - .child(new Row() - .widthRel(1f).height(12) - .child(IKey.str("V: ").asWidget().heightRel(1f)) - .child(createSlider(this.sliderBackgroundV) - .bounds(0, 1) - .value(new DoubleValue.Dynamic(() -> Color.getValue(this.color), - val -> updateColor(Color.withValue(this.color, (float) val)))))) - .childIf(alphaSlider != null, alphaSlider); - } - - private SliderWidget createSlider(IDrawable background) { - var result = new SliderWidget() - .expanded() - .heightRel(1f) - .background(background.asIcon().size(0, 4)) - .sliderTexture(handleBackground) - .sliderSize(2, 8); - sliders.add(result); - return result; + super(name, resultConsumer, startColor, controlAlpha); } @Override public void onResized() { super.onResized(); - // HACK: work around this not getting called by MUI2 in some situations - for (var slider : sliders) { - slider.onResized(); - } - } - - private String validateRawColor(String raw) { - if (!raw.startsWith("#")) { - if (raw.startsWith("0x") || raw.startsWith("0X")) { - raw = raw.substring(2); + // forEachChild has flawed logic and doesnt actually work + WidgetTree.foreachChildBFS(getThis(), (w) -> { + if (w instanceof SliderWidget slider) { + // HACK: work around this not getting called by MUI2 in some situations + slider.onResized(); } - return "#" + raw; - } - return raw; - } - - public void updateColor(int color) { - this.color = color; - if (!this.controlAlpha) { - this.color = Color.withAlpha(this.color, this.alpha); - } - color = Color.withAlpha(color, 255); - int rs = Color.withRed(color, 0), re = Color.withRed(color, 255); - int gs = Color.withGreen(color, 0), ge = Color.withGreen(color, 255); - int bs = Color.withBlue(color, 0), be = Color.withBlue(color, 255); - int as = Color.withAlpha(color, 0), ae = Color.withAlpha(color, 255); - this.sliderBackgroundR.setHorizontalGradient(rs, re); - this.sliderBackgroundG.setHorizontalGradient(gs, ge); - this.sliderBackgroundB.setHorizontalGradient(bs, be); - this.sliderBackgroundA.setHorizontalGradient(as, ae); - this.sliderBackgroundS.setHorizontalGradient(Color.withHSVSaturation(color, 0f), - Color.withHSVSaturation(color, 1f)); - this.sliderBackgroundV.setHorizontalGradient(Color.withValue(color, 0f), Color.withValue(color, 1f)); - this.preview.setColor(this.color); + return true; + }); } } diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java index 1de63f588a2..036656bafaf 100644 --- a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -40,7 +40,7 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager var capeGrid = new Grid() .sizeRel(1f) .posRel(0.5f, 0.5f) - .margin(21) + .minElementMargin(21) .scrollable(new ColorableVScrollData()) .nextRow(); Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(capeGrid); diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java index 8740789b4c3..126343654a3 100644 --- a/src/main/java/gregtech/common/terminal2/SettingsApp.java +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -13,8 +13,8 @@ import com.cleanroommc.modularui.drawable.GuiTextures; import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.SecondaryPanel; import com.cleanroommc.modularui.utils.Alignment; -import com.cleanroommc.modularui.value.sync.PanelSyncHandler; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widget.ScrollWidget; @@ -32,7 +32,7 @@ public class SettingsApp implements ITerminalApp { @Override public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { - var backgroundSelectPanel = (PanelSyncHandler) guiSyncManager.panel("terminal_background_select", + var backgroundSelectPanel = IPanelHandler.simple(panel, backgroundSelectWidget(), true); int rows = Terminal2Theme.colors.size() + 1; @@ -115,7 +115,7 @@ public IDrawable getIcon() { return GuiTextures.GEAR; } - private PanelSyncHandler.IPanelBuilder backgroundSelectWidget() { + private SecondaryPanel.IPanelBuilder backgroundSelectWidget() { return (syncManager, syncHandler) -> { String[] files = Terminal2Theme.backgroundsDir.list(); List options; @@ -127,12 +127,12 @@ private PanelSyncHandler.IPanelBuilder backgroundSelectWidget() { options.sort(Comparator.naturalOrder()); options.add(0, "default"); - var list = ListWidget.builder(options, (st) -> new ButtonWidget<>() - .overlay(IKey.str(st)) + var list = new ListWidget<>().children(options.size(), (i) -> new ButtonWidget<>() + .overlay(IKey.str(options.get(i))) .size(140, 18) .leftRel(0.2F) - .onMousePressed(i -> { - Terminal2Theme.setBackground(st); + .onMousePressed(j -> { + Terminal2Theme.setBackground(options.get(i)); Terminal2Theme.saveConfig(); return true; })) From 283896ee247a74e129ba34a9d2acf964b3b130e7 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Mon, 19 May 2025 18:17:48 -0400 Subject: [PATCH 10/17] cape selector finished --- .../java/gregtech/api/mui/GTGuiTextures.java | 1 + .../gregtech/api/terminal2/ITerminalApp.java | 2 + .../java/gregtech/api/util/CapesRegistry.java | 6 +- .../items/behaviors/Terminal2Behavior.java | 8 +- .../common/terminal2/CapeSelectorApp.java | 108 ++++++++++++++---- .../resources/assets/gregtech/lang/en_us.lang | 3 + .../textures/gui/terminal/capes/icon.png | Bin 0 -> 424 bytes 7 files changed, 99 insertions(+), 29 deletions(-) create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/capes/icon.png diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index 499166b5c66..484c98f62ab 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -293,6 +293,7 @@ private static String id(String path) { public static final UITexture TERMINAL_FRAME = fullImage("textures/gui/terminal/terminal_frame.png"); public static final UITexture HOME_BUTTON = fullImage("textures/gui/terminal/home_button.png"); public static final UITexture HOME_BUTTON_HOVER = fullImage("textures/gui/terminal/home_button_hover.png"); + public static final UITexture CAPES_APP_ICON = fullImage("textures/gui/terminal/capes/icon.png"); // todo bronze/steel/primitive fluid slots? diff --git a/src/main/java/gregtech/api/terminal2/ITerminalApp.java b/src/main/java/gregtech/api/terminal2/ITerminalApp.java index e43eea88241..b12ab443e10 100644 --- a/src/main/java/gregtech/api/terminal2/ITerminalApp.java +++ b/src/main/java/gregtech/api/terminal2/ITerminalApp.java @@ -15,5 +15,7 @@ default IDrawable getIcon() { return GuiTextures.IMAGE; } + default void onOpen() {} + default void dispose() {} } diff --git a/src/main/java/gregtech/api/util/CapesRegistry.java b/src/main/java/gregtech/api/util/CapesRegistry.java index 899c1a2cde4..a6caa9db8cf 100644 --- a/src/main/java/gregtech/api/util/CapesRegistry.java +++ b/src/main/java/gregtech/api/util/CapesRegistry.java @@ -36,7 +36,8 @@ public class CapesRegistry { private static final Map> UNLOCKED_CAPES = new HashMap<>(); private static final Map WORN_CAPES = new HashMap<>(); - private static final Map CAPE_ADVANCEMENTS = new LinkedHashMap<>(); + private static final Map CAPE_ADVANCEMENTS = new HashMap<>(); + private static final Set ADVANCEMENT_CAPES = new LinkedHashSet<>(); private static final Set FREE_CAPES = new LinkedHashSet<>(); public static void registerDevCapes() { @@ -199,6 +200,7 @@ public static void registerCape(ResourceLocation advancement, ResourceLocation c CAPE_ADVANCEMENTS.put(advObject, cape); } } + ADVANCEMENT_CAPES.add(cape); } /** @@ -256,7 +258,7 @@ public static void unlockCapeOnAdvancement(EntityPlayer player, Advancement adva */ public static List allCapes() { List result = new ArrayList<>(); - result.addAll(CAPE_ADVANCEMENTS.values()); + result.addAll(ADVANCEMENT_CAPES); result.addAll(FREE_CAPES); return result; } diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index 4de2b92c8d5..b2ed31dfe0a 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -6,6 +6,7 @@ import gregtech.api.mui.GTGuiTheme; import gregtech.api.mui.GTGuis; import gregtech.api.mui.factory.MetaItemGuiFactory; +import gregtech.api.terminal2.ITerminalApp; import gregtech.api.terminal2.Terminal2; import gregtech.api.terminal2.Terminal2Theme; import gregtech.common.mui.widget.IDPagedWidget; @@ -71,11 +72,13 @@ public void dispose() { .minElementMargin(6) .nextRow(); - for (ResourceLocation appID : Terminal2.appMap.keySet()) { + for (var appEntry : Terminal2.appMap.entrySet()) { + ResourceLocation appID = appEntry.getKey(); + ITerminalApp app = appEntry.getValue(); if (appID == Terminal2.HOME_ID) continue; appGrid.child(new ButtonWidget<>() - .overlay(Terminal2.appMap.get(appID).getIcon()) + .overlay(app.getIcon()) .background(Terminal2Theme.COLOR_BACKGROUND_2.getCircle()) .hoverBackground(Terminal2Theme.COLOR_BACKGROUND_2.getCircle(), Terminal2Theme.COLOR_BRIGHT_2.getRing()) @@ -83,6 +86,7 @@ public void dispose() { .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) .onMousePressed(i -> { appPages.setPage(appID); + app.onOpen(); return true; })); diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java index 036656bafaf..51059112dbb 100644 --- a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -1,10 +1,9 @@ package gregtech.common.terminal2; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.terminal2.ITerminalApp; import gregtech.api.terminal2.Terminal2Theme; import gregtech.api.util.CapesRegistry; -import gregtech.api.util.GTLog; -import gregtech.client.renderer.texture.Textures; import gregtech.common.mui.widget.ColorableVScrollData; import net.minecraft.network.PacketBuffer; @@ -12,6 +11,7 @@ import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.DynamicDrawable; import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; @@ -22,25 +22,28 @@ import com.cleanroommc.modularui.widgets.layout.Grid; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.function.Supplier; -// todo: this needs testing on dedicated server once that no longer crashes (mui rc3) public class CapeSelectorApp implements ITerminalApp { private static final int SYNC_UNLOCKED_CAPES = 1; private static final int SELECT_CAPE = 2; + private CapeSelectorSyncHandler syncHandler; + @Override public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { UUID uuid = guiData.getPlayer().getPersistentID(); - var syncHandler = new CapeSelectorSyncHandler(uuid); + syncHandler = new CapeSelectorSyncHandler(uuid); guiSyncManager.syncValue("cape_handler", syncHandler); var capeGrid = new Grid() .sizeRel(1f) .posRel(0.5f, 0.5f) - .minElementMargin(21) + .minElementMargin(18) .scrollable(new ColorableVScrollData()) .nextRow(); Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(capeGrid); @@ -50,17 +53,25 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager capeGrid.nextRow(); } - capeGrid.child(new ButtonWidget<>() + IWidget capeButton = new ButtonWidget<>() .size(40, 72) + .posRel(0.5F, 0.5F) .overlay(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, false)) .background(Terminal2Theme.COLOR_BACKGROUND_2) .disableHoverOverlay() - .hoverBackground(Terminal2Theme.COLOR_DARK_4) .onMousePressed(b -> { - GTLog.logger.info("set {}", cape.toString()); syncHandler.syncToServer(SELECT_CAPE, buf -> buf.writeString(cape.toString())); return true; - })); + }); + + capeGrid.child(new ParentWidget<>() + .size(46, 78) + .background(new DynamicDrawable(capeBackground(cape))) + .overlay(new DynamicDrawable(capeForeground(cape))) + .child(capeButton) + .child(new DynamicDrawable(capeOverlay(cape)).asWidget() + .size(24) + .posRel(0.5F, 0.5F))); } return new ParentWidget<>() @@ -72,31 +83,69 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager @Override public IDrawable getIcon() { - return new UITexture(Textures.GREGTECH_CAPE_TEXTURE, 32f / 64, 0, 46f / 64, 22f / 32, false); + return GTGuiTextures.CAPES_APP_ICON; + } + + @Override + public void onOpen() { + syncHandler.syncUnlockedCapes(); + } + + @Override + public void dispose() { + syncHandler = null; + } + + private Supplier capeBackground(ResourceLocation cape) { + return () -> { + if (cape.equals(CapesRegistry.getPlayerCape(syncHandler.uuid))) { + return Terminal2Theme.COLOR_BRIGHT_1; + } else if (syncHandler.unlockedCapes.contains(cape)) { + return Terminal2Theme.COLOR_BACKGROUND_2; + } + return Terminal2Theme.COLOR_BRIGHT_3; + }; + } + + private Supplier capeOverlay(ResourceLocation cape) { + return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : GTGuiTextures.RECIPE_LOCK; + } + + private Supplier capeForeground(ResourceLocation cape) { + return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : Terminal2Theme.COLOR_FOREGROUND_DARK; } private static final class CapeSelectorSyncHandler extends SyncHandler { private final UUID uuid; - private List unlockedCapes; + private List unlockedCapes = Collections.emptyList(); public CapeSelectorSyncHandler(UUID uuid) { this.uuid = uuid; } -// @Override -// public void init(String key, PanelSyncManager syncManager) { -// super.init(key, syncManager); -// if (!getSyncManager().isClient()) { -// unlockedCapes = CapesRegistry.getUnlockedCapes(uuid); -// syncToClient(SYNC_UNLOCKED_CAPES, buf -> { -// buf.writeVarInt(unlockedCapes.size()); -// for (ResourceLocation cape : unlockedCapes) { -// buf.writeString(cape.toString()); -// } -// }); -// } -// } + private void syncUnlockedCapes() { + if (!getSyncManager().isClient()) { + unlockedCapes = CapesRegistry.getUnlockedCapes(uuid); + syncToClient(SYNC_UNLOCKED_CAPES, buf -> { + buf.writeVarInt(unlockedCapes.size()); + for (ResourceLocation cape : unlockedCapes) { + buf.writeString(cape.toString()); + } + }); + } else { + syncToServer(SYNC_UNLOCKED_CAPES); + } + } + + @Override + public void detectAndSendChanges(boolean init) { + super.detectAndSendChanges(init); + if (init) { + // prevents flicker when opening the app on dedicated server + syncUnlockedCapes(); + } + } @Override public void readOnClient(int id, PacketBuffer buf) { @@ -112,7 +161,16 @@ public void readOnClient(int id, PacketBuffer buf) { @Override public void readOnServer(int id, PacketBuffer buf) { if (id == SELECT_CAPE) { - CapesRegistry.giveCape(uuid, new ResourceLocation(buf.readString(Short.MAX_VALUE))); + ResourceLocation cape = new ResourceLocation(buf.readString(Short.MAX_VALUE)); + if (unlockedCapes.contains(cape)) { + if (cape.equals(CapesRegistry.getPlayerCape(uuid))) { + CapesRegistry.giveCape(uuid, null); + } else { + CapesRegistry.giveCape(uuid, cape); + } + } + } else if (id == SYNC_UNLOCKED_CAPES) { + syncUnlockedCapes(); } } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 114916d5e57..6284bc5ed43 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -6061,6 +6061,9 @@ terminal.settings.background_select=Select Background terminal.settings.color=Set color %s terminal.settings.reset_color=Reset to default color +terminal.capes.locked=Unlock this cape by progressing through GregTech's advancements +terminal.capes.selected=Equipped + # old terminal # currently indirectly used in alarm terminal.component.searching=searching diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/capes/icon.png b/src/main/resources/assets/gregtech/textures/gui/terminal/capes/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9858d9325ed634dc5a561f8f7c3fbfeafbb47f90 GIT binary patch literal 424 zcmV;Z0ayNsP)Px$Vo5|nR7i>Kl}}2;Kop0+O2BMFD5cCsp)EA@240}x#$}HncmY8{H-d{4y+9A( zuFEVc3O$3kk>aA@D!3>in-mJ^;-!CrWG32$2tEii!*Aa2n|T>#;6HvlDq8WlpW=04 z@(iDE8=>BjHq+9_i$Whui(i>~T~M98<{o?ne;Z)g@ctwpfP1*nq7P|nZLP(gR;@O2 zrr~u!(hme&Yv+MQYc$RP!n>FJ_;LtFa>gGMo^K}Vaf{|B?_+K|P3-B;rgQ7jNs=mAKbT?eQ(P<{{POQ~{Y(}cc6iv%p2 zD2DLterv_U&CX_1t%Y$1ASF?QbD~)4UVojS#-lQ+B>-E;Q2D*QvEhi819)AWW=pP% zAA}xY+3T*;Y{Ai~w5##X0FzOPU77D9QyAuG--9$w%>bZMDYhwfOm~UD4_E?A3tQ=5 SLTj4<0000 Date: Tue, 20 May 2025 15:19:15 -0400 Subject: [PATCH 11/17] cleanup, javadocs --- .../java/gregtech/api/mui/GTGuiTextures.java | 1 + .../java/gregtech/api/mui/GTGuiTheme.java | 1 + .../gregtech/api/terminal2/ITerminalApp.java | 12 ++++++++++ .../gregtech/api/terminal2/Terminal2.java | 19 +++++++++++---- .../api/terminal2/Terminal2Theme.java | 4 ++++ .../items/behaviors/Terminal2Behavior.java | 2 +- .../gregtech/common/mui/drawable/Ring.java | 2 +- .../mui/widget/IColorableScrollData.java | 1 + .../common/terminal2/CapeSelectorApp.java | 8 +++---- .../common/terminal2/SettingsApp.java | 1 + .../gregtech/common/terminal2/TestApp.java | 23 ------------------- 11 files changed, 41 insertions(+), 33 deletions(-) delete mode 100644 src/main/java/gregtech/common/terminal2/TestApp.java diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index 484c98f62ab..a90a838feb5 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -267,6 +267,7 @@ private static String id(String path) { public static final UITexture MENU_OVERLAY = fullImage("textures/gui/overlay/menu_overlay.png"); public static final UITexture RECIPE_LOCK = fullImage("textures/gui/widget/lock.png"); + public static final UITexture RECIPE_LOCK_WHITE = fullImage("textures/gui/widget/lock_white.png"); public static final UITexture PRIMITIVE_FURNACE_OVERLAY = fullImage( "textures/gui/primitive/overlay_primitive_furnace.png"); public static final UITexture PRIMITIVE_DUST_OVERLAY = fullImage( diff --git a/src/main/java/gregtech/api/mui/GTGuiTheme.java b/src/main/java/gregtech/api/mui/GTGuiTheme.java index 429dff24c73..0195d844425 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTheme.java +++ b/src/main/java/gregtech/api/mui/GTGuiTheme.java @@ -99,6 +99,7 @@ private static String gregtech(String s) { .itemSlot(GTGuiTextures.IDs.PRIMITIVE_SLOT) .build(); + // TODO make this better public static final GTGuiTheme TERMINAL = templateBuilder("gregtech_terminal") .parent("gregtech_standard") .textColor(0xFFFDFDFD) diff --git a/src/main/java/gregtech/api/terminal2/ITerminalApp.java b/src/main/java/gregtech/api/terminal2/ITerminalApp.java index b12ab443e10..76c6e43206d 100644 --- a/src/main/java/gregtech/api/terminal2/ITerminalApp.java +++ b/src/main/java/gregtech/api/terminal2/ITerminalApp.java @@ -9,13 +9,25 @@ public interface ITerminalApp { + /** + * Create the UI for your app. + */ IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel); + /** + * @return The drawable that will be used for the icon of your app on the terminal home screen. + */ default IDrawable getIcon() { return GuiTextures.IMAGE; } + /** + * Called when the user opens your app from the terminal home screen. + */ default void onOpen() {} + /** + * Called when the terminal is closed. Free any references to UI elements or sync handlers here. + */ default void dispose() {} } diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java index 31626319c86..3dbe2f8018c 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -5,7 +5,6 @@ import gregtech.common.ConfigHolder; import gregtech.common.terminal2.CapeSelectorApp; import gregtech.common.terminal2.SettingsApp; -import gregtech.common.terminal2.TestApp; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -34,11 +33,23 @@ public static void init() { } registerApp(GTUtility.gregtechId("settings"), new SettingsApp()); registerApp(GTUtility.gregtechId("capes"), new CapeSelectorApp()); - for (int i = 0; i < 18; i++) { - registerApp(GTUtility.gregtechId("test" + i), new TestApp(i)); - } + + /* + * TODO potential apps to create/port: + * guide/tutorial app using mui2 rich text and markup files of some sort + * terminal games (minesweeper, pong, theseus' escape) + * recipe chart (if anyone actually wants to port it) + * teleporter (would require a system allowing gating apps behind some requirement, too powerful to be default) + */ } + /** + * Register a terminal app. Call this during initialization. + * + * @param id A unique identifier for your app. This is used to determine the lang key for the app name tooltip. + *

+ * e.g. gregtech:capes -> terminal.app.gregtech.capes + */ public static void registerApp(ResourceLocation id, ITerminalApp app) { if (appMap.containsKey(id) || HOME_ID.equals(id)) { throw new AssertionError("A terminal app with id " + id + " already exists!"); diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java index 9ff0026f015..98d7b2e93bf 100644 --- a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -131,6 +131,10 @@ public static void resetToDefaultColor(String color) { setColor(color, defaultColors.get(color)); } + public static boolean isDefaultColor(String color) { + return getColorRect(color).getColor() == defaultColors.get(color); + } + public static void gcBoundRects() { for (String color : colors) { getColorRect(color).gc(); diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index b2ed31dfe0a..a7db615f470 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -48,7 +48,7 @@ public GTGuiTheme getUITheme() { public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { ModularPanel panel = GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248); - // to avoid tying the terminal bound rect gc logic to IDPagedWidget itself + // to avoid tying the custom disposal logic to IDPagedWidget itself @SuppressWarnings("rawtypes") IDPagedWidget appPages = new IDPagedWidget() { diff --git a/src/main/java/gregtech/common/mui/drawable/Ring.java b/src/main/java/gregtech/common/mui/drawable/Ring.java index ac7c75626c3..21acb867945 100644 --- a/src/main/java/gregtech/common/mui/drawable/Ring.java +++ b/src/main/java/gregtech/common/mui/drawable/Ring.java @@ -63,7 +63,7 @@ public void draw(GuiContext context, int x, int y, int width, int height, Widget drawRing(x, y, width, height, ringWidth, color, segments, start, end); } - // modified from mui0 Widget#drawTorus to + // modified from mui0 Widget#drawTorus private static void drawRing(float x, float y, float w, float h, float ringWidth, int color, int segments, int from, int to) { float cx = x + w / 2f, cy = y + h / 2f; diff --git a/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java b/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java index 76afa9b5477..d0dd180834f 100644 --- a/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java +++ b/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java @@ -1,5 +1,6 @@ package gregtech.common.mui.widget; +// TODO remove when similar functionality is added to mui2 public interface IColorableScrollData { IColorableScrollData setColor(int color); diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java index 51059112dbb..0f5dfbfeff6 100644 --- a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -56,9 +56,10 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager IWidget capeButton = new ButtonWidget<>() .size(40, 72) .posRel(0.5F, 0.5F) - .overlay(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, false)) - .background(Terminal2Theme.COLOR_BACKGROUND_2) + .background(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, false)) + .overlay(new DynamicDrawable(capeForeground(cape))) .disableHoverOverlay() + .disableHoverBackground() .onMousePressed(b -> { syncHandler.syncToServer(SELECT_CAPE, buf -> buf.writeString(cape.toString())); return true; @@ -67,7 +68,6 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager capeGrid.child(new ParentWidget<>() .size(46, 78) .background(new DynamicDrawable(capeBackground(cape))) - .overlay(new DynamicDrawable(capeForeground(cape))) .child(capeButton) .child(new DynamicDrawable(capeOverlay(cape)).asWidget() .size(24) @@ -108,7 +108,7 @@ private Supplier capeBackground(ResourceLocation cape) { } private Supplier capeOverlay(ResourceLocation cape) { - return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : GTGuiTextures.RECIPE_LOCK; + return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : GTGuiTextures.RECIPE_LOCK_WHITE; } private Supplier capeForeground(ResourceLocation cape) { diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java index 126343654a3..e085b370ea2 100644 --- a/src/main/java/gregtech/common/terminal2/SettingsApp.java +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -77,6 +77,7 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager .left(276) .topRelAnchor(0.5F, 0.5F) .addTooltipLine(IKey.lang("terminal.settings.reset_color")) + .setEnabledIf((w) -> !Terminal2Theme.isDefaultColor(color)) .onMousePressed(i -> { Terminal2Theme.resetToDefaultColor(color); Terminal2Theme.saveConfig(); diff --git a/src/main/java/gregtech/common/terminal2/TestApp.java b/src/main/java/gregtech/common/terminal2/TestApp.java deleted file mode 100644 index 8532efc61af..00000000000 --- a/src/main/java/gregtech/common/terminal2/TestApp.java +++ /dev/null @@ -1,23 +0,0 @@ -package gregtech.common.terminal2; - -import gregtech.api.terminal2.ITerminalApp; - -import com.cleanroommc.modularui.api.drawable.IKey; -import com.cleanroommc.modularui.api.widget.IWidget; -import com.cleanroommc.modularui.factory.HandGuiData; -import com.cleanroommc.modularui.screen.ModularPanel; -import com.cleanroommc.modularui.value.sync.PanelSyncManager; - -public class TestApp implements ITerminalApp { - - private final int n; - - public TestApp(int n) { - this.n = n; - } - - @Override - public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { - return IKey.str("test app " + n).color(0xFFFFFF).shadow(true).asWidget(); - } -} From c8e8745266283a0d9b0f28f3c6583b416c0276c7 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Wed, 28 May 2025 22:51:32 -0400 Subject: [PATCH 12/17] remove test lang --- src/main/resources/assets/gregtech/lang/en_us.lang | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 6284bc5ed43..d288206c24b 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -6054,7 +6054,6 @@ gregtech.creative.activity.off=Not active terminal.app.gregtech.home.name=Home terminal.app.gregtech.settings.name=Theme Settings terminal.app.gregtech.capes.name=Cape Selector -terminal.app.gregtech.test.name=test app terminal.settings.background=Background terminal.settings.background_select=Select Background From ebc90deb305d2001fc0ff2c4995d4c691d53f9d9 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Mon, 27 Oct 2025 22:07:46 -0400 Subject: [PATCH 13/17] nice constant for this now --- src/main/java/gregtech/api/mui/GTGuiTheme.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/mui/GTGuiTheme.java b/src/main/java/gregtech/api/mui/GTGuiTheme.java index 0195d844425..91144635b04 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTheme.java +++ b/src/main/java/gregtech/api/mui/GTGuiTheme.java @@ -101,7 +101,7 @@ private static String gregtech(String s) { // TODO make this better public static final GTGuiTheme TERMINAL = templateBuilder("gregtech_terminal") - .parent("gregtech_standard") + .parent(Names.STANDARD) .textColor(0xFFFDFDFD) .build(); From 7f489230098de192b08ae592cdf5d29d980db018 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Mon, 17 Nov 2025 21:55:37 -0500 Subject: [PATCH 14/17] fix for mui update --- src/main/java/gregtech/api/terminal2/ITerminalApp.java | 3 ++- .../gregtech/common/items/behaviors/Terminal2Behavior.java | 5 +++-- src/main/java/gregtech/common/terminal2/CapeSelectorApp.java | 4 +++- src/main/java/gregtech/common/terminal2/SettingsApp.java | 4 +++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/terminal2/ITerminalApp.java b/src/main/java/gregtech/api/terminal2/ITerminalApp.java index 76c6e43206d..0865c6baf4a 100644 --- a/src/main/java/gregtech/api/terminal2/ITerminalApp.java +++ b/src/main/java/gregtech/api/terminal2/ITerminalApp.java @@ -5,6 +5,7 @@ import com.cleanroommc.modularui.drawable.GuiTextures; import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.value.sync.PanelSyncManager; public interface ITerminalApp { @@ -12,7 +13,7 @@ public interface ITerminalApp { /** * Create the UI for your app. */ - IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel); + IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings, ModularPanel panel); /** * @return The drawable that will be used for the icon of your app on the terminal home screen. diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java index a7db615f470..fb0bf74a208 100644 --- a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -24,6 +24,7 @@ import com.cleanroommc.modularui.drawable.DynamicDrawable; import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widgets.ButtonWidget; import com.cleanroommc.modularui.widgets.layout.Grid; @@ -45,7 +46,7 @@ public GTGuiTheme getUITheme() { } @Override - public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { + public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings) { ModularPanel panel = GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248); // to avoid tying the custom disposal logic to IDPagedWidget itself @@ -62,7 +63,7 @@ public void dispose() { } }; for (var app : Terminal2.appMap.entrySet()) { - appPages.addPage(app.getKey(), app.getValue().buildWidgets(guiData, guiSyncManager, panel)); + appPages.addPage(app.getKey(), app.getValue().buildWidgets(guiData, guiSyncManager, settings, panel)); } appPages.size(Terminal2.SCREEN_WIDTH, Terminal2.SCREEN_HEIGHT).pos(4, 4); diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java index 0f5dfbfeff6..0e2cf0b66b2 100644 --- a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -15,6 +15,7 @@ import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.ParentWidget; @@ -35,7 +36,8 @@ public class CapeSelectorApp implements ITerminalApp { private CapeSelectorSyncHandler syncHandler; @Override - public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings, + ModularPanel panel) { UUID uuid = guiData.getPlayer().getPersistentID(); syncHandler = new CapeSelectorSyncHandler(uuid); guiSyncManager.syncValue("cape_handler", syncHandler); diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java index e085b370ea2..f50c827cf0e 100644 --- a/src/main/java/gregtech/common/terminal2/SettingsApp.java +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -14,6 +14,7 @@ import com.cleanroommc.modularui.factory.HandGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.SecondaryPanel; +import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.utils.Alignment; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widget.ParentWidget; @@ -31,7 +32,8 @@ public class SettingsApp implements ITerminalApp { @Override - public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, ModularPanel panel) { + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings, + ModularPanel panel) { var backgroundSelectPanel = IPanelHandler.simple(panel, backgroundSelectWidget(), true); From 95c2acee828d603ac7e1f5d2239e1c2902cbf35d Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Mon, 17 Nov 2025 21:56:04 -0500 Subject: [PATCH 15/17] better scrollbar coloring and theming --- .../common/mui/drawable/BoundRectangle.java | 10 ++--- .../mui/widget/ColorableHScrollData.java | 42 ------------------- .../mui/widget/ColorableVScrollData.java | 42 ------------------- .../mui/widget/IColorableScrollData.java | 7 ---- .../common/terminal2/CapeSelectorApp.java | 7 ++-- .../common/terminal2/SettingsApp.java | 16 +++---- 6 files changed, 13 insertions(+), 111 deletions(-) delete mode 100644 src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java delete mode 100644 src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java delete mode 100644 src/main/java/gregtech/common/mui/widget/IColorableScrollData.java diff --git a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java index be21767f71b..e4b144256a6 100644 --- a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java +++ b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java @@ -1,7 +1,5 @@ package gregtech.common.mui.drawable; -import gregtech.common.mui.widget.IColorableScrollData; - import com.cleanroommc.modularui.drawable.Circle; import com.cleanroommc.modularui.drawable.Rectangle; import com.cleanroommc.modularui.widget.AbstractScrollWidget; @@ -57,11 +55,11 @@ public BoundRectangle bind(IntConsumer colorSetter, BooleanSupplier removeCondit public BoundRectangle bindScrollFG(AbstractScrollWidget widget) { HorizontalScrollData scrollX = widget.getScrollArea().getScrollX(); VerticalScrollData scrollY = widget.getScrollArea().getScrollY(); - if (scrollX instanceof IColorableScrollData scroll) { - bind(scroll::setColor, () -> !widget.isValid()); + if (scrollX != null) { + scrollX.texture(this); } - if (scrollY instanceof IColorableScrollData scroll) { - bind(scroll::setColor, () -> !widget.isValid()); + if (scrollY != null) { + scrollY.texture(this); } return this; } diff --git a/src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java b/src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java deleted file mode 100644 index 1353a40670d..00000000000 --- a/src/main/java/gregtech/common/mui/widget/ColorableHScrollData.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.common.mui.widget; - -import com.cleanroommc.modularui.drawable.GuiDraw; -import com.cleanroommc.modularui.utils.Color; -import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; - -public class ColorableHScrollData extends HorizontalScrollData implements IColorableScrollData { - - private int color; - - public ColorableHScrollData() { - this(0xFFFFFFFF); - } - - public ColorableHScrollData(int color) { - super(); - this.color = color; - } - - public ColorableHScrollData(int color, boolean topAlignment) { - super(topAlignment); - this.color = color; - } - - public ColorableHScrollData(int color, boolean topAlignment, int thickness) { - super(topAlignment, thickness); - this.color = color; - } - - @Override - public IColorableScrollData setColor(int color) { - this.color = color; - return this; - } - - @Override - protected void drawScrollBar(int x, int y, int w, int h) { - GuiDraw.drawRect(x, y, w, h, Color.multiply(color, 14f / 15f, false)); - GuiDraw.drawRect(x + 1, y + 1, w - 1, h - 1, Color.multiply(color, 6f / 15f, false)); - GuiDraw.drawRect(x + 1, y + 1, w - 2, h - 2, Color.multiply(color, 10f / 15f, false)); - } -} diff --git a/src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java b/src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java deleted file mode 100644 index 604865c07fb..00000000000 --- a/src/main/java/gregtech/common/mui/widget/ColorableVScrollData.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.common.mui.widget; - -import com.cleanroommc.modularui.drawable.GuiDraw; -import com.cleanroommc.modularui.utils.Color; -import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; - -public class ColorableVScrollData extends VerticalScrollData implements IColorableScrollData { - - private int color; - - public ColorableVScrollData() { - this(0xFFFFFFFF); - } - - public ColorableVScrollData(int color) { - super(); - this.color = color; - } - - public ColorableVScrollData(int color, boolean leftAlignment) { - super(leftAlignment); - this.color = color; - } - - public ColorableVScrollData(int color, boolean leftAlignment, int thickness) { - super(leftAlignment, thickness); - this.color = color; - } - - @Override - public IColorableScrollData setColor(int color) { - this.color = color; - return this; - } - - @Override - protected void drawScrollBar(int x, int y, int w, int h) { - GuiDraw.drawRect(x, y, w, h, Color.multiply(color, 14f / 15f, false)); - GuiDraw.drawRect(x + 1, y + 1, w - 1, h - 1, Color.multiply(color, 6f / 15f, false)); - GuiDraw.drawRect(x + 1, y + 1, w - 2, h - 2, Color.multiply(color, 10f / 15f, false)); - } -} diff --git a/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java b/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java deleted file mode 100644 index d0dd180834f..00000000000 --- a/src/main/java/gregtech/common/mui/widget/IColorableScrollData.java +++ /dev/null @@ -1,7 +0,0 @@ -package gregtech.common.mui.widget; - -// TODO remove when similar functionality is added to mui2 -public interface IColorableScrollData { - - IColorableScrollData setColor(int color); -} diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java index 0e2cf0b66b2..124317065a9 100644 --- a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -4,7 +4,6 @@ import gregtech.api.terminal2.ITerminalApp; import gregtech.api.terminal2.Terminal2Theme; import gregtech.api.util.CapesRegistry; -import gregtech.common.mui.widget.ColorableVScrollData; import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; @@ -19,6 +18,7 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; import com.cleanroommc.modularui.widgets.ButtonWidget; import com.cleanroommc.modularui.widgets.layout.Grid; @@ -46,9 +46,8 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager .sizeRel(1f) .posRel(0.5f, 0.5f) .minElementMargin(18) - .scrollable(new ColorableVScrollData()) + .scrollable(new VerticalScrollData().texture(Terminal2Theme.COLOR_FOREGROUND_BRIGHT)) .nextRow(); - Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(capeGrid); for (ResourceLocation cape : CapesRegistry.allCapes()) { if (capeGrid.getChildren().size() % 4 == 0 && !capeGrid.getChildren().isEmpty()) { @@ -58,7 +57,7 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager IWidget capeButton = new ButtonWidget<>() .size(40, 72) .posRel(0.5F, 0.5F) - .background(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, false)) + .background(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, null, false)) .overlay(new DynamicDrawable(capeForeground(cape))) .disableHoverOverlay() .disableHoverBackground() diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java index f50c827cf0e..d5711f255eb 100644 --- a/src/main/java/gregtech/common/terminal2/SettingsApp.java +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -3,7 +3,6 @@ import gregtech.api.mui.GTGuis; import gregtech.api.terminal2.ITerminalApp; import gregtech.api.terminal2.Terminal2Theme; -import gregtech.common.mui.widget.ColorableVScrollData; import gregtech.common.mui.widget.GTColorPickerDialog; import com.cleanroommc.modularui.api.IPanelHandler; @@ -19,7 +18,7 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widget.ScrollWidget; -import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; import com.cleanroommc.modularui.widgets.ButtonWidget; import com.cleanroommc.modularui.widgets.ListWidget; import com.cleanroommc.modularui.widgets.layout.Flow; @@ -99,12 +98,13 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager }))); } - var scroll = new ScrollWidget<>(new ColorableVScrollData()) + var scroll = new ScrollWidget<>(new VerticalScrollData()) .child(column) .sizeRel(1.0F); - scroll.getScrollArea().getScrollY().setScrollSize(rows * 24); - Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(scroll); + scroll.getScrollArea().getScrollY() + .texture(Terminal2Theme.COLOR_FOREGROUND_BRIGHT) + .setScrollSize(rows * 24); return new ParentWidget<>() .sizeRel(0.98F) @@ -139,13 +139,9 @@ private SecondaryPanel.IPanelBuilder backgroundSelectWidget() { Terminal2Theme.saveConfig(); return true; })) - // convince it to accept the colorable scroll data by giving it one with a different axis first - .scrollDirection(new HorizontalScrollData()) - .scrollDirection(new ColorableVScrollData()) + .scrollDirection(new VerticalScrollData().texture(Terminal2Theme.COLOR_FOREGROUND_BRIGHT)) .size(150, 90).pos(9, 16); - Terminal2Theme.COLOR_FOREGROUND_BRIGHT.bindScrollFG(list); - return GTGuis.createPopupPanel("terminal_background_select", 168, 112) .child(IKey.lang("terminal.settings.background_select").asWidget() .leftRel(0.5F) From 3ac3258dd5ea2da1b4c78c040d1292858beb1b19 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:14:09 -0500 Subject: [PATCH 16/17] fix that inconsistently named method in CapesRegistry --- src/main/java/gregtech/api/util/CapesRegistry.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/util/CapesRegistry.java b/src/main/java/gregtech/api/util/CapesRegistry.java index a6caa9db8cf..fcdfa3bd27d 100644 --- a/src/main/java/gregtech/api/util/CapesRegistry.java +++ b/src/main/java/gregtech/api/util/CapesRegistry.java @@ -23,6 +23,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import crafttweaker.annotations.ZenRegister; +import org.jetbrains.annotations.ApiStatus; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenMethod; @@ -208,10 +209,19 @@ public static void registerCape(ResourceLocation advancement, ResourceLocation c * * @param cape A ResourceLocation pointing to the cape texture. */ - public static void addFreeCape(ResourceLocation cape) { + public static void registerFreeCape(ResourceLocation cape) { FREE_CAPES.add(cape); } + /** + * Deprecated for naming consistency, use {@link #registerFreeCape(ResourceLocation)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + @Deprecated + public static void addFreeCape(ResourceLocation cape) { + registerFreeCape(cape); + } + private static final List> ctRegisterCapes = new ArrayList<>(); private static final List ctFreeCapes = new ArrayList<>(); From bf82b73cd2f2756f1bed418496f16f8a56a3f38f Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:34:19 -0500 Subject: [PATCH 17/17] cape app tooltips --- .../mui/widget/DrawableNoHoverWidget.java | 15 ++++++++++++++ .../common/terminal2/CapeSelectorApp.java | 20 ++++++++++++++++++- .../resources/assets/gregtech/lang/en_us.lang | 3 ++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java diff --git a/src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java b/src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java new file mode 100644 index 00000000000..f14f7ffe5ee --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java @@ -0,0 +1,15 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.api.drawable.IDrawable; + +public class DrawableNoHoverWidget extends IDrawable.DrawableWidget { + + public DrawableNoHoverWidget(IDrawable drawable) { + super(drawable); + } + + @Override + public boolean canHover() { + return false; + } +} diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java index 124317065a9..216183bd530 100644 --- a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -1,10 +1,15 @@ package gregtech.common.terminal2; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.RichTooltip; + import gregtech.api.mui.GTGuiTextures; import gregtech.api.terminal2.ITerminalApp; import gregtech.api.terminal2.Terminal2Theme; import gregtech.api.util.CapesRegistry; +import gregtech.common.mui.widget.DrawableNoHoverWidget; + import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; @@ -26,6 +31,7 @@ import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.function.Consumer; import java.util.function.Supplier; public class CapeSelectorApp implements ITerminalApp { @@ -61,6 +67,7 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager .overlay(new DynamicDrawable(capeForeground(cape))) .disableHoverOverlay() .disableHoverBackground() + .tooltipDynamic(capeTooltip(cape)) .onMousePressed(b -> { syncHandler.syncToServer(SELECT_CAPE, buf -> buf.writeString(cape.toString())); return true; @@ -70,7 +77,7 @@ public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager .size(46, 78) .background(new DynamicDrawable(capeBackground(cape))) .child(capeButton) - .child(new DynamicDrawable(capeOverlay(cape)).asWidget() + .child(new DrawableNoHoverWidget(new DynamicDrawable(capeOverlay(cape))) .size(24) .posRel(0.5F, 0.5F))); } @@ -116,6 +123,17 @@ private Supplier capeForeground(ResourceLocation cape) { return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : Terminal2Theme.COLOR_FOREGROUND_DARK; } + private Consumer capeTooltip(ResourceLocation cape) { + return (tooltip) -> { + if (cape.equals(CapesRegistry.getPlayerCape(syncHandler.uuid))) { + tooltip.addLine(IKey.lang("terminal.capes.selected")); + } else if (!syncHandler.unlockedCapes.contains(cape)) { + tooltip.addLine(IKey.lang("terminal.capes.locked")); + tooltip.addLine(IKey.lang("terminal.capes.advancement")); + } + }; + } + private static final class CapeSelectorSyncHandler extends SyncHandler { private final UUID uuid; diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index d288206c24b..64959e03fdd 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -6060,7 +6060,8 @@ terminal.settings.background_select=Select Background terminal.settings.color=Set color %s terminal.settings.reset_color=Reset to default color -terminal.capes.locked=Unlock this cape by progressing through GregTech's advancements +terminal.capes.locked=Locked +terminal.capes.advancement=Unlock this cape by progressing through GregTech's advancements terminal.capes.selected=Equipped # old terminal