From 8e52b22762368f4f247297798060d53bb21b5831 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 25 Jan 2024 14:29:40 +0000 Subject: [PATCH 01/28] feat: Settings screen redesign --- .../core/persisted/config/Category.java | 44 +- .../chattabs/ChatTabEditingScreen.java | 5 +- .../itemsharing/ItemSharingScreen.java | 2 + .../settings/WynntilsBookSettingsScreen.java | 964 +++++++++++++----- .../screens/settings/widgets/ApplyButton.java | 37 - .../widgets/BooleanSettingsButton.java | 26 +- .../settings/widgets/CategoryButton.java | 4 +- .../screens/settings/widgets/CloseButton.java | 35 - .../screens/settings/widgets/ConfigTile.java | 20 +- .../settings/widgets/ConfigurableButton.java | 89 +- .../widgets/CustomColorSettingsButton.java | 4 +- .../settings/widgets/EnumSettingsButton.java | 24 +- .../widgets/GeneralSettingsTabButton.java | 105 ++ .../screens/settings/widgets/ResetButton.java | 11 +- .../widgets/SettingsCategoryTabButton.java | 61 ++ .../widgets/SettingsPageTabButton.java | 26 + .../widgets/SettingsSideTabButton.java | 24 + .../widgets/TextInputBoxSettingsWidget.java | 10 +- .../wynntils/utils/render/FontRenderer.java | 103 ++ .../com/wynntils/utils/render/Texture.java | 30 + .../resources/assets/wynntils/lang/en_us.json | 16 + .../content_book/config_book_scroll_area.png | Bin 1086 -> 0 bytes .../textures/content_book/tag_blue.png | Bin 0 -> 421 bytes .../textures/content_book/tag_red.png | Bin 0 -> 408 bytes .../content_book/tag_red_selected.png | Bin 0 -> 498 bytes .../textures/content_book/tag_search.png | Bin 0 -> 605 bytes .../config_categories/all_config_icon.png | Bin 0 -> 293 bytes .../config_categories/chat_config_icon.png | Bin 0 -> 289 bytes .../config_categories/combat_config_icon.png | Bin 0 -> 275 bytes .../commands_config_icon.png | Bin 0 -> 278 bytes .../config_categories/debug_config_icon.png | Bin 0 -> 296 bytes .../embellishments_config_icon.png | Bin 0 -> 283 bytes .../inventory_config_icon.png | Bin 0 -> 261 bytes .../config_categories/map_config_icon.png | Bin 0 -> 234 bytes .../overlays_config_icon.png | Bin 0 -> 237 bytes .../config_categories/players_config_icon.png | Bin 0 -> 343 bytes .../redirects_config_icon.png | Bin 0 -> 282 bytes .../tooltips_config_icon.png | Bin 0 -> 304 bytes .../trade_market_config_icon.png | Bin 0 -> 267 bytes .../config_categories/ui_config_icon.png | Bin 0 -> 207 bytes .../uncategorized_config_icon.png | Bin 0 -> 299 bytes .../utilities_config_icon.png | Bin 0 -> 314 bytes .../wynntils_config_icon.png | Bin 0 -> 304 bytes .../wynntils/textures/icons/generic/close.png | Bin 0 -> 254 bytes .../wynntils/textures/icons/generic/next.png | Bin 0 -> 253 bytes .../textures/icons/generic/previous.png | Bin 0 -> 235 bytes .../wynntils/textures/icons/generic/reset.png | Bin 0 -> 307 bytes .../wynntils/textures/icons/generic/save.png | Bin 0 -> 257 bytes 48 files changed, 1257 insertions(+), 383 deletions(-) delete mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java delete mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java delete mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/config_book_scroll_area.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_search.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/all_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/chat_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/inventory_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/overlays_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/redirects_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/utilities_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/close.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/next.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/previous.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/reset.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/save.png diff --git a/common/src/main/java/com/wynntils/core/persisted/config/Category.java b/common/src/main/java/com/wynntils/core/persisted/config/Category.java index 439cb3c17e..acbaaa6c69 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/Category.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/Category.java @@ -1,32 +1,40 @@ /* - * Copyright © Wynntils 2022-2023. + * Copyright © Wynntils 2022-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.core.persisted.config; +import com.wynntils.utils.render.Texture; import java.util.Locale; import net.minecraft.client.resources.language.I18n; public enum Category { - UNCATEGORIZED, - CHAT, - COMBAT, - COMMANDS, - DEBUG, - EMBELLISHMENTS, - INVENTORY, - MAP, - OVERLAYS, - PLAYERS, - REDIRECTS, - TOOLTIPS, - TRADEMARKET, - UI, - UTILITIES, - WYNNTILS; + UNCATEGORIZED(Texture.UNCATEGORIZED_CONFIG_ICON), + CHAT(Texture.CHAT_CONFIG_ICON), + COMBAT(Texture.COMBAT_CONFIG_ICON), + COMMANDS(Texture.COMMANDS_CONFIG_ICON), + DEBUG(Texture.DEBUG_CONFIG_ICON), + EMBELLISHMENTS(Texture.EMBELLISHMENTS_CONFIG_ICON), + INVENTORY(Texture.INVENTORY_CONFIG_ICON), + MAP(Texture.MAP_CONFIG_ICON), + OVERLAYS(Texture.OVERLAYS_CONFIG_ICON), + PLAYERS(Texture.PLAYERS_CONFIG_ICON), + REDIRECTS(Texture.REDIRECTS_CONFIG_ICON), + TOOLTIPS(Texture.TOOLTIPS_CONFIG_ICON), + TRADEMARKET(Texture.TRADE_MARKET_CONFIG_ICON), + UI(Texture.UI_CONFIG_ICON), + UTILITIES(Texture.UTILITIES_CONFIG_ICON), + WYNNTILS(Texture.WYNNTILS_CONFIG_ICON); - Category() { + private final Texture categoryIcon; + + Category(Texture categoryIcon) { assert !toString().startsWith("core.wynntils"); + this.categoryIcon = categoryIcon; + } + + public Texture getCategoryIcon() { + return categoryIcon; } @Override diff --git a/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java b/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java index a14f107216..ea6c4683fa 100644 --- a/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java +++ b/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java @@ -1,5 +1,5 @@ /* - * Copyright © Wynntils 2022-2023. + * Copyright © Wynntils 2022-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.screens.chattabs; @@ -167,7 +167,8 @@ protected void doInit() { BUTTON_HEIGHT, Component.literal(type.getName()), ticked, - (int) (dividedWidth * 7) - 24); + (int) (dividedWidth * 7) - 24, + true); this.addRenderableWidget(newBox); recipientTypeBoxes.add(newBox); diff --git a/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java b/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java index 574b2a91ca..c8cf0efc7c 100644 --- a/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java +++ b/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java @@ -230,6 +230,7 @@ private void addSharingOptions() { Component.translatable("screens.wynntils.itemSharing.extended.name"), Models.ItemEncoding.extendedIdentificationEncoding.get(), Texture.ITEM_SHARING_BACKGROUND.width() - 30, + true, (b) -> { if (b == 0) { Models.ItemEncoding.extendedIdentificationEncoding.store( @@ -251,6 +252,7 @@ private void addSharingOptions() { Component.translatable("screens.wynntils.itemSharing.itemName.name"), Models.ItemEncoding.shareItemName.get(), Texture.ITEM_SHARING_BACKGROUND.width() - 30, + true, (b) -> { if (b == 0) { Models.ItemEncoding.shareItemName.store(!Models.ItemEncoding.shareItemName.get()); diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index d749a893a1..1989ac4d9f 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -4,7 +4,6 @@ */ package com.wynntils.screens.settings; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.wynntils.core.components.Managers; import com.wynntils.core.consumers.features.Configurable; @@ -16,17 +15,21 @@ import com.wynntils.core.persisted.config.Category; import com.wynntils.core.persisted.config.Config; import com.wynntils.core.text.StyledText; +import com.wynntils.screens.base.TooltipProvider; import com.wynntils.screens.base.widgets.SearchWidget; import com.wynntils.screens.base.widgets.TextInputBoxWidget; import com.wynntils.screens.base.widgets.WynntilsButton; -import com.wynntils.screens.settings.widgets.ApplyButton; import com.wynntils.screens.settings.widgets.CategoryButton; -import com.wynntils.screens.settings.widgets.CloseButton; import com.wynntils.screens.settings.widgets.ConfigTile; import com.wynntils.screens.settings.widgets.ConfigurableButton; +import com.wynntils.screens.settings.widgets.SettingsCategoryTabButton; +import com.wynntils.screens.settings.widgets.SettingsPageTabButton; +import com.wynntils.screens.settings.widgets.SettingsSideTabButton; import com.wynntils.utils.MathUtils; import com.wynntils.utils.StringUtils; import com.wynntils.utils.colors.CommonColors; +import com.wynntils.utils.mc.ComponentUtils; +import com.wynntils.utils.mc.McUtils; import com.wynntils.utils.render.FontRenderer; import com.wynntils.utils.render.RenderUtils; import com.wynntils.utils.render.Texture; @@ -34,6 +37,7 @@ import com.wynntils.utils.render.type.TextShadow; import com.wynntils.utils.render.type.VerticalAlignment; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.List; @@ -42,44 +46,75 @@ import java.util.stream.Stream; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; public final class WynntilsBookSettingsScreen extends WynntilsScreen { + // Constants private static final float SCROLL_FACTOR = 10f; - private static final int CONFIG_MASK_TOP_Y = 21; + private static final int MASK_TOP_Y = 21; private static final int CONFIG_MASK_BOTTOM_Y = 205; - private static final int CONFIGURABLES_PER_PAGE = 13; + private static final int CONFIGURABLE_MASK_BOTTOM_Y = 211; + private static final int CONFIGURABLES_PER_PAGE = 16; private static final int CONFIGS_PER_PAGE = 4; - private static final int CONFIGURABLE_SCROLL_X = 23; + private static final int CONFIGURABLE_SCROLL_X = (int) (Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 12); private static final int CONFIG_SCROLL_X = Texture.CONFIG_BOOK_BACKGROUND.width() - 23; - private static final int SCROLL_START_Y = 17; + private static final int MAX_DISPLAYED_CATEGORIES = 7; + private static final int SCROLL_AREA_HEIGHT = 186; + private static final int SCROLL_START_Y = 21; + // Collections + private final List sortedCategories; private final List configurables = new ArrayList<>(); private final List configs = new ArrayList<>(); private List configurableList; + private List categoryButtons = new ArrayList<>(); - private TextInputBoxWidget focusedTextInput; + // Renderables private final SearchWidget searchWidget; + private SettingsCategoryTabButton allCategoriesButton; + private SettingsCategoryTabButton selectedCategoryButton; + private TextInputBoxWidget focusedTextInput; - private Configurable selected = null; - + // UI size, postions, etc private boolean draggingConfigurableScroll = false; private boolean draggingConfigScroll = false; - private int configurableScrollOffset = 0; + private int categoriesScrollOffset = 0; + private int configurablesScrollOffset = 0; private int configScrollOffset = 0; private float configurableScrollRenderY; private float configScrollRenderY; + private float translationX; + private float translationY; + + // Settings display + private Category selectedCategory; + private Configurable selectedConfigurable = null; private WynntilsBookSettingsScreen() { super(Component.translatable("screens.wynntils.settingsScreen.name")); searchWidget = new SearchWidget( - 95, Texture.CONFIG_BOOK_BACKGROUND.height() - 32, 100, 20, s -> reloadConfigurableButtons(), this); + 60, + Texture.CONFIG_BOOK_BACKGROUND.height() + 5, + 100, + 20, + (s) -> { + configurablesScrollOffset = 0; + getFilteredConfigurables(); + populateConfigurables(); + }, + this); setFocusedTextInput(searchWidget); + + // Get all categories, sort a-z + sortedCategories = Arrays.asList(Category.values()); + sortedCategories.sort(Comparator.comparing(Enum::name)); } public static Screen create() { @@ -88,39 +123,230 @@ public static Screen create() { @Override protected void doInit() { - reloadConfigurableButtons(); + populateCategories(); + getFilteredConfigurables(); + populateConfigurables(); + // Render position for the book background + translationX = (this.width - Texture.CONFIG_BOOK_BACKGROUND.width()) / 2f; + translationY = (this.height - Texture.CONFIG_BOOK_BACKGROUND.height()) / 2f; + + int yPos = Texture.TAG_BLUE.height() / 2; + + // region Side tags + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + this::importSettings, + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.import") + .withStyle(ChatFormatting.YELLOW), + Component.translatable("screens.wynntils.settingsScreen.import.all") + .withStyle(ChatFormatting.GRAY), + Component.translatable("screens.wynntils.settingsScreen.import.selected") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.ADD_ICON)); + + yPos += 15 + Texture.TAG_BLUE.height() / 2; + + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + this::exportSettings, + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.export") + .withStyle(ChatFormatting.BLUE), + Component.translatable("screens.wynntils.settingsScreen.export.all") + .withStyle(ChatFormatting.GRAY), + Component.translatable("screens.wynntils.settingsScreen.export.selected") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.SHARE_ICON)); + + yPos += 15 + Texture.TAG_BLUE.height() / 2; + + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + (b) -> { + Managers.Config.saveConfig(); + onClose(); + }, + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.apply") + .withStyle(ChatFormatting.GREEN), + Component.translatable("screens.wynntils.settingsScreen.apply.description") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.SAVE)); + + yPos += 15 + Texture.TAG_BLUE.height() / 2; + + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + (b) -> onClose(), + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.close") + .withStyle(ChatFormatting.RED), + Component.translatable("screens.wynntils.settingsScreen.close.description") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.CLOSE)); + // endregion + + // region Category tags + int xPos = 18; + + allCategoriesButton = this.addRenderableWidget(new SettingsCategoryTabButton( + 18, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> changeCategory(null), + List.of(Component.literal("All")), + selectedCategory == null)); + + if (selectedCategory == null) { + selectedCategoryButton = allCategoriesButton; + } - this.addRenderableWidget(searchWidget); + xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75; + + this.addRenderableWidget(new SettingsPageTabButton( + xPos, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> scrollCategorories(-1), + List.of(Component.translatable("screens.wynntils.settingsScreen.previous")), + false)); - this.addRenderableWidget(new ApplyButton(this)); + xPos += (Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75) * (MAX_DISPLAYED_CATEGORIES + 1); - this.addRenderableWidget(new CloseButton(this)); + this.addRenderableWidget(new SettingsPageTabButton( + xPos, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> scrollCategorories(1), + List.of(Component.translatable("screens.wynntils.settingsScreen.next")), + true)); + + this.addRenderableWidget(searchWidget); } @Override public void doRender(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { - float backgroundRenderX = getTranslationX(); - float backgroundRenderY = getTranslationY(); - PoseStack poseStack = guiGraphics.pose(); poseStack.pushPose(); - poseStack.translate(backgroundRenderX, backgroundRenderY, 0); + poseStack.translate(translationX, translationY, 0); + + int adjustedMouseX = mouseX - (int) translationX; + int adjustedMouseY = mouseY - (int) translationY; + + renderSearchBar(poseStack); + + renderTags(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); renderBg(poseStack); - renderScrollArea(poseStack); + String categoryName = selectedCategory == null + ? I18n.get("screens.wynntils.settingsScreen.all") + : I18n.get(selectedCategory.toString()); - renderConfigurableScroll(poseStack); + FontRenderer.getInstance() + .renderText( + poseStack, + StyledText.fromString(categoryName), + Texture.CONFIG_BOOK_BACKGROUND.width() * 0.25f, + McUtils.mc().font.lineHeight + 5, + CommonColors.LIGHT_GRAY, + HorizontalAlignment.CENTER, + VerticalAlignment.MIDDLE, + TextShadow.NORMAL); + + RenderUtils.drawLine( + poseStack, CommonColors.GRAY, 11, 19, Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 6, 19, 0, 1); + + if (selectedConfigurable != null) { + String textToRender = selectedConfigurable.getTranslatedName(); + + // Show the custom name for info boxes/custom bars if given + if (selectedConfigurable instanceof CustomNameProperty customNameProperty) { + if (!customNameProperty.getCustomName().get().isEmpty()) { + textToRender = customNameProperty.getCustomName().get(); + } + } - renderWidgets(guiGraphics, mouseX, mouseY, partialTick); + FontRenderer.getInstance() + .renderText( + poseStack, + StyledText.fromString(textToRender), + Texture.CONFIG_BOOK_BACKGROUND.width() * 0.75f, + McUtils.mc().font.lineHeight + 5, + CommonColors.LIGHT_GRAY, + HorizontalAlignment.CENTER, + VerticalAlignment.MIDDLE, + TextShadow.NORMAL); + + RenderUtils.drawLine( + poseStack, + CommonColors.GRAY, + Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 6, + 19, + Texture.CONFIG_BOOK_BACKGROUND.width() - 11, + 19, + 0, + 1); + } else { + FontRenderer.getInstance() + .renderAlignedTextInBox( + poseStack, + StyledText.fromComponent( + Component.translatable("screens.wynntils.settingsScreen.unselectedConfig")), + Texture.CONFIG_BOOK_BACKGROUND.width() / 2f, + Texture.CONFIG_BOOK_BACKGROUND.width(), + Texture.CONFIG_BOOK_BACKGROUND.height() * 0.25f, + Texture.CONFIG_BOOK_BACKGROUND.height() * 0.75f, + Texture.CONFIG_BOOK_BACKGROUND.width() / 3f, + CommonColors.WHITE, + HorizontalAlignment.CENTER, + VerticalAlignment.TOP, + TextShadow.NORMAL); + } - if (selected != null) { - renderConfigTitle(poseStack); + if (configurables.size() > CONFIGURABLES_PER_PAGE) { + renderConfigurableScroll(poseStack); + } + if (configs.size() > CONFIGS_PER_PAGE) { renderConfigScroll(poseStack); } + renderConfigs(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + + renderConfigurables(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + + renderTooltips(guiGraphics, adjustedMouseX, adjustedMouseY); + poseStack.popPose(); } @@ -138,8 +364,8 @@ public void onClose() { @Override public boolean doMouseClicked(double mouseX, double mouseY, int button) { - double adjustedMouseX = mouseX - getTranslationX(); - double adjustedMouseY = mouseY - getTranslationY(); + double adjustedMouseX = mouseX - translationX; + double adjustedMouseY = mouseY - translationY; for (GuiEventListener listener : getWidgetsForIteration().toList()) { if (listener.isMouseOver(adjustedMouseX, adjustedMouseY)) { @@ -149,12 +375,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigurableScroll && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIGURABLE_SCROLL_X, - CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configurableScrollRenderY, - (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIGURABLE_SCROLL_X, + CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configurableScrollRenderY, + (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigurableScroll = true; return true; } @@ -162,12 +388,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigScroll && (configs.size() > CONFIGS_PER_PAGE) && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIG_SCROLL_X, - CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configScrollRenderY, - (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIG_SCROLL_X, + CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configScrollRenderY, + (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigScroll = true; return true; } @@ -177,18 +403,16 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { - double adjustedMouseX = mouseX - getTranslationX(); - double adjustedMouseY = mouseY - getTranslationY(); + double adjustedMouseX = mouseX - translationX; + double adjustedMouseY = mouseY - translationY; if (draggingConfigurableScroll) { int scrollAreaStartY = SCROLL_START_Y + 7; - int scrollAreaHeight = - (int) (CONFIGURABLES_PER_PAGE * 12 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); int newOffset = Math.round(MathUtils.map( (float) adjustedMouseY, scrollAreaStartY, - scrollAreaStartY + scrollAreaHeight, + scrollAreaStartY + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f, 0, getMaxConfigurableScrollOffset())); @@ -201,12 +425,11 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double dra if (draggingConfigScroll) { int scrollAreaStartY = SCROLL_START_Y + 7; - int scrollAreaHeight = (int) (CONFIGS_PER_PAGE * 46 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); int newOffset = Math.round(MathUtils.map( (float) adjustedMouseY, scrollAreaStartY, - scrollAreaStartY + scrollAreaHeight, + scrollAreaStartY + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f, 0, getMaxConfigScrollOffset())); @@ -228,8 +451,8 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double dra @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - double adjustedMouseX = mouseX - getTranslationX(); - double adjustedMouseY = mouseY - getTranslationY(); + double adjustedMouseX = mouseX - translationX; + double adjustedMouseY = mouseY - translationY; for (GuiEventListener listener : getWidgetsForIteration().toList()) { listener.mouseReleased(adjustedMouseX, adjustedMouseY, button); @@ -243,12 +466,17 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean mouseScrolled(double mouseX, double mouseY, double deltaX, double deltaY) { - double adjustedMouseX = mouseX - getTranslationX(); + double adjustedMouseX = mouseX - translationX; int scrollAmount = (int) (-deltaY * SCROLL_FACTOR); - if (adjustedMouseX <= Texture.CONFIG_BOOK_BACKGROUND.width() / 2f) { + // When mouse above the book, scroll the categories. + // When below top of book and left side scroll configurables + // Otherwise scroll configs + if (mouseY <= translationY) { + scrollCategorories((int) -Math.signum(deltaY)); + } else if (adjustedMouseX <= Texture.CONFIG_BOOK_BACKGROUND.width() / 2f) { int newOffset = - Math.max(0, Math.min(configurableScrollOffset + scrollAmount, getMaxConfigurableScrollOffset())); + Math.max(0, Math.min(configurablesScrollOffset + scrollAmount, getMaxConfigurableScrollOffset())); scrollConfigurables(newOffset); } else if (configs.size() > CONFIGS_PER_PAGE) { int newOffset = Math.max(0, Math.min(configScrollOffset + scrollAmount, getMaxConfigScrollOffset())); @@ -283,155 +511,248 @@ public void setFocusedTextInput(TextInputBoxWidget focusedTextInput) { this.focusedTextInput = focusedTextInput; } - public boolean configOptionContains(Config config) { - return !searchWidget.getTextBoxInput().isEmpty() - && StringUtils.containsIgnoreCase(config.getDisplayName(), searchWidget.getTextBoxInput()); - } + public void populateConfigurables() { + configurables.clear(); - public Configurable getSelected() { - return selected; - } + Category oldCategory = selectedCategory; - public void setSelected(Configurable selected) { - this.selected = selected; - reloadConfigButtons(); - } + int renderY = 21; - public float getTranslationY() { - return (this.height - Texture.CONFIG_BOOK_BACKGROUND.height()) / 2f; - } + for (Configurable configurable : configurableList) { + Category category; - public float getTranslationX() { - return (this.width - Texture.CONFIG_BOOK_BACKGROUND.width()) / 2f; - } + if (configurable instanceof Feature feature) { + category = feature.getCategory(); + } else if (configurable instanceof Overlay overlay) { + category = Managers.Overlay.getOverlayParent(overlay).getCategory(); + } else { + throw new IllegalStateException("Unknown configurable type: " + configurable.getClass()); + } - public int getConfigMaskTopY() { - return CONFIG_MASK_TOP_Y; - } + if (category != oldCategory) { + CategoryButton categoryButton = new CategoryButton(12, renderY, 170, 10, category); + categoryButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); + configurables.add(categoryButton); + oldCategory = category; + renderY += 12; + } - public int getConfigMaskBottomY() { - return CONFIG_MASK_BOTTOM_Y; - } + int matchingConfigs = 0; - private void renderConfigTitle(PoseStack poseStack) { - String name = ""; - boolean enabled = false; - if (selected instanceof Overlay selectedOverlay) { - enabled = Managers.Overlay.isEnabled(selectedOverlay); - name = selectedOverlay.getTranslatedName(); + for (Config config : configurable.getVisibleConfigOptions()) { + if (configOptionContains(config)) { + matchingConfigs++; + } + } - if (selected instanceof CustomNameProperty customNameProperty) { - if (!customNameProperty.getCustomName().get().isEmpty()) { - name = customNameProperty.getCustomName().get(); + ConfigurableButton configurableButton = + new ConfigurableButton(12, renderY, 170, 10, configurable, this, matchingConfigs); + configurableButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); + configurables.add(configurableButton); + + renderY += 12; + + if (configurable instanceof Feature feature) { + for (Overlay overlay : Managers.Overlay.getFeatureOverlays(feature).stream() + .sorted() + .toList()) { + matchingConfigs = 0; + + for (Config config : overlay.getVisibleConfigOptions()) { + if (configOptionContains(config)) { + matchingConfigs++; + } + } + + ConfigurableButton overlayButton = + new ConfigurableButton(12, renderY, 170, 10, overlay, this, matchingConfigs); + overlayButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); + configurables.add(overlayButton); + renderY += 12; } } - } else if (selected instanceof Feature selectedFeature) { - enabled = selectedFeature.isEnabled(); - name = selectedFeature.getTranslatedName(); } - FontRenderer.getInstance() - .renderScrollingText( - poseStack, - StyledText.fromString(name + ": " - + (enabled - ? ChatFormatting.DARK_GREEN + "Enabled" - : ChatFormatting.DARK_RED + "Disabled")), - Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 10, - 10, - Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 20, - getTranslationX(), - getTranslationY(), - CommonColors.BLACK, - HorizontalAlignment.LEFT, - VerticalAlignment.TOP, - TextShadow.NONE, - 0.8f); - } - - private void renderWidgets(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { - int adjustedMouseX = mouseX - (int) getTranslationX(); - int adjustedMouseY = mouseY - (int) getTranslationY(); + if (selectedConfigurable != null) { + Stream configurablesList = Stream.concat( + Managers.Feature.getFeatures().stream(), + Managers.Feature.getFeatures().stream() + .map(Managers.Overlay::getFeatureOverlays) + .flatMap(Collection::stream) + .map(overlay -> (Configurable) overlay)); - for (Renderable renderable : renderables) { - renderable.render(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + Configurable newSelected = configurablesList + .filter(configurable -> configurable.getJsonName().equals(selectedConfigurable.getJsonName())) + .findFirst() + .orElse(null); + + setSelectedConfigurable(newSelected); } - RenderUtils.createRectMask(guiGraphics.pose(), 37, 16, 140, 163); + scrollConfigurables(configurablesScrollOffset); + } - for (WynntilsButton configurable : configurables) { - configurable.render(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + public void populateConfigs() { + configs.clear(); + configScrollOffset = 0; + + if (selectedConfigurable == null) return; + + List> configsOptions = selectedConfigurable.getVisibleConfigOptions().stream() + .sorted(Comparator.comparing(config -> !Objects.equals(config.getFieldName(), "userEnabled"))) + .toList(); + + int renderY = 21; + + for (Config config : configsOptions) { + ConfigTile configTile = + new ConfigTile(Texture.CONFIG_BOOK_BACKGROUND.width() / 2 + 10, renderY, 160, 45, this, config); + configTile.visible = renderY >= (21 - 46) && renderY <= (21 + CONFIGS_PER_PAGE * 45); + + configs.add(configTile); + + renderY += 46; } - RenderUtils.clearMask(); + scrollConfigs(configScrollOffset); + } - RenderUtils.createRectMask( - guiGraphics.pose(), Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 10, 21, 160, CONFIGS_PER_PAGE * 46); + public boolean configOptionContains(Config config) { + return !searchWidget.getTextBoxInput().isEmpty() + && StringUtils.containsIgnoreCase(config.getDisplayName(), searchWidget.getTextBoxInput()); + } - for (WynntilsButton config : configs) { - config.render(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + public void setSelectedConfigurable(Configurable selectedConfigurable) { + this.selectedConfigurable = selectedConfigurable; + populateConfigs(); + + // If there is a search query, scroll the configs list so that the matching config + // is found unless the configurable itself matches the search query + if (!searchWidget.getTextBoxInput().isEmpty()) { + if (!searchMatches(selectedConfigurable)) { + scrollToMatchingConfig(); + } } + } - RenderUtils.clearMask(); + public Configurable getSelectedConfigurable() { + return selectedConfigurable; } - private static void renderScrollArea(PoseStack poseStack) { - RenderSystem.enableBlend(); - RenderUtils.drawTexturedRect( - poseStack, - Texture.CONFIG_BOOK_SCROLL_AREA, - (Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - Texture.CONFIG_BOOK_SCROLL_AREA.width()) / 2f, - 10); - RenderSystem.disableBlend(); + public float getTranslationX() { + return translationX; } - private void renderConfigurableScroll(PoseStack poseStack) { - configurableScrollRenderY = SCROLL_START_Y - + MathUtils.map( - configurableScrollOffset, - 0, - getMaxConfigurableScrollOffset(), - 0, - 161 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + public float getTranslationY() { + return translationY; + } - RenderUtils.drawHoverableTexturedRect( - poseStack, - Texture.CONFIG_BOOK_SCROLL_BUTTON, - CONFIGURABLE_SCROLL_X, - configurableScrollRenderY, - draggingConfigurableScroll); + public int getMaskTopY() { + return MASK_TOP_Y; } - private void renderConfigScroll(PoseStack poseStack) { - if (configs.size() <= CONFIGS_PER_PAGE) return; + public int getConfigMaskBottomY() { + return CONFIG_MASK_BOTTOM_Y; + } - RenderUtils.drawRect( - poseStack, - CommonColors.GRAY, - CONFIG_SCROLL_X, - SCROLL_START_Y, - 0, - Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - CONFIGS_PER_PAGE * 46); + public int getConfigurableMaskBottomY() { + return CONFIGURABLE_MASK_BOTTOM_Y; + } - configScrollRenderY = SCROLL_START_Y - + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - CONFIGS_PER_PAGE * 46 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + private void populateCategories() { + for (AbstractWidget widget : categoryButtons) { + this.removeWidget(widget); + } - RenderUtils.drawHoverableTexturedRect( - poseStack, - Texture.CONFIG_BOOK_SCROLL_BUTTON, - CONFIG_SCROLL_X, - configScrollRenderY, - draggingConfigScroll); + int xPos = (int) (18 + Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75); + + categoryButtons = new ArrayList<>(); + + for (int i = 0; i < MAX_DISPLAYED_CATEGORIES; i++) { + xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75; + + int categoryIndex; + + if (i + categoriesScrollOffset < 0) { + categoryIndex = (i + categoriesScrollOffset) + sortedCategories.size(); + } else if (i + categoriesScrollOffset > sortedCategories.size() - 1) { + categoryIndex = (i + categoriesScrollOffset) - sortedCategories.size(); + } else { + categoryIndex = (i + categoriesScrollOffset); + } + + Category category = sortedCategories.get(categoryIndex); + + categoryButtons.add(this.addRenderableWidget(new SettingsCategoryTabButton( + xPos, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> changeCategory(category), + List.of(Component.literal(I18n.get(category.toString()))), + category, + selectedCategory == category))); + } } - private static void renderBg(PoseStack poseStack) { - RenderUtils.drawTexturedRect(poseStack, Texture.CONFIG_BOOK_BACKGROUND, 0, 0); + private void getFilteredConfigurables() { + configurableList = new ArrayList<>(); + + List filteredConfigurables; + + // Add all configurables for selected category + if (selectedCategory != null) { + filteredConfigurables = Managers.Feature.getFeatures().stream() + .filter(feature -> searchMatches(feature) + || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .map(feature -> (Configurable) feature) + .sorted() + .filter(configurable -> isCategoryMatching(configurable, selectedCategory)) + .collect(Collectors.toList()); + + filteredConfigurables.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !filteredConfigurables.contains(Managers.Overlay.getOverlayParent(overlay))) + .filter(overlay -> searchMatches(overlay) + || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .sorted() + .filter(configurable -> isCategoryMatching(configurable, selectedCategory)) + .toList()); + + // If there is a search query, add all matches from every other category + if (!searchWidget.getTextBoxInput().isEmpty()) { + filteredConfigurables.addAll(Managers.Feature.getFeatures().stream() + .filter(feature -> searchMatches(feature) + || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .map(feature -> (Configurable) feature) + .sorted() + .filter(configurable -> !isCategoryMatching(configurable, selectedCategory)) + .toList()); + + filteredConfigurables.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !filteredConfigurables.contains(Managers.Overlay.getOverlayParent(overlay))) + .filter(overlay -> searchMatches(overlay) + || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .sorted() + .filter(configurable -> !isCategoryMatching(configurable, selectedCategory)) + .toList()); + } + } else { // All tab, add all configurables + filteredConfigurables = Managers.Feature.getFeatures().stream() + .filter(feature -> searchMatches(feature) + || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .map(feature -> (Configurable) feature) + .sorted() + .collect(Collectors.toList()); + + filteredConfigurables.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !filteredConfigurables.contains(Managers.Overlay.getOverlayParent(overlay))) + .filter(overlay -> searchMatches(overlay) + || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .sorted() + .toList()); + } + + configurableList.addAll(filteredConfigurables); } private Stream getWidgetsForIteration() { @@ -439,10 +760,10 @@ private Stream getWidgetsForIteration() { } private void scrollConfigurables(int newOffset) { - configurableScrollOffset = newOffset; + configurablesScrollOffset = newOffset; for (WynntilsButton configurable : configurables) { - int newY = 21 + (configurables.indexOf(configurable) * 12) - configurableScrollOffset; + int newY = 21 + (configurables.indexOf(configurable) * 12) - configurablesScrollOffset; configurable.setY(newY); configurable.visible = newY >= (21 - 12) && newY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); @@ -468,81 +789,77 @@ private int getMaxConfigScrollOffset() { return (configs.size() - CONFIGS_PER_PAGE) * 46; } - private void reloadConfigurableButtons() { - configurables.clear(); - configurableScrollOffset = 0; - - Category oldCategory = null; - - configurableList = Managers.Feature.getFeatures().stream() - .filter(feature -> searchMatches(feature) - || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) - .map(feature -> (Configurable) feature) - .sorted() - .collect(Collectors.toList()); - - configurableList.addAll(Managers.Overlay.getOverlays().stream() - .filter(overlay -> !configurableList.contains(Managers.Overlay.getOverlayParent(overlay))) - .filter(overlay -> searchMatches(overlay) - || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) - .sorted() - .toList()); - - int renderY = 21; + private void scrollCategorories(int direction) { + if (Math.abs(categoriesScrollOffset + direction) == sortedCategories.size()) { + categoriesScrollOffset = 0; + } else { + categoriesScrollOffset = MathUtils.clamp( + categoriesScrollOffset + direction, -(sortedCategories.size() - 1), (sortedCategories.size() - 1)); + } - for (int i = 0; i < configurableList.size(); i++) { - Configurable configurable = configurableList.get(i); + populateCategories(); + } - Category category; + private boolean isCategoryMatching(Configurable configurable, Category selectedCategory) { + return getCategory(configurable) == selectedCategory; + } - if (configurable instanceof Feature feature) { - category = feature.getCategory(); - } else if (configurable instanceof Overlay overlay) { - category = Managers.Overlay.getOverlayParent(overlay).getCategory(); - } else { - throw new IllegalStateException("Unknown configurable type: " + configurable.getClass()); - } + private void scrollToMatchingConfig() { + List> configsOptions = selectedConfigurable.getVisibleConfigOptions().stream() + .sorted(Comparator.comparing(config -> !Objects.equals(config.getFieldName(), "userEnabled"))) + .toList(); - if (category != oldCategory) { - CategoryButton categoryButton = new CategoryButton(37, renderY, 140, 10, category); - categoryButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); - configurables.add(categoryButton); - oldCategory = category; - renderY += 12; + // Find a config that matches current search query and get scroll offset to make that config visible + for (Config config : configsOptions) { + if (StringUtils.containsIgnoreCase(config.getDisplayName(), searchWidget.getTextBoxInput())) { + int newOffset = Math.max( + 0, + Math.min( + (configsOptions.indexOf(config) - (CONFIGS_PER_PAGE - 1)) * 46, + getMaxConfigScrollOffset())); + scrollConfigs(newOffset); + return; } + } + } - ConfigurableButton configurableButton = new ConfigurableButton(37, renderY, 140, 10, configurable, this); - configurableButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); - configurables.add(configurableButton); + private void changeCategory(Category category) { + configurablesScrollOffset = 0; - renderY += 12; + // Deselect old category, reset texture to default + if (selectedCategoryButton != null) { + selectedCategoryButton.setSelectedCategory(false); + } - if (configurable instanceof Feature feature) { - for (Overlay overlay : Managers.Overlay.getFeatureOverlays(feature).stream() - .sorted() - .toList()) { - ConfigurableButton overlayButton = new ConfigurableButton(37, renderY, 140, 10, overlay, this); - overlayButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); - configurables.add(overlayButton); - renderY += 12; + selectedCategory = category; + + // If null, the all categories button was selected. + // Otherwise find which was selected and update that + if (category == null) { + selectedCategoryButton = allCategoriesButton; + allCategoriesButton.setSelectedCategory(true); + } else { + for (SettingsCategoryTabButton settingsTabButton : categoryButtons) { + if (settingsTabButton.getCategory() == selectedCategory) { + selectedCategoryButton = settingsTabButton; + settingsTabButton.setSelectedCategory(true); + break; } } } - if (selected != null) { - Stream configurablesList = Stream.concat( - Managers.Feature.getFeatures().stream(), - Managers.Feature.getFeatures().stream() - .map(Managers.Overlay::getFeatureOverlays) - .flatMap(Collection::stream) - .map(overlay -> (Configurable) overlay)); - - Configurable newSelected = configurablesList - .filter(configurable -> configurable.getJsonName().equals(selected.getJsonName())) - .findFirst() - .orElse(null); + getFilteredConfigurables(); + populateConfigurables(); + populateCategories(); + } - setSelected(newSelected); + private Category getCategory(Configurable configurable) { + if (configurable instanceof Feature feature) { + return feature.getCategory(); + } else if (configurable instanceof Overlay overlay) { + return Managers.Overlay.getOverlayParent(overlay).getCategory(); + } else { + throw new IllegalStateException("Unknown configurable type: " + configurable.getClass()); } } @@ -558,28 +875,185 @@ private boolean searchMatches(Translatable translatable) { return StringUtils.partialMatch(translatable.getTranslatedName(), searchWidget.getTextBoxInput()); } - private void reloadConfigButtons() { - configs.clear(); - configScrollOffset = 0; + private void renderBg(PoseStack poseStack) { + RenderUtils.drawTexturedRect(poseStack, Texture.CONFIG_BOOK_BACKGROUND, 0, 0); + } - if (selected == null) return; + private void renderSearchBar(PoseStack poseStack) { + RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 2); + } - List> configsOptions = selected.getVisibleConfigOptions().stream() - .sorted(Comparator.comparing(config -> !Objects.equals(config.getFieldName(), "userEnabled"))) - .toList(); + private void renderTags(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + for (Renderable renderable : renderables) { + renderable.render(guiGraphics, mouseX, mouseY, partialTick); + } + } - int renderY = 21; + private void renderConfigurables(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + RenderUtils.createRectMask(guiGraphics.pose(), 12, 21, 170, CONFIGURABLES_PER_PAGE * 12 - 3); - for (int i = 0; i < configsOptions.size(); i++) { - Config config = configsOptions.get(i); + for (WynntilsButton configurable : configurables) { + configurable.render(guiGraphics, mouseX, mouseY, partialTick); + } - ConfigTile configTile = - new ConfigTile(Texture.CONFIG_BOOK_BACKGROUND.width() / 2 + 10, renderY, 160, 45, this, config); - configTile.visible = renderY >= (21 - 46) && renderY <= (21 + CONFIGS_PER_PAGE * 45); + RenderUtils.clearMask(); + } - configs.add(configTile); + private void renderConfigurableScroll(PoseStack poseStack) { + RenderUtils.drawRect( + poseStack, + CommonColors.GRAY, + CONFIGURABLE_SCROLL_X, + 21, + 0, + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + SCROLL_AREA_HEIGHT); - renderY += 46; + configurableScrollRenderY = SCROLL_START_Y + + MathUtils.map( + configurablesScrollOffset, + 0, + getMaxConfigurableScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + + RenderUtils.drawHoverableTexturedRect( + poseStack, + Texture.CONFIG_BOOK_SCROLL_BUTTON, + CONFIGURABLE_SCROLL_X, + configurableScrollRenderY, + draggingConfigurableScroll); + } + + private void renderConfigs(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + RenderUtils.createRectMask( + guiGraphics.pose(), Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 10, 21, 160, CONFIGS_PER_PAGE * 46); + + for (WynntilsButton config : configs) { + config.render(guiGraphics, mouseX, mouseY, partialTick); + } + + RenderUtils.clearMask(); + } + + private void renderConfigScroll(PoseStack poseStack) { + if (configs.size() <= CONFIGS_PER_PAGE) return; + + RenderUtils.drawRect( + poseStack, + CommonColors.GRAY, + CONFIG_SCROLL_X, + SCROLL_START_Y, + 0, + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + SCROLL_AREA_HEIGHT); + + configScrollRenderY = SCROLL_START_Y + + MathUtils.map( + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + + RenderUtils.drawHoverableTexturedRect( + poseStack, + Texture.CONFIG_BOOK_SCROLL_BUTTON, + CONFIG_SCROLL_X, + configScrollRenderY, + draggingConfigScroll); + } + + private void renderTooltips(GuiGraphics guiGraphics, int mouseX, int mouseY) { + // The tags have a slight bit rendered underneath the book, we don't want to render the tooltip + // when hovering that bit. + if (mouseX >= 0 && mouseY >= 0) return; + + for (GuiEventListener child : children()) { + if (child instanceof TooltipProvider tooltipProvider && child.isMouseOver(mouseX, mouseY)) { + guiGraphics.renderComponentTooltip( + FontRenderer.getInstance().getFont(), tooltipProvider.getTooltipLines(), mouseX, mouseY); + break; + } + } + } + + private void importSettings(int clicked) { + String clipboard = McUtils.mc().keyboardHandler.getClipboard(); + + if (clicked == GLFW.GLFW_MOUSE_BUTTON_LEFT) { + List configsToImport = Managers.Feature.getFeatures().stream() + .map(feature -> (Configurable) feature) + .collect(Collectors.toList()); + + configsToImport.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !configsToImport.contains(Managers.Overlay.getOverlayParent(overlay))) + .toList()); + + boolean imported = Managers.Config.importConfig(clipboard, configsToImport); + + if (imported) { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.importedAll") + .withStyle(ChatFormatting.GREEN)); + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.import.failed") + .withStyle(ChatFormatting.RED)); + } + } else if (clicked == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { + if (selectedConfigurable != null) { + boolean imported = Managers.Config.importConfig(clipboard, List.of(selectedConfigurable)); + + if (imported) { + McUtils.sendMessageToClient(Component.translatable( + "screens.wynntils.settingsScreen.imported", + selectedConfigurable.getTranslatedName()) + .withStyle(ChatFormatting.GREEN)); + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.import.failed") + .withStyle(ChatFormatting.RED)); + } + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.needToSelect") + .withStyle(ChatFormatting.RED)); + } + } + + // Repopulate the configurables and configs after importing + populateConfigurables(); + populateConfigs(); + } + + private void exportSettings(int clicked) { + String exportedSettings = ""; + + if (clicked == GLFW.GLFW_MOUSE_BUTTON_LEFT) { + // Get all features and overlays into a list + List featuresToExport = Managers.Feature.getFeatures().stream() + .map(feature -> (Configurable) feature) + .collect(Collectors.toList()); + + featuresToExport.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !featuresToExport.contains(Managers.Overlay.getOverlayParent(overlay))) + .toList()); + + exportedSettings = Managers.Config.exportConfig(featuresToExport); + + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.exportedAll") + .withStyle(ChatFormatting.GREEN)); + } else if (clicked == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { + if (selectedConfigurable != null) { + exportedSettings = Managers.Config.exportConfig(List.of(selectedConfigurable)); + + McUtils.sendMessageToClient(Component.translatable( + "screens.wynntils.settingsScreen.exported", selectedConfigurable.getTranslatedName()) + .withStyle(ChatFormatting.GREEN)); + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.needToSelect") + .withStyle(ChatFormatting.RED)); + } } + + // Save to clipboard + McUtils.mc().keyboardHandler.setClipboard(exportedSettings); } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java deleted file mode 100644 index 2d049d5b53..0000000000 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © Wynntils 2023-2024. - * This file is released under LGPLv3. See LICENSE for full license details. - */ -package com.wynntils.screens.settings.widgets; - -import com.wynntils.core.components.Managers; -import com.wynntils.screens.settings.WynntilsBookSettingsScreen; -import com.wynntils.utils.mc.McUtils; -import com.wynntils.utils.render.Texture; -import java.util.List; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; - -public class ApplyButton extends GeneralSettingsButton { - private final WynntilsBookSettingsScreen screen; - - public ApplyButton(WynntilsBookSettingsScreen screen) { - super( - 55, - Texture.CONFIG_BOOK_BACKGROUND.height() - 30, - 35, - 14, - Component.translatable("screens.wynntils.settingsScreen.apply"), - List.of(Component.translatable("screens.wynntils.settingsScreen.apply.description") - .withStyle(ChatFormatting.GREEN)), - 0, - McUtils.mc().screen.height); - this.screen = screen; - } - - @Override - public void onPress() { - Managers.Config.saveConfig(); - screen.onClose(); - } -} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java index 6d75c21630..de67e0a103 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java @@ -5,10 +5,11 @@ package com.wynntils.screens.settings.widgets; import com.wynntils.core.persisted.config.Config; +import com.wynntils.screens.settings.WynntilsBookSettingsScreen; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; import com.wynntils.utils.mc.ComponentUtils; -import com.wynntils.utils.render.FontRenderer; +import com.wynntils.utils.mc.McUtils; import java.util.List; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -16,16 +17,25 @@ public class BooleanSettingsButton extends GeneralSettingsButton { private final Config config; - public BooleanSettingsButton(int x, int y, Config config, int maskTopY, int maskBottomY) { + public BooleanSettingsButton( + int x, + int y, + Config config, + int maskTopY, + int maskBottomY, + float translationX, + float translationY) { super( x, y, - 50, - FontRenderer.getInstance().getFont().lineHeight + 8, + 90, + 20, getTitle(config), ComponentUtils.wrapTooltips(List.of(Component.literal(config.getDescription())), 150), maskTopY, - maskBottomY); + maskBottomY, + translationX, + translationY); this.config = config; } @@ -33,6 +43,12 @@ public BooleanSettingsButton(int x, int y, Config config, int maskTopY, public void onPress() { config.setValue(!isEnabled(config)); setMessage(getTitle(config)); + + // Reload the configurables in case the enabled button was toggled so the checkboxes + // can change state + if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { + bookSettingsScreen.populateConfigurables(); + } } private static MutableComponent getTitle(Config config) { diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java index 047f6b0fd1..d39a33d81d 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java @@ -1,5 +1,5 @@ /* - * Copyright © Wynntils 2022-2023. + * Copyright © Wynntils 2022-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.screens.settings.widgets; @@ -36,7 +36,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float this.getY(), 0, CommonColors.CYAN, - HorizontalAlignment.CENTER, + HorizontalAlignment.LEFT, TextShadow.NORMAL); } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java deleted file mode 100644 index 3fa01f4135..0000000000 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright © Wynntils 2023-2024. - * This file is released under LGPLv3. See LICENSE for full license details. - */ -package com.wynntils.screens.settings.widgets; - -import com.wynntils.screens.settings.WynntilsBookSettingsScreen; -import com.wynntils.utils.mc.McUtils; -import com.wynntils.utils.render.Texture; -import java.util.List; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; - -public class CloseButton extends GeneralSettingsButton { - private final WynntilsBookSettingsScreen screen; - - public CloseButton(WynntilsBookSettingsScreen screen) { - super( - 15, - Texture.CONFIG_BOOK_BACKGROUND.height() - 30, - 35, - 14, - Component.translatable("screens.wynntils.settingsScreen.close"), - List.of(Component.translatable("screens.wynntils.settingsScreen.close.description") - .withStyle(ChatFormatting.DARK_RED)), - 0, - McUtils.mc().screen.height); - this.screen = screen; - } - - @Override - public void onPress() { - screen.onClose(); - } -} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java index c212011df4..3b2979dd10 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java @@ -26,7 +26,6 @@ public class ConfigTile extends WynntilsButton { private final TextboxScreen screen; - private final Config config; private final int maskTopY; private final int maskBottomY; private final float translationX; @@ -40,7 +39,7 @@ public ConfigTile(int x, int y, int width, int height, TextboxScreen screen, Con this.screen = screen; if (screen instanceof WynntilsBookSettingsScreen settingsScreen) { - maskTopY = settingsScreen.getConfigMaskTopY(); + maskTopY = settingsScreen.getMaskTopY(); maskBottomY = settingsScreen.getConfigMaskBottomY(); displayName = settingsScreen.configOptionContains(config) ? StyledText.fromString(ChatFormatting.UNDERLINE + config.getDisplayName()) @@ -63,7 +62,6 @@ public ConfigTile(int x, int y, int width, int height, TextboxScreen screen, Con translationY = 0; } - this.config = config; this.configOptionElement = getWidgetFromConfig(config); this.resetButton = new ResetButton( config, @@ -160,10 +158,22 @@ private int getRenderX() { private > AbstractWidget getWidgetFromConfig(Config configOption) { if (configOption.getType().equals(Boolean.class)) { return new BooleanSettingsButton( - getRenderX(), getRenderY(), (Config) configOption, maskTopY, maskBottomY); + getRenderX(), + getRenderY(), + (Config) configOption, + maskTopY, + maskBottomY, + translationX, + translationY); } else if (configOption.isEnum()) { return new EnumSettingsButton<>( - getRenderX(), getRenderY(), (Config) configOption, maskTopY, maskBottomY); + getRenderX(), + getRenderY(), + (Config) configOption, + maskTopY, + maskBottomY, + translationX, + translationY); } else if (configOption.getType().equals(CustomColor.class)) { return new CustomColorSettingsButton( getRenderX(), getRenderY(), (Config) configOption, screen, maskTopY, maskBottomY); diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java index 94626dd632..13c0f00d5d 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java @@ -6,12 +6,15 @@ import com.google.common.collect.Lists; import com.mojang.blaze3d.vertex.PoseStack; +import com.wynntils.core.components.Managers; import com.wynntils.core.consumers.features.Configurable; import com.wynntils.core.consumers.features.Feature; import com.wynntils.core.consumers.overlays.CustomNameProperty; import com.wynntils.core.consumers.overlays.Overlay; +import com.wynntils.core.persisted.config.Config; import com.wynntils.core.text.StyledText; import com.wynntils.screens.base.widgets.WynntilsButton; +import com.wynntils.screens.base.widgets.WynntilsCheckbox; import com.wynntils.screens.settings.WynntilsBookSettingsScreen; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; @@ -22,17 +25,28 @@ import com.wynntils.utils.render.type.TextShadow; import com.wynntils.utils.render.type.VerticalAlignment; import java.util.List; +import java.util.Optional; +import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; public class ConfigurableButton extends WynntilsButton { private final Configurable configurable; - private final WynntilsBookSettingsScreen settingsScreen; - + private final WynntilsCheckbox enabledCheckbox; + private final int maskTopY; + private final int maskBottomY; + private final int matchingConfigs; private final List descriptionTooltip; + private final WynntilsBookSettingsScreen settingsScreen; public ConfigurableButton( - int x, int y, int width, int height, Configurable configurable, WynntilsBookSettingsScreen screen) { + int x, + int y, + int width, + int height, + Configurable configurable, + WynntilsBookSettingsScreen screen, + int matchingConfigs) { super(x, y, width, height, Component.literal(configurable.getTranslatedName())); this.configurable = configurable; this.settingsScreen = screen; @@ -43,16 +57,34 @@ public ConfigurableButton( } else { descriptionTooltip = List.of(); } + + boolean enabled = false; + if (configurable instanceof Overlay selectedOverlay) { + enabled = Managers.Overlay.isEnabled(selectedOverlay); + } else if (configurable instanceof Feature selectedFeature) { + enabled = selectedFeature.isEnabled(); + } + + this.enabledCheckbox = new WynntilsCheckbox(x + width - 10, y, 10, 10, Component.literal(""), enabled, 0); + + this.maskTopY = settingsScreen.getMaskTopY(); + this.maskBottomY = settingsScreen.getConfigurableMaskBottomY(); + this.matchingConfigs = matchingConfigs; } @Override public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { PoseStack poseStack = guiGraphics.pose(); + // Don't want to display tooltip when the tile is outside the mask from the screen + if (isHovered && (mouseY <= maskTopY || mouseY >= maskBottomY)) { + isHovered = false; + } + CustomColor color = isHovered ? CommonColors.YELLOW : CommonColors.WHITE; if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { - if (bookSettingsScreen.getSelected() == configurable) { + if (bookSettingsScreen.getSelectedConfigurable() == configurable) { color = CommonColors.GRAY; } } @@ -67,13 +99,17 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float } } + if (matchingConfigs > 0) { + textToRender += ChatFormatting.GRAY + " [" + matchingConfigs + "]"; + } + FontRenderer.getInstance() .renderScrollingText( poseStack, StyledText.fromString(textToRender), (isOverlay ? this.getX() + 12 : this.getX()), this.getY(), - (isOverlay ? this.width - 12 : this.width), + (isOverlay ? this.width - 12 : this.width) - 11, settingsScreen.getTranslationX(), settingsScreen.getTranslationY(), color, @@ -82,6 +118,8 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float TextShadow.NORMAL, 1f); + enabledCheckbox.render(guiGraphics, mouseX, mouseY, partialTick); + if (isHovered && configurable instanceof Feature) { McUtils.mc() .screen @@ -89,10 +127,49 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float } } + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + // Prevent interaction when the tile is outside of the mask from the screen + if ((mouseY <= maskTopY || mouseY >= maskBottomY)) return false; + + // Toggle the enabled state of the configurable when toggling the checkbox + if (enabledCheckbox.isMouseOver(mouseX, mouseY)) { + if (configurable instanceof Feature feature) { + feature.setUserEnabled(!feature.isEnabled()); + } else if (configurable instanceof Overlay) { + Optional> configOpt = configurable.getConfigOptionFromString("userEnabled"); + + if (configOpt.isPresent()) { + Config config = (Config) configOpt.get(); + config.setValue(!config.get()); + } else { + return false; + } + } + + // Repopulate screen to update new enabled/disabled states + if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { + bookSettingsScreen.populateConfigurables(); + bookSettingsScreen.populateConfigs(); + } + + return enabledCheckbox.mouseClicked(mouseX, mouseY, button); + } + + return super.mouseClicked(mouseX, mouseY, button); + } + @Override public void onPress() { if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { - bookSettingsScreen.setSelected(configurable); + bookSettingsScreen.setSelectedConfigurable(configurable); } } + + @Override + public void setY(int y) { + super.setY(y); + + enabledCheckbox.setY(y); + } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java index 38b780aebf..7e9ff98cfa 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java @@ -14,7 +14,7 @@ public class CustomColorSettingsButton extends TextInputBoxSettingsWidget { public CustomColorSettingsButton( int x, int y, Config config, TextboxScreen textboxScreen, int maskTopY, int maskBottomY) { - super(x, y, config, textboxScreen, 80, maskTopY, maskBottomY); + super(x, y, config, textboxScreen, maskTopY, maskBottomY); } @Override @@ -24,6 +24,6 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float PoseStack poseStack = guiGraphics.pose(); CustomColor value = config.get(); - RenderUtils.drawRect(poseStack, value, width + 5, 6, 0, height, height); + RenderUtils.drawRect(poseStack, value, getX() + getWidth() + 4, getY(), 0, height, height); } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java index 39b3a5f19e..ad8fbec5c9 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java @@ -5,14 +5,10 @@ package com.wynntils.screens.settings.widgets; import com.wynntils.core.persisted.config.Config; -import com.wynntils.utils.EnumUtils; import com.wynntils.utils.mc.ComponentUtils; import com.wynntils.utils.mc.McUtils; -import com.wynntils.utils.render.FontRenderer; -import java.lang.reflect.Type; import java.util.EnumSet; import java.util.List; -import net.minecraft.client.gui.Font; import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; @@ -20,16 +16,19 @@ public class EnumSettingsButton> extends GeneralSettingsButton private final Config config; private final List enumConstants; - public EnumSettingsButton(int x, int y, Config config, int maskTopY, int maskBottomY) { + public EnumSettingsButton( + int x, int y, Config config, int maskTopY, int maskBottomY, float translationX, float translationY) { super( x, y, - getWidth(config.getType()), - FontRenderer.getInstance().getFont().lineHeight + 8, + 90, + 20, Component.literal(config.getValueString()), ComponentUtils.wrapTooltips(List.of(Component.literal(config.getDescription())), 150), maskTopY, - maskBottomY); + maskBottomY, + translationX, + translationY); this.config = config; enumConstants = EnumSet.allOf((Class) config.getType()).stream().toList(); } @@ -63,13 +62,4 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { public void onPress() { // We use instead AbstractWidget#mouseClicked, because we also want to have an action on the right mouse button } - - private static > int getWidth(Type type) { - Font font = FontRenderer.getInstance().getFont(); - int maxWidth = EnumSet.allOf((Class) type).stream() - .mapToInt(enumValue -> font.width(EnumUtils.toNiceString(enumValue))) - .max() - .orElse(0); - return maxWidth + 8; - } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java new file mode 100644 index 0000000000..6ff36a27ae --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java @@ -0,0 +1,105 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.wynntils.screens.base.widgets.BasicTexturedButton; +import com.wynntils.utils.render.RenderUtils; +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; + +public abstract class GeneralSettingsTabButton extends BasicTexturedButton { + private static final int MAX_OFFSET = -8; + private static final int MIN_OFFSET = 0; + + protected boolean selectedTab = false; + protected Texture tagTexture; + + private final OffsetDirection offsetDirection; + private final Texture iconTexture; + + private int hoverOffset = 0; + + GeneralSettingsTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + Texture tagTexture, + Texture iconTexture, + OffsetDirection offsetDirection) { + super(x, y, width, height, tagTexture, onClick, tooltip); + this.tagTexture = tagTexture; + this.iconTexture = iconTexture; + this.offsetDirection = offsetDirection; + } + + @Override + public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + PoseStack poseStack = guiGraphics.pose(); + + // Don't count as hovered if mouse is hovering the book as the tags render + // slightly underneath the book + if (isHovered + && ((offsetDirection == OffsetDirection.UP && mouseY >= 0) + || (offsetDirection == OffsetDirection.RIGHT + && mouseX <= Texture.CONFIG_BOOK_BACKGROUND.width()) + || (offsetDirection == OffsetDirection.DOWN + && mouseY <= Texture.CONFIG_BOOK_BACKGROUND.height()) + || (offsetDirection == OffsetDirection.LEFT && mouseX >= 0))) { + isHovered = false; + } + + // Determine the offset of the tag. When selected the max offset should be used, otherwise when hovered + // increase until limit reached. + if (selectedTab) { + this.hoverOffset = (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) + ? MAX_OFFSET + : -MAX_OFFSET; + } else if (this.isHovered) { + hoverOffset += (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) ? -1 : 1; + hoverOffset = (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) + ? Math.max(hoverOffset, MAX_OFFSET) + : Math.min(hoverOffset, -MAX_OFFSET); + } else { + hoverOffset += (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) ? 1 : -1; + hoverOffset = (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) + ? Math.min(hoverOffset, MIN_OFFSET) + : Math.max(hoverOffset, MIN_OFFSET); + } + + // Move the tag render position + poseStack.pushPose(); + poseStack.translate( + (offsetDirection == OffsetDirection.RIGHT || offsetDirection == OffsetDirection.LEFT) ? hoverOffset : 0, + (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.DOWN) ? hoverOffset : 0, + 0); + + RenderUtils.drawTexturedRect(poseStack, tagTexture, this.getX(), this.getY()); + + // Render icon on tag + if (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.DOWN) { + RenderUtils.drawTexturedRect( + poseStack, iconTexture, getX() + (getWidth() - iconTexture.width()) / 2f, getY() + 14); + } else { + RenderUtils.drawTexturedRect( + poseStack, iconTexture, getX() + 14, getY() + (getHeight() - iconTexture.height()) / 2f); + } + + poseStack.popPose(); + } + + protected enum OffsetDirection { + UP, + RIGHT, + DOWN, + LEFT + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java index 87931bc2e0..229b552ecc 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java @@ -5,8 +5,10 @@ package com.wynntils.screens.settings.widgets; import com.wynntils.core.persisted.config.Config; +import com.wynntils.screens.settings.WynntilsBookSettingsScreen; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; +import com.wynntils.utils.mc.McUtils; import com.wynntils.utils.render.FontRenderer; import java.util.List; import net.minecraft.client.sounds.SoundManager; @@ -25,7 +27,9 @@ public class ResetButton extends GeneralSettingsButton { Component.translatable("screens.wynntils.settingsScreen.reset.name"), List.of(Component.translatable("screens.wynntils.settingsScreen.reset.description")), maskTopY, - maskBottomY); + maskBottomY, + 0, + 0); this.config = config; this.onClick = onClick; } @@ -51,5 +55,10 @@ public void onPress() { if (!config.valueChanged()) return; config.reset(); onClick.run(); + + // Reload configurables to update checkbox + if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { + bookSettingsScreen.populateConfigurables(); + } } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java new file mode 100644 index 0000000000..b61c5b950c --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java @@ -0,0 +1,61 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.wynntils.core.persisted.config.Category; +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.network.chat.Component; + +public class SettingsCategoryTabButton extends GeneralSettingsTabButton { + private Category category; + + public SettingsCategoryTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + Category category, + boolean selectedCategory) { + super(x, y, width, height, onClick, tooltip, Texture.TAG_RED, category.getCategoryIcon(), OffsetDirection.UP); + this.category = category; + this.selectedTab = selectedCategory; + + setSelectedCategory(selectedCategory); + } + + public SettingsCategoryTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + boolean selectedCategory) { + super(x, y, width, height, onClick, tooltip, Texture.TAG_RED, Texture.ALL_CONFIG_ICON, OffsetDirection.UP); + this.category = null; + this.selectedTab = selectedCategory; + + setSelectedCategory(selectedCategory); + } + + public void setSelectedCategory(boolean selectedCategory) { + this.selectedTab = selectedCategory; + + // When selected use a different texture to show the category has been selected + if (this.selectedTab) { + tagTexture = Texture.TAG_RED_SELECTED; + } else { + tagTexture = Texture.TAG_RED; + } + } + + public Category getCategory() { + return category; + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java new file mode 100644 index 0000000000..a89962c7e9 --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java @@ -0,0 +1,26 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.network.chat.Component; + +public class SettingsPageTabButton extends GeneralSettingsTabButton { + public SettingsPageTabButton( + int x, int y, int width, int height, Consumer onClick, List tooltip, boolean nextPage) { + super( + x, + y, + width, + height, + onClick, + tooltip, + Texture.TAG_RED, + nextPage ? Texture.NEXT : Texture.PREVIOUS, + OffsetDirection.UP); + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java new file mode 100644 index 0000000000..1339421329 --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java @@ -0,0 +1,24 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.network.chat.Component; + +public class SettingsSideTabButton extends GeneralSettingsTabButton { + public SettingsSideTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + Texture tagTexture, + Texture iconTexture) { + super(x, y, width, height, onClick, tooltip, tagTexture, iconTexture, OffsetDirection.LEFT); + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java b/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java index d30a69d288..618322fbf2 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java @@ -9,7 +9,6 @@ import com.wynntils.screens.base.widgets.TextInputBoxWidget; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.mc.ComponentUtils; -import com.wynntils.utils.render.FontRenderer; import java.util.List; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; @@ -20,8 +19,8 @@ public class TextInputBoxSettingsWidget extends TextInputBoxWidget { private final int maskBottomY; protected TextInputBoxSettingsWidget( - int x, int y, Config config, TextboxScreen textboxScreen, int width, int maskTopY, int maskBottomY) { - super(x, y, width, FontRenderer.getInstance().getFont().lineHeight + 8, null, textboxScreen); + int x, int y, Config config, TextboxScreen textboxScreen, int maskTopY, int maskBottomY) { + super(x, y, 90, 20, null, textboxScreen); this.config = config; this.maskTopY = maskTopY; this.maskBottomY = maskBottomY; @@ -29,11 +28,6 @@ protected TextInputBoxSettingsWidget( tooltip = ComponentUtils.wrapTooltips(List.of(Component.literal(config.getDescription())), 150); } - public TextInputBoxSettingsWidget( - int x, int y, Config config, TextboxScreen textboxScreen, int maskTopY, int maskBottomY) { - this(x, y, config, textboxScreen, 100, maskTopY, maskBottomY); - } - @Override public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { // Don't want to display tooltip when the tile is outside the mask from the screen diff --git a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java index 16950d912d..d35a17363f 100644 --- a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java +++ b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java @@ -259,6 +259,109 @@ public void renderAlignedTextInBox( 1f); } + public void renderScrollingString( + PoseStack poseStack, + StyledText styledText, + float x, + float y, + float renderArea, + float scissorX, + float scissorY, + CustomColor customColor, + HorizontalAlignment horizontalAlignment, + VerticalAlignment verticalAlignment, + TextShadow shadow, + float textScale) { + int textLength = (int) ((font.width(styledText.getString()) + 1) * textScale); + float m; + + if (textLength > renderArea) { + m = textLength - renderArea; + double currentTimeInSeconds = (double) Util.getMillis() / 1000.0; + double e = Math.max((double) m * 0.5, 3.0); + double f = + Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * currentTimeInSeconds / e)) / 2.0 + 0.5; + double scrollOffset = Mth.lerp(f, 0.0, m); + + RenderUtils.enableScissor((int) scissorX, (int) scissorY, (int) renderArea, font.lineHeight); + renderText( + poseStack, + styledText, + x - (int) scrollOffset, + y, + customColor, + horizontalAlignment, + verticalAlignment, + shadow, + textScale); + RenderUtils.disableScissor(); + } else { + renderText( + poseStack, + styledText, + x, + y, + customColor, + horizontalAlignment, + verticalAlignment, + shadow, + textScale); + } + } + + public void renderScrollingString( + PoseStack poseStack, + StyledText styledText, + float x, + float y, + float renderArea, + float scissorX, + float scissorY, + CustomColor customColor, + HorizontalAlignment horizontalAlignment, + VerticalAlignment verticalAlignment, + TextShadow shadow) { + renderScrollingString( + poseStack, + styledText, + x, + y, + renderArea, + scissorX, + scissorY, + customColor, + horizontalAlignment, + verticalAlignment, + shadow, + 1); + } + + public void renderScrollingString( + PoseStack poseStack, + StyledText styledText, + float x, + float y, + float renderArea, + CustomColor customColor, + HorizontalAlignment horizontalAlignment, + VerticalAlignment verticalAlignment, + TextShadow shadow, + float textScale) { + renderScrollingString( + poseStack, + styledText, + x, + y, + renderArea, + x, + y, + customColor, + horizontalAlignment, + verticalAlignment, + shadow, + textScale); + } + private void renderText( PoseStack poseStack, StyledText text, diff --git a/common/src/main/java/com/wynntils/utils/render/Texture.java b/common/src/main/java/com/wynntils/utils/render/Texture.java index 928162ea17..2d1c43903e 100644 --- a/common/src/main/java/com/wynntils/utils/render/Texture.java +++ b/common/src/main/java/com/wynntils/utils/render/Texture.java @@ -26,6 +26,10 @@ public enum Texture { CONTENT_BOOK_BACKGROUND("content_book/content_book.png", 339, 220), CONTENT_BOOK_SEARCH("content_book/content_book_search.png", 133, 23), CONTENT_BOOK_TITLE("content_book/content_book_title.png", 168, 33), + TAG_BLUE("content_book/tag_blue.png", 44, 22), + TAG_RED("content_book/tag_red.png", 22, 44), + TAG_RED_SELECTED("content_book/tag_red_selected.png", 22, 44), + TAG_SEARCH("content_book/tag_search.png", 140, 34), // endregion // region Icons @@ -38,6 +42,25 @@ public enum Texture { ACTIVITY_STARTED("icons/activities/activity_started_icon.png", 7, 7), CAVE_AVALIABLE_ICON("icons/activities/cave_avaliable_icon.png", 7, 7), + // Config Categories + ALL_CONFIG_ICON("icons/config_categories/all_config_icon.png", 16, 16), + CHAT_CONFIG_ICON("icons/config_categories/chat_config_icon.png", 16, 16), + COMBAT_CONFIG_ICON("icons/config_categories/combat_config_icon.png", 16, 16), + COMMANDS_CONFIG_ICON("icons/config_categories/commands_config_icon.png", 16, 16), + DEBUG_CONFIG_ICON("icons/config_categories/debug_config_icon.png", 16, 16), + EMBELLISHMENTS_CONFIG_ICON("icons/config_categories/embellishments_config_icon.png", 16, 16), + INVENTORY_CONFIG_ICON("icons/config_categories/inventory_config_icon.png", 16, 16), + MAP_CONFIG_ICON("icons/config_categories/map_config_icon.png", 16, 16), + OVERLAYS_CONFIG_ICON("icons/config_categories/overlays_config_icon.png", 16, 16), + PLAYERS_CONFIG_ICON("icons/config_categories/players_config_icon.png", 16, 16), + REDIRECTS_CONFIG_ICON("icons/config_categories/redirects_config_icon.png", 16, 16), + TOOLTIPS_CONFIG_ICON("icons/config_categories/tooltips_config_icon.png", 16, 16), + TRADE_MARKET_CONFIG_ICON("icons/config_categories/trade_market_config_icon.png", 16, 16), + UI_CONFIG_ICON("icons/config_categories/ui_config_icon.png", 16, 16), + UNCATEGORIZED_CONFIG_ICON("icons/config_categories/uncategorized_config_icon.png", 16, 16), + UTILITIES_CONFIG_ICON("icons/config_categories/utilities_config_icon.png", 16, 16), + WYNNTILS_CONFIG_ICON("icons/config_categories/wynntils_config_icon.png", 16, 16), + // Content Book DIALOGUE_ICON("icons/content_book/dialogue_icon.png", 14, 11), DISCOVERIES_ICON("icons/content_book/discoveries_icon.png", 16, 32), @@ -76,15 +99,20 @@ public enum Texture { CHECKMARK_GRAY("icons/generic/check_gray.png", 16, 16), CHECKMARK_GREEN("icons/generic/check_green.png", 16, 16), CHECKMARK_YELLOW("icons/generic/check_yellow.png", 16, 16), + CLOSE("icons/generic/close.png", 16, 16), DEFENSE_FILTER_ICON("icons/generic/defense_filter_icon.png", 16, 16), EDIT_ICON("icons/generic/edit_icon.png", 6, 16), FAVORITE_ICON("icons/generic/favorite_icon.png", 18, 18), HELP_ICON("icons/generic/help_icon.png", 10, 16), INFO("icons/generic/info.png", 25, 25), ITEM_LOCK("icons/generic/item_lock_icon.png", 16, 16), + NEXT("icons/generic/next.png", 16, 16), OVERLAY_EXTRA_ICON("icons/generic/overlay_extra_icon.png", 16, 16), + PREVIOUS("icons/generic/previous.png", 16, 16), QUESTION_MARK("icons/generic/question_mark.png", 4, 7), QUESTS_SCROLL_ICON("icons/generic/quests_scroll_icon.png", 16, 16), + RESET("icons/generic/reset.png", 16, 16), + SAVE("icons/generic/save.png", 16, 16), SHARE_ICON("icons/generic/share_icon.png", 16, 14), SIGN_ICON("icons/generic/sign_icon.png", 17, 18), SMALL_ADD_ICON("icons/generic/small_add_icon.png", 16, 16), @@ -226,6 +254,8 @@ public enum Texture { BACKGROUND_SPLASH("ui_components/background_splash.png", 1920, 1027), COSMETIC_VIEWER_BACKGROUND("ui_components/cosmetics_viewer_background.png", 72, 92), CONTAINER_SIDEBAR("ui_components/container_sidebar.png", 25, 136), + CROWD_SOURCE_BACKGROUND("ui_components/crowd_source_background.png", 180, 260), + CROWD_SOURCE_STICKER("ui_components/crowd_source_sticker.png", 36, 36), EMERALD_COUNT_BACKGROUND("ui_components/emerald_count_background.png", 24, 24), GEAR_ICONS("ui_components/gear_icons.png", 64, 128), GEAR_VIEWER_BACKGROUND("ui_components/gear_viewer_background.png", 103, 92), diff --git a/common/src/main/resources/assets/wynntils/lang/en_us.json b/common/src/main/resources/assets/wynntils/lang/en_us.json index 96117d5b6d..190dc13012 100644 --- a/common/src/main/resources/assets/wynntils/lang/en_us.json +++ b/common/src/main/resources/assets/wynntils/lang/en_us.json @@ -2315,15 +2315,31 @@ "screens.wynntils.savedItems.name": "Item Record", "screens.wynntils.savedItems.unableToShare": "Unable to share item", "screens.wynntils.searchWidget.defaultSearchText": "Search...", + "screens.wynntils.settingsScreen.all": "All", "screens.wynntils.settingsScreen.apply": "Apply", "screens.wynntils.settingsScreen.apply.description": "Save changes", "screens.wynntils.settingsScreen.booleanConfig.disabled": "Disabled", "screens.wynntils.settingsScreen.booleanConfig.enabled": "Enabled", "screens.wynntils.settingsScreen.close": "Close", "screens.wynntils.settingsScreen.close.description": "Close without saving changes", + "screens.wynntils.settingsScreen.export": "Export Settings", + "screens.wynntils.settingsScreen.export.all": "- Left click to export settings from your clipboard for all settings.", + "screens.wynntils.settingsScreen.export.selected": "- Right click to export settings from your clipboard for the currently selected setting.", + "screens.wynntils.settingsScreen.exported": "Sucessfully exported settings for %s", + "screens.wynntils.settingsScreen.exportedAll": "Sucessfully exported all settings", + "screens.wynntils.settingsScreen.import": "Import Settings", + "screens.wynntils.settingsScreen.import.all": "- Left click to import settings from your clipboard for all settings.", + "screens.wynntils.settingsScreen.import.failed": "Failed to import settings", + "screens.wynntils.settingsScreen.import.selected": "- Right click to import settings from your clipboard for the currently selected setting.", + "screens.wynntils.settingsScreen.imported": "Sucessfully imported settings for %s", + "screens.wynntils.settingsScreen.importedAll": "Sucessfully imported all settings", "screens.wynntils.settingsScreen.name": "Wynntils Settings", + "screens.wynntils.settingsScreen.needToSelect": "You need to select a setting to perform this action!", + "screens.wynntils.settingsScreen.next": "Next", + "screens.wynntils.settingsScreen.previous": "Previous", "screens.wynntils.settingsScreen.reset.description": "Reset config to default value.", "screens.wynntils.settingsScreen.reset.name": "Reset", + "screens.wynntils.settingsScreen.unselectedConfig": "Here you can edit all of the various features available in Wynntils. Click any of the features in the left page of the book and the options available for that feature will appear here!", "screens.wynntils.skillPointLoadouts.assigned": "Assigned (%d)", "screens.wynntils.skillPointLoadouts.confirm": "Confirm", "screens.wynntils.skillPointLoadouts.convert": "Convert Types", diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/config_book_scroll_area.png b/common/src/main/resources/assets/wynntils/textures/content_book/config_book_scroll_area.png deleted file mode 100644 index e196c35f56255fb0f2bdab56ba5528a4ea35eed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1086 zcmeAS@N?(olHy`uVBq!ia0vp^D}Z=C2OE&g^qb1Vz`)p?>FgZf>FlgfP?VpRnUl)E zpfRy_qOHea2brVs!Apa*_}(f!ny}C+Qb4ruik8Sirxl`6r3O2{aL+PP(bVf}%076o z|LCgb?#=7?)-@^oV0`rA$&wdJs{iygw{(1butWa+JKJ~n7@ansGFhE2bD`w+nI)5w z^!97D#R;}GXt*3nO_MC1G^OqRk6rE!>&rRkJ*|It{^EKu9X1x1N0DhW%s#Sx{IV>! z;GTNl#!YL4<_q`FEOC6~zD`?if1%z^oeyVb%shKW_;|O7N}db8A1$_u^?|2+20v0xEPLbSILm1x$Da8Y&7U^D&=rXLT$TO) z@fXGuLE$f@A3P9{&<*^y>-_HDyQ+VG_u0K)J}swc(L*E6ZeXmiC3(BMF#HF>1$&oI z28wVNctjR6Fz_7!VaBX$ot!{H_7YEDSN3OIOu|Z5lh-k<4oV2=o^Ircwa`%^(vF(b=D!<9MWsTD8^UJDbD~kWmxFvZbZDUPk z;e9)swYPI_6<%}M))hRX#(l+V5BA$y?}F`Wu4UZF`NLkj**5xX*(+n_t-icgb@lf? z=3Gi<3%Y%!vHGFDum%%rqf&r?28T#vlY=0TV(D^lTmYoFm|Pbq1OO?BJX0wvR1Pc% zk`o}HmykT%Y=U;P5^x(#9;ghf+tKAgUPSgAPWh+u(j_*tzgXly^7`p@_I3JB8>=%J zH&Qn0SlU|Nv#hY)=lz!FjnRDH%@Nb?*x9IhZr4B6`Oz z@11e^QCZeF TNih$Yv=}^H{an^LB{Ts5bVjaZ diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3df19ac5677d14b96f37ab6b92aa574e260305 GIT binary patch literal 421 zcmeAS@N?(olHy`uVBq!ia0vp^IzTMO!3-pOcK7`NQjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W>Rgz$e6&f#E+k1eC@qP7}dPvv$n_TBuVJ84Oq z01xwp2cgZ2HtkS8wQ9k?|NlD|yw99>zQih%G5^sNpY-BG(_c(roz~dHT(EVT>51Mo z)n^Qh5{`8;7VkDrc*oCn=JCmfNk#zKI)b s^|Y^AUFpqv{~_hIT*gtgUC&?tWpw!<;K5*K6by2Xr>mdKI;Vst0F-5*4FCWD literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png new file mode 100644 index 0000000000000000000000000000000000000000..d23614133cac6dcbc0224b91f3a5addc8e9a89bb GIT binary patch literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^VnD3J!3-qBx_2A`QjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W>Rsz$e7@KLY~<0R`Y}dNK~Qh06f#)-DP13+{Rw#E||u@Ad!RzA?X^ zeYbKq`t(81QOo#=oW@=87dMq3T>N-)U$kfa&jMy1(Y~8NZIzxbjv*Cu-k!KE*61M7 zaB+T*-SWWR%`F=3-|HP(ugyAU)6o6xso2Y}%*P#gRZ~pz-lv@MVX)n9ekt^7Z`WGi z45`f-Wk2ubCx^|Cm41`9d2PA)rMz#MTiNfZdH1W=%`R?RpBr2Lcm3SoVJDAX57(@T g^(wfWcTfJj_+xST!jey(pb%&9boFyt=akR{08YA?l>h($ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..2ccec693270cc50204f621a7d8c9980969d7d942 GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^VnD3J!3-qBx_2A`QjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W<5(fKQ0)|LN2JfB5jfsR=0Xzog{|2J>`FCg&$%9Z~> zGq-F3k;jhx4+;6dZQK9*_x~#>{6BHx|B4m=4Gciq0|NdhB>dmK`~R6U|EsJ2uU-4U zrw3%q;>AFX`}H_GfG#sF3Gxfx`>&Rvcio@=Rn`Ch{)^9w{2Lni*WBUH|Np;qOn?6W zDgNXCSHrLW|9}1na{jybEq&|%t!FlRyR#fFSZ%<^3H5u@@J`B5}@yI5? zy@xAm&c(m$&rXSAc_XyL{!@|Nv5K>rq0f1*v1EvDee2ZD*l_)9_Ic$Xo;~v~GfJ@8 znOJ#!J#8>AWA3>F8}u`tb1ywDy4NWqPWwK~lIW$`@y5&caerfEY7%Z`?h`|IB9chLBHH a^$bR5f7z`K~9B>$d%W&evU9>K%0Btla3GxeOnECnthiCa0KK(}n`!1g0zj|Fn zTKtZ@UA1kby|+L*}F2vnM~h zp&;ryp?k#x*4FR!W*NCz9;K(=9jKq?_iOE%B`384mrJvLJ$Fc5z3ZH#{y*Ja4%~ZQ z2qm zf`n?`Q>nlVo^ENW#5t;SB(*K2CSS=`JG_48mE1)$RNa#KW_xTg4cok-FQM$HDza=yVWrB?8=;v9mjR%uXwey{g_VtioB~oGz+87{F=JwUV&6qznxjhmFMC- io8P|E$k@!5_$|}a@f;UJ*9~A0GkCiCxvXjY`0gtzqa~6@!FNP(ENXW?p{Zi hEcvz9_sfbI6%6OTu(L-e?hgQY!_(EzWt~$(698BJSiArL literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6dc0343cf0686edbd92e45760db6da0c7abd6d GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFX8=RZ&@enAN z;OXKRQZXkvAt50oje*fEby|SIWK|KChdc`;qAjB>BYK?o?3tu3apH!Ql+=-v#ac5Q zO-(|c=DetuW4l_wRu{fNbP0l+XkKTYg0n literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..64208bb1c627023c0261384d0b33c957fbc1b930 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVag8LcH|4(puFR=gqe1!mmg7x+H_FN4B zO2&J-IEGZr2|XXk*Py_|e4+PIThoER{@Oxz*Xkxt59sR9a1}B-%o@X@WuShc>Cgjn zIi|G^$`{14%u*tHKS)_kRcqP$+G2u@6F+P9uA5btZ+phhpZzP|+Hhud>h{SW8CCO{ Ue!h5XtPXO!r>mdKI;Vst0C0Rs_5c6? literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..120fd015d098ed45eada17b6ce32063ce3117e06 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFa z2NdMESV9xFI<8Z=x_040#dQl8PUM;G>)4Z!&Bm4{pv;gW(6N#6L=0T)M;%y s*qD8v_Dngs_isTKBlB^$2}dvSGVBzWuXZ-?j0O3|)78&qol`;+0HDrJegFUf literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..74d5ea441e39258b86e57cdbd158107284a67433 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF+kmqoPQhZAPAJp z@N{tushE?TAYfFKz!R37knnzvB5je)m)^X+H}sz`a8MAK|Kj2SIiOUS zr;B4q#hm1X1OX#6vqXl*3tP4*7#yC{xKP5SI-;yZ#oWlCK(e`!p;@>k@sI#dqJ*J@ zGvkDZyly<1nE@rwctj+n;~A6{9m~w+FaRmdz4ng_V=9;I|Ku+~^^>bP0 Hl+XkKZ2dlr literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..17badfe1340dca17fa446e9262fadc575c85c72e GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFEaktF()}8AtWpzA%QbFVNJ&ykCctC5>CA6c=N*J-HU`53rrW!Uif&!;j?{D-f{Cp h%SuShke_A1z#t@OacZN$_nRR1c)I$ztaD0e0sv!CJ_vlmz(&Gpzr=U*Y|E0cAe5OrThlr;B4q#hlVp zhI|bQBFq;aDOjs3s3tz+kjQ_)*r0>D#>Hf7vgvFiNzJ2%E%_(#+42f7eay zid~Gba(FY_7k()dZYi~@R_$**Iv>UTk9c|?%$xg)`?)1=|BEL-EI>~3boFyt=akR{ E0K(Qk*8l(j literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..76f7ee61af10347b196d2e77ed0f07e07b9601f1 GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6toHO32_C|WP=O(Y6d{fA|*k7!3^{7D+ugg|G&SW{=GxMc>|pUIjhdI zzte#7Q#@T9Ln`Lj_D2dGR^V}Njbt&LV6yjrY+>GgHf&F}h$bN;#s%FK(}Se4->wl&l&>~9=6vsO`Qw}Sqi(TJNL}NpR_~nlWA4gr Zm$>6Xm=*?ZnGptZzo)C8%Q~loCICy2QO^JX literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd3dd0af545c1716d3d986375df147b57c8cad7 GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFlFzshFeMYskkK$lwyMy85QmbB?NBW(}D{Ypsi!+k-u)9CDK@yEt)2gWtl77R`%) z+@GHomu4in;Ih0QXH?%6!<6k0aehE=IY{VfNxE$fOI zFIBJGE^HX literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b3bcb883edebe0672e3f4845ec37f5adaa363b35 GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*Bmn?>7+WfB%2J!u^Ex0R{En_?l&a zk|CZhjv*Cu*7jZGYfunz+Bvi7?wWu9vyJa&eY@hEzUP1hbH)vkG@BzXo|TesTwmp0 z=M7iLR#4c(d}N~4qn_3@odw%N!*y=0*>-e))7+%L_eyIjs+jg@vTn@CoZSy{u&1k^ J%Q~loCIB?gNc;c* literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6029861fe8a80723371a6bbc8bda9cecd7bfd049 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFqA+A6g57@4ep9PfWDhcunPPqU7eZYB!{SF12-)~|Bikf)3IEGZr zNlpl1Vismo^m%p5(W&d>X}TOZCgZ?7c@vun8+CPa2gxK{)1|* T3a{HjL6&;D`njxgN@xNAVka=u literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8bc4143a6ac1356aabf5bc984227d421dfd946 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*Bm@&%eLluORS${eFXlg82bU?qt0I zN|t!KIEGZr3GMe3JD|YfoIKZ|aL4~l?W2A-Kb&-CJ}}9;hQly*h6byd>T7QMRaq+k zRxm939Cyt> literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..78eb080f2e2f49c4f2eef03cae60c90abd5e2a1e GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_I)32_C|WPt5u8AU*CLM1_d!3+ZR=l47GzyH5JVE%oDf&_zx!`6yf zK-p4H7srr_IlleTLPr!hSR9iirtY};JKpSv*BgG#TScc7vkE3C8|Xe-nX$w||M#?R zd9e;5HkWYI2MX1#pFgkMy`%P&o>9xW*gt_Wbxpi8!(LS^yfb-uf@4P9vIi`$@9%GW tz|_0hTR3n*<<{NR8}{rD_I-zU;uumfNA}!C-Ub5!=fHFp_mvrv5A~QYEZHw9(a0&$*t>D^sj5r0tZ#YtzDfA5 z@n}&-k%I5hRsqhu77qcAi3gN5Kg@Wt+5KXB!Q)WwydA9OcMd%l7UaoWc1a6@#a%pUXO@geCwXDOXAW literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/generic/next.png b/common/src/main/resources/assets/wynntils/textures/icons/generic/next.png new file mode 100644 index 0000000000000000000000000000000000000000..806b3e43695e5d8c38aa719915177896c0a62c47 GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFFVdQ&MBb@0Ohvp;X}SJiX>0Q&Z%LQT(O>YVTV}(f1?RfMl2~RW zOu6P+W7=>`J?+b)IE%Z@fyX{IYU`!1&i=*78NqxyfpP03kjFe-{an^LB{Ts5p`cg8 literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/generic/save.png b/common/src/main/resources/assets/wynntils/textures/icons/generic/save.png new file mode 100644 index 0000000000000000000000000000000000000000..496229626622dd7fd62bd34db13e570f5649b36a GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFFHHlZyP>gkTVOxe#N Date: Thu, 8 Feb 2024 18:31:19 +0000 Subject: [PATCH 02/28] feat: Overlay selection screen redesign --- .../selection/CustomBarSelectionScreen.java | 28 ++++++++-------- .../selection/OverlaySelectionScreen.java | 30 ++++++++++-------- .../selection/widgets/OverlayButton.java | 2 +- .../ui_components/overlay_button_bottom.png | Bin 0 -> 931 bytes .../ui_components/overlay_button_left.png | Bin 0 -> 782 bytes .../ui_components/overlay_button_top.png | Bin 0 -> 1095 bytes 6 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_bottom.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_left.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java index 234b0ef348..ff30998df8 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java @@ -62,12 +62,12 @@ protected void doInit() { calculateBarPosition(); textureButton = this.addRenderableWidget(new Button.Builder( - Component.literal(availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .toString()), - (b) -> {}) + Component.literal(availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .toString()), + (b) -> {}) .pos((int) ((this.width / 2f) - 30), (int) (barY + 20)) .size(60, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.customBarSelection.textureTooltip"))) @@ -79,14 +79,14 @@ protected void doInit() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) + Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) .pos((int) (this.width / 2f) - 90, (int) (barY + 45)) .size(80, 20) .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.select"), - (button) -> addCustomBar()) + Component.translatable("screens.wynntils.customBarSelection.select"), + (button) -> addCustomBar()) .pos((int) (this.width / 2f) + 10, (int) (barY + 45)) .size(80, 20) .build()); @@ -163,11 +163,11 @@ private void calculateBarPosition() { // Calculate the central position to render the current selected bar at barX = (this.width - availableBars.get(barTypeIndex).a().width()) / 2f; barY = (this.height - - availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .getHeight()) + - availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .getHeight()) / 2f; } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java index e76bcbfd54..ca983d2c5d 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java @@ -123,8 +123,8 @@ protected void doInit() { // region Preview renderables exitPreviewButton = this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlaySelection.exitPreview"), - (button) -> togglePreview(false)) + Component.translatable("screens.wynntils.overlaySelection.exitPreview"), + (button) -> togglePreview(false)) .pos((Texture.OVERLAY_SELECTION_GUI.width() / 2) - 40, (int) (this.height - 25 - translationY)) .size(80, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlaySelection.exitPreviewTooltip"))) @@ -464,7 +464,7 @@ public void populateOverlays() { // Don't deselect custom overlays as they will always fail the above check if (filterType == FilterType.BUILT_IN || !(selectedOverlay instanceof CustomBarOverlayBase - || selectedOverlay instanceof InfoBoxOverlay)) { + || selectedOverlay instanceof InfoBoxOverlay)) { setSelectedOverlay(null); } } @@ -488,6 +488,8 @@ public void populateOverlays() { setSelectedOverlay(newSelected); } + + scrollOverlays(overlayScrollOffset); } public void setSelectedOverlay(Overlay selectedOverlay) { @@ -604,6 +606,8 @@ private void populateConfigs() { renderY += 43; } + + scrollConfigs(configScrollOffset); } private void togglePreview(boolean enabled) { @@ -924,11 +928,11 @@ private void renderWidgets(GuiGraphics guiGraphics, int mouseX, int mouseY, floa private void renderOverlayScroll(PoseStack poseStack) { overlayScrollY = 24 + MathUtils.map( - overlayScrollOffset, - 0, - getMaxOverlayScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + overlayScrollOffset, + 0, + getMaxOverlayScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 132, overlayScrollY); } @@ -936,11 +940,11 @@ private void renderOverlayScroll(PoseStack poseStack) { private void renderConfigScroll(PoseStack poseStack) { configScrollY = 24 + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 344, configScrollY); } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java index fa94b3e4ed..66a6c6ead7 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java @@ -128,7 +128,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float // Don't want to display tooltip when the tile is outside the mask from the screen if (isHovered && (mouseY <= selectionScreen.getConfigMaskTopY() - || mouseY >= selectionScreen.getConfigMaskBottomY())) { + || mouseY >= selectionScreen.getConfigMaskBottomY())) { isHovered = false; } diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_bottom.png b/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..c672b9f0fd17e53962d9deff7436031fea938a83 GIT binary patch literal 931 zcmeAS@N?(olHy`uVBq!ia0vp^4nSLfOtV=S9I&8k6*wQS3&%{z9!X2|U+l2N>O)6X;}be&M< zdB$(vCyJOh-mr{%c))E-kj$P2g)nu2%|921uG}=imtCNJhL%FwLaT=t4u^Who7`aL z>+{;seQVAXp?HaDVK+WUR#cwRw<>a5 zZa>-E?k#yLI`z-o9ozWiv{LPZ86W9SDSJCL>`d3@z$qRs6Ip}ThOdsiJU2cjZtLGy zx89jn{d)L#`MId#AfL1l|CvoS7q-=3-qCb* zSM#a$H7onlE^TkTva|WZ*80w(U=tO&*1UjoTk5XuYPq(%<!F1 zy&}r};`WB7RG%ZODnM4XCQPo3*t@v+%Fd>1yIZgCY3(fz1&XHy*c@C@c4|X)W2UdO zq58C%s5O%^&uy+t_OX%^5d(kE$Ql=$Ae!>6$zh2wVaP824Two?tA_lHtvHXo` z*0R9BIPU4<7*a83>y*x-Lka?IzFRH|M7>G9m1cPC_lvvx{%@Wt?UQl5blDNk*Wz_$ z;$l^MUAApmzw6*php#sS_PFKFis`uKT@(~hRe4lGHvayddv_;${`~MGWJ>DQWlP0G z4m1`|$p5?|e)b7Rw*#S*lT*ZJWrRXzOF>EtU|?m z0mXaHnVXC3jbF`Z`0U_&!m7j|Z8}FV=cSpE+z-w*#CHgpd_J%;*1bbOI%u=NG*vb4 z`57KQ9yc#l7ff_$*|CIEg8#wuZXxXm%l>sm3Qj4{%Wvs-bz1msNyxP=vX*veso)RY zaQWNA*hl46!Lvgr?A1KI%eyc8q-CId%}zF#u0z7l!-V_J^{Lyn$6UG<)?m8($hx5V z)kn5+JI#ze^!C`>Z|ian_(~~0IQ3g#%IW!AQ;IbvJXbs!dGN&N)30y;KHe1;x^?D- zCWC3=p|k6>8uw{UUjN?he)qawU{J9(O@4PRM5Jd`jZAkc6mKN3zKC*?Um&CTB7b7jT{%q;evgBa mp7U$A3%PL|zO%M-O_#jT6-FtK6AYkq%HZkh=d#Wzp$P!CVrxAB literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png b/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png new file mode 100644 index 0000000000000000000000000000000000000000..8532a8f1e41defc52a913ee070ae6ee8b9593f4d GIT binary patch literal 1095 zcmeAS@N?(olHy`uVBq!ia0vp^4M1$e!3-p4zHs^uq!^2X+?^P2p46!aaySb-B8wRq zxP?KOkzv*x383Ki0G|+7Sz!SK1!+D`4xoUfAfJ|uIFO+vE_`NF&E*|US9UgC+TM75 zck87cjaPOyU)tVqbyv%|Ep@9Vq)#XdUq3bL?B@Ejn`^J`YQDC+<;I@2Yr9)7Y^y)G zqAV@Irnfls`kvN{+Z*;SE}mQ&F~2q8$f}BpDEFpRpNe?*QyZ#Jt*?<25p2x#UD=lg zwA9&9eOgV_nn{`GHrHL)THjd|EXd7eq9O;BYRwC{wyR~={G#o13X*-Sq=oqZI&265 zO4ybJ`33*~zjo%K*D=@r69kL@|Cfg->i^FGVN6xOs>{H@^uW`_F{EP7+whxV(uO>9 zXHHO?thlgb_KYp6u_+hl=1ti4=YRRtYZVjQp9JjYuR7SyJnhlzn6(k1p`Wk%^u7AU z=Ns!UZ<1&~+h^H-#+9q8?&`jtD04bD9<{OgB%f{M``)1w^=T`Xe`-J_;n%xBpzr0uf z(Z281T3`U)GJhyz@asoX^a6kKa8u@35*kRX>Z@ z(fff{#a-bE>IL?)*PkWtbiKS$r7`Rlvx%&?@Qw*84nQvBtUguF3ne-}3wBOH5%6qS zmV6SZ;mNLP-xz$4Ph!cinx?X0^17z2Uz$@i|H>_R88Hbio-pZy+o#`8Iakc~>I`#S j-NN~$tsz6S Date: Tue, 20 Feb 2024 14:40:19 +0000 Subject: [PATCH 03/28] feat: Overlay management screen redesign --- .../placement/OverlayManagementScreen.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java index c8ec6aa84c..f8846e4e8c 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java @@ -798,20 +798,20 @@ private void setupButtons() { 150))); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.close"), button -> { - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.close"), button -> { + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 - BUTTON_WIDTH - 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.closeTooltip"))) .build()); this.addRenderableWidget(new Button.Builder( - buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { - buttonsAtBottom = !buttonsAtBottom; - setupButtons(); - }) + buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { + buttonsAtBottom = !buttonsAtBottom; + setupButtons(); + }) .pos(this.width / 2 - 10, yPos) .size(BUTTON_HEIGHT, BUTTON_HEIGHT) .tooltip(Tooltip.create( @@ -821,11 +821,11 @@ private void setupButtons() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { - Managers.Config.saveConfig(); - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { + Managers.Config.saveConfig(); + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 + 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.applyTooltip"))) From dfe58e14a5ab5abf2e1d07b2ef588f1a0c0e22c9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Feb 2024 16:53:35 +0000 Subject: [PATCH 04/28] feat: Custom names for info boxes & custom bars --- .../java/com/wynntils/overlays/infobox/InfoBoxOverlay.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java b/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java index a2a9fe3eb6..449fe39fec 100644 --- a/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java +++ b/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java @@ -14,6 +14,9 @@ public class InfoBoxOverlay extends TextOverlay implements CustomNameProperty { @Persisted public final HiddenConfig customName = new HiddenConfig<>(""); + @Persisted + public final Config customName = new Config<>(""); + @Persisted public final Config content = new Config<>(""); From f7f931a4c62bb87c613dc4bcd645e9f67da18102 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Feb 2024 20:29:33 +0000 Subject: [PATCH 05/28] refactor: Introduce CustomNamedOverlay Instead of chaining instanceof for info boxes and custom bars --- .../core/consumers/overlays/CustomNamedOverlay.java | 11 +++++++++++ .../com/wynntils/overlays/infobox/InfoBoxOverlay.java | 3 --- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java diff --git a/common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java b/common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java new file mode 100644 index 0000000000..0bebb6d00b --- /dev/null +++ b/common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java @@ -0,0 +1,11 @@ +/* + * Copyright © Wynntils 2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.core.consumers.overlays; + +import com.wynntils.core.persisted.config.Config; + +public interface CustomNamedOverlay { + Config getCustomName(); +} diff --git a/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java b/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java index 449fe39fec..a2a9fe3eb6 100644 --- a/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java +++ b/common/src/main/java/com/wynntils/overlays/infobox/InfoBoxOverlay.java @@ -14,9 +14,6 @@ public class InfoBoxOverlay extends TextOverlay implements CustomNameProperty { @Persisted public final HiddenConfig customName = new HiddenConfig<>(""); - @Persisted - public final Config customName = new Config<>(""); - @Persisted public final Config content = new Config<>(""); From 2897d446c2d6792db24f83d2aff75e1a08bfd706 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 23 Feb 2024 13:32:18 +0000 Subject: [PATCH 06/28] feat: Crowd Sourcing screen redesign --- .../com/wynntils/utils/render/FontRenderer.java | 6 +++++- .../resources/assets/wynntils/lang/en_us.json | 5 +++++ .../ui_components/crowd_source_background.png | Bin 0 -> 1287 bytes .../ui_components/crowd_source_sticker.png | Bin 0 -> 323 bytes 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png diff --git a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java index d35a17363f..4e5f4eda58 100644 --- a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java +++ b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java @@ -283,7 +283,11 @@ public void renderScrollingString( Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * currentTimeInSeconds / e)) / 2.0 + 0.5; double scrollOffset = Mth.lerp(f, 0.0, m); - RenderUtils.enableScissor((int) scissorX, (int) scissorY, (int) renderArea, font.lineHeight); + RenderUtils.enableScissor( + (int) scissorX, + (int) scissorY, + (int) renderArea, + font.lineHeight + 1); // + 1 to account for letters that sit lower, eg y renderText( poseStack, styledText, diff --git a/common/src/main/resources/assets/wynntils/lang/en_us.json b/common/src/main/resources/assets/wynntils/lang/en_us.json index 190dc13012..df1396fb3c 100644 --- a/common/src/main/resources/assets/wynntils/lang/en_us.json +++ b/common/src/main/resources/assets/wynntils/lang/en_us.json @@ -2399,8 +2399,13 @@ "screens.wynntils.wynntilsContentBook.sort.distance.name": "Sort by Distance", "screens.wynntils.wynntilsContentBook.sort.level.description": "Quests are sorted by level, lowest first", "screens.wynntils.wynntilsContentBook.sort.level.name": "Sort by Level", + "screens.wynntils.wynntilsCrowdSourcing.collecting": "Collecting", + "screens.wynntils.wynntilsCrowdSourcing.copiedToClipboard": "Copied %d %s to clipboard", "screens.wynntils.wynntilsCrowdSourcing.name": "Crowd Sourcing", + "screens.wynntils.wynntilsCrowdSourcing.noDataTypes": "There are no data types currently being crowd sourced matching your search query.", + "screens.wynntils.wynntilsCrowdSourcing.notCollecting": "Not Collecting", "screens.wynntils.wynntilsCrowdSourcing.screenDescription": "Here you can see all the data types the mod can collect. If you opt-in to help us collect these data, we can improve the mod and the Wynncraft experience for everyone. You can opt-out at any time.", + "screens.wynntils.wynntilsCrowdSourcing.unconfirmed": "Unconfirmed", "screens.wynntils.wynntilsDialogueHistory.description": "Here you can read your last few conversations with NPCs on your current class.", "screens.wynntils.wynntilsDialogueHistory.name": "Dialogue History", "screens.wynntils.wynntilsDialogueHistory.questsPageButton.description": "Click here to open the quest book", diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png b/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png new file mode 100644 index 0000000000000000000000000000000000000000..31397471c028d037103a4638dc8c697bf6790517 GIT binary patch literal 1287 zcmeAS@N?(olHy`uVBq!ia0vp^TNoG^SvZ)1tZnPw9RyO0#X;^)j5kl})B`!31s;*b z3=G`DAk4@xYmNj^0Y`vOh$~QX(LjS(F);{gNlk4^Oa!tE?d^*k9U+1lIy&=a&6+oJ zW}1cuM5H4x56H;3vdXu%o>*U>XKA@;;lgAkrG}W8>fqpbDX9hX=G8_-OiD_+a_G?i z|NoC3J-T_)q;1=_?cBL@V}E~dboAP_Yr7*OuOB_SYSpT*A3rW#x^&aSCm(=e5m6H4 z7tElL(z9s$*@xfG=yc!xFHw52gd-!3)##`eWA&d(p>1N9WN+V+{&<}tTd zYv={6YT(+!>Kb+G|9|zS7ZImoC-GGpTRi_e$GTE2*y32riuLsg1uss0IC0{`)rAKe z|Ls$l9+R;+`SG^ZA2(jSv1*UnI^VKx|Ji%&1aD8f*gN~V+|I{4^L>wgTUuIeHM{20 zm$^3%6`#E`_pEueb#=blwof_5pIx6!e)c@c+B$m2`y{)6%`qLif3G*U=cQ%K+xF%D zy}jtM_5ZrpM{nG^{I&YimAg4_H=od+xv6fQYt+dzUyFO=Pu}@jT$fj-+I{W(Eqiuu zzeerIJ$16}pZSwOjPyS7IjLcn693j*IN@crCjPp(>+!?umz@4pxu|*llPjN-Hk;qt zSMhSW##G_?ah5Z3ubcD5?JB7rw1sop5tTdEK+`@=gow*X@uB z^F7MH_gTt2*4*ncyrRKhjp~bx%U8*XMc5z+x_t3ZprZL*^w{y#uP37XlwJ!{n^vsFJH`OeRj;T;)~Moyp|DK<#_)O)+(t8&^{%2F=;_jEBwQyz2GND;s z!-TQwKl|OjwWrq4?aDiv_Vl`!t9kO~Pua^BP2PKB-JWlgOG<)PA77Rlx?VN%#py{G zLY#s*eN|1SA~B{5$M))eSf8b}k@H{ZnXH_q`qjsDj+*`0meZ#_HQBgEYkJR5)>VSx Vnd_e%3k2p-22WQ%mvv4FO#lW0jc@<} literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png b/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png new file mode 100644 index 0000000000000000000000000000000000000000..ffaae4a1a07cc3df5914d4e1e1b4fb82b7275acd GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k3?#4J%UA`Z7>k44ofvPP)Tsw@I14-?iy0WW zg+Z8+Vb&Z8prBKLPl)UPzlrznhEC`=cd(Zb5MToezkeHDkgsiEAf&G^6d$KjUuSUs ztUo_L+x&Sp`FUFYescTwdiM93DJbyR+e@rp=los#qbyL{EKe85kcv5PC*9?1R^V}S z)!|~jBXIwJ==Cg)xR8ixZ_X7TJ>3LE+pZEH9)l0{`GAz^8nYwbd zQr@}b9Jf4`b??v{%lEd=y=yjqVRrqRU;cl|1dEDS9>*AW Date: Sat, 24 Feb 2024 21:12:57 +0000 Subject: [PATCH 07/28] feat: Import and export configs --- .../main/java/com/wynntils/core/persisted/config/Config.java | 4 ++-- .../com/wynntils/core/persisted/config/ConfigManager.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/com/wynntils/core/persisted/config/Config.java b/common/src/main/java/com/wynntils/core/persisted/config/Config.java index a5dc80b8ac..9069774150 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/Config.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/Config.java @@ -1,5 +1,5 @@ /* - * Copyright © Wynntils 2023. + * Copyright © Wynntils 2023-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.core.persisted.config; @@ -49,7 +49,7 @@ public void setValue(T value) { this.userEdited = true; } - void restoreValue(Object value) { + public void setValueFromObject(Object value) { setValue((T) value); } diff --git a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java index 60dc22b4ad..f91ced0106 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java @@ -150,7 +150,7 @@ public void loadConfigOptions(boolean resetIfNotFound, boolean initOverlayGroups // read value and update option JsonElement configJson = configObject.get(config.getJsonName()); Object value = Managers.Json.GSON.fromJson(configJson, config.getType()); - config.restoreValue(value); + config.setValueFromObject(value); } // Newly created group overlays need to be enabled From bbf7a0ac547bf38629d5ea29973c156a5639a94c Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 26 Feb 2024 14:18:17 +0000 Subject: [PATCH 08/28] refactor: CustomNamedOverlay -> CustomNameProperty --- .../core/consumers/overlays/CustomNamedOverlay.java | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java diff --git a/common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java b/common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java deleted file mode 100644 index 0bebb6d00b..0000000000 --- a/common/src/main/java/com/wynntils/core/consumers/overlays/CustomNamedOverlay.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright © Wynntils 2024. - * This file is released under LGPLv3. See LICENSE for full license details. - */ -package com.wynntils.core.consumers.overlays; - -import com.wynntils.core.persisted.config.Config; - -public interface CustomNamedOverlay { - Config getCustomName(); -} From 76e25d5c37207d3b34dda3e570cecb6c45c77e14 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 26 Feb 2024 14:19:22 +0000 Subject: [PATCH 09/28] chore: Better copied response --- common/src/main/resources/assets/wynntils/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/resources/assets/wynntils/lang/en_us.json b/common/src/main/resources/assets/wynntils/lang/en_us.json index df1396fb3c..0911c7f8df 100644 --- a/common/src/main/resources/assets/wynntils/lang/en_us.json +++ b/common/src/main/resources/assets/wynntils/lang/en_us.json @@ -2400,7 +2400,7 @@ "screens.wynntils.wynntilsContentBook.sort.level.description": "Quests are sorted by level, lowest first", "screens.wynntils.wynntilsContentBook.sort.level.name": "Sort by Level", "screens.wynntils.wynntilsCrowdSourcing.collecting": "Collecting", - "screens.wynntils.wynntilsCrowdSourcing.copiedToClipboard": "Copied %d %s to clipboard", + "screens.wynntils.wynntilsCrowdSourcing.copiedToClipboard": "Copied %d data points of %s to clipboard", "screens.wynntils.wynntilsCrowdSourcing.name": "Crowd Sourcing", "screens.wynntils.wynntilsCrowdSourcing.noDataTypes": "There are no data types currently being crowd sourced matching your search query.", "screens.wynntils.wynntilsCrowdSourcing.notCollecting": "Not Collecting", From d9a51fa59c6ac46fa83f06f32dc0460a1d1a5e79 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 26 Feb 2024 15:39:15 +0000 Subject: [PATCH 10/28] refactor: Move import/export to ConfigManager, use setValue --- .../core/persisted/config/Config.java | 2 +- .../core/persisted/config/ConfigManager.java | 63 ++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/wynntils/core/persisted/config/Config.java b/common/src/main/java/com/wynntils/core/persisted/config/Config.java index 9069774150..df84c34447 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/Config.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/Config.java @@ -49,7 +49,7 @@ public void setValue(T value) { this.userEdited = true; } - public void setValueFromObject(Object value) { + public void restoreValue(Object value) { setValue((T) value); } diff --git a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java index f91ced0106..78d966b837 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java @@ -4,9 +4,11 @@ */ package com.wynntils.core.persisted.config; +import com.google.common.reflect.TypeToken; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; import com.mojang.util.UndashedUuid; import com.wynntils.core.WynntilsMod; import com.wynntils.core.components.Manager; @@ -24,8 +26,10 @@ import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.stream.Stream; @@ -150,7 +154,7 @@ public void loadConfigOptions(boolean resetIfNotFound, boolean initOverlayGroups // read value and update option JsonElement configJson = configObject.get(config.getJsonName()); Object value = Managers.Json.GSON.fromJson(configJson, config.getType()); - config.setValueFromObject(value); + config.restoreValue(value); } // Newly created group overlays need to be enabled @@ -267,4 +271,61 @@ public Stream> getConfigsForOwner(PersistedOwner owner) { return getConfigs() .filter(config -> Managers.Persisted.getMetadata(config).owner() == owner); } + + public boolean importConfig(String jsonInput, List configsToImport) { + try { + Map configData = + Managers.Json.GSON.fromJson(jsonInput, new TypeToken>() {}.getType()); + + // Loop through all features chosen to import to + for (Configurable feature : configsToImport) { + // Loop through the visible configs only as they are the only configs to be imported + for (Config configOption : feature.getVisibleConfigOptions()) { + String configOptionName = configOption.getJsonName(); + + // If the config data contains this config option, then it can be imported + if (configData.containsKey(configOptionName)) { + Object configOptionValue = configData.get(configOptionName); + setConfigValue(configOption, configOptionValue); + } + } + } + + return true; + } catch (JsonSyntaxException ex) { + WynntilsMod.warn("Failed to import config ", ex); + return false; + } + } + + public String exportConfig(List featuresToExport) { + Map configData = new HashMap<>(); + + // Loop through all features to be exported + for (Configurable feature : featuresToExport) { + List> visibleConfigOptions = feature.getVisibleConfigOptions(); + + // Loop through visible config options, as we don't want this to export + // hidden configs since they should be exportable in their + // own features, like favorites and waypoints + for (Config configOption : visibleConfigOptions) { + String configOptionName = configOption.getJsonName(); + Object configOptionValue = configOption.get(); + + // Save the config option to the map + configData.put(configOptionName, configOptionValue); + } + } + + // Return the json string of the exported settings + return Managers.Json.GSON.toJson(configData); + } + + private void setConfigValue(Config config, Object value) { + T typedValue = config.tryParseStringValue(value.toString()); + + if (typedValue != null) { + config.setValue(typedValue); + } + } } From 3d50dfaff20d2fdba11e158a99fe8c393e1a77e9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 26 Feb 2024 21:13:46 +0000 Subject: [PATCH 11/28] feat: Correctly handle horizontal alignment in renderScrollingText. Use scrolling text for GeneralSettingsButton --- .../widgets/GeneralSettingsButton.java | 14 ++- .../wynntils/utils/render/FontRenderer.java | 112 ++++++++++++++---- 2 files changed, 103 insertions(+), 23 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java index 17df60fef6..9c761f89ca 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java @@ -25,6 +25,8 @@ public abstract class GeneralSettingsButton extends WynntilsButton { public static final CustomColor HOVER_BACKGROUND_COLOR = new CustomColor(158, 52, 16); private final int maskTopY; private final int maskBottomY; + private final float translationX; + private final float translationY; private final List tooltip; protected GeneralSettingsButton( @@ -35,11 +37,15 @@ protected GeneralSettingsButton( Component title, List tooltip, int maskTopY, - int maskBottomY) { + int maskBottomY, + float translationX, + float translationY) { super(x, y, width, height, title); this.tooltip = tooltip; this.maskTopY = maskTopY; this.maskBottomY = maskBottomY; + this.translationX = translationX; + this.translationY = translationY; } @Override @@ -59,14 +65,16 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float 3); FontRenderer.getInstance() - .renderAlignedTextInBox( + .renderScrollingAlignedTextInBox( poseStack, StyledText.fromComponent(getMessage()), this.getX(), this.getX() + this.width, this.getY(), this.getY() + this.height, - 0, + this.width - 2, + translationX, + translationY, getTextColor(), HorizontalAlignment.CENTER, VerticalAlignment.MIDDLE, diff --git a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java index 4e5f4eda58..6a4e8fb1c9 100644 --- a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java +++ b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java @@ -8,6 +8,7 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.wynntils.core.text.StyledText; import com.wynntils.mc.mixin.accessors.MinecraftAccessor; +import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; import com.wynntils.utils.mc.ComponentUtils; import com.wynntils.utils.mc.McUtils; @@ -264,30 +265,58 @@ public void renderScrollingString( StyledText styledText, float x, float y, - float renderArea, - float scissorX, - float scissorY, + float renderWidth, + float translationX, + float translationY, CustomColor customColor, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, TextShadow shadow, float textScale) { int textLength = (int) ((font.width(styledText.getString()) + 1) * textScale); - float m; - if (textLength > renderArea) { - m = textLength - renderArea; + if (textLength > renderWidth) { + float maxScrollOffset = switch (horizontalAlignment) { + case CENTER -> -(textLength / 2f) + (renderWidth / 2); + case RIGHT -> 0.0f; + default -> textLength - renderWidth; + }; + double currentTimeInSeconds = (double) Util.getMillis() / 1000.0; - double e = Math.max((double) m * 0.5, 3.0); + double e = Math.max((double) maxScrollOffset * 0.5, 3.0); double f = Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * currentTimeInSeconds / e)) / 2.0 + 0.5; - double scrollOffset = Mth.lerp(f, 0.0, m); + + float startOffset = switch (horizontalAlignment) { + case CENTER -> (textLength / 2f) - (renderWidth / 2); + case RIGHT -> renderWidth - textLength; + default -> 0.0f; + }; + + double scrollOffset = Mth.lerp(f, startOffset, maxScrollOffset); + + float scissorX = + switch (horizontalAlignment) { + case LEFT -> x; + case CENTER -> x - (renderWidth / 2); + case RIGHT -> x - renderWidth; + }; + + float scissorY = + switch (verticalAlignment) { + case TOP -> y; + case MIDDLE -> y - (font.lineHeight / 2f) - 1; + case BOTTOM -> y - font.lineHeight - 1; + }; + + scissorX += translationX; + scissorY += translationY; RenderUtils.enableScissor( (int) scissorX, (int) scissorY, - (int) renderArea, - font.lineHeight + 1); // + 1 to account for letters that sit lower, eg y + (int) renderWidth, + (int) ((font.lineHeight + 1) * textScale)); // + 1 to account for letters that sit lower, eg y renderText( poseStack, styledText, @@ -318,9 +347,9 @@ public void renderScrollingString( StyledText styledText, float x, float y, - float renderArea, - float scissorX, - float scissorY, + float renderWidth, + float translationX, + float translationY, CustomColor customColor, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, @@ -330,9 +359,9 @@ public void renderScrollingString( styledText, x, y, - renderArea, - scissorX, - scissorY, + renderWidth, + translationX, + translationY, customColor, horizontalAlignment, verticalAlignment, @@ -345,7 +374,7 @@ public void renderScrollingString( StyledText styledText, float x, float y, - float renderArea, + float renderWidth, CustomColor customColor, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, @@ -356,9 +385,9 @@ public void renderScrollingString( styledText, x, y, - renderArea, - x, - y, + renderWidth, + 0, + 0, customColor, horizontalAlignment, verticalAlignment, @@ -366,6 +395,49 @@ public void renderScrollingString( textScale); } + public void renderScrollingAlignedTextInBox( + PoseStack poseStack, + StyledText text, + float x1, + float x2, + float y1, + float y2, + float renderWidth, + float translationX, + float translationY, + CustomColor customColor, + HorizontalAlignment horizontalAlignment, + VerticalAlignment verticalAlignment, + TextShadow textShadow) { + float renderX = + switch (horizontalAlignment) { + case LEFT -> x1; + case CENTER -> (x1 + x2) / 2f; + case RIGHT -> x2; + }; + + float renderY = + switch (verticalAlignment) { + case TOP -> y1; + case MIDDLE -> (y1 + y2) / 2f; + case BOTTOM -> y2; + }; + + renderScrollingString( + poseStack, + text, + renderX, + renderY, + renderWidth, + translationX, + translationY, + customColor, + horizontalAlignment, + verticalAlignment, + textShadow, + 1f); + } + private void renderText( PoseStack poseStack, StyledText text, From f119336c16f94d5aa2d7522ba25e0850ef5e5c39 Mon Sep 17 00:00:00 2001 From: JamieCallan117 Date: Mon, 26 Feb 2024 21:14:52 +0000 Subject: [PATCH 12/28] ci: spotless formatting --- .../wynntils/utils/render/FontRenderer.java | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java index 6a4e8fb1c9..297901c5b0 100644 --- a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java +++ b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java @@ -8,7 +8,6 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.wynntils.core.text.StyledText; import com.wynntils.mc.mixin.accessors.MinecraftAccessor; -import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; import com.wynntils.utils.mc.ComponentUtils; import com.wynntils.utils.mc.McUtils; @@ -276,22 +275,24 @@ public void renderScrollingString( int textLength = (int) ((font.width(styledText.getString()) + 1) * textScale); if (textLength > renderWidth) { - float maxScrollOffset = switch (horizontalAlignment) { - case CENTER -> -(textLength / 2f) + (renderWidth / 2); - case RIGHT -> 0.0f; - default -> textLength - renderWidth; - }; + float maxScrollOffset = + switch (horizontalAlignment) { + case CENTER -> -(textLength / 2f) + (renderWidth / 2); + case RIGHT -> 0.0f; + default -> textLength - renderWidth; + }; double currentTimeInSeconds = (double) Util.getMillis() / 1000.0; double e = Math.max((double) maxScrollOffset * 0.5, 3.0); double f = Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * currentTimeInSeconds / e)) / 2.0 + 0.5; - float startOffset = switch (horizontalAlignment) { - case CENTER -> (textLength / 2f) - (renderWidth / 2); - case RIGHT -> renderWidth - textLength; - default -> 0.0f; - }; + float startOffset = + switch (horizontalAlignment) { + case CENTER -> (textLength / 2f) - (renderWidth / 2); + case RIGHT -> renderWidth - textLength; + default -> 0.0f; + }; double scrollOffset = Mth.lerp(f, startOffset, maxScrollOffset); @@ -312,11 +313,8 @@ public void renderScrollingString( scissorX += translationX; scissorY += translationY; - RenderUtils.enableScissor( - (int) scissorX, - (int) scissorY, - (int) renderWidth, - (int) ((font.lineHeight + 1) * textScale)); // + 1 to account for letters that sit lower, eg y + RenderUtils.enableScissor((int) scissorX, (int) scissorY, (int) renderWidth, (int) + ((font.lineHeight + 1) * textScale)); // + 1 to account for letters that sit lower, eg y renderText( poseStack, styledText, From a931288774e669da7e848d32ee273d6ed04dfcef Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 26 Feb 2024 22:22:31 +0000 Subject: [PATCH 13/28] chore: Undo change to Config --- .../main/java/com/wynntils/core/persisted/config/Config.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/wynntils/core/persisted/config/Config.java b/common/src/main/java/com/wynntils/core/persisted/config/Config.java index df84c34447..a5dc80b8ac 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/Config.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/Config.java @@ -1,5 +1,5 @@ /* - * Copyright © Wynntils 2023-2024. + * Copyright © Wynntils 2023. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.core.persisted.config; @@ -49,7 +49,7 @@ public void setValue(T value) { this.userEdited = true; } - public void restoreValue(Object value) { + void restoreValue(Object value) { setValue((T) value); } From 90815e16dfb814e70aea8afda92c3d09b0e8517a Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 3 Mar 2024 12:08:12 +0000 Subject: [PATCH 14/28] fix: Fix crash when configData is null in import --- .../com/wynntils/core/persisted/config/ConfigManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java index 78d966b837..0132382e33 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java @@ -277,6 +277,11 @@ public boolean importConfig(String jsonInput, List configsToImport Map configData = Managers.Json.GSON.fromJson(jsonInput, new TypeToken>() {}.getType()); + if (configData == null) { + WynntilsMod.warn("Unable to import config due to invalid input"); + return false; + } + // Loop through all features chosen to import to for (Configurable feature : configsToImport) { // Loop through the visible configs only as they are the only configs to be imported From 964b25b1b56d49f5a746f10da23b5a1aed341cbc Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 21 May 2024 14:44:40 +0100 Subject: [PATCH 15/28] feat: Settings Screen redesign --- .../chattabs/ChatTabEditingScreen.java | 3 +- .../itemsharing/ItemSharingScreen.java | 2 - .../wynntils/utils/render/FontRenderer.java | 177 ------------------ 3 files changed, 1 insertion(+), 181 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java b/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java index ea6c4683fa..ec33f5a989 100644 --- a/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java +++ b/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java @@ -167,8 +167,7 @@ protected void doInit() { BUTTON_HEIGHT, Component.literal(type.getName()), ticked, - (int) (dividedWidth * 7) - 24, - true); + (int) (dividedWidth * 7) - 24); this.addRenderableWidget(newBox); recipientTypeBoxes.add(newBox); diff --git a/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java b/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java index c8cf0efc7c..574b2a91ca 100644 --- a/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java +++ b/common/src/main/java/com/wynntils/screens/itemsharing/ItemSharingScreen.java @@ -230,7 +230,6 @@ private void addSharingOptions() { Component.translatable("screens.wynntils.itemSharing.extended.name"), Models.ItemEncoding.extendedIdentificationEncoding.get(), Texture.ITEM_SHARING_BACKGROUND.width() - 30, - true, (b) -> { if (b == 0) { Models.ItemEncoding.extendedIdentificationEncoding.store( @@ -252,7 +251,6 @@ private void addSharingOptions() { Component.translatable("screens.wynntils.itemSharing.itemName.name"), Models.ItemEncoding.shareItemName.get(), Texture.ITEM_SHARING_BACKGROUND.width() - 30, - true, (b) -> { if (b == 0) { Models.ItemEncoding.shareItemName.store(!Models.ItemEncoding.shareItemName.get()); diff --git a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java index 297901c5b0..16950d912d 100644 --- a/common/src/main/java/com/wynntils/utils/render/FontRenderer.java +++ b/common/src/main/java/com/wynntils/utils/render/FontRenderer.java @@ -259,183 +259,6 @@ public void renderAlignedTextInBox( 1f); } - public void renderScrollingString( - PoseStack poseStack, - StyledText styledText, - float x, - float y, - float renderWidth, - float translationX, - float translationY, - CustomColor customColor, - HorizontalAlignment horizontalAlignment, - VerticalAlignment verticalAlignment, - TextShadow shadow, - float textScale) { - int textLength = (int) ((font.width(styledText.getString()) + 1) * textScale); - - if (textLength > renderWidth) { - float maxScrollOffset = - switch (horizontalAlignment) { - case CENTER -> -(textLength / 2f) + (renderWidth / 2); - case RIGHT -> 0.0f; - default -> textLength - renderWidth; - }; - - double currentTimeInSeconds = (double) Util.getMillis() / 1000.0; - double e = Math.max((double) maxScrollOffset * 0.5, 3.0); - double f = - Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * currentTimeInSeconds / e)) / 2.0 + 0.5; - - float startOffset = - switch (horizontalAlignment) { - case CENTER -> (textLength / 2f) - (renderWidth / 2); - case RIGHT -> renderWidth - textLength; - default -> 0.0f; - }; - - double scrollOffset = Mth.lerp(f, startOffset, maxScrollOffset); - - float scissorX = - switch (horizontalAlignment) { - case LEFT -> x; - case CENTER -> x - (renderWidth / 2); - case RIGHT -> x - renderWidth; - }; - - float scissorY = - switch (verticalAlignment) { - case TOP -> y; - case MIDDLE -> y - (font.lineHeight / 2f) - 1; - case BOTTOM -> y - font.lineHeight - 1; - }; - - scissorX += translationX; - scissorY += translationY; - - RenderUtils.enableScissor((int) scissorX, (int) scissorY, (int) renderWidth, (int) - ((font.lineHeight + 1) * textScale)); // + 1 to account for letters that sit lower, eg y - renderText( - poseStack, - styledText, - x - (int) scrollOffset, - y, - customColor, - horizontalAlignment, - verticalAlignment, - shadow, - textScale); - RenderUtils.disableScissor(); - } else { - renderText( - poseStack, - styledText, - x, - y, - customColor, - horizontalAlignment, - verticalAlignment, - shadow, - textScale); - } - } - - public void renderScrollingString( - PoseStack poseStack, - StyledText styledText, - float x, - float y, - float renderWidth, - float translationX, - float translationY, - CustomColor customColor, - HorizontalAlignment horizontalAlignment, - VerticalAlignment verticalAlignment, - TextShadow shadow) { - renderScrollingString( - poseStack, - styledText, - x, - y, - renderWidth, - translationX, - translationY, - customColor, - horizontalAlignment, - verticalAlignment, - shadow, - 1); - } - - public void renderScrollingString( - PoseStack poseStack, - StyledText styledText, - float x, - float y, - float renderWidth, - CustomColor customColor, - HorizontalAlignment horizontalAlignment, - VerticalAlignment verticalAlignment, - TextShadow shadow, - float textScale) { - renderScrollingString( - poseStack, - styledText, - x, - y, - renderWidth, - 0, - 0, - customColor, - horizontalAlignment, - verticalAlignment, - shadow, - textScale); - } - - public void renderScrollingAlignedTextInBox( - PoseStack poseStack, - StyledText text, - float x1, - float x2, - float y1, - float y2, - float renderWidth, - float translationX, - float translationY, - CustomColor customColor, - HorizontalAlignment horizontalAlignment, - VerticalAlignment verticalAlignment, - TextShadow textShadow) { - float renderX = - switch (horizontalAlignment) { - case LEFT -> x1; - case CENTER -> (x1 + x2) / 2f; - case RIGHT -> x2; - }; - - float renderY = - switch (verticalAlignment) { - case TOP -> y1; - case MIDDLE -> (y1 + y2) / 2f; - case BOTTOM -> y2; - }; - - renderScrollingString( - poseStack, - text, - renderX, - renderY, - renderWidth, - translationX, - translationY, - customColor, - horizontalAlignment, - verticalAlignment, - textShadow, - 1f); - } - private void renderText( PoseStack poseStack, StyledText text, From 1f48a17a1aff4debc6fd3794709df1fdf7a46ceb Mon Sep 17 00:00:00 2001 From: JamieCallan117 Date: Tue, 21 May 2024 14:19:09 +0000 Subject: [PATCH 16/28] ci: spotless formatting --- .../placement/OverlayManagementScreen.java | 26 +++++------ .../selection/CustomBarSelectionScreen.java | 28 ++++++------ .../selection/OverlaySelectionScreen.java | 26 +++++------ .../selection/widgets/OverlayButton.java | 2 +- .../settings/WynntilsBookSettingsScreen.java | 44 +++++++++---------- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java index f8846e4e8c..c8ec6aa84c 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java @@ -798,20 +798,20 @@ private void setupButtons() { 150))); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.close"), button -> { - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.close"), button -> { + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 - BUTTON_WIDTH - 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.closeTooltip"))) .build()); this.addRenderableWidget(new Button.Builder( - buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { - buttonsAtBottom = !buttonsAtBottom; - setupButtons(); - }) + buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { + buttonsAtBottom = !buttonsAtBottom; + setupButtons(); + }) .pos(this.width / 2 - 10, yPos) .size(BUTTON_HEIGHT, BUTTON_HEIGHT) .tooltip(Tooltip.create( @@ -821,11 +821,11 @@ private void setupButtons() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { - Managers.Config.saveConfig(); - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { + Managers.Config.saveConfig(); + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 + 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.applyTooltip"))) diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java index ff30998df8..234b0ef348 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java @@ -62,12 +62,12 @@ protected void doInit() { calculateBarPosition(); textureButton = this.addRenderableWidget(new Button.Builder( - Component.literal(availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .toString()), - (b) -> {}) + Component.literal(availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .toString()), + (b) -> {}) .pos((int) ((this.width / 2f) - 30), (int) (barY + 20)) .size(60, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.customBarSelection.textureTooltip"))) @@ -79,14 +79,14 @@ protected void doInit() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) + Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) .pos((int) (this.width / 2f) - 90, (int) (barY + 45)) .size(80, 20) .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.select"), - (button) -> addCustomBar()) + Component.translatable("screens.wynntils.customBarSelection.select"), + (button) -> addCustomBar()) .pos((int) (this.width / 2f) + 10, (int) (barY + 45)) .size(80, 20) .build()); @@ -163,11 +163,11 @@ private void calculateBarPosition() { // Calculate the central position to render the current selected bar at barX = (this.width - availableBars.get(barTypeIndex).a().width()) / 2f; barY = (this.height - - availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .getHeight()) + - availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .getHeight()) / 2f; } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java index ca983d2c5d..265876db51 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java @@ -123,8 +123,8 @@ protected void doInit() { // region Preview renderables exitPreviewButton = this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlaySelection.exitPreview"), - (button) -> togglePreview(false)) + Component.translatable("screens.wynntils.overlaySelection.exitPreview"), + (button) -> togglePreview(false)) .pos((Texture.OVERLAY_SELECTION_GUI.width() / 2) - 40, (int) (this.height - 25 - translationY)) .size(80, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlaySelection.exitPreviewTooltip"))) @@ -464,7 +464,7 @@ public void populateOverlays() { // Don't deselect custom overlays as they will always fail the above check if (filterType == FilterType.BUILT_IN || !(selectedOverlay instanceof CustomBarOverlayBase - || selectedOverlay instanceof InfoBoxOverlay)) { + || selectedOverlay instanceof InfoBoxOverlay)) { setSelectedOverlay(null); } } @@ -928,11 +928,11 @@ private void renderWidgets(GuiGraphics guiGraphics, int mouseX, int mouseY, floa private void renderOverlayScroll(PoseStack poseStack) { overlayScrollY = 24 + MathUtils.map( - overlayScrollOffset, - 0, - getMaxOverlayScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + overlayScrollOffset, + 0, + getMaxOverlayScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 132, overlayScrollY); } @@ -940,11 +940,11 @@ private void renderOverlayScroll(PoseStack poseStack) { private void renderConfigScroll(PoseStack poseStack) { configScrollY = 24 + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 344, configScrollY); } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java index 66a6c6ead7..fa94b3e4ed 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java @@ -128,7 +128,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float // Don't want to display tooltip when the tile is outside the mask from the screen if (isHovered && (mouseY <= selectionScreen.getConfigMaskTopY() - || mouseY >= selectionScreen.getConfigMaskBottomY())) { + || mouseY >= selectionScreen.getConfigMaskBottomY())) { isHovered = false; } diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index 1989ac4d9f..a7cd1c0901 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -375,12 +375,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigurableScroll && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIGURABLE_SCROLL_X, - CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configurableScrollRenderY, - (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIGURABLE_SCROLL_X, + CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configurableScrollRenderY, + (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigurableScroll = true; return true; } @@ -388,12 +388,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigScroll && (configs.size() > CONFIGS_PER_PAGE) && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIG_SCROLL_X, - CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configScrollRenderY, - (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIG_SCROLL_X, + CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configScrollRenderY, + (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigScroll = true; return true; } @@ -911,11 +911,11 @@ private void renderConfigurableScroll(PoseStack poseStack) { configurableScrollRenderY = SCROLL_START_Y + MathUtils.map( - configurablesScrollOffset, - 0, - getMaxConfigurableScrollOffset(), - 0, - SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + configurablesScrollOffset, + 0, + getMaxConfigurableScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); RenderUtils.drawHoverableTexturedRect( poseStack, @@ -950,11 +950,11 @@ private void renderConfigScroll(PoseStack poseStack) { configScrollRenderY = SCROLL_START_Y + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); RenderUtils.drawHoverableTexturedRect( poseStack, From 684c672383c43fdf6daed8efd6f134fc4d0213e1 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 25 Jan 2024 14:29:40 +0000 Subject: [PATCH 17/28] feat: Settings screen redesign --- .../core/persisted/config/Category.java | 44 +- .../core/persisted/config/ConfigManager.java | 66 ++ .../chattabs/ChatTabEditingScreen.java | 2 +- .../placement/OverlayManagementScreen.java | 26 +- .../selection/CustomBarSelectionScreen.java | 28 +- .../selection/OverlaySelectionScreen.java | 30 +- .../selection/widgets/OverlayButton.java | 2 +- .../settings/WynntilsBookSettingsScreen.java | 964 +++++++++++++----- .../screens/settings/widgets/ApplyButton.java | 37 - .../widgets/BooleanSettingsButton.java | 26 +- .../settings/widgets/CategoryButton.java | 4 +- .../screens/settings/widgets/CloseButton.java | 35 - .../screens/settings/widgets/ConfigTile.java | 20 +- .../settings/widgets/ConfigurableButton.java | 89 +- .../widgets/CustomColorSettingsButton.java | 4 +- .../settings/widgets/EnumSettingsButton.java | 24 +- .../widgets/GeneralSettingsButton.java | 14 +- .../widgets/GeneralSettingsTabButton.java | 105 ++ .../screens/settings/widgets/ResetButton.java | 11 +- .../widgets/SettingsCategoryTabButton.java | 61 ++ .../widgets/SettingsPageTabButton.java | 26 + .../widgets/SettingsSideTabButton.java | 24 + .../widgets/TextInputBoxSettingsWidget.java | 10 +- .../com/wynntils/utils/render/Texture.java | 30 + .../resources/assets/wynntils/lang/en_us.json | 21 + .../content_book/config_book_scroll_area.png | Bin 1086 -> 0 bytes .../textures/content_book/tag_blue.png | Bin 0 -> 421 bytes .../textures/content_book/tag_red.png | Bin 0 -> 408 bytes .../content_book/tag_red_selected.png | Bin 0 -> 498 bytes .../textures/content_book/tag_search.png | Bin 0 -> 605 bytes .../config_categories/all_config_icon.png | Bin 0 -> 293 bytes .../config_categories/chat_config_icon.png | Bin 0 -> 289 bytes .../config_categories/combat_config_icon.png | Bin 0 -> 275 bytes .../commands_config_icon.png | Bin 0 -> 278 bytes .../config_categories/debug_config_icon.png | Bin 0 -> 296 bytes .../embellishments_config_icon.png | Bin 0 -> 283 bytes .../inventory_config_icon.png | Bin 0 -> 261 bytes .../config_categories/map_config_icon.png | Bin 0 -> 234 bytes .../overlays_config_icon.png | Bin 0 -> 237 bytes .../config_categories/players_config_icon.png | Bin 0 -> 343 bytes .../redirects_config_icon.png | Bin 0 -> 282 bytes .../tooltips_config_icon.png | Bin 0 -> 304 bytes .../trade_market_config_icon.png | Bin 0 -> 267 bytes .../config_categories/ui_config_icon.png | Bin 0 -> 207 bytes .../uncategorized_config_icon.png | Bin 0 -> 299 bytes .../utilities_config_icon.png | Bin 0 -> 314 bytes .../wynntils_config_icon.png | Bin 0 -> 304 bytes .../wynntils/textures/icons/generic/close.png | Bin 0 -> 254 bytes .../wynntils/textures/icons/generic/next.png | Bin 0 -> 253 bytes .../textures/icons/generic/previous.png | Bin 0 -> 235 bytes .../wynntils/textures/icons/generic/reset.png | Bin 0 -> 307 bytes .../wynntils/textures/icons/generic/save.png | Bin 0 -> 257 bytes .../ui_components/crowd_source_background.png | Bin 0 -> 1287 bytes .../ui_components/crowd_source_sticker.png | Bin 0 -> 323 bytes .../ui_components/overlay_button_bottom.png | Bin 0 -> 931 bytes .../ui_components/overlay_button_left.png | Bin 0 -> 782 bytes .../ui_components/overlay_button_top.png | Bin 0 -> 1095 bytes 57 files changed, 1277 insertions(+), 426 deletions(-) delete mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java delete mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java delete mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/config_book_scroll_area.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png create mode 100644 common/src/main/resources/assets/wynntils/textures/content_book/tag_search.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/all_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/chat_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/inventory_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/overlays_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/redirects_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/utilities_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/close.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/next.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/previous.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/reset.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/save.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_bottom.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_left.png create mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png diff --git a/common/src/main/java/com/wynntils/core/persisted/config/Category.java b/common/src/main/java/com/wynntils/core/persisted/config/Category.java index 439cb3c17e..acbaaa6c69 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/Category.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/Category.java @@ -1,32 +1,40 @@ /* - * Copyright © Wynntils 2022-2023. + * Copyright © Wynntils 2022-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.core.persisted.config; +import com.wynntils.utils.render.Texture; import java.util.Locale; import net.minecraft.client.resources.language.I18n; public enum Category { - UNCATEGORIZED, - CHAT, - COMBAT, - COMMANDS, - DEBUG, - EMBELLISHMENTS, - INVENTORY, - MAP, - OVERLAYS, - PLAYERS, - REDIRECTS, - TOOLTIPS, - TRADEMARKET, - UI, - UTILITIES, - WYNNTILS; + UNCATEGORIZED(Texture.UNCATEGORIZED_CONFIG_ICON), + CHAT(Texture.CHAT_CONFIG_ICON), + COMBAT(Texture.COMBAT_CONFIG_ICON), + COMMANDS(Texture.COMMANDS_CONFIG_ICON), + DEBUG(Texture.DEBUG_CONFIG_ICON), + EMBELLISHMENTS(Texture.EMBELLISHMENTS_CONFIG_ICON), + INVENTORY(Texture.INVENTORY_CONFIG_ICON), + MAP(Texture.MAP_CONFIG_ICON), + OVERLAYS(Texture.OVERLAYS_CONFIG_ICON), + PLAYERS(Texture.PLAYERS_CONFIG_ICON), + REDIRECTS(Texture.REDIRECTS_CONFIG_ICON), + TOOLTIPS(Texture.TOOLTIPS_CONFIG_ICON), + TRADEMARKET(Texture.TRADE_MARKET_CONFIG_ICON), + UI(Texture.UI_CONFIG_ICON), + UTILITIES(Texture.UTILITIES_CONFIG_ICON), + WYNNTILS(Texture.WYNNTILS_CONFIG_ICON); - Category() { + private final Texture categoryIcon; + + Category(Texture categoryIcon) { assert !toString().startsWith("core.wynntils"); + this.categoryIcon = categoryIcon; + } + + public Texture getCategoryIcon() { + return categoryIcon; } @Override diff --git a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java index 60dc22b4ad..0132382e33 100644 --- a/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java +++ b/common/src/main/java/com/wynntils/core/persisted/config/ConfigManager.java @@ -4,9 +4,11 @@ */ package com.wynntils.core.persisted.config; +import com.google.common.reflect.TypeToken; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; import com.mojang.util.UndashedUuid; import com.wynntils.core.WynntilsMod; import com.wynntils.core.components.Manager; @@ -24,8 +26,10 @@ import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.stream.Stream; @@ -267,4 +271,66 @@ public Stream> getConfigsForOwner(PersistedOwner owner) { return getConfigs() .filter(config -> Managers.Persisted.getMetadata(config).owner() == owner); } + + public boolean importConfig(String jsonInput, List configsToImport) { + try { + Map configData = + Managers.Json.GSON.fromJson(jsonInput, new TypeToken>() {}.getType()); + + if (configData == null) { + WynntilsMod.warn("Unable to import config due to invalid input"); + return false; + } + + // Loop through all features chosen to import to + for (Configurable feature : configsToImport) { + // Loop through the visible configs only as they are the only configs to be imported + for (Config configOption : feature.getVisibleConfigOptions()) { + String configOptionName = configOption.getJsonName(); + + // If the config data contains this config option, then it can be imported + if (configData.containsKey(configOptionName)) { + Object configOptionValue = configData.get(configOptionName); + setConfigValue(configOption, configOptionValue); + } + } + } + + return true; + } catch (JsonSyntaxException ex) { + WynntilsMod.warn("Failed to import config ", ex); + return false; + } + } + + public String exportConfig(List featuresToExport) { + Map configData = new HashMap<>(); + + // Loop through all features to be exported + for (Configurable feature : featuresToExport) { + List> visibleConfigOptions = feature.getVisibleConfigOptions(); + + // Loop through visible config options, as we don't want this to export + // hidden configs since they should be exportable in their + // own features, like favorites and waypoints + for (Config configOption : visibleConfigOptions) { + String configOptionName = configOption.getJsonName(); + Object configOptionValue = configOption.get(); + + // Save the config option to the map + configData.put(configOptionName, configOptionValue); + } + } + + // Return the json string of the exported settings + return Managers.Json.GSON.toJson(configData); + } + + private void setConfigValue(Config config, Object value) { + T typedValue = config.tryParseStringValue(value.toString()); + + if (typedValue != null) { + config.setValue(typedValue); + } + } } diff --git a/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java b/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java index a14f107216..ec33f5a989 100644 --- a/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java +++ b/common/src/main/java/com/wynntils/screens/chattabs/ChatTabEditingScreen.java @@ -1,5 +1,5 @@ /* - * Copyright © Wynntils 2022-2023. + * Copyright © Wynntils 2022-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.screens.chattabs; diff --git a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java index c8ec6aa84c..f8846e4e8c 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java @@ -798,20 +798,20 @@ private void setupButtons() { 150))); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.close"), button -> { - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.close"), button -> { + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 - BUTTON_WIDTH - 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.closeTooltip"))) .build()); this.addRenderableWidget(new Button.Builder( - buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { - buttonsAtBottom = !buttonsAtBottom; - setupButtons(); - }) + buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { + buttonsAtBottom = !buttonsAtBottom; + setupButtons(); + }) .pos(this.width / 2 - 10, yPos) .size(BUTTON_HEIGHT, BUTTON_HEIGHT) .tooltip(Tooltip.create( @@ -821,11 +821,11 @@ private void setupButtons() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { - Managers.Config.saveConfig(); - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { + Managers.Config.saveConfig(); + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 + 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.applyTooltip"))) diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java index 234b0ef348..ff30998df8 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java @@ -62,12 +62,12 @@ protected void doInit() { calculateBarPosition(); textureButton = this.addRenderableWidget(new Button.Builder( - Component.literal(availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .toString()), - (b) -> {}) + Component.literal(availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .toString()), + (b) -> {}) .pos((int) ((this.width / 2f) - 30), (int) (barY + 20)) .size(60, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.customBarSelection.textureTooltip"))) @@ -79,14 +79,14 @@ protected void doInit() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) + Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) .pos((int) (this.width / 2f) - 90, (int) (barY + 45)) .size(80, 20) .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.select"), - (button) -> addCustomBar()) + Component.translatable("screens.wynntils.customBarSelection.select"), + (button) -> addCustomBar()) .pos((int) (this.width / 2f) + 10, (int) (barY + 45)) .size(80, 20) .build()); @@ -163,11 +163,11 @@ private void calculateBarPosition() { // Calculate the central position to render the current selected bar at barX = (this.width - availableBars.get(barTypeIndex).a().width()) / 2f; barY = (this.height - - availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .getHeight()) + - availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .getHeight()) / 2f; } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java index e76bcbfd54..ca983d2c5d 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java @@ -123,8 +123,8 @@ protected void doInit() { // region Preview renderables exitPreviewButton = this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlaySelection.exitPreview"), - (button) -> togglePreview(false)) + Component.translatable("screens.wynntils.overlaySelection.exitPreview"), + (button) -> togglePreview(false)) .pos((Texture.OVERLAY_SELECTION_GUI.width() / 2) - 40, (int) (this.height - 25 - translationY)) .size(80, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlaySelection.exitPreviewTooltip"))) @@ -464,7 +464,7 @@ public void populateOverlays() { // Don't deselect custom overlays as they will always fail the above check if (filterType == FilterType.BUILT_IN || !(selectedOverlay instanceof CustomBarOverlayBase - || selectedOverlay instanceof InfoBoxOverlay)) { + || selectedOverlay instanceof InfoBoxOverlay)) { setSelectedOverlay(null); } } @@ -488,6 +488,8 @@ public void populateOverlays() { setSelectedOverlay(newSelected); } + + scrollOverlays(overlayScrollOffset); } public void setSelectedOverlay(Overlay selectedOverlay) { @@ -604,6 +606,8 @@ private void populateConfigs() { renderY += 43; } + + scrollConfigs(configScrollOffset); } private void togglePreview(boolean enabled) { @@ -924,11 +928,11 @@ private void renderWidgets(GuiGraphics guiGraphics, int mouseX, int mouseY, floa private void renderOverlayScroll(PoseStack poseStack) { overlayScrollY = 24 + MathUtils.map( - overlayScrollOffset, - 0, - getMaxOverlayScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + overlayScrollOffset, + 0, + getMaxOverlayScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 132, overlayScrollY); } @@ -936,11 +940,11 @@ private void renderOverlayScroll(PoseStack poseStack) { private void renderConfigScroll(PoseStack poseStack) { configScrollY = 24 + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 344, configScrollY); } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java index fa94b3e4ed..66a6c6ead7 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java @@ -128,7 +128,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float // Don't want to display tooltip when the tile is outside the mask from the screen if (isHovered && (mouseY <= selectionScreen.getConfigMaskTopY() - || mouseY >= selectionScreen.getConfigMaskBottomY())) { + || mouseY >= selectionScreen.getConfigMaskBottomY())) { isHovered = false; } diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index d749a893a1..1989ac4d9f 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -4,7 +4,6 @@ */ package com.wynntils.screens.settings; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.wynntils.core.components.Managers; import com.wynntils.core.consumers.features.Configurable; @@ -16,17 +15,21 @@ import com.wynntils.core.persisted.config.Category; import com.wynntils.core.persisted.config.Config; import com.wynntils.core.text.StyledText; +import com.wynntils.screens.base.TooltipProvider; import com.wynntils.screens.base.widgets.SearchWidget; import com.wynntils.screens.base.widgets.TextInputBoxWidget; import com.wynntils.screens.base.widgets.WynntilsButton; -import com.wynntils.screens.settings.widgets.ApplyButton; import com.wynntils.screens.settings.widgets.CategoryButton; -import com.wynntils.screens.settings.widgets.CloseButton; import com.wynntils.screens.settings.widgets.ConfigTile; import com.wynntils.screens.settings.widgets.ConfigurableButton; +import com.wynntils.screens.settings.widgets.SettingsCategoryTabButton; +import com.wynntils.screens.settings.widgets.SettingsPageTabButton; +import com.wynntils.screens.settings.widgets.SettingsSideTabButton; import com.wynntils.utils.MathUtils; import com.wynntils.utils.StringUtils; import com.wynntils.utils.colors.CommonColors; +import com.wynntils.utils.mc.ComponentUtils; +import com.wynntils.utils.mc.McUtils; import com.wynntils.utils.render.FontRenderer; import com.wynntils.utils.render.RenderUtils; import com.wynntils.utils.render.Texture; @@ -34,6 +37,7 @@ import com.wynntils.utils.render.type.TextShadow; import com.wynntils.utils.render.type.VerticalAlignment; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.List; @@ -42,44 +46,75 @@ import java.util.stream.Stream; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; public final class WynntilsBookSettingsScreen extends WynntilsScreen { + // Constants private static final float SCROLL_FACTOR = 10f; - private static final int CONFIG_MASK_TOP_Y = 21; + private static final int MASK_TOP_Y = 21; private static final int CONFIG_MASK_BOTTOM_Y = 205; - private static final int CONFIGURABLES_PER_PAGE = 13; + private static final int CONFIGURABLE_MASK_BOTTOM_Y = 211; + private static final int CONFIGURABLES_PER_PAGE = 16; private static final int CONFIGS_PER_PAGE = 4; - private static final int CONFIGURABLE_SCROLL_X = 23; + private static final int CONFIGURABLE_SCROLL_X = (int) (Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 12); private static final int CONFIG_SCROLL_X = Texture.CONFIG_BOOK_BACKGROUND.width() - 23; - private static final int SCROLL_START_Y = 17; + private static final int MAX_DISPLAYED_CATEGORIES = 7; + private static final int SCROLL_AREA_HEIGHT = 186; + private static final int SCROLL_START_Y = 21; + // Collections + private final List sortedCategories; private final List configurables = new ArrayList<>(); private final List configs = new ArrayList<>(); private List configurableList; + private List categoryButtons = new ArrayList<>(); - private TextInputBoxWidget focusedTextInput; + // Renderables private final SearchWidget searchWidget; + private SettingsCategoryTabButton allCategoriesButton; + private SettingsCategoryTabButton selectedCategoryButton; + private TextInputBoxWidget focusedTextInput; - private Configurable selected = null; - + // UI size, postions, etc private boolean draggingConfigurableScroll = false; private boolean draggingConfigScroll = false; - private int configurableScrollOffset = 0; + private int categoriesScrollOffset = 0; + private int configurablesScrollOffset = 0; private int configScrollOffset = 0; private float configurableScrollRenderY; private float configScrollRenderY; + private float translationX; + private float translationY; + + // Settings display + private Category selectedCategory; + private Configurable selectedConfigurable = null; private WynntilsBookSettingsScreen() { super(Component.translatable("screens.wynntils.settingsScreen.name")); searchWidget = new SearchWidget( - 95, Texture.CONFIG_BOOK_BACKGROUND.height() - 32, 100, 20, s -> reloadConfigurableButtons(), this); + 60, + Texture.CONFIG_BOOK_BACKGROUND.height() + 5, + 100, + 20, + (s) -> { + configurablesScrollOffset = 0; + getFilteredConfigurables(); + populateConfigurables(); + }, + this); setFocusedTextInput(searchWidget); + + // Get all categories, sort a-z + sortedCategories = Arrays.asList(Category.values()); + sortedCategories.sort(Comparator.comparing(Enum::name)); } public static Screen create() { @@ -88,39 +123,230 @@ public static Screen create() { @Override protected void doInit() { - reloadConfigurableButtons(); + populateCategories(); + getFilteredConfigurables(); + populateConfigurables(); + // Render position for the book background + translationX = (this.width - Texture.CONFIG_BOOK_BACKGROUND.width()) / 2f; + translationY = (this.height - Texture.CONFIG_BOOK_BACKGROUND.height()) / 2f; + + int yPos = Texture.TAG_BLUE.height() / 2; + + // region Side tags + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + this::importSettings, + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.import") + .withStyle(ChatFormatting.YELLOW), + Component.translatable("screens.wynntils.settingsScreen.import.all") + .withStyle(ChatFormatting.GRAY), + Component.translatable("screens.wynntils.settingsScreen.import.selected") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.ADD_ICON)); + + yPos += 15 + Texture.TAG_BLUE.height() / 2; + + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + this::exportSettings, + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.export") + .withStyle(ChatFormatting.BLUE), + Component.translatable("screens.wynntils.settingsScreen.export.all") + .withStyle(ChatFormatting.GRAY), + Component.translatable("screens.wynntils.settingsScreen.export.selected") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.SHARE_ICON)); + + yPos += 15 + Texture.TAG_BLUE.height() / 2; + + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + (b) -> { + Managers.Config.saveConfig(); + onClose(); + }, + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.apply") + .withStyle(ChatFormatting.GREEN), + Component.translatable("screens.wynntils.settingsScreen.apply.description") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.SAVE)); + + yPos += 15 + Texture.TAG_BLUE.height() / 2; + + this.addRenderableWidget(new SettingsSideTabButton( + (int) -(Texture.TAG_BLUE.width() * 0.75f), + yPos, + Texture.TAG_BLUE.width(), + Texture.TAG_BLUE.height(), + (b) -> onClose(), + ComponentUtils.wrapTooltips( + List.of( + Component.translatable("screens.wynntils.settingsScreen.close") + .withStyle(ChatFormatting.RED), + Component.translatable("screens.wynntils.settingsScreen.close.description") + .withStyle(ChatFormatting.GRAY)), + 150), + Texture.TAG_BLUE, + Texture.CLOSE)); + // endregion + + // region Category tags + int xPos = 18; + + allCategoriesButton = this.addRenderableWidget(new SettingsCategoryTabButton( + 18, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> changeCategory(null), + List.of(Component.literal("All")), + selectedCategory == null)); + + if (selectedCategory == null) { + selectedCategoryButton = allCategoriesButton; + } - this.addRenderableWidget(searchWidget); + xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75; + + this.addRenderableWidget(new SettingsPageTabButton( + xPos, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> scrollCategorories(-1), + List.of(Component.translatable("screens.wynntils.settingsScreen.previous")), + false)); - this.addRenderableWidget(new ApplyButton(this)); + xPos += (Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75) * (MAX_DISPLAYED_CATEGORIES + 1); - this.addRenderableWidget(new CloseButton(this)); + this.addRenderableWidget(new SettingsPageTabButton( + xPos, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> scrollCategorories(1), + List.of(Component.translatable("screens.wynntils.settingsScreen.next")), + true)); + + this.addRenderableWidget(searchWidget); } @Override public void doRender(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { - float backgroundRenderX = getTranslationX(); - float backgroundRenderY = getTranslationY(); - PoseStack poseStack = guiGraphics.pose(); poseStack.pushPose(); - poseStack.translate(backgroundRenderX, backgroundRenderY, 0); + poseStack.translate(translationX, translationY, 0); + + int adjustedMouseX = mouseX - (int) translationX; + int adjustedMouseY = mouseY - (int) translationY; + + renderSearchBar(poseStack); + + renderTags(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); renderBg(poseStack); - renderScrollArea(poseStack); + String categoryName = selectedCategory == null + ? I18n.get("screens.wynntils.settingsScreen.all") + : I18n.get(selectedCategory.toString()); - renderConfigurableScroll(poseStack); + FontRenderer.getInstance() + .renderText( + poseStack, + StyledText.fromString(categoryName), + Texture.CONFIG_BOOK_BACKGROUND.width() * 0.25f, + McUtils.mc().font.lineHeight + 5, + CommonColors.LIGHT_GRAY, + HorizontalAlignment.CENTER, + VerticalAlignment.MIDDLE, + TextShadow.NORMAL); + + RenderUtils.drawLine( + poseStack, CommonColors.GRAY, 11, 19, Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 6, 19, 0, 1); + + if (selectedConfigurable != null) { + String textToRender = selectedConfigurable.getTranslatedName(); + + // Show the custom name for info boxes/custom bars if given + if (selectedConfigurable instanceof CustomNameProperty customNameProperty) { + if (!customNameProperty.getCustomName().get().isEmpty()) { + textToRender = customNameProperty.getCustomName().get(); + } + } - renderWidgets(guiGraphics, mouseX, mouseY, partialTick); + FontRenderer.getInstance() + .renderText( + poseStack, + StyledText.fromString(textToRender), + Texture.CONFIG_BOOK_BACKGROUND.width() * 0.75f, + McUtils.mc().font.lineHeight + 5, + CommonColors.LIGHT_GRAY, + HorizontalAlignment.CENTER, + VerticalAlignment.MIDDLE, + TextShadow.NORMAL); + + RenderUtils.drawLine( + poseStack, + CommonColors.GRAY, + Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 6, + 19, + Texture.CONFIG_BOOK_BACKGROUND.width() - 11, + 19, + 0, + 1); + } else { + FontRenderer.getInstance() + .renderAlignedTextInBox( + poseStack, + StyledText.fromComponent( + Component.translatable("screens.wynntils.settingsScreen.unselectedConfig")), + Texture.CONFIG_BOOK_BACKGROUND.width() / 2f, + Texture.CONFIG_BOOK_BACKGROUND.width(), + Texture.CONFIG_BOOK_BACKGROUND.height() * 0.25f, + Texture.CONFIG_BOOK_BACKGROUND.height() * 0.75f, + Texture.CONFIG_BOOK_BACKGROUND.width() / 3f, + CommonColors.WHITE, + HorizontalAlignment.CENTER, + VerticalAlignment.TOP, + TextShadow.NORMAL); + } - if (selected != null) { - renderConfigTitle(poseStack); + if (configurables.size() > CONFIGURABLES_PER_PAGE) { + renderConfigurableScroll(poseStack); + } + if (configs.size() > CONFIGS_PER_PAGE) { renderConfigScroll(poseStack); } + renderConfigs(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + + renderConfigurables(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + + renderTooltips(guiGraphics, adjustedMouseX, adjustedMouseY); + poseStack.popPose(); } @@ -138,8 +364,8 @@ public void onClose() { @Override public boolean doMouseClicked(double mouseX, double mouseY, int button) { - double adjustedMouseX = mouseX - getTranslationX(); - double adjustedMouseY = mouseY - getTranslationY(); + double adjustedMouseX = mouseX - translationX; + double adjustedMouseY = mouseY - translationY; for (GuiEventListener listener : getWidgetsForIteration().toList()) { if (listener.isMouseOver(adjustedMouseX, adjustedMouseY)) { @@ -149,12 +375,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigurableScroll && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIGURABLE_SCROLL_X, - CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configurableScrollRenderY, - (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIGURABLE_SCROLL_X, + CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configurableScrollRenderY, + (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigurableScroll = true; return true; } @@ -162,12 +388,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigScroll && (configs.size() > CONFIGS_PER_PAGE) && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIG_SCROLL_X, - CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configScrollRenderY, - (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIG_SCROLL_X, + CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configScrollRenderY, + (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigScroll = true; return true; } @@ -177,18 +403,16 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { - double adjustedMouseX = mouseX - getTranslationX(); - double adjustedMouseY = mouseY - getTranslationY(); + double adjustedMouseX = mouseX - translationX; + double adjustedMouseY = mouseY - translationY; if (draggingConfigurableScroll) { int scrollAreaStartY = SCROLL_START_Y + 7; - int scrollAreaHeight = - (int) (CONFIGURABLES_PER_PAGE * 12 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); int newOffset = Math.round(MathUtils.map( (float) adjustedMouseY, scrollAreaStartY, - scrollAreaStartY + scrollAreaHeight, + scrollAreaStartY + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f, 0, getMaxConfigurableScrollOffset())); @@ -201,12 +425,11 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double dra if (draggingConfigScroll) { int scrollAreaStartY = SCROLL_START_Y + 7; - int scrollAreaHeight = (int) (CONFIGS_PER_PAGE * 46 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); int newOffset = Math.round(MathUtils.map( (float) adjustedMouseY, scrollAreaStartY, - scrollAreaStartY + scrollAreaHeight, + scrollAreaStartY + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f, 0, getMaxConfigScrollOffset())); @@ -228,8 +451,8 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double dra @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - double adjustedMouseX = mouseX - getTranslationX(); - double adjustedMouseY = mouseY - getTranslationY(); + double adjustedMouseX = mouseX - translationX; + double adjustedMouseY = mouseY - translationY; for (GuiEventListener listener : getWidgetsForIteration().toList()) { listener.mouseReleased(adjustedMouseX, adjustedMouseY, button); @@ -243,12 +466,17 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean mouseScrolled(double mouseX, double mouseY, double deltaX, double deltaY) { - double adjustedMouseX = mouseX - getTranslationX(); + double adjustedMouseX = mouseX - translationX; int scrollAmount = (int) (-deltaY * SCROLL_FACTOR); - if (adjustedMouseX <= Texture.CONFIG_BOOK_BACKGROUND.width() / 2f) { + // When mouse above the book, scroll the categories. + // When below top of book and left side scroll configurables + // Otherwise scroll configs + if (mouseY <= translationY) { + scrollCategorories((int) -Math.signum(deltaY)); + } else if (adjustedMouseX <= Texture.CONFIG_BOOK_BACKGROUND.width() / 2f) { int newOffset = - Math.max(0, Math.min(configurableScrollOffset + scrollAmount, getMaxConfigurableScrollOffset())); + Math.max(0, Math.min(configurablesScrollOffset + scrollAmount, getMaxConfigurableScrollOffset())); scrollConfigurables(newOffset); } else if (configs.size() > CONFIGS_PER_PAGE) { int newOffset = Math.max(0, Math.min(configScrollOffset + scrollAmount, getMaxConfigScrollOffset())); @@ -283,155 +511,248 @@ public void setFocusedTextInput(TextInputBoxWidget focusedTextInput) { this.focusedTextInput = focusedTextInput; } - public boolean configOptionContains(Config config) { - return !searchWidget.getTextBoxInput().isEmpty() - && StringUtils.containsIgnoreCase(config.getDisplayName(), searchWidget.getTextBoxInput()); - } + public void populateConfigurables() { + configurables.clear(); - public Configurable getSelected() { - return selected; - } + Category oldCategory = selectedCategory; - public void setSelected(Configurable selected) { - this.selected = selected; - reloadConfigButtons(); - } + int renderY = 21; - public float getTranslationY() { - return (this.height - Texture.CONFIG_BOOK_BACKGROUND.height()) / 2f; - } + for (Configurable configurable : configurableList) { + Category category; - public float getTranslationX() { - return (this.width - Texture.CONFIG_BOOK_BACKGROUND.width()) / 2f; - } + if (configurable instanceof Feature feature) { + category = feature.getCategory(); + } else if (configurable instanceof Overlay overlay) { + category = Managers.Overlay.getOverlayParent(overlay).getCategory(); + } else { + throw new IllegalStateException("Unknown configurable type: " + configurable.getClass()); + } - public int getConfigMaskTopY() { - return CONFIG_MASK_TOP_Y; - } + if (category != oldCategory) { + CategoryButton categoryButton = new CategoryButton(12, renderY, 170, 10, category); + categoryButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); + configurables.add(categoryButton); + oldCategory = category; + renderY += 12; + } - public int getConfigMaskBottomY() { - return CONFIG_MASK_BOTTOM_Y; - } + int matchingConfigs = 0; - private void renderConfigTitle(PoseStack poseStack) { - String name = ""; - boolean enabled = false; - if (selected instanceof Overlay selectedOverlay) { - enabled = Managers.Overlay.isEnabled(selectedOverlay); - name = selectedOverlay.getTranslatedName(); + for (Config config : configurable.getVisibleConfigOptions()) { + if (configOptionContains(config)) { + matchingConfigs++; + } + } - if (selected instanceof CustomNameProperty customNameProperty) { - if (!customNameProperty.getCustomName().get().isEmpty()) { - name = customNameProperty.getCustomName().get(); + ConfigurableButton configurableButton = + new ConfigurableButton(12, renderY, 170, 10, configurable, this, matchingConfigs); + configurableButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); + configurables.add(configurableButton); + + renderY += 12; + + if (configurable instanceof Feature feature) { + for (Overlay overlay : Managers.Overlay.getFeatureOverlays(feature).stream() + .sorted() + .toList()) { + matchingConfigs = 0; + + for (Config config : overlay.getVisibleConfigOptions()) { + if (configOptionContains(config)) { + matchingConfigs++; + } + } + + ConfigurableButton overlayButton = + new ConfigurableButton(12, renderY, 170, 10, overlay, this, matchingConfigs); + overlayButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); + configurables.add(overlayButton); + renderY += 12; } } - } else if (selected instanceof Feature selectedFeature) { - enabled = selectedFeature.isEnabled(); - name = selectedFeature.getTranslatedName(); } - FontRenderer.getInstance() - .renderScrollingText( - poseStack, - StyledText.fromString(name + ": " - + (enabled - ? ChatFormatting.DARK_GREEN + "Enabled" - : ChatFormatting.DARK_RED + "Disabled")), - Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 10, - 10, - Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 20, - getTranslationX(), - getTranslationY(), - CommonColors.BLACK, - HorizontalAlignment.LEFT, - VerticalAlignment.TOP, - TextShadow.NONE, - 0.8f); - } - - private void renderWidgets(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { - int adjustedMouseX = mouseX - (int) getTranslationX(); - int adjustedMouseY = mouseY - (int) getTranslationY(); + if (selectedConfigurable != null) { + Stream configurablesList = Stream.concat( + Managers.Feature.getFeatures().stream(), + Managers.Feature.getFeatures().stream() + .map(Managers.Overlay::getFeatureOverlays) + .flatMap(Collection::stream) + .map(overlay -> (Configurable) overlay)); - for (Renderable renderable : renderables) { - renderable.render(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + Configurable newSelected = configurablesList + .filter(configurable -> configurable.getJsonName().equals(selectedConfigurable.getJsonName())) + .findFirst() + .orElse(null); + + setSelectedConfigurable(newSelected); } - RenderUtils.createRectMask(guiGraphics.pose(), 37, 16, 140, 163); + scrollConfigurables(configurablesScrollOffset); + } - for (WynntilsButton configurable : configurables) { - configurable.render(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + public void populateConfigs() { + configs.clear(); + configScrollOffset = 0; + + if (selectedConfigurable == null) return; + + List> configsOptions = selectedConfigurable.getVisibleConfigOptions().stream() + .sorted(Comparator.comparing(config -> !Objects.equals(config.getFieldName(), "userEnabled"))) + .toList(); + + int renderY = 21; + + for (Config config : configsOptions) { + ConfigTile configTile = + new ConfigTile(Texture.CONFIG_BOOK_BACKGROUND.width() / 2 + 10, renderY, 160, 45, this, config); + configTile.visible = renderY >= (21 - 46) && renderY <= (21 + CONFIGS_PER_PAGE * 45); + + configs.add(configTile); + + renderY += 46; } - RenderUtils.clearMask(); + scrollConfigs(configScrollOffset); + } - RenderUtils.createRectMask( - guiGraphics.pose(), Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 10, 21, 160, CONFIGS_PER_PAGE * 46); + public boolean configOptionContains(Config config) { + return !searchWidget.getTextBoxInput().isEmpty() + && StringUtils.containsIgnoreCase(config.getDisplayName(), searchWidget.getTextBoxInput()); + } - for (WynntilsButton config : configs) { - config.render(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); + public void setSelectedConfigurable(Configurable selectedConfigurable) { + this.selectedConfigurable = selectedConfigurable; + populateConfigs(); + + // If there is a search query, scroll the configs list so that the matching config + // is found unless the configurable itself matches the search query + if (!searchWidget.getTextBoxInput().isEmpty()) { + if (!searchMatches(selectedConfigurable)) { + scrollToMatchingConfig(); + } } + } - RenderUtils.clearMask(); + public Configurable getSelectedConfigurable() { + return selectedConfigurable; } - private static void renderScrollArea(PoseStack poseStack) { - RenderSystem.enableBlend(); - RenderUtils.drawTexturedRect( - poseStack, - Texture.CONFIG_BOOK_SCROLL_AREA, - (Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - Texture.CONFIG_BOOK_SCROLL_AREA.width()) / 2f, - 10); - RenderSystem.disableBlend(); + public float getTranslationX() { + return translationX; } - private void renderConfigurableScroll(PoseStack poseStack) { - configurableScrollRenderY = SCROLL_START_Y - + MathUtils.map( - configurableScrollOffset, - 0, - getMaxConfigurableScrollOffset(), - 0, - 161 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + public float getTranslationY() { + return translationY; + } - RenderUtils.drawHoverableTexturedRect( - poseStack, - Texture.CONFIG_BOOK_SCROLL_BUTTON, - CONFIGURABLE_SCROLL_X, - configurableScrollRenderY, - draggingConfigurableScroll); + public int getMaskTopY() { + return MASK_TOP_Y; } - private void renderConfigScroll(PoseStack poseStack) { - if (configs.size() <= CONFIGS_PER_PAGE) return; + public int getConfigMaskBottomY() { + return CONFIG_MASK_BOTTOM_Y; + } - RenderUtils.drawRect( - poseStack, - CommonColors.GRAY, - CONFIG_SCROLL_X, - SCROLL_START_Y, - 0, - Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - CONFIGS_PER_PAGE * 46); + public int getConfigurableMaskBottomY() { + return CONFIGURABLE_MASK_BOTTOM_Y; + } - configScrollRenderY = SCROLL_START_Y - + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - CONFIGS_PER_PAGE * 46 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + private void populateCategories() { + for (AbstractWidget widget : categoryButtons) { + this.removeWidget(widget); + } - RenderUtils.drawHoverableTexturedRect( - poseStack, - Texture.CONFIG_BOOK_SCROLL_BUTTON, - CONFIG_SCROLL_X, - configScrollRenderY, - draggingConfigScroll); + int xPos = (int) (18 + Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75); + + categoryButtons = new ArrayList<>(); + + for (int i = 0; i < MAX_DISPLAYED_CATEGORIES; i++) { + xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75; + + int categoryIndex; + + if (i + categoriesScrollOffset < 0) { + categoryIndex = (i + categoriesScrollOffset) + sortedCategories.size(); + } else if (i + categoriesScrollOffset > sortedCategories.size() - 1) { + categoryIndex = (i + categoriesScrollOffset) - sortedCategories.size(); + } else { + categoryIndex = (i + categoriesScrollOffset); + } + + Category category = sortedCategories.get(categoryIndex); + + categoryButtons.add(this.addRenderableWidget(new SettingsCategoryTabButton( + xPos, + (int) -(Texture.TAG_RED.height() * 0.75f), + Texture.TAG_RED.width(), + Texture.TAG_RED.height(), + (b) -> changeCategory(category), + List.of(Component.literal(I18n.get(category.toString()))), + category, + selectedCategory == category))); + } } - private static void renderBg(PoseStack poseStack) { - RenderUtils.drawTexturedRect(poseStack, Texture.CONFIG_BOOK_BACKGROUND, 0, 0); + private void getFilteredConfigurables() { + configurableList = new ArrayList<>(); + + List filteredConfigurables; + + // Add all configurables for selected category + if (selectedCategory != null) { + filteredConfigurables = Managers.Feature.getFeatures().stream() + .filter(feature -> searchMatches(feature) + || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .map(feature -> (Configurable) feature) + .sorted() + .filter(configurable -> isCategoryMatching(configurable, selectedCategory)) + .collect(Collectors.toList()); + + filteredConfigurables.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !filteredConfigurables.contains(Managers.Overlay.getOverlayParent(overlay))) + .filter(overlay -> searchMatches(overlay) + || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .sorted() + .filter(configurable -> isCategoryMatching(configurable, selectedCategory)) + .toList()); + + // If there is a search query, add all matches from every other category + if (!searchWidget.getTextBoxInput().isEmpty()) { + filteredConfigurables.addAll(Managers.Feature.getFeatures().stream() + .filter(feature -> searchMatches(feature) + || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .map(feature -> (Configurable) feature) + .sorted() + .filter(configurable -> !isCategoryMatching(configurable, selectedCategory)) + .toList()); + + filteredConfigurables.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !filteredConfigurables.contains(Managers.Overlay.getOverlayParent(overlay))) + .filter(overlay -> searchMatches(overlay) + || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .sorted() + .filter(configurable -> !isCategoryMatching(configurable, selectedCategory)) + .toList()); + } + } else { // All tab, add all configurables + filteredConfigurables = Managers.Feature.getFeatures().stream() + .filter(feature -> searchMatches(feature) + || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .map(feature -> (Configurable) feature) + .sorted() + .collect(Collectors.toList()); + + filteredConfigurables.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !filteredConfigurables.contains(Managers.Overlay.getOverlayParent(overlay))) + .filter(overlay -> searchMatches(overlay) + || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) + .sorted() + .toList()); + } + + configurableList.addAll(filteredConfigurables); } private Stream getWidgetsForIteration() { @@ -439,10 +760,10 @@ private Stream getWidgetsForIteration() { } private void scrollConfigurables(int newOffset) { - configurableScrollOffset = newOffset; + configurablesScrollOffset = newOffset; for (WynntilsButton configurable : configurables) { - int newY = 21 + (configurables.indexOf(configurable) * 12) - configurableScrollOffset; + int newY = 21 + (configurables.indexOf(configurable) * 12) - configurablesScrollOffset; configurable.setY(newY); configurable.visible = newY >= (21 - 12) && newY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); @@ -468,81 +789,77 @@ private int getMaxConfigScrollOffset() { return (configs.size() - CONFIGS_PER_PAGE) * 46; } - private void reloadConfigurableButtons() { - configurables.clear(); - configurableScrollOffset = 0; - - Category oldCategory = null; - - configurableList = Managers.Feature.getFeatures().stream() - .filter(feature -> searchMatches(feature) - || feature.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) - .map(feature -> (Configurable) feature) - .sorted() - .collect(Collectors.toList()); - - configurableList.addAll(Managers.Overlay.getOverlays().stream() - .filter(overlay -> !configurableList.contains(Managers.Overlay.getOverlayParent(overlay))) - .filter(overlay -> searchMatches(overlay) - || overlay.getVisibleConfigOptions().stream().anyMatch(this::configOptionContains)) - .sorted() - .toList()); - - int renderY = 21; + private void scrollCategorories(int direction) { + if (Math.abs(categoriesScrollOffset + direction) == sortedCategories.size()) { + categoriesScrollOffset = 0; + } else { + categoriesScrollOffset = MathUtils.clamp( + categoriesScrollOffset + direction, -(sortedCategories.size() - 1), (sortedCategories.size() - 1)); + } - for (int i = 0; i < configurableList.size(); i++) { - Configurable configurable = configurableList.get(i); + populateCategories(); + } - Category category; + private boolean isCategoryMatching(Configurable configurable, Category selectedCategory) { + return getCategory(configurable) == selectedCategory; + } - if (configurable instanceof Feature feature) { - category = feature.getCategory(); - } else if (configurable instanceof Overlay overlay) { - category = Managers.Overlay.getOverlayParent(overlay).getCategory(); - } else { - throw new IllegalStateException("Unknown configurable type: " + configurable.getClass()); - } + private void scrollToMatchingConfig() { + List> configsOptions = selectedConfigurable.getVisibleConfigOptions().stream() + .sorted(Comparator.comparing(config -> !Objects.equals(config.getFieldName(), "userEnabled"))) + .toList(); - if (category != oldCategory) { - CategoryButton categoryButton = new CategoryButton(37, renderY, 140, 10, category); - categoryButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); - configurables.add(categoryButton); - oldCategory = category; - renderY += 12; + // Find a config that matches current search query and get scroll offset to make that config visible + for (Config config : configsOptions) { + if (StringUtils.containsIgnoreCase(config.getDisplayName(), searchWidget.getTextBoxInput())) { + int newOffset = Math.max( + 0, + Math.min( + (configsOptions.indexOf(config) - (CONFIGS_PER_PAGE - 1)) * 46, + getMaxConfigScrollOffset())); + scrollConfigs(newOffset); + return; } + } + } - ConfigurableButton configurableButton = new ConfigurableButton(37, renderY, 140, 10, configurable, this); - configurableButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); - configurables.add(configurableButton); + private void changeCategory(Category category) { + configurablesScrollOffset = 0; - renderY += 12; + // Deselect old category, reset texture to default + if (selectedCategoryButton != null) { + selectedCategoryButton.setSelectedCategory(false); + } - if (configurable instanceof Feature feature) { - for (Overlay overlay : Managers.Overlay.getFeatureOverlays(feature).stream() - .sorted() - .toList()) { - ConfigurableButton overlayButton = new ConfigurableButton(37, renderY, 140, 10, overlay, this); - overlayButton.visible = renderY >= (21 - 12) && renderY <= (21 + (CONFIGURABLES_PER_PAGE + 1) * 11); - configurables.add(overlayButton); - renderY += 12; + selectedCategory = category; + + // If null, the all categories button was selected. + // Otherwise find which was selected and update that + if (category == null) { + selectedCategoryButton = allCategoriesButton; + allCategoriesButton.setSelectedCategory(true); + } else { + for (SettingsCategoryTabButton settingsTabButton : categoryButtons) { + if (settingsTabButton.getCategory() == selectedCategory) { + selectedCategoryButton = settingsTabButton; + settingsTabButton.setSelectedCategory(true); + break; } } } - if (selected != null) { - Stream configurablesList = Stream.concat( - Managers.Feature.getFeatures().stream(), - Managers.Feature.getFeatures().stream() - .map(Managers.Overlay::getFeatureOverlays) - .flatMap(Collection::stream) - .map(overlay -> (Configurable) overlay)); - - Configurable newSelected = configurablesList - .filter(configurable -> configurable.getJsonName().equals(selected.getJsonName())) - .findFirst() - .orElse(null); + getFilteredConfigurables(); + populateConfigurables(); + populateCategories(); + } - setSelected(newSelected); + private Category getCategory(Configurable configurable) { + if (configurable instanceof Feature feature) { + return feature.getCategory(); + } else if (configurable instanceof Overlay overlay) { + return Managers.Overlay.getOverlayParent(overlay).getCategory(); + } else { + throw new IllegalStateException("Unknown configurable type: " + configurable.getClass()); } } @@ -558,28 +875,185 @@ private boolean searchMatches(Translatable translatable) { return StringUtils.partialMatch(translatable.getTranslatedName(), searchWidget.getTextBoxInput()); } - private void reloadConfigButtons() { - configs.clear(); - configScrollOffset = 0; + private void renderBg(PoseStack poseStack) { + RenderUtils.drawTexturedRect(poseStack, Texture.CONFIG_BOOK_BACKGROUND, 0, 0); + } - if (selected == null) return; + private void renderSearchBar(PoseStack poseStack) { + RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 2); + } - List> configsOptions = selected.getVisibleConfigOptions().stream() - .sorted(Comparator.comparing(config -> !Objects.equals(config.getFieldName(), "userEnabled"))) - .toList(); + private void renderTags(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + for (Renderable renderable : renderables) { + renderable.render(guiGraphics, mouseX, mouseY, partialTick); + } + } - int renderY = 21; + private void renderConfigurables(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + RenderUtils.createRectMask(guiGraphics.pose(), 12, 21, 170, CONFIGURABLES_PER_PAGE * 12 - 3); - for (int i = 0; i < configsOptions.size(); i++) { - Config config = configsOptions.get(i); + for (WynntilsButton configurable : configurables) { + configurable.render(guiGraphics, mouseX, mouseY, partialTick); + } - ConfigTile configTile = - new ConfigTile(Texture.CONFIG_BOOK_BACKGROUND.width() / 2 + 10, renderY, 160, 45, this, config); - configTile.visible = renderY >= (21 - 46) && renderY <= (21 + CONFIGS_PER_PAGE * 45); + RenderUtils.clearMask(); + } - configs.add(configTile); + private void renderConfigurableScroll(PoseStack poseStack) { + RenderUtils.drawRect( + poseStack, + CommonColors.GRAY, + CONFIGURABLE_SCROLL_X, + 21, + 0, + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + SCROLL_AREA_HEIGHT); - renderY += 46; + configurableScrollRenderY = SCROLL_START_Y + + MathUtils.map( + configurablesScrollOffset, + 0, + getMaxConfigurableScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + + RenderUtils.drawHoverableTexturedRect( + poseStack, + Texture.CONFIG_BOOK_SCROLL_BUTTON, + CONFIGURABLE_SCROLL_X, + configurableScrollRenderY, + draggingConfigurableScroll); + } + + private void renderConfigs(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + RenderUtils.createRectMask( + guiGraphics.pose(), Texture.CONFIG_BOOK_BACKGROUND.width() / 2f + 10, 21, 160, CONFIGS_PER_PAGE * 46); + + for (WynntilsButton config : configs) { + config.render(guiGraphics, mouseX, mouseY, partialTick); + } + + RenderUtils.clearMask(); + } + + private void renderConfigScroll(PoseStack poseStack) { + if (configs.size() <= CONFIGS_PER_PAGE) return; + + RenderUtils.drawRect( + poseStack, + CommonColors.GRAY, + CONFIG_SCROLL_X, + SCROLL_START_Y, + 0, + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + SCROLL_AREA_HEIGHT); + + configScrollRenderY = SCROLL_START_Y + + MathUtils.map( + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + + RenderUtils.drawHoverableTexturedRect( + poseStack, + Texture.CONFIG_BOOK_SCROLL_BUTTON, + CONFIG_SCROLL_X, + configScrollRenderY, + draggingConfigScroll); + } + + private void renderTooltips(GuiGraphics guiGraphics, int mouseX, int mouseY) { + // The tags have a slight bit rendered underneath the book, we don't want to render the tooltip + // when hovering that bit. + if (mouseX >= 0 && mouseY >= 0) return; + + for (GuiEventListener child : children()) { + if (child instanceof TooltipProvider tooltipProvider && child.isMouseOver(mouseX, mouseY)) { + guiGraphics.renderComponentTooltip( + FontRenderer.getInstance().getFont(), tooltipProvider.getTooltipLines(), mouseX, mouseY); + break; + } + } + } + + private void importSettings(int clicked) { + String clipboard = McUtils.mc().keyboardHandler.getClipboard(); + + if (clicked == GLFW.GLFW_MOUSE_BUTTON_LEFT) { + List configsToImport = Managers.Feature.getFeatures().stream() + .map(feature -> (Configurable) feature) + .collect(Collectors.toList()); + + configsToImport.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !configsToImport.contains(Managers.Overlay.getOverlayParent(overlay))) + .toList()); + + boolean imported = Managers.Config.importConfig(clipboard, configsToImport); + + if (imported) { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.importedAll") + .withStyle(ChatFormatting.GREEN)); + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.import.failed") + .withStyle(ChatFormatting.RED)); + } + } else if (clicked == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { + if (selectedConfigurable != null) { + boolean imported = Managers.Config.importConfig(clipboard, List.of(selectedConfigurable)); + + if (imported) { + McUtils.sendMessageToClient(Component.translatable( + "screens.wynntils.settingsScreen.imported", + selectedConfigurable.getTranslatedName()) + .withStyle(ChatFormatting.GREEN)); + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.import.failed") + .withStyle(ChatFormatting.RED)); + } + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.needToSelect") + .withStyle(ChatFormatting.RED)); + } + } + + // Repopulate the configurables and configs after importing + populateConfigurables(); + populateConfigs(); + } + + private void exportSettings(int clicked) { + String exportedSettings = ""; + + if (clicked == GLFW.GLFW_MOUSE_BUTTON_LEFT) { + // Get all features and overlays into a list + List featuresToExport = Managers.Feature.getFeatures().stream() + .map(feature -> (Configurable) feature) + .collect(Collectors.toList()); + + featuresToExport.addAll(Managers.Overlay.getOverlays().stream() + .filter(overlay -> !featuresToExport.contains(Managers.Overlay.getOverlayParent(overlay))) + .toList()); + + exportedSettings = Managers.Config.exportConfig(featuresToExport); + + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.exportedAll") + .withStyle(ChatFormatting.GREEN)); + } else if (clicked == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { + if (selectedConfigurable != null) { + exportedSettings = Managers.Config.exportConfig(List.of(selectedConfigurable)); + + McUtils.sendMessageToClient(Component.translatable( + "screens.wynntils.settingsScreen.exported", selectedConfigurable.getTranslatedName()) + .withStyle(ChatFormatting.GREEN)); + } else { + McUtils.sendMessageToClient(Component.translatable("screens.wynntils.settingsScreen.needToSelect") + .withStyle(ChatFormatting.RED)); + } } + + // Save to clipboard + McUtils.mc().keyboardHandler.setClipboard(exportedSettings); } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java deleted file mode 100644 index 2d049d5b53..0000000000 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ApplyButton.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © Wynntils 2023-2024. - * This file is released under LGPLv3. See LICENSE for full license details. - */ -package com.wynntils.screens.settings.widgets; - -import com.wynntils.core.components.Managers; -import com.wynntils.screens.settings.WynntilsBookSettingsScreen; -import com.wynntils.utils.mc.McUtils; -import com.wynntils.utils.render.Texture; -import java.util.List; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; - -public class ApplyButton extends GeneralSettingsButton { - private final WynntilsBookSettingsScreen screen; - - public ApplyButton(WynntilsBookSettingsScreen screen) { - super( - 55, - Texture.CONFIG_BOOK_BACKGROUND.height() - 30, - 35, - 14, - Component.translatable("screens.wynntils.settingsScreen.apply"), - List.of(Component.translatable("screens.wynntils.settingsScreen.apply.description") - .withStyle(ChatFormatting.GREEN)), - 0, - McUtils.mc().screen.height); - this.screen = screen; - } - - @Override - public void onPress() { - Managers.Config.saveConfig(); - screen.onClose(); - } -} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java index 6d75c21630..de67e0a103 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/BooleanSettingsButton.java @@ -5,10 +5,11 @@ package com.wynntils.screens.settings.widgets; import com.wynntils.core.persisted.config.Config; +import com.wynntils.screens.settings.WynntilsBookSettingsScreen; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; import com.wynntils.utils.mc.ComponentUtils; -import com.wynntils.utils.render.FontRenderer; +import com.wynntils.utils.mc.McUtils; import java.util.List; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -16,16 +17,25 @@ public class BooleanSettingsButton extends GeneralSettingsButton { private final Config config; - public BooleanSettingsButton(int x, int y, Config config, int maskTopY, int maskBottomY) { + public BooleanSettingsButton( + int x, + int y, + Config config, + int maskTopY, + int maskBottomY, + float translationX, + float translationY) { super( x, y, - 50, - FontRenderer.getInstance().getFont().lineHeight + 8, + 90, + 20, getTitle(config), ComponentUtils.wrapTooltips(List.of(Component.literal(config.getDescription())), 150), maskTopY, - maskBottomY); + maskBottomY, + translationX, + translationY); this.config = config; } @@ -33,6 +43,12 @@ public BooleanSettingsButton(int x, int y, Config config, int maskTopY, public void onPress() { config.setValue(!isEnabled(config)); setMessage(getTitle(config)); + + // Reload the configurables in case the enabled button was toggled so the checkboxes + // can change state + if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { + bookSettingsScreen.populateConfigurables(); + } } private static MutableComponent getTitle(Config config) { diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java index 047f6b0fd1..d39a33d81d 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/CategoryButton.java @@ -1,5 +1,5 @@ /* - * Copyright © Wynntils 2022-2023. + * Copyright © Wynntils 2022-2024. * This file is released under LGPLv3. See LICENSE for full license details. */ package com.wynntils.screens.settings.widgets; @@ -36,7 +36,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float this.getY(), 0, CommonColors.CYAN, - HorizontalAlignment.CENTER, + HorizontalAlignment.LEFT, TextShadow.NORMAL); } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java deleted file mode 100644 index 3fa01f4135..0000000000 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/CloseButton.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright © Wynntils 2023-2024. - * This file is released under LGPLv3. See LICENSE for full license details. - */ -package com.wynntils.screens.settings.widgets; - -import com.wynntils.screens.settings.WynntilsBookSettingsScreen; -import com.wynntils.utils.mc.McUtils; -import com.wynntils.utils.render.Texture; -import java.util.List; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; - -public class CloseButton extends GeneralSettingsButton { - private final WynntilsBookSettingsScreen screen; - - public CloseButton(WynntilsBookSettingsScreen screen) { - super( - 15, - Texture.CONFIG_BOOK_BACKGROUND.height() - 30, - 35, - 14, - Component.translatable("screens.wynntils.settingsScreen.close"), - List.of(Component.translatable("screens.wynntils.settingsScreen.close.description") - .withStyle(ChatFormatting.DARK_RED)), - 0, - McUtils.mc().screen.height); - this.screen = screen; - } - - @Override - public void onPress() { - screen.onClose(); - } -} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java index c212011df4..3b2979dd10 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigTile.java @@ -26,7 +26,6 @@ public class ConfigTile extends WynntilsButton { private final TextboxScreen screen; - private final Config config; private final int maskTopY; private final int maskBottomY; private final float translationX; @@ -40,7 +39,7 @@ public ConfigTile(int x, int y, int width, int height, TextboxScreen screen, Con this.screen = screen; if (screen instanceof WynntilsBookSettingsScreen settingsScreen) { - maskTopY = settingsScreen.getConfigMaskTopY(); + maskTopY = settingsScreen.getMaskTopY(); maskBottomY = settingsScreen.getConfigMaskBottomY(); displayName = settingsScreen.configOptionContains(config) ? StyledText.fromString(ChatFormatting.UNDERLINE + config.getDisplayName()) @@ -63,7 +62,6 @@ public ConfigTile(int x, int y, int width, int height, TextboxScreen screen, Con translationY = 0; } - this.config = config; this.configOptionElement = getWidgetFromConfig(config); this.resetButton = new ResetButton( config, @@ -160,10 +158,22 @@ private int getRenderX() { private > AbstractWidget getWidgetFromConfig(Config configOption) { if (configOption.getType().equals(Boolean.class)) { return new BooleanSettingsButton( - getRenderX(), getRenderY(), (Config) configOption, maskTopY, maskBottomY); + getRenderX(), + getRenderY(), + (Config) configOption, + maskTopY, + maskBottomY, + translationX, + translationY); } else if (configOption.isEnum()) { return new EnumSettingsButton<>( - getRenderX(), getRenderY(), (Config) configOption, maskTopY, maskBottomY); + getRenderX(), + getRenderY(), + (Config) configOption, + maskTopY, + maskBottomY, + translationX, + translationY); } else if (configOption.getType().equals(CustomColor.class)) { return new CustomColorSettingsButton( getRenderX(), getRenderY(), (Config) configOption, screen, maskTopY, maskBottomY); diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java index 94626dd632..13c0f00d5d 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java @@ -6,12 +6,15 @@ import com.google.common.collect.Lists; import com.mojang.blaze3d.vertex.PoseStack; +import com.wynntils.core.components.Managers; import com.wynntils.core.consumers.features.Configurable; import com.wynntils.core.consumers.features.Feature; import com.wynntils.core.consumers.overlays.CustomNameProperty; import com.wynntils.core.consumers.overlays.Overlay; +import com.wynntils.core.persisted.config.Config; import com.wynntils.core.text.StyledText; import com.wynntils.screens.base.widgets.WynntilsButton; +import com.wynntils.screens.base.widgets.WynntilsCheckbox; import com.wynntils.screens.settings.WynntilsBookSettingsScreen; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; @@ -22,17 +25,28 @@ import com.wynntils.utils.render.type.TextShadow; import com.wynntils.utils.render.type.VerticalAlignment; import java.util.List; +import java.util.Optional; +import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; public class ConfigurableButton extends WynntilsButton { private final Configurable configurable; - private final WynntilsBookSettingsScreen settingsScreen; - + private final WynntilsCheckbox enabledCheckbox; + private final int maskTopY; + private final int maskBottomY; + private final int matchingConfigs; private final List descriptionTooltip; + private final WynntilsBookSettingsScreen settingsScreen; public ConfigurableButton( - int x, int y, int width, int height, Configurable configurable, WynntilsBookSettingsScreen screen) { + int x, + int y, + int width, + int height, + Configurable configurable, + WynntilsBookSettingsScreen screen, + int matchingConfigs) { super(x, y, width, height, Component.literal(configurable.getTranslatedName())); this.configurable = configurable; this.settingsScreen = screen; @@ -43,16 +57,34 @@ public ConfigurableButton( } else { descriptionTooltip = List.of(); } + + boolean enabled = false; + if (configurable instanceof Overlay selectedOverlay) { + enabled = Managers.Overlay.isEnabled(selectedOverlay); + } else if (configurable instanceof Feature selectedFeature) { + enabled = selectedFeature.isEnabled(); + } + + this.enabledCheckbox = new WynntilsCheckbox(x + width - 10, y, 10, 10, Component.literal(""), enabled, 0); + + this.maskTopY = settingsScreen.getMaskTopY(); + this.maskBottomY = settingsScreen.getConfigurableMaskBottomY(); + this.matchingConfigs = matchingConfigs; } @Override public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { PoseStack poseStack = guiGraphics.pose(); + // Don't want to display tooltip when the tile is outside the mask from the screen + if (isHovered && (mouseY <= maskTopY || mouseY >= maskBottomY)) { + isHovered = false; + } + CustomColor color = isHovered ? CommonColors.YELLOW : CommonColors.WHITE; if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { - if (bookSettingsScreen.getSelected() == configurable) { + if (bookSettingsScreen.getSelectedConfigurable() == configurable) { color = CommonColors.GRAY; } } @@ -67,13 +99,17 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float } } + if (matchingConfigs > 0) { + textToRender += ChatFormatting.GRAY + " [" + matchingConfigs + "]"; + } + FontRenderer.getInstance() .renderScrollingText( poseStack, StyledText.fromString(textToRender), (isOverlay ? this.getX() + 12 : this.getX()), this.getY(), - (isOverlay ? this.width - 12 : this.width), + (isOverlay ? this.width - 12 : this.width) - 11, settingsScreen.getTranslationX(), settingsScreen.getTranslationY(), color, @@ -82,6 +118,8 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float TextShadow.NORMAL, 1f); + enabledCheckbox.render(guiGraphics, mouseX, mouseY, partialTick); + if (isHovered && configurable instanceof Feature) { McUtils.mc() .screen @@ -89,10 +127,49 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float } } + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + // Prevent interaction when the tile is outside of the mask from the screen + if ((mouseY <= maskTopY || mouseY >= maskBottomY)) return false; + + // Toggle the enabled state of the configurable when toggling the checkbox + if (enabledCheckbox.isMouseOver(mouseX, mouseY)) { + if (configurable instanceof Feature feature) { + feature.setUserEnabled(!feature.isEnabled()); + } else if (configurable instanceof Overlay) { + Optional> configOpt = configurable.getConfigOptionFromString("userEnabled"); + + if (configOpt.isPresent()) { + Config config = (Config) configOpt.get(); + config.setValue(!config.get()); + } else { + return false; + } + } + + // Repopulate screen to update new enabled/disabled states + if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { + bookSettingsScreen.populateConfigurables(); + bookSettingsScreen.populateConfigs(); + } + + return enabledCheckbox.mouseClicked(mouseX, mouseY, button); + } + + return super.mouseClicked(mouseX, mouseY, button); + } + @Override public void onPress() { if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { - bookSettingsScreen.setSelected(configurable); + bookSettingsScreen.setSelectedConfigurable(configurable); } } + + @Override + public void setY(int y) { + super.setY(y); + + enabledCheckbox.setY(y); + } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java index 38b780aebf..7e9ff98cfa 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/CustomColorSettingsButton.java @@ -14,7 +14,7 @@ public class CustomColorSettingsButton extends TextInputBoxSettingsWidget { public CustomColorSettingsButton( int x, int y, Config config, TextboxScreen textboxScreen, int maskTopY, int maskBottomY) { - super(x, y, config, textboxScreen, 80, maskTopY, maskBottomY); + super(x, y, config, textboxScreen, maskTopY, maskBottomY); } @Override @@ -24,6 +24,6 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float PoseStack poseStack = guiGraphics.pose(); CustomColor value = config.get(); - RenderUtils.drawRect(poseStack, value, width + 5, 6, 0, height, height); + RenderUtils.drawRect(poseStack, value, getX() + getWidth() + 4, getY(), 0, height, height); } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java index 39b3a5f19e..ad8fbec5c9 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/EnumSettingsButton.java @@ -5,14 +5,10 @@ package com.wynntils.screens.settings.widgets; import com.wynntils.core.persisted.config.Config; -import com.wynntils.utils.EnumUtils; import com.wynntils.utils.mc.ComponentUtils; import com.wynntils.utils.mc.McUtils; -import com.wynntils.utils.render.FontRenderer; -import java.lang.reflect.Type; import java.util.EnumSet; import java.util.List; -import net.minecraft.client.gui.Font; import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; @@ -20,16 +16,19 @@ public class EnumSettingsButton> extends GeneralSettingsButton private final Config config; private final List enumConstants; - public EnumSettingsButton(int x, int y, Config config, int maskTopY, int maskBottomY) { + public EnumSettingsButton( + int x, int y, Config config, int maskTopY, int maskBottomY, float translationX, float translationY) { super( x, y, - getWidth(config.getType()), - FontRenderer.getInstance().getFont().lineHeight + 8, + 90, + 20, Component.literal(config.getValueString()), ComponentUtils.wrapTooltips(List.of(Component.literal(config.getDescription())), 150), maskTopY, - maskBottomY); + maskBottomY, + translationX, + translationY); this.config = config; enumConstants = EnumSet.allOf((Class) config.getType()).stream().toList(); } @@ -63,13 +62,4 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { public void onPress() { // We use instead AbstractWidget#mouseClicked, because we also want to have an action on the right mouse button } - - private static > int getWidth(Type type) { - Font font = FontRenderer.getInstance().getFont(); - int maxWidth = EnumSet.allOf((Class) type).stream() - .mapToInt(enumValue -> font.width(EnumUtils.toNiceString(enumValue))) - .max() - .orElse(0); - return maxWidth + 8; - } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java index 17df60fef6..9c761f89ca 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsButton.java @@ -25,6 +25,8 @@ public abstract class GeneralSettingsButton extends WynntilsButton { public static final CustomColor HOVER_BACKGROUND_COLOR = new CustomColor(158, 52, 16); private final int maskTopY; private final int maskBottomY; + private final float translationX; + private final float translationY; private final List tooltip; protected GeneralSettingsButton( @@ -35,11 +37,15 @@ protected GeneralSettingsButton( Component title, List tooltip, int maskTopY, - int maskBottomY) { + int maskBottomY, + float translationX, + float translationY) { super(x, y, width, height, title); this.tooltip = tooltip; this.maskTopY = maskTopY; this.maskBottomY = maskBottomY; + this.translationX = translationX; + this.translationY = translationY; } @Override @@ -59,14 +65,16 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float 3); FontRenderer.getInstance() - .renderAlignedTextInBox( + .renderScrollingAlignedTextInBox( poseStack, StyledText.fromComponent(getMessage()), this.getX(), this.getX() + this.width, this.getY(), this.getY() + this.height, - 0, + this.width - 2, + translationX, + translationY, getTextColor(), HorizontalAlignment.CENTER, VerticalAlignment.MIDDLE, diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java new file mode 100644 index 0000000000..6ff36a27ae --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/GeneralSettingsTabButton.java @@ -0,0 +1,105 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.wynntils.screens.base.widgets.BasicTexturedButton; +import com.wynntils.utils.render.RenderUtils; +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; + +public abstract class GeneralSettingsTabButton extends BasicTexturedButton { + private static final int MAX_OFFSET = -8; + private static final int MIN_OFFSET = 0; + + protected boolean selectedTab = false; + protected Texture tagTexture; + + private final OffsetDirection offsetDirection; + private final Texture iconTexture; + + private int hoverOffset = 0; + + GeneralSettingsTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + Texture tagTexture, + Texture iconTexture, + OffsetDirection offsetDirection) { + super(x, y, width, height, tagTexture, onClick, tooltip); + this.tagTexture = tagTexture; + this.iconTexture = iconTexture; + this.offsetDirection = offsetDirection; + } + + @Override + public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + PoseStack poseStack = guiGraphics.pose(); + + // Don't count as hovered if mouse is hovering the book as the tags render + // slightly underneath the book + if (isHovered + && ((offsetDirection == OffsetDirection.UP && mouseY >= 0) + || (offsetDirection == OffsetDirection.RIGHT + && mouseX <= Texture.CONFIG_BOOK_BACKGROUND.width()) + || (offsetDirection == OffsetDirection.DOWN + && mouseY <= Texture.CONFIG_BOOK_BACKGROUND.height()) + || (offsetDirection == OffsetDirection.LEFT && mouseX >= 0))) { + isHovered = false; + } + + // Determine the offset of the tag. When selected the max offset should be used, otherwise when hovered + // increase until limit reached. + if (selectedTab) { + this.hoverOffset = (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) + ? MAX_OFFSET + : -MAX_OFFSET; + } else if (this.isHovered) { + hoverOffset += (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) ? -1 : 1; + hoverOffset = (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) + ? Math.max(hoverOffset, MAX_OFFSET) + : Math.min(hoverOffset, -MAX_OFFSET); + } else { + hoverOffset += (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) ? 1 : -1; + hoverOffset = (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.LEFT) + ? Math.min(hoverOffset, MIN_OFFSET) + : Math.max(hoverOffset, MIN_OFFSET); + } + + // Move the tag render position + poseStack.pushPose(); + poseStack.translate( + (offsetDirection == OffsetDirection.RIGHT || offsetDirection == OffsetDirection.LEFT) ? hoverOffset : 0, + (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.DOWN) ? hoverOffset : 0, + 0); + + RenderUtils.drawTexturedRect(poseStack, tagTexture, this.getX(), this.getY()); + + // Render icon on tag + if (offsetDirection == OffsetDirection.UP || offsetDirection == OffsetDirection.DOWN) { + RenderUtils.drawTexturedRect( + poseStack, iconTexture, getX() + (getWidth() - iconTexture.width()) / 2f, getY() + 14); + } else { + RenderUtils.drawTexturedRect( + poseStack, iconTexture, getX() + 14, getY() + (getHeight() - iconTexture.height()) / 2f); + } + + poseStack.popPose(); + } + + protected enum OffsetDirection { + UP, + RIGHT, + DOWN, + LEFT + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java index 87931bc2e0..229b552ecc 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ResetButton.java @@ -5,8 +5,10 @@ package com.wynntils.screens.settings.widgets; import com.wynntils.core.persisted.config.Config; +import com.wynntils.screens.settings.WynntilsBookSettingsScreen; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.colors.CustomColor; +import com.wynntils.utils.mc.McUtils; import com.wynntils.utils.render.FontRenderer; import java.util.List; import net.minecraft.client.sounds.SoundManager; @@ -25,7 +27,9 @@ public class ResetButton extends GeneralSettingsButton { Component.translatable("screens.wynntils.settingsScreen.reset.name"), List.of(Component.translatable("screens.wynntils.settingsScreen.reset.description")), maskTopY, - maskBottomY); + maskBottomY, + 0, + 0); this.config = config; this.onClick = onClick; } @@ -51,5 +55,10 @@ public void onPress() { if (!config.valueChanged()) return; config.reset(); onClick.run(); + + // Reload configurables to update checkbox + if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { + bookSettingsScreen.populateConfigurables(); + } } } diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java new file mode 100644 index 0000000000..b61c5b950c --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsCategoryTabButton.java @@ -0,0 +1,61 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.wynntils.core.persisted.config.Category; +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.network.chat.Component; + +public class SettingsCategoryTabButton extends GeneralSettingsTabButton { + private Category category; + + public SettingsCategoryTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + Category category, + boolean selectedCategory) { + super(x, y, width, height, onClick, tooltip, Texture.TAG_RED, category.getCategoryIcon(), OffsetDirection.UP); + this.category = category; + this.selectedTab = selectedCategory; + + setSelectedCategory(selectedCategory); + } + + public SettingsCategoryTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + boolean selectedCategory) { + super(x, y, width, height, onClick, tooltip, Texture.TAG_RED, Texture.ALL_CONFIG_ICON, OffsetDirection.UP); + this.category = null; + this.selectedTab = selectedCategory; + + setSelectedCategory(selectedCategory); + } + + public void setSelectedCategory(boolean selectedCategory) { + this.selectedTab = selectedCategory; + + // When selected use a different texture to show the category has been selected + if (this.selectedTab) { + tagTexture = Texture.TAG_RED_SELECTED; + } else { + tagTexture = Texture.TAG_RED; + } + } + + public Category getCategory() { + return category; + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java new file mode 100644 index 0000000000..a89962c7e9 --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsPageTabButton.java @@ -0,0 +1,26 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.network.chat.Component; + +public class SettingsPageTabButton extends GeneralSettingsTabButton { + public SettingsPageTabButton( + int x, int y, int width, int height, Consumer onClick, List tooltip, boolean nextPage) { + super( + x, + y, + width, + height, + onClick, + tooltip, + Texture.TAG_RED, + nextPage ? Texture.NEXT : Texture.PREVIOUS, + OffsetDirection.UP); + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java new file mode 100644 index 0000000000..1339421329 --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSideTabButton.java @@ -0,0 +1,24 @@ +/* + * Copyright © Wynntils 2023-2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.wynntils.utils.render.Texture; +import java.util.List; +import java.util.function.Consumer; +import net.minecraft.network.chat.Component; + +public class SettingsSideTabButton extends GeneralSettingsTabButton { + public SettingsSideTabButton( + int x, + int y, + int width, + int height, + Consumer onClick, + List tooltip, + Texture tagTexture, + Texture iconTexture) { + super(x, y, width, height, onClick, tooltip, tagTexture, iconTexture, OffsetDirection.LEFT); + } +} diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java b/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java index d30a69d288..618322fbf2 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/TextInputBoxSettingsWidget.java @@ -9,7 +9,6 @@ import com.wynntils.screens.base.widgets.TextInputBoxWidget; import com.wynntils.utils.colors.CommonColors; import com.wynntils.utils.mc.ComponentUtils; -import com.wynntils.utils.render.FontRenderer; import java.util.List; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; @@ -20,8 +19,8 @@ public class TextInputBoxSettingsWidget extends TextInputBoxWidget { private final int maskBottomY; protected TextInputBoxSettingsWidget( - int x, int y, Config config, TextboxScreen textboxScreen, int width, int maskTopY, int maskBottomY) { - super(x, y, width, FontRenderer.getInstance().getFont().lineHeight + 8, null, textboxScreen); + int x, int y, Config config, TextboxScreen textboxScreen, int maskTopY, int maskBottomY) { + super(x, y, 90, 20, null, textboxScreen); this.config = config; this.maskTopY = maskTopY; this.maskBottomY = maskBottomY; @@ -29,11 +28,6 @@ protected TextInputBoxSettingsWidget( tooltip = ComponentUtils.wrapTooltips(List.of(Component.literal(config.getDescription())), 150); } - public TextInputBoxSettingsWidget( - int x, int y, Config config, TextboxScreen textboxScreen, int maskTopY, int maskBottomY) { - this(x, y, config, textboxScreen, 100, maskTopY, maskBottomY); - } - @Override public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { // Don't want to display tooltip when the tile is outside the mask from the screen diff --git a/common/src/main/java/com/wynntils/utils/render/Texture.java b/common/src/main/java/com/wynntils/utils/render/Texture.java index 928162ea17..2d1c43903e 100644 --- a/common/src/main/java/com/wynntils/utils/render/Texture.java +++ b/common/src/main/java/com/wynntils/utils/render/Texture.java @@ -26,6 +26,10 @@ public enum Texture { CONTENT_BOOK_BACKGROUND("content_book/content_book.png", 339, 220), CONTENT_BOOK_SEARCH("content_book/content_book_search.png", 133, 23), CONTENT_BOOK_TITLE("content_book/content_book_title.png", 168, 33), + TAG_BLUE("content_book/tag_blue.png", 44, 22), + TAG_RED("content_book/tag_red.png", 22, 44), + TAG_RED_SELECTED("content_book/tag_red_selected.png", 22, 44), + TAG_SEARCH("content_book/tag_search.png", 140, 34), // endregion // region Icons @@ -38,6 +42,25 @@ public enum Texture { ACTIVITY_STARTED("icons/activities/activity_started_icon.png", 7, 7), CAVE_AVALIABLE_ICON("icons/activities/cave_avaliable_icon.png", 7, 7), + // Config Categories + ALL_CONFIG_ICON("icons/config_categories/all_config_icon.png", 16, 16), + CHAT_CONFIG_ICON("icons/config_categories/chat_config_icon.png", 16, 16), + COMBAT_CONFIG_ICON("icons/config_categories/combat_config_icon.png", 16, 16), + COMMANDS_CONFIG_ICON("icons/config_categories/commands_config_icon.png", 16, 16), + DEBUG_CONFIG_ICON("icons/config_categories/debug_config_icon.png", 16, 16), + EMBELLISHMENTS_CONFIG_ICON("icons/config_categories/embellishments_config_icon.png", 16, 16), + INVENTORY_CONFIG_ICON("icons/config_categories/inventory_config_icon.png", 16, 16), + MAP_CONFIG_ICON("icons/config_categories/map_config_icon.png", 16, 16), + OVERLAYS_CONFIG_ICON("icons/config_categories/overlays_config_icon.png", 16, 16), + PLAYERS_CONFIG_ICON("icons/config_categories/players_config_icon.png", 16, 16), + REDIRECTS_CONFIG_ICON("icons/config_categories/redirects_config_icon.png", 16, 16), + TOOLTIPS_CONFIG_ICON("icons/config_categories/tooltips_config_icon.png", 16, 16), + TRADE_MARKET_CONFIG_ICON("icons/config_categories/trade_market_config_icon.png", 16, 16), + UI_CONFIG_ICON("icons/config_categories/ui_config_icon.png", 16, 16), + UNCATEGORIZED_CONFIG_ICON("icons/config_categories/uncategorized_config_icon.png", 16, 16), + UTILITIES_CONFIG_ICON("icons/config_categories/utilities_config_icon.png", 16, 16), + WYNNTILS_CONFIG_ICON("icons/config_categories/wynntils_config_icon.png", 16, 16), + // Content Book DIALOGUE_ICON("icons/content_book/dialogue_icon.png", 14, 11), DISCOVERIES_ICON("icons/content_book/discoveries_icon.png", 16, 32), @@ -76,15 +99,20 @@ public enum Texture { CHECKMARK_GRAY("icons/generic/check_gray.png", 16, 16), CHECKMARK_GREEN("icons/generic/check_green.png", 16, 16), CHECKMARK_YELLOW("icons/generic/check_yellow.png", 16, 16), + CLOSE("icons/generic/close.png", 16, 16), DEFENSE_FILTER_ICON("icons/generic/defense_filter_icon.png", 16, 16), EDIT_ICON("icons/generic/edit_icon.png", 6, 16), FAVORITE_ICON("icons/generic/favorite_icon.png", 18, 18), HELP_ICON("icons/generic/help_icon.png", 10, 16), INFO("icons/generic/info.png", 25, 25), ITEM_LOCK("icons/generic/item_lock_icon.png", 16, 16), + NEXT("icons/generic/next.png", 16, 16), OVERLAY_EXTRA_ICON("icons/generic/overlay_extra_icon.png", 16, 16), + PREVIOUS("icons/generic/previous.png", 16, 16), QUESTION_MARK("icons/generic/question_mark.png", 4, 7), QUESTS_SCROLL_ICON("icons/generic/quests_scroll_icon.png", 16, 16), + RESET("icons/generic/reset.png", 16, 16), + SAVE("icons/generic/save.png", 16, 16), SHARE_ICON("icons/generic/share_icon.png", 16, 14), SIGN_ICON("icons/generic/sign_icon.png", 17, 18), SMALL_ADD_ICON("icons/generic/small_add_icon.png", 16, 16), @@ -226,6 +254,8 @@ public enum Texture { BACKGROUND_SPLASH("ui_components/background_splash.png", 1920, 1027), COSMETIC_VIEWER_BACKGROUND("ui_components/cosmetics_viewer_background.png", 72, 92), CONTAINER_SIDEBAR("ui_components/container_sidebar.png", 25, 136), + CROWD_SOURCE_BACKGROUND("ui_components/crowd_source_background.png", 180, 260), + CROWD_SOURCE_STICKER("ui_components/crowd_source_sticker.png", 36, 36), EMERALD_COUNT_BACKGROUND("ui_components/emerald_count_background.png", 24, 24), GEAR_ICONS("ui_components/gear_icons.png", 64, 128), GEAR_VIEWER_BACKGROUND("ui_components/gear_viewer_background.png", 103, 92), diff --git a/common/src/main/resources/assets/wynntils/lang/en_us.json b/common/src/main/resources/assets/wynntils/lang/en_us.json index 96117d5b6d..0911c7f8df 100644 --- a/common/src/main/resources/assets/wynntils/lang/en_us.json +++ b/common/src/main/resources/assets/wynntils/lang/en_us.json @@ -2315,15 +2315,31 @@ "screens.wynntils.savedItems.name": "Item Record", "screens.wynntils.savedItems.unableToShare": "Unable to share item", "screens.wynntils.searchWidget.defaultSearchText": "Search...", + "screens.wynntils.settingsScreen.all": "All", "screens.wynntils.settingsScreen.apply": "Apply", "screens.wynntils.settingsScreen.apply.description": "Save changes", "screens.wynntils.settingsScreen.booleanConfig.disabled": "Disabled", "screens.wynntils.settingsScreen.booleanConfig.enabled": "Enabled", "screens.wynntils.settingsScreen.close": "Close", "screens.wynntils.settingsScreen.close.description": "Close without saving changes", + "screens.wynntils.settingsScreen.export": "Export Settings", + "screens.wynntils.settingsScreen.export.all": "- Left click to export settings from your clipboard for all settings.", + "screens.wynntils.settingsScreen.export.selected": "- Right click to export settings from your clipboard for the currently selected setting.", + "screens.wynntils.settingsScreen.exported": "Sucessfully exported settings for %s", + "screens.wynntils.settingsScreen.exportedAll": "Sucessfully exported all settings", + "screens.wynntils.settingsScreen.import": "Import Settings", + "screens.wynntils.settingsScreen.import.all": "- Left click to import settings from your clipboard for all settings.", + "screens.wynntils.settingsScreen.import.failed": "Failed to import settings", + "screens.wynntils.settingsScreen.import.selected": "- Right click to import settings from your clipboard for the currently selected setting.", + "screens.wynntils.settingsScreen.imported": "Sucessfully imported settings for %s", + "screens.wynntils.settingsScreen.importedAll": "Sucessfully imported all settings", "screens.wynntils.settingsScreen.name": "Wynntils Settings", + "screens.wynntils.settingsScreen.needToSelect": "You need to select a setting to perform this action!", + "screens.wynntils.settingsScreen.next": "Next", + "screens.wynntils.settingsScreen.previous": "Previous", "screens.wynntils.settingsScreen.reset.description": "Reset config to default value.", "screens.wynntils.settingsScreen.reset.name": "Reset", + "screens.wynntils.settingsScreen.unselectedConfig": "Here you can edit all of the various features available in Wynntils. Click any of the features in the left page of the book and the options available for that feature will appear here!", "screens.wynntils.skillPointLoadouts.assigned": "Assigned (%d)", "screens.wynntils.skillPointLoadouts.confirm": "Confirm", "screens.wynntils.skillPointLoadouts.convert": "Convert Types", @@ -2383,8 +2399,13 @@ "screens.wynntils.wynntilsContentBook.sort.distance.name": "Sort by Distance", "screens.wynntils.wynntilsContentBook.sort.level.description": "Quests are sorted by level, lowest first", "screens.wynntils.wynntilsContentBook.sort.level.name": "Sort by Level", + "screens.wynntils.wynntilsCrowdSourcing.collecting": "Collecting", + "screens.wynntils.wynntilsCrowdSourcing.copiedToClipboard": "Copied %d data points of %s to clipboard", "screens.wynntils.wynntilsCrowdSourcing.name": "Crowd Sourcing", + "screens.wynntils.wynntilsCrowdSourcing.noDataTypes": "There are no data types currently being crowd sourced matching your search query.", + "screens.wynntils.wynntilsCrowdSourcing.notCollecting": "Not Collecting", "screens.wynntils.wynntilsCrowdSourcing.screenDescription": "Here you can see all the data types the mod can collect. If you opt-in to help us collect these data, we can improve the mod and the Wynncraft experience for everyone. You can opt-out at any time.", + "screens.wynntils.wynntilsCrowdSourcing.unconfirmed": "Unconfirmed", "screens.wynntils.wynntilsDialogueHistory.description": "Here you can read your last few conversations with NPCs on your current class.", "screens.wynntils.wynntilsDialogueHistory.name": "Dialogue History", "screens.wynntils.wynntilsDialogueHistory.questsPageButton.description": "Click here to open the quest book", diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/config_book_scroll_area.png b/common/src/main/resources/assets/wynntils/textures/content_book/config_book_scroll_area.png deleted file mode 100644 index e196c35f56255fb0f2bdab56ba5528a4ea35eed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1086 zcmeAS@N?(olHy`uVBq!ia0vp^D}Z=C2OE&g^qb1Vz`)p?>FgZf>FlgfP?VpRnUl)E zpfRy_qOHea2brVs!Apa*_}(f!ny}C+Qb4ruik8Sirxl`6r3O2{aL+PP(bVf}%076o z|LCgb?#=7?)-@^oV0`rA$&wdJs{iygw{(1butWa+JKJ~n7@ansGFhE2bD`w+nI)5w z^!97D#R;}GXt*3nO_MC1G^OqRk6rE!>&rRkJ*|It{^EKu9X1x1N0DhW%s#Sx{IV>! z;GTNl#!YL4<_q`FEOC6~zD`?if1%z^oeyVb%shKW_;|O7N}db8A1$_u^?|2+20v0xEPLbSILm1x$Da8Y&7U^D&=rXLT$TO) z@fXGuLE$f@A3P9{&<*^y>-_HDyQ+VG_u0K)J}swc(L*E6ZeXmiC3(BMF#HF>1$&oI z28wVNctjR6Fz_7!VaBX$ot!{H_7YEDSN3OIOu|Z5lh-k<4oV2=o^Ircwa`%^(vF(b=D!<9MWsTD8^UJDbD~kWmxFvZbZDUPk z;e9)swYPI_6<%}M))hRX#(l+V5BA$y?}F`Wu4UZF`NLkj**5xX*(+n_t-icgb@lf? z=3Gi<3%Y%!vHGFDum%%rqf&r?28T#vlY=0TV(D^lTmYoFm|Pbq1OO?BJX0wvR1Pc% zk`o}HmykT%Y=U;P5^x(#9;ghf+tKAgUPSgAPWh+u(j_*tzgXly^7`p@_I3JB8>=%J zH&Qn0SlU|Nv#hY)=lz!FjnRDH%@Nb?*x9IhZr4B6`Oz z@11e^QCZeF TNih$Yv=}^H{an^LB{Ts5bVjaZ diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3df19ac5677d14b96f37ab6b92aa574e260305 GIT binary patch literal 421 zcmeAS@N?(olHy`uVBq!ia0vp^IzTMO!3-pOcK7`NQjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W>Rgz$e6&f#E+k1eC@qP7}dPvv$n_TBuVJ84Oq z01xwp2cgZ2HtkS8wQ9k?|NlD|yw99>zQih%G5^sNpY-BG(_c(roz~dHT(EVT>51Mo z)n^Qh5{`8;7VkDrc*oCn=JCmfNk#zKI)b s^|Y^AUFpqv{~_hIT*gtgUC&?tWpw!<;K5*K6by2Xr>mdKI;Vst0F-5*4FCWD literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png new file mode 100644 index 0000000000000000000000000000000000000000..d23614133cac6dcbc0224b91f3a5addc8e9a89bb GIT binary patch literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^VnD3J!3-qBx_2A`QjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W>Rsz$e7@KLY~<0R`Y}dNK~Qh06f#)-DP13+{Rw#E||u@Ad!RzA?X^ zeYbKq`t(81QOo#=oW@=87dMq3T>N-)U$kfa&jMy1(Y~8NZIzxbjv*Cu-k!KE*61M7 zaB+T*-SWWR%`F=3-|HP(ugyAU)6o6xso2Y}%*P#gRZ~pz-lv@MVX)n9ekt^7Z`WGi z45`f-Wk2ubCx^|Cm41`9d2PA)rMz#MTiNfZdH1W=%`R?RpBr2Lcm3SoVJDAX57(@T g^(wfWcTfJj_+xST!jey(pb%&9boFyt=akR{08YA?l>h($ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..2ccec693270cc50204f621a7d8c9980969d7d942 GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^VnD3J!3-qBx_2A`QjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W<5(fKQ0)|LN2JfB5jfsR=0Xzog{|2J>`FCg&$%9Z~> zGq-F3k;jhx4+;6dZQK9*_x~#>{6BHx|B4m=4Gciq0|NdhB>dmK`~R6U|EsJ2uU-4U zrw3%q;>AFX`}H_GfG#sF3Gxfx`>&Rvcio@=Rn`Ch{)^9w{2Lni*WBUH|Np;qOn?6W zDgNXCSHrLW|9}1na{jybEq&|%t!FlRyR#fFSZ%<^3H5u@@J`B5}@yI5? zy@xAm&c(m$&rXSAc_XyL{!@|Nv5K>rq0f1*v1EvDee2ZD*l_)9_Ic$Xo;~v~GfJ@8 znOJ#!J#8>AWA3>F8}u`tb1ywDy4NWqPWwK~lIW$`@y5&caerfEY7%Z`?h`|IB9chLBHH a^$bR5f7z`K~9B>$d%W&evU9>K%0Btla3GxeOnECnthiCa0KK(}n`!1g0zj|Fn zTKtZ@UA1kby|+L*}F2vnM~h zp&;ryp?k#x*4FR!W*NCz9;K(=9jKq?_iOE%B`384mrJvLJ$Fc5z3ZH#{y*Ja4%~ZQ z2qm zf`n?`Q>nlVo^ENW#5t;SB(*K2CSS=`JG_48mE1)$RNa#KW_xTg4cok-FQM$HDza=yVWrB?8=;v9mjR%uXwey{g_VtioB~oGz+87{F=JwUV&6qznxjhmFMC- io8P|E$k@!5_$|}a@f;UJ*9~A0GkCiCxvXjY`0gtzqa~6@!FNP(ENXW?p{Zi hEcvz9_sfbI6%6OTu(L-e?hgQY!_(EzWt~$(698BJSiArL literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6dc0343cf0686edbd92e45760db6da0c7abd6d GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFX8=RZ&@enAN z;OXKRQZXkvAt50oje*fEby|SIWK|KChdc`;qAjB>BYK?o?3tu3apH!Ql+=-v#ac5Q zO-(|c=DetuW4l_wRu{fNbP0l+XkKTYg0n literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..64208bb1c627023c0261384d0b33c957fbc1b930 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVag8LcH|4(puFR=gqe1!mmg7x+H_FN4B zO2&J-IEGZr2|XXk*Py_|e4+PIThoER{@Oxz*Xkxt59sR9a1}B-%o@X@WuShc>Cgjn zIi|G^$`{14%u*tHKS)_kRcqP$+G2u@6F+P9uA5btZ+phhpZzP|+Hhud>h{SW8CCO{ Ue!h5XtPXO!r>mdKI;Vst0C0Rs_5c6? literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..120fd015d098ed45eada17b6ce32063ce3117e06 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFa z2NdMESV9xFI<8Z=x_040#dQl8PUM;G>)4Z!&Bm4{pv;gW(6N#6L=0T)M;%y s*qD8v_Dngs_isTKBlB^$2}dvSGVBzWuXZ-?j0O3|)78&qol`;+0HDrJegFUf literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..74d5ea441e39258b86e57cdbd158107284a67433 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF+kmqoPQhZAPAJp z@N{tushE?TAYfFKz!R37knnzvB5je)m)^X+H}sz`a8MAK|Kj2SIiOUS zr;B4q#hm1X1OX#6vqXl*3tP4*7#yC{xKP5SI-;yZ#oWlCK(e`!p;@>k@sI#dqJ*J@ zGvkDZyly<1nE@rwctj+n;~A6{9m~w+FaRmdz4ng_V=9;I|Ku+~^^>bP0 Hl+XkKZ2dlr literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..17badfe1340dca17fa446e9262fadc575c85c72e GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFEaktF()}8AtWpzA%QbFVNJ&ykCctC5>CA6c=N*J-HU`53rrW!Uif&!;j?{D-f{Cp h%SuShke_A1z#t@OacZN$_nRR1c)I$ztaD0e0sv!CJ_vlmz(&Gpzr=U*Y|E0cAe5OrThlr;B4q#hlVp zhI|bQBFq;aDOjs3s3tz+kjQ_)*r0>D#>Hf7vgvFiNzJ2%E%_(#+42f7eay zid~Gba(FY_7k()dZYi~@R_$**Iv>UTk9c|?%$xg)`?)1=|BEL-EI>~3boFyt=akR{ E0K(Qk*8l(j literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..76f7ee61af10347b196d2e77ed0f07e07b9601f1 GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6toHO32_C|WP=O(Y6d{fA|*k7!3^{7D+ugg|G&SW{=GxMc>|pUIjhdI zzte#7Q#@T9Ln`Lj_D2dGR^V}Njbt&LV6yjrY+>GgHf&F}h$bN;#s%FK(}Se4->wl&l&>~9=6vsO`Qw}Sqi(TJNL}NpR_~nlWA4gr Zm$>6Xm=*?ZnGptZzo)C8%Q~loCICy2QO^JX literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd3dd0af545c1716d3d986375df147b57c8cad7 GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFlFzshFeMYskkK$lwyMy85QmbB?NBW(}D{Ypsi!+k-u)9CDK@yEt)2gWtl77R`%) z+@GHomu4in;Ih0QXH?%6!<6k0aehE=IY{VfNxE$fOI zFIBJGE^HX literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b3bcb883edebe0672e3f4845ec37f5adaa363b35 GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*Bmn?>7+WfB%2J!u^Ex0R{En_?l&a zk|CZhjv*Cu*7jZGYfunz+Bvi7?wWu9vyJa&eY@hEzUP1hbH)vkG@BzXo|TesTwmp0 z=M7iLR#4c(d}N~4qn_3@odw%N!*y=0*>-e))7+%L_eyIjs+jg@vTn@CoZSy{u&1k^ J%Q~loCIB?gNc;c* literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6029861fe8a80723371a6bbc8bda9cecd7bfd049 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFqA+A6g57@4ep9PfWDhcunPPqU7eZYB!{SF12-)~|Bikf)3IEGZr zNlpl1Vismo^m%p5(W&d>X}TOZCgZ?7c@vun8+CPa2gxK{)1|* T3a{HjL6&;D`njxgN@xNAVka=u literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8bc4143a6ac1356aabf5bc984227d421dfd946 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*Bm@&%eLluORS${eFXlg82bU?qt0I zN|t!KIEGZr3GMe3JD|YfoIKZ|aL4~l?W2A-Kb&-CJ}}9;hQly*h6byd>T7QMRaq+k zRxm939Cyt> literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..78eb080f2e2f49c4f2eef03cae60c90abd5e2a1e GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_I)32_C|WPt5u8AU*CLM1_d!3+ZR=l47GzyH5JVE%oDf&_zx!`6yf zK-p4H7srr_IlleTLPr!hSR9iirtY};JKpSv*BgG#TScc7vkE3C8|Xe-nX$w||M#?R zd9e;5HkWYI2MX1#pFgkMy`%P&o>9xW*gt_Wbxpi8!(LS^yfb-uf@4P9vIi`$@9%GW tz|_0hTR3n*<<{NR8}{rD_I-zU;uumfNA}!C-Ub5!=fHFp_mvrv5A~QYEZHw9(a0&$*t>D^sj5r0tZ#YtzDfA5 z@n}&-k%I5hRsqhu77qcAi3gN5Kg@Wt+5KXB!Q)WwydA9OcMd%l7UaoWc1a6@#a%pUXO@geCwXDOXAW literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/generic/next.png b/common/src/main/resources/assets/wynntils/textures/icons/generic/next.png new file mode 100644 index 0000000000000000000000000000000000000000..806b3e43695e5d8c38aa719915177896c0a62c47 GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFFVdQ&MBb@0Ohvp;X}SJiX>0Q&Z%LQT(O>YVTV}(f1?RfMl2~RW zOu6P+W7=>`J?+b)IE%Z@fyX{IYU`!1&i=*78NqxyfpP03kjFe-{an^LB{Ts5p`cg8 literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/generic/save.png b/common/src/main/resources/assets/wynntils/textures/icons/generic/save.png new file mode 100644 index 0000000000000000000000000000000000000000..496229626622dd7fd62bd34db13e570f5649b36a GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFFHHlZyP>gkTVOxe#N*U>XKA@;;lgAkrG}W8>fqpbDX9hX=G8_-OiD_+a_G?i z|NoC3J-T_)q;1=_?cBL@V}E~dboAP_Yr7*OuOB_SYSpT*A3rW#x^&aSCm(=e5m6H4 z7tElL(z9s$*@xfG=yc!xFHw52gd-!3)##`eWA&d(p>1N9WN+V+{&<}tTd zYv={6YT(+!>Kb+G|9|zS7ZImoC-GGpTRi_e$GTE2*y32riuLsg1uss0IC0{`)rAKe z|Ls$l9+R;+`SG^ZA2(jSv1*UnI^VKx|Ji%&1aD8f*gN~V+|I{4^L>wgTUuIeHM{20 zm$^3%6`#E`_pEueb#=blwof_5pIx6!e)c@c+B$m2`y{)6%`qLif3G*U=cQ%K+xF%D zy}jtM_5ZrpM{nG^{I&YimAg4_H=od+xv6fQYt+dzUyFO=Pu}@jT$fj-+I{W(Eqiuu zzeerIJ$16}pZSwOjPyS7IjLcn693j*IN@crCjPp(>+!?umz@4pxu|*llPjN-Hk;qt zSMhSW##G_?ah5Z3ubcD5?JB7rw1sop5tTdEK+`@=gow*X@uB z^F7MH_gTt2*4*ncyrRKhjp~bx%U8*XMc5z+x_t3ZprZL*^w{y#uP37XlwJ!{n^vsFJH`OeRj;T;)~Moyp|DK<#_)O)+(t8&^{%2F=;_jEBwQyz2GND;s z!-TQwKl|OjwWrq4?aDiv_Vl`!t9kO~Pua^BP2PKB-JWlgOG<)PA77Rlx?VN%#py{G zLY#s*eN|1SA~B{5$M))eSf8b}k@H{ZnXH_q`qjsDj+*`0meZ#_HQBgEYkJR5)>VSx Vnd_e%3k2p-22WQ%mvv4FO#lW0jc@<} literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png b/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png new file mode 100644 index 0000000000000000000000000000000000000000..ffaae4a1a07cc3df5914d4e1e1b4fb82b7275acd GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k3?#4J%UA`Z7>k44ofvPP)Tsw@I14-?iy0WW zg+Z8+Vb&Z8prBKLPl)UPzlrznhEC`=cd(Zb5MToezkeHDkgsiEAf&G^6d$KjUuSUs ztUo_L+x&Sp`FUFYescTwdiM93DJbyR+e@rp=los#qbyL{EKe85kcv5PC*9?1R^V}S z)!|~jBXIwJ==Cg)xR8ixZ_X7TJ>3LE+pZEH9)l0{`GAz^8nYwbd zQr@}b9Jf4`b??v{%lEd=y=yjqVRrqRU;cl|1dEDS9>*AWLfOtV=S9I&8k6*wQS3&%{z9!X2|U+l2N>O)6X;}be&M< zdB$(vCyJOh-mr{%c))E-kj$P2g)nu2%|921uG}=imtCNJhL%FwLaT=t4u^Who7`aL z>+{;seQVAXp?HaDVK+WUR#cwRw<>a5 zZa>-E?k#yLI`z-o9ozWiv{LPZ86W9SDSJCL>`d3@z$qRs6Ip}ThOdsiJU2cjZtLGy zx89jn{d)L#`MId#AfL1l|CvoS7q-=3-qCb* zSM#a$H7onlE^TkTva|WZ*80w(U=tO&*1UjoTk5XuYPq(%<!F1 zy&}r};`WB7RG%ZODnM4XCQPo3*t@v+%Fd>1yIZgCY3(fz1&XHy*c@C@c4|X)W2UdO zq58C%s5O%^&uy+t_OX%^5d(kE$Ql=$Ae!>6$zh2wVaP824Two?tA_lHtvHXo` z*0R9BIPU4<7*a83>y*x-Lka?IzFRH|M7>G9m1cPC_lvvx{%@Wt?UQl5blDNk*Wz_$ z;$l^MUAApmzw6*php#sS_PFKFis`uKT@(~hRe4lGHvayddv_;${`~MGWJ>DQWlP0G z4m1`|$p5?|e)b7Rw*#S*lT*ZJWrRXzOF>EtU|?m z0mXaHnVXC3jbF`Z`0U_&!m7j|Z8}FV=cSpE+z-w*#CHgpd_J%;*1bbOI%u=NG*vb4 z`57KQ9yc#l7ff_$*|CIEg8#wuZXxXm%l>sm3Qj4{%Wvs-bz1msNyxP=vX*veso)RY zaQWNA*hl46!Lvgr?A1KI%eyc8q-CId%}zF#u0z7l!-V_J^{Lyn$6UG<)?m8($hx5V z)kn5+JI#ze^!C`>Z|ian_(~~0IQ3g#%IW!AQ;IbvJXbs!dGN&N)30y;KHe1;x^?D- zCWC3=p|k6>8uw{UUjN?he)qawU{J9(O@4PRM5Jd`jZAkc6mKN3zKC*?Um&CTB7b7jT{%q;evgBa mp7U$A3%PL|zO%M-O_#jT6-FtK6AYkq%HZkh=d#Wzp$P!CVrxAB literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png b/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png new file mode 100644 index 0000000000000000000000000000000000000000..8532a8f1e41defc52a913ee070ae6ee8b9593f4d GIT binary patch literal 1095 zcmeAS@N?(olHy`uVBq!ia0vp^4M1$e!3-p4zHs^uq!^2X+?^P2p46!aaySb-B8wRq zxP?KOkzv*x383Ki0G|+7Sz!SK1!+D`4xoUfAfJ|uIFO+vE_`NF&E*|US9UgC+TM75 zck87cjaPOyU)tVqbyv%|Ep@9Vq)#XdUq3bL?B@Ejn`^J`YQDC+<;I@2Yr9)7Y^y)G zqAV@Irnfls`kvN{+Z*;SE}mQ&F~2q8$f}BpDEFpRpNe?*QyZ#Jt*?<25p2x#UD=lg zwA9&9eOgV_nn{`GHrHL)THjd|EXd7eq9O;BYRwC{wyR~={G#o13X*-Sq=oqZI&265 zO4ybJ`33*~zjo%K*D=@r69kL@|Cfg->i^FGVN6xOs>{H@^uW`_F{EP7+whxV(uO>9 zXHHO?thlgb_KYp6u_+hl=1ti4=YRRtYZVjQp9JjYuR7SyJnhlzn6(k1p`Wk%^u7AU z=Ns!UZ<1&~+h^H-#+9q8?&`jtD04bD9<{OgB%f{M``)1w^=T`Xe`-J_;n%xBpzr0uf z(Z281T3`U)GJhyz@asoX^a6kKa8u@35*kRX>Z@ z(fff{#a-bE>IL?)*PkWtbiKS$r7`Rlvx%&?@Qw*84nQvBtUguF3ne-}3wBOH5%6qS zmV6SZ;mNLP-xz$4Ph!cinx?X0^17z2Uz$@i|H>_R88Hbio-pZy+o#`8Iakc~>I`#S j-NN~$tsz6S Date: Tue, 21 May 2024 14:33:06 +0000 Subject: [PATCH 18/28] ci: spotless formatting --- .../placement/OverlayManagementScreen.java | 26 +++++------ .../selection/CustomBarSelectionScreen.java | 28 ++++++------ .../selection/OverlaySelectionScreen.java | 26 +++++------ .../selection/widgets/OverlayButton.java | 2 +- .../settings/WynntilsBookSettingsScreen.java | 44 +++++++++---------- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java index f8846e4e8c..c8ec6aa84c 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/placement/OverlayManagementScreen.java @@ -798,20 +798,20 @@ private void setupButtons() { 150))); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.close"), button -> { - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.close"), button -> { + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 - BUTTON_WIDTH - 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.closeTooltip"))) .build()); this.addRenderableWidget(new Button.Builder( - buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { - buttonsAtBottom = !buttonsAtBottom; - setupButtons(); - }) + buttonsAtBottom ? Component.literal("🠝") : Component.literal("🠟"), button -> { + buttonsAtBottom = !buttonsAtBottom; + setupButtons(); + }) .pos(this.width / 2 - 10, yPos) .size(BUTTON_HEIGHT, BUTTON_HEIGHT) .tooltip(Tooltip.create( @@ -821,11 +821,11 @@ private void setupButtons() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { - Managers.Config.saveConfig(); - onClose(); - McUtils.mc().setScreen(previousScreen); - }) + Component.translatable("screens.wynntils.overlayManagement.apply"), button -> { + Managers.Config.saveConfig(); + onClose(); + McUtils.mc().setScreen(previousScreen); + }) .pos(this.width / 2 + 12, yPos) .size(BUTTON_WIDTH, BUTTON_HEIGHT) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlayManagement.applyTooltip"))) diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java index ff30998df8..234b0ef348 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/CustomBarSelectionScreen.java @@ -62,12 +62,12 @@ protected void doInit() { calculateBarPosition(); textureButton = this.addRenderableWidget(new Button.Builder( - Component.literal(availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .toString()), - (b) -> {}) + Component.literal(availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .toString()), + (b) -> {}) .pos((int) ((this.width / 2f) - 30), (int) (barY + 20)) .size(60, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.customBarSelection.textureTooltip"))) @@ -79,14 +79,14 @@ protected void doInit() { .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) + Component.translatable("screens.wynntils.customBarSelection.cancel"), (button) -> onClose()) .pos((int) (this.width / 2f) - 90, (int) (barY + 45)) .size(80, 20) .build()); this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.customBarSelection.select"), - (button) -> addCustomBar()) + Component.translatable("screens.wynntils.customBarSelection.select"), + (button) -> addCustomBar()) .pos((int) (this.width / 2f) + 10, (int) (barY + 45)) .size(80, 20) .build()); @@ -163,11 +163,11 @@ private void calculateBarPosition() { // Calculate the central position to render the current selected bar at barX = (this.width - availableBars.get(barTypeIndex).a().width()) / 2f; barY = (this.height - - availableBars - .get(barTypeIndex) - .b() - .get(barTextureIndex) - .getHeight()) + - availableBars + .get(barTypeIndex) + .b() + .get(barTextureIndex) + .getHeight()) / 2f; } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java index ca983d2c5d..265876db51 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/OverlaySelectionScreen.java @@ -123,8 +123,8 @@ protected void doInit() { // region Preview renderables exitPreviewButton = this.addRenderableWidget(new Button.Builder( - Component.translatable("screens.wynntils.overlaySelection.exitPreview"), - (button) -> togglePreview(false)) + Component.translatable("screens.wynntils.overlaySelection.exitPreview"), + (button) -> togglePreview(false)) .pos((Texture.OVERLAY_SELECTION_GUI.width() / 2) - 40, (int) (this.height - 25 - translationY)) .size(80, 20) .tooltip(Tooltip.create(Component.translatable("screens.wynntils.overlaySelection.exitPreviewTooltip"))) @@ -464,7 +464,7 @@ public void populateOverlays() { // Don't deselect custom overlays as they will always fail the above check if (filterType == FilterType.BUILT_IN || !(selectedOverlay instanceof CustomBarOverlayBase - || selectedOverlay instanceof InfoBoxOverlay)) { + || selectedOverlay instanceof InfoBoxOverlay)) { setSelectedOverlay(null); } } @@ -928,11 +928,11 @@ private void renderWidgets(GuiGraphics guiGraphics, int mouseX, int mouseY, floa private void renderOverlayScroll(PoseStack poseStack) { overlayScrollY = 24 + MathUtils.map( - overlayScrollOffset, - 0, - getMaxOverlayScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + overlayScrollOffset, + 0, + getMaxOverlayScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 132, overlayScrollY); } @@ -940,11 +940,11 @@ private void renderOverlayScroll(PoseStack poseStack) { private void renderConfigScroll(PoseStack poseStack) { configScrollY = 24 + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + 177 - Texture.CONFIG_BOOK_SCROLL_BUTTON.height()); RenderUtils.drawTexturedRect(poseStack, Texture.SCROLL_BUTTON, 344, configScrollY); } diff --git a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java index 66a6c6ead7..fa94b3e4ed 100644 --- a/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java +++ b/common/src/main/java/com/wynntils/screens/overlays/selection/widgets/OverlayButton.java @@ -128,7 +128,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float // Don't want to display tooltip when the tile is outside the mask from the screen if (isHovered && (mouseY <= selectionScreen.getConfigMaskTopY() - || mouseY >= selectionScreen.getConfigMaskBottomY())) { + || mouseY >= selectionScreen.getConfigMaskBottomY())) { isHovered = false; } diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index 1989ac4d9f..a7cd1c0901 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -375,12 +375,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigurableScroll && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIGURABLE_SCROLL_X, - CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configurableScrollRenderY, - (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIGURABLE_SCROLL_X, + CONFIGURABLE_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configurableScrollRenderY, + (int) (configurableScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigurableScroll = true; return true; } @@ -388,12 +388,12 @@ public boolean doMouseClicked(double mouseX, double mouseY, int button) { if (!draggingConfigScroll && (configs.size() > CONFIGS_PER_PAGE) && MathUtils.isInside( - (int) adjustedMouseX, - (int) adjustedMouseY, - CONFIG_SCROLL_X, - CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), - (int) configScrollRenderY, - (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { + (int) adjustedMouseX, + (int) adjustedMouseY, + CONFIG_SCROLL_X, + CONFIG_SCROLL_X + Texture.CONFIG_BOOK_SCROLL_BUTTON.width(), + (int) configScrollRenderY, + (int) (configScrollRenderY + Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2))) { draggingConfigScroll = true; return true; } @@ -911,11 +911,11 @@ private void renderConfigurableScroll(PoseStack poseStack) { configurableScrollRenderY = SCROLL_START_Y + MathUtils.map( - configurablesScrollOffset, - 0, - getMaxConfigurableScrollOffset(), - 0, - SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + configurablesScrollOffset, + 0, + getMaxConfigurableScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); RenderUtils.drawHoverableTexturedRect( poseStack, @@ -950,11 +950,11 @@ private void renderConfigScroll(PoseStack poseStack) { configScrollRenderY = SCROLL_START_Y + MathUtils.map( - configScrollOffset, - 0, - getMaxConfigScrollOffset(), - 0, - SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); + configScrollOffset, + 0, + getMaxConfigScrollOffset(), + 0, + SCROLL_AREA_HEIGHT - Texture.CONFIG_BOOK_SCROLL_BUTTON.height() / 2f); RenderUtils.drawHoverableTexturedRect( poseStack, From 3c2d8cd29596153a15a0a9fd8c3254fbf0bb221b Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 21 May 2024 16:01:57 +0100 Subject: [PATCH 19/28] fix: Don't scroll configs up when importing --- .../screens/settings/WynntilsBookSettingsScreen.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index a7cd1c0901..a144249175 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -594,7 +594,6 @@ public void populateConfigurables() { public void populateConfigs() { configs.clear(); - configScrollOffset = 0; if (selectedConfigurable == null) return; @@ -623,6 +622,11 @@ public boolean configOptionContains(Config config) { } public void setSelectedConfigurable(Configurable selectedConfigurable) { + // Only reset offset when a new configurable is selected + if (this.selectedConfigurable != selectedConfigurable) { + configScrollOffset = 0; + } + this.selectedConfigurable = selectedConfigurable; populateConfigs(); @@ -1020,7 +1024,11 @@ private void importSettings(int clicked) { // Repopulate the configurables and configs after importing populateConfigurables(); - populateConfigs(); + + // Don't need to populate configs if something is selected as populateConfigurables will call this + if (selectedConfigurable == null) { + populateConfigs(); + } } private void exportSettings(int clicked) { From c91aa4598f9a0f005738738a7707cea18f4817c6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 21 May 2024 16:11:34 +0100 Subject: [PATCH 20/28] chore: Remove redundant calls to populateConfigs --- .../screens/settings/WynntilsBookSettingsScreen.java | 7 +------ .../screens/settings/widgets/ConfigurableButton.java | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index a144249175..b33cc923fe 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -1022,13 +1022,8 @@ private void importSettings(int clicked) { } } - // Repopulate the configurables and configs after importing + // Repopulate the configurables after importing populateConfigurables(); - - // Don't need to populate configs if something is selected as populateConfigurables will call this - if (selectedConfigurable == null) { - populateConfigs(); - } } private void exportSettings(int clicked) { diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java index 13c0f00d5d..d0806c2bda 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/ConfigurableButton.java @@ -150,7 +150,6 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { // Repopulate screen to update new enabled/disabled states if (McUtils.mc().screen instanceof WynntilsBookSettingsScreen bookSettingsScreen) { bookSettingsScreen.populateConfigurables(); - bookSettingsScreen.populateConfigs(); } return enabledCheckbox.mouseClicked(mouseX, mouseY, button); From 62bb27291eafa992f9444e92e7bf3002a1d896aa Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 21 May 2024 16:13:20 +0100 Subject: [PATCH 21/28] chore: Remove unused textures --- .../java/com/wynntils/utils/render/Texture.java | 2 -- .../ui_components/crowd_source_background.png | Bin 1287 -> 0 bytes .../ui_components/crowd_source_sticker.png | Bin 323 -> 0 bytes .../ui_components/overlay_button_bottom.png | Bin 931 -> 0 bytes .../ui_components/overlay_button_left.png | Bin 782 -> 0 bytes .../ui_components/overlay_button_top.png | Bin 1095 -> 0 bytes 6 files changed, 2 deletions(-) delete mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png delete mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png delete mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_bottom.png delete mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_left.png delete mode 100644 common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png diff --git a/common/src/main/java/com/wynntils/utils/render/Texture.java b/common/src/main/java/com/wynntils/utils/render/Texture.java index 2d1c43903e..75a6c6b794 100644 --- a/common/src/main/java/com/wynntils/utils/render/Texture.java +++ b/common/src/main/java/com/wynntils/utils/render/Texture.java @@ -254,8 +254,6 @@ public enum Texture { BACKGROUND_SPLASH("ui_components/background_splash.png", 1920, 1027), COSMETIC_VIEWER_BACKGROUND("ui_components/cosmetics_viewer_background.png", 72, 92), CONTAINER_SIDEBAR("ui_components/container_sidebar.png", 25, 136), - CROWD_SOURCE_BACKGROUND("ui_components/crowd_source_background.png", 180, 260), - CROWD_SOURCE_STICKER("ui_components/crowd_source_sticker.png", 36, 36), EMERALD_COUNT_BACKGROUND("ui_components/emerald_count_background.png", 24, 24), GEAR_ICONS("ui_components/gear_icons.png", 64, 128), GEAR_VIEWER_BACKGROUND("ui_components/gear_viewer_background.png", 103, 92), diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png b/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_background.png deleted file mode 100644 index 31397471c028d037103a4638dc8c697bf6790517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1287 zcmeAS@N?(olHy`uVBq!ia0vp^TNoG^SvZ)1tZnPw9RyO0#X;^)j5kl})B`!31s;*b z3=G`DAk4@xYmNj^0Y`vOh$~QX(LjS(F);{gNlk4^Oa!tE?d^*k9U+1lIy&=a&6+oJ zW}1cuM5H4x56H;3vdXu%o>*U>XKA@;;lgAkrG}W8>fqpbDX9hX=G8_-OiD_+a_G?i z|NoC3J-T_)q;1=_?cBL@V}E~dboAP_Yr7*OuOB_SYSpT*A3rW#x^&aSCm(=e5m6H4 z7tElL(z9s$*@xfG=yc!xFHw52gd-!3)##`eWA&d(p>1N9WN+V+{&<}tTd zYv={6YT(+!>Kb+G|9|zS7ZImoC-GGpTRi_e$GTE2*y32riuLsg1uss0IC0{`)rAKe z|Ls$l9+R;+`SG^ZA2(jSv1*UnI^VKx|Ji%&1aD8f*gN~V+|I{4^L>wgTUuIeHM{20 zm$^3%6`#E`_pEueb#=blwof_5pIx6!e)c@c+B$m2`y{)6%`qLif3G*U=cQ%K+xF%D zy}jtM_5ZrpM{nG^{I&YimAg4_H=od+xv6fQYt+dzUyFO=Pu}@jT$fj-+I{W(Eqiuu zzeerIJ$16}pZSwOjPyS7IjLcn693j*IN@crCjPp(>+!?umz@4pxu|*llPjN-Hk;qt zSMhSW##G_?ah5Z3ubcD5?JB7rw1sop5tTdEK+`@=gow*X@uB z^F7MH_gTt2*4*ncyrRKhjp~bx%U8*XMc5z+x_t3ZprZL*^w{y#uP37XlwJ!{n^vsFJH`OeRj;T;)~Moyp|DK<#_)O)+(t8&^{%2F=;_jEBwQyz2GND;s z!-TQwKl|OjwWrq4?aDiv_Vl`!t9kO~Pua^BP2PKB-JWlgOG<)PA77Rlx?VN%#py{G zLY#s*eN|1SA~B{5$M))eSf8b}k@H{ZnXH_q`qjsDj+*`0meZ#_HQBgEYkJR5)>VSx Vnd_e%3k2p-22WQ%mvv4FO#lW0jc@<} diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png b/common/src/main/resources/assets/wynntils/textures/ui_components/crowd_source_sticker.png deleted file mode 100644 index ffaae4a1a07cc3df5914d4e1e1b4fb82b7275acd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k3?#4J%UA`Z7>k44ofvPP)Tsw@I14-?iy0WW zg+Z8+Vb&Z8prBKLPl)UPzlrznhEC`=cd(Zb5MToezkeHDkgsiEAf&G^6d$KjUuSUs ztUo_L+x&Sp`FUFYescTwdiM93DJbyR+e@rp=los#qbyL{EKe85kcv5PC*9?1R^V}S z)!|~jBXIwJ==Cg)xR8ixZ_X7TJ>3LE+pZEH9)l0{`GAz^8nYwbd zQr@}b9Jf4`b??v{%lEd=y=yjqVRrqRU;cl|1dEDS9>*AWLfOtV=S9I&8k6*wQS3&%{z9!X2|U+l2N>O)6X;}be&M< zdB$(vCyJOh-mr{%c))E-kj$P2g)nu2%|921uG}=imtCNJhL%FwLaT=t4u^Who7`aL z>+{;seQVAXp?HaDVK+WUR#cwRw<>a5 zZa>-E?k#yLI`z-o9ozWiv{LPZ86W9SDSJCL>`d3@z$qRs6Ip}ThOdsiJU2cjZtLGy zx89jn{d)L#`MId#AfL1l|CvoS7q-=3-qCb* zSM#a$H7onlE^TkTva|WZ*80w(U=tO&*1UjoTk5XuYPq(%<!F1 zy&}r};`WB7RG%ZODnM4XCQPo3*t@v+%Fd>1yIZgCY3(fz1&XHy*c@C@c4|X)W2UdO zq58C%s5O%^&uy+t_OX%^5d(kE$Ql=$Ae!>6$zh2wVaP824Two?tA_lHtvHXo` z*0R9BIPU4<7*a83>y*x-Lka?IzFRH|M7>G9m1cPC_lvvx{%@Wt?UQl5blDNk*Wz_$ z;$l^MUAApmzw6*php#sS_PFKFis`uKT@(~hRe4lGHvayddv_;${`~MGWJ>DQWlP0G z4m1`|$p5?|e)b7Rw*#S*lT*ZJWrRXzOF>EtU|?m z0mXaHnVXC3jbF`Z`0U_&!m7j|Z8}FV=cSpE+z-w*#CHgpd_J%;*1bbOI%u=NG*vb4 z`57KQ9yc#l7ff_$*|CIEg8#wuZXxXm%l>sm3Qj4{%Wvs-bz1msNyxP=vX*veso)RY zaQWNA*hl46!Lvgr?A1KI%eyc8q-CId%}zF#u0z7l!-V_J^{Lyn$6UG<)?m8($hx5V z)kn5+JI#ze^!C`>Z|ian_(~~0IQ3g#%IW!AQ;IbvJXbs!dGN&N)30y;KHe1;x^?D- zCWC3=p|k6>8uw{UUjN?he)qawU{J9(O@4PRM5Jd`jZAkc6mKN3zKC*?Um&CTB7b7jT{%q;evgBa mp7U$A3%PL|zO%M-O_#jT6-FtK6AYkq%HZkh=d#Wzp$P!CVrxAB diff --git a/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png b/common/src/main/resources/assets/wynntils/textures/ui_components/overlay_button_top.png deleted file mode 100644 index 8532a8f1e41defc52a913ee070ae6ee8b9593f4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1095 zcmeAS@N?(olHy`uVBq!ia0vp^4M1$e!3-p4zHs^uq!^2X+?^P2p46!aaySb-B8wRq zxP?KOkzv*x383Ki0G|+7Sz!SK1!+D`4xoUfAfJ|uIFO+vE_`NF&E*|US9UgC+TM75 zck87cjaPOyU)tVqbyv%|Ep@9Vq)#XdUq3bL?B@Ejn`^J`YQDC+<;I@2Yr9)7Y^y)G zqAV@Irnfls`kvN{+Z*;SE}mQ&F~2q8$f}BpDEFpRpNe?*QyZ#Jt*?<25p2x#UD=lg zwA9&9eOgV_nn{`GHrHL)THjd|EXd7eq9O;BYRwC{wyR~={G#o13X*-Sq=oqZI&265 zO4ybJ`33*~zjo%K*D=@r69kL@|Cfg->i^FGVN6xOs>{H@^uW`_F{EP7+whxV(uO>9 zXHHO?thlgb_KYp6u_+hl=1ti4=YRRtYZVjQp9JjYuR7SyJnhlzn6(k1p`Wk%^u7AU z=Ns!UZ<1&~+h^H-#+9q8?&`jtD04bD9<{OgB%f{M``)1w^=T`Xe`-J_;n%xBpzr0uf z(Z281T3`U)GJhyz@asoX^a6kKa8u@35*kRX>Z@ z(fff{#a-bE>IL?)*PkWtbiKS$r7`Rlvx%&?@Qw*84nQvBtUguF3ne-}3wBOH5%6qS zmV6SZ;mNLP-xz$4Ph!cinx?X0^17z2Uz$@i|H>_R88Hbio-pZy+o#`8Iakc~>I`#S j-NN~$tsz6S Date: Tue, 21 May 2024 16:14:56 +0100 Subject: [PATCH 22/28] chore: Remove reset textures --- .../java/com/wynntils/utils/render/Texture.java | 1 - .../wynntils/textures/icons/generic/reset.png | Bin 307 -> 0 bytes 2 files changed, 1 deletion(-) delete mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/reset.png diff --git a/common/src/main/java/com/wynntils/utils/render/Texture.java b/common/src/main/java/com/wynntils/utils/render/Texture.java index 75a6c6b794..e323df7f60 100644 --- a/common/src/main/java/com/wynntils/utils/render/Texture.java +++ b/common/src/main/java/com/wynntils/utils/render/Texture.java @@ -111,7 +111,6 @@ public enum Texture { PREVIOUS("icons/generic/previous.png", 16, 16), QUESTION_MARK("icons/generic/question_mark.png", 4, 7), QUESTS_SCROLL_ICON("icons/generic/quests_scroll_icon.png", 16, 16), - RESET("icons/generic/reset.png", 16, 16), SAVE("icons/generic/save.png", 16, 16), SHARE_ICON("icons/generic/share_icon.png", 16, 14), SIGN_ICON("icons/generic/sign_icon.png", 17, 18), diff --git a/common/src/main/resources/assets/wynntils/textures/icons/generic/reset.png b/common/src/main/resources/assets/wynntils/textures/icons/generic/reset.png deleted file mode 100644 index 0f879ab34ebcee9e7b2201663a4fdb64c39afc70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf)yAH90czFFF3zHVg391fd2U=X%jSn zk~N+#jv*CuV*3O64jXVddpgP7+IjX}{Vm4K(9(ZS{L+$wntCgJy}hhL+7E7h%h~XY z@kaFmR*t?8{VIG1wmss#A-v;Lk>vp;X}SJiX>0Q&Z%LQT(O>YVTV}(f1?RfMl2~RW zOu6P+W7=>`J?+b)IE%Z@fyX{IYU`!1&i=*78NqxyfpP03kjFe-{an^LB{Ts5p`cg8 From b75acf15c5a0cbe09613779e5e47e69bfbcddac5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 21 May 2024 16:16:30 +0100 Subject: [PATCH 23/28] chore: Remove unused i18n --- common/src/main/resources/assets/wynntils/lang/en_us.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/common/src/main/resources/assets/wynntils/lang/en_us.json b/common/src/main/resources/assets/wynntils/lang/en_us.json index 0911c7f8df..190dc13012 100644 --- a/common/src/main/resources/assets/wynntils/lang/en_us.json +++ b/common/src/main/resources/assets/wynntils/lang/en_us.json @@ -2399,13 +2399,8 @@ "screens.wynntils.wynntilsContentBook.sort.distance.name": "Sort by Distance", "screens.wynntils.wynntilsContentBook.sort.level.description": "Quests are sorted by level, lowest first", "screens.wynntils.wynntilsContentBook.sort.level.name": "Sort by Level", - "screens.wynntils.wynntilsCrowdSourcing.collecting": "Collecting", - "screens.wynntils.wynntilsCrowdSourcing.copiedToClipboard": "Copied %d data points of %s to clipboard", "screens.wynntils.wynntilsCrowdSourcing.name": "Crowd Sourcing", - "screens.wynntils.wynntilsCrowdSourcing.noDataTypes": "There are no data types currently being crowd sourced matching your search query.", - "screens.wynntils.wynntilsCrowdSourcing.notCollecting": "Not Collecting", "screens.wynntils.wynntilsCrowdSourcing.screenDescription": "Here you can see all the data types the mod can collect. If you opt-in to help us collect these data, we can improve the mod and the Wynncraft experience for everyone. You can opt-out at any time.", - "screens.wynntils.wynntilsCrowdSourcing.unconfirmed": "Unconfirmed", "screens.wynntils.wynntilsDialogueHistory.description": "Here you can read your last few conversations with NPCs on your current class.", "screens.wynntils.wynntilsDialogueHistory.name": "Dialogue History", "screens.wynntils.wynntilsDialogueHistory.questsPageButton.description": "Click here to open the quest book", From 952e026ee6da99b6b94ec1d4883282e63fef0362 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 21 May 2024 16:24:21 +0100 Subject: [PATCH 24/28] fix: Don't scroll to matching configs when already selected configurable --- .../screens/settings/WynntilsBookSettingsScreen.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index b33cc923fe..d8bd30da11 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -622,14 +622,20 @@ public boolean configOptionContains(Config config) { } public void setSelectedConfigurable(Configurable selectedConfigurable) { + boolean skipScroll = true; + // Only reset offset when a new configurable is selected if (this.selectedConfigurable != selectedConfigurable) { configScrollOffset = 0; + skipScroll = false; } this.selectedConfigurable = selectedConfigurable; populateConfigs(); + // If we are already on this configurable, then we don't want to scroll to any matching configs + if (skipScroll) return; + // If there is a search query, scroll the configs list so that the matching config // is found unless the configurable itself matches the search query if (!searchWidget.getTextBoxInput().isEmpty()) { From 0257ac64a5a67658758e7c7110df1cbddf2b1e65 Mon Sep 17 00:00:00 2001 From: Rafii2198 Date: Wed, 22 May 2024 17:19:16 +0200 Subject: [PATCH 25/28] move everything to new branch --- .../com/wynntils/utils/render/Texture.java | 4 ++++ .../textures/content_book/tag_blue.png | Bin 421 -> 4902 bytes .../wynntils/textures/content_book/tag_red.png | Bin 408 -> 5379 bytes .../textures/content_book/tag_red_selected.png | Bin 498 -> 5407 bytes .../textures/content_book/tag_search.png | Bin 605 -> 4764 bytes .../config_categories/all_config_icon.png | Bin 293 -> 4702 bytes .../config_categories/apply_settings_icon.png | Bin 0 -> 4943 bytes .../config_categories/chat_config_icon.png | Bin 289 -> 4508 bytes .../config_categories/combat_config_icon.png | Bin 275 -> 4488 bytes .../config_categories/commands_config_icon.png | Bin 278 -> 4661 bytes .../config_categories/debug_config_icon.png | Bin 296 -> 4452 bytes .../discard_settings_icon.png | Bin 0 -> 5168 bytes .../embellishments_config_icon.png | Bin 283 -> 4500 bytes .../config_categories/export_settings_icon.png | Bin 0 -> 4962 bytes .../config_categories/import_settings_icon.png | Bin 0 -> 4736 bytes .../inventory_config_icon.png | Bin 261 -> 4508 bytes .../config_categories/map_config_icon.png | Bin 234 -> 4496 bytes .../config_categories/overlays_config_icon.png | Bin 237 -> 4500 bytes .../config_categories/players_config_icon.png | Bin 343 -> 4530 bytes .../redirects_config_icon.png | Bin 282 -> 4516 bytes .../config_categories/tooltips_config_icon.png | Bin 304 -> 4696 bytes .../trade_market_config_icon.png | Bin 267 -> 4493 bytes .../icons/config_categories/ui_config_icon.png | Bin 207 -> 4281 bytes .../uncategorized_config_icon.png | Bin 299 -> 570 bytes .../utilities_config_icon.png | Bin 314 -> 4497 bytes .../config_categories/wynntils_config_icon.png | Bin 304 -> 4492 bytes .../wynntils/textures/icons/generic/close.png | Bin 254 -> 0 bytes .../wynntils/textures/icons/generic/next.png | Bin 253 -> 4262 bytes .../textures/icons/generic/previous.png | Bin 235 -> 4269 bytes .../wynntils/textures/icons/generic/save.png | Bin 257 -> 0 bytes 30 files changed, 4 insertions(+) create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/apply_settings_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/discard_settings_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/export_settings_icon.png create mode 100644 common/src/main/resources/assets/wynntils/textures/icons/config_categories/import_settings_icon.png delete mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/close.png delete mode 100644 common/src/main/resources/assets/wynntils/textures/icons/generic/save.png diff --git a/common/src/main/java/com/wynntils/utils/render/Texture.java b/common/src/main/java/com/wynntils/utils/render/Texture.java index e323df7f60..c1e83c9827 100644 --- a/common/src/main/java/com/wynntils/utils/render/Texture.java +++ b/common/src/main/java/com/wynntils/utils/render/Texture.java @@ -60,6 +60,10 @@ public enum Texture { UNCATEGORIZED_CONFIG_ICON("icons/config_categories/uncategorized_config_icon.png", 16, 16), UTILITIES_CONFIG_ICON("icons/config_categories/utilities_config_icon.png", 16, 16), WYNNTILS_CONFIG_ICON("icons/config_categories/wynntils_config_icon.png", 16, 16), + APPLY_SETTINGS_ICON("icons/config_categories/apply_settings_icon.png", 16, 16), + DISCARD_SETTINGS_ICON("icons/config_categories/discard_settings_icon.png", 16, 16), + EXPORT_SETTINGS_ICON("icons/config_categories/export_settings_icon.png", 16, 16), + IMPORT_SETTINGS_ICON("icons/config_categories/import_settings_icon.png", 16, 16), // Content Book DIALOGUE_ICON("icons/content_book/dialogue_icon.png", 14, 11), diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_blue.png index 9a3df19ac5677d14b96f37ab6b92aa574e260305..540d923afa0a2951d1b9a31c9db873ca7786fd6b 100644 GIT binary patch literal 4902 zcmeHKc~leU79S8n5J6O2C@o`D#ATAnMivQzBtpa>+Y=Bi%oZ3Si%B2>r7AAfx*~m| zfUQt!QBZjTRiRW6+;KnEx>Rwg8zLZX&jsI?fQaYyoOe9u^*<*knfdPW`|kbSd%u%e z85$Bez`@M{f}jENAZa+bPXyng{cOQ+HTBhTa66P98Epv1jIdUxQPRm2Y)I2mFlC~Z z5M;Wn3XOHDhaF#?9+ztK7&pmPEE||T47ILWIN_h$p1xj21xFRLhBu@rJw`q+kIcK4dy*_%la!B|5j-C-;lF8hIU01~yRJhJcLH9rDpUWFPj=457sjhC_p&d(BmG5%el?lJF zy7{oF=pJKCCu>~AiuR^`9<7fgkFHrwDLEWj&T=ZwrN|BT?6_#xS8*=2{WANF9M6uJ zK@HQlxyLi`HH=^a=79NAX4{}ea!dx^1PpfB%?`GUYOM)EQMeRlY!$yB~ zyXxWN&+hK2w?6Io+5SeKd7GjqJ}@nSzJHidoQyl0O>(BbR@}pOr-I0Ye0$$lWzuk0eMs~1gl1^yZojB|+hp9U zq|=Wp96T4*u2Lm;W#RUw$vnQYu4aeQTMHU5l?DwKt(Yz*G%6-WYH*5aQUL|Hd?uT;7?DI7V4O;z)e=T) z^#KMv_?W~1Kt&la*rZBU>%}Gs!-6XY z&t@@;0b5KANfJi1A`}kL=qQ-SM@K5f;nJzy5MU)?BpM7_F^gq1 z8kt5eQ=>~@u|*;g3+1pl90XV(`ZToxGa+jIC^JMChLqA1I$CR>HEP(5iQ$?QgM`5V zdiY&@Dy>4%1FzP1vjF&DnJ_Jj%|ux$6|1+0-XKc_Al(7|rH4Ke%qc6J(rZ$51SLzQ z)P_;LAxNUfUz?&!wxmN6EGn5&0aHELmHok%fpSG?kB6Cp1X`uFcmc9Mur$!h_hfw# zn^|K?r*|O0y$AOL>vy?ZjDeLxA(m>06mxiTsf1zPUrcHUniN|e*&?1uK!Hk-93_tM zNCHDJAtpqGe2T|RiEwcdcK3Cauwz?n3_@dgN_K!76zmn%ScN{WwQT(HDZ zr2wV4N*q%PdO^(4(V#1_=s~m|?4M>4bYu@GZKR|b|6)HdlO0G9SbyctjU9V9ZjF^t{ zPXIguu0VrYxPra9OEvDpXpD)JxekCb1mz>WC}Xg?lVzDtjCa}ku>Ok=AB#b+BL?_& z$-vPCPC{1CQP|BFi1qKhy6f@f40{Alno^I+MpOc1oaV$ae?@c8k$oh<2>K_?&#ot8itJyYsmtV=I+{W!kiSXtj171q<0+-I+cT3Hif5>XV;5OI9p*2ZAZR~px zieEZ1<`n|k zkLR3UbImS)>(~f>(U_7{*@MEeuoF2G7c?ql>Z*ztwoQ#+?jBZx(n;=VP4PUJx%ao- ziCgvC_}WtWo5Ec+HV@_Xv(8%o<5+DOKAt}!PoUt0g-wf$ZuWWFzxL1MQ{0Y4iT#E? z%~@JCe`oIAI}!P~>f*uEBRXHdcs$7JtPs7|HS-bHuEOj6Wf?tM1f z{Qk|<^Mu}eTI`6hzKcam+I(9N>&srfC?E6+9pQH8>Ce7vsWqo!rks7=pgMEF>h%Ne z_T$q!20m>MUph51a!dB_`5O-o=7&A$JX&2;ZFi;M=iQn8eNB#T>`^&uH@l4pL-v%W z%s-ImKJkz3m9vuL7}n(7gsd%d*A*03m$XiAg*yAZ8Cw3bUvl3Qpxq(4EJV6%N_^&j E07X$g?EnA( literal 421 zcmeAS@N?(olHy`uVBq!ia0vp^IzTMO!3-pOcK7`NQjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W>Rgz$e6&f#E+k1eC@qP7}dPvv$n_TBuVJ84Oq z01xwp2cgZ2HtkS8wQ9k?|NlD|yw99>zQih%G5^sNpY-BG(_c(roz~dHT(EVT>51Mo z)n^Qh5{`8;7VkDrc*oCn=JCmfNk#zKI)b s^|Y^AUFpqv{~_hIT*gtgUC&?tWpw!<;K5*K6by2Xr>mdKI;Vst0F-5*4FCWD diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_red.png index d23614133cac6dcbc0224b91f3a5addc8e9a89bb..5ab1939710595c043be9e590c0ab3933f26a9c4a 100644 GIT binary patch literal 5379 zcmeHKeN+=y79UW{hY>*qETYC}DYi^9NhXD^=$EUY zR$4_-s~p8@X{Cs+McY~|RThb2Yom4TqFBL?YFkjTYQ-ZJ&SYlZ zz3=z#{oUW4mw87$HF-#2L?8q~LzD`6I=F^`GsgcJ@Jqa+=meJo1sW}rPB_?Bo5euq zQfwyQO0g*?ZGa%>DU-ToNCTU7@79RXK5>vRh)(}x6mu`4L#|w1D)~+v>Dqb!>#@!u z!GVe$GiOe0VyhzZhL=UYDTrF%5&uraoa>XXMwfilJpXs~dEYDfv8*@RKmM&r(cu4n z&Sqs-`;q7|=Z=M}*EUoZg_MRPtlGC!BOMK&J`jR@3hBf|wK6gBVLl*> z4R5ZLDH=*&Fi%Nv8s&@J^k9c>jqbDrzwP29coTHBtnSFgyfobgH6=F;rq1yz<&*$;h5qAS;Af;!;r7nRtXrMeZgO3_zH;A}E?&K*3EHHHG}aO!mSDGeCVuJ7bI3MD z;5F&BiumveZ(XSE_-)jsng(AtYt)zD#?D)(jk&e+bVIeS@__I_NYaVutV4UNt!K_v z{}54aPwW0i_Ow@7^ydCWnf&OOI8p)NvB;1`K_$?tEHlO4RhwcOwT^ zCKg@js(;Yt_`*OJ999KJE!baddRzXt?%5ywxcl-|eT#V$)NO2gx&2N%oPDMAhGBYf zq)$W3{>HrNrMDJ*GdlZ*@_km*%6n*0dVn+TL(2=$=2x?=M=o#Qwc@xRJ9#$T3i&PB zFJE8tFWDK{(Uz8dM*RMLXxlhjU6ny>g`lA*4fLf|rQ&*viA#_c9mRE;fB_t_aZW3t z&!HH$jxy3_8RzQWeH=DT$~e3$k9tlPTWg@u}&NSm?(x| zJ59M}JMNTmytp{H_YCtmY_AKGBjadQYIdTG=kXj42iGCwT5LuhUn-UI5CKmhfPn{W&o?uK6E@q&dmwr+4t^>Naor%Bv< zi(#ZxgorShphSEa6&S=Yp)=@UfdHeVQWO>PDP12ZrPhUQSn~4DBq)mj8;#ti`ufan&98Qgc|A`(kGZtBnb>S^Ti}GgCj~n( zpCY|+0<0dBelB4)QsDj3E7*tQ^dE>pLh=P76sSlfmKcDZ5HYMH_(GTvp*jL1^g^9L z+8^C+F)$9oM#UQekAN#6P%l^P=-yII?CI#)P(ofr^hET zsZcBxgUm=F&^n31QZb^3Nxn{x3H2x?5Q_ST`#-107viW8N6`OEdKAb@Pogk^iYOQb zT?o?SOJNC0i6}&%;|ryKYW4aE{$YBtJkR_7p;lvg|Dom{hdvtwsCv&B*m%G`#(T7p z^~%AsW&DLlZx{WAD*))Hi#!p(Pw9F}*Ap@DM9xpu^^~qBV&I9KpQ`Imqbu<7r!Zv( z|6d*8LwDS=PZxualtmyvV5uJ0h2hGsC(aLj#8T53a4H*IQorKlDMC4-|V;@pe^4hZEd{wVcn%k0ry+Vub)`-ptkFc#%*r- zE>`<+S8HqevnNb9eW78HYj`)ul?<)!ynFeTh1tQ;zQL{_f8Tmj^8|(Op*@+|vp9DO zYJV~4_Fed4P3w}ge!o>*an6l#)~B3uFJsHZ+goQm5PjZG4~txWW}9TTn%y}L+WXP> zcO;W0RzNC9y>-B{*Ch#)%a47`J73o}D){HX#-I(*pnwvI?+@ZcW9r5+Af1%(u|xT@}V$$MKJMM2@;*IC^v_wCVRUUjA}_&oNY;Q(awp1hO2XWGurub;cROgR2-xa+8I*p)4Z6}wrync35f0TriG zmL}eobY?Yule(fNY*s0+>3ZR3r}w0-T|F_Twn91r!H&FEMkKGlYZMnY-b|f?uuh5s zEv7Xm6vr!`y)aAxbHLHh*{2q@H5E5s zmYgk9H{a+O*M<>LC~cyQAr={WF#eO; z*8i;<{%Ca}Qsx@g?#!=bdJ6zvx9#!<|zzMekt|wJd~4+k*BdH> ghp57eKj<1zzc?$ERr~rr&<>C?X{vljLiWOc12CMw;Q#;t literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^VnD3J!3-qBx_2A`QjEnx?oNz1PwLbIIh+L^k;M!Q z+`=Ht$S`Y;1W>Rsz$e7@KLY~<0R`Y}dNK~Qh06f#)-DP13+{Rw#E||u@Ad!RzA?X^ zeYbKq`t(81QOo#=oW@=87dMq3T>N-)U$kfa&jMy1(Y~8NZIzxbjv*Cu-k!KE*61M7 zaB+T*-SWWR%`F=3-|HP(ugyAU)6o6xso2Y}%*P#gRZ~pz-lv@MVX)n9ekt^7Z`WGi z45`f-Wk2ubCx^|Cm41`9d2PA)rMz#MTiNfZdH1W=%`R?RpBr2Lcm3SoVJDAX57(@T g^(wfWcTfJj_+xST!jey(pb%&9boFyt=akR{08YA?l>h($ diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_red_selected.png index 2ccec693270cc50204f621a7d8c9980969d7d942..6b994758cdf9e043009552eda3e6e7b1a3781096 100644 GIT binary patch literal 5407 zcmeHKdsGu=79V^Q@IjSF5hX^!N1bGnOhOWgfP_Md0fZ>jT46E|m?bZgK!BqaQEOW& zinP`TDppESkXB%~6>EV4E~qWAimhOgQmk62fMTH)b-x5uINNjfc(&cYoO32K^L_XJ zzI%W7cjwEz9TpNemEp>OAZV&QNEQyRPT*WRWfJ(sRtNQhOHHaW$`p>7nR!a_IehvF^-0c)^`wd&%t=9RtOy95_%?{%J;IlJy+PEw^iy!X}6;2r8&5M;BJ_V*8y`};r62V{}6 zF-sa$?dw(>9g)Fu-0tL%P}eBA5)j}P?3fXAq|9+`B66zVZa=zUF*`FozN%_x?eQ%c zrNz^V)0u-d9o_ADH(4GJIg88Q>TCbpz2~;{cAL$L!n4X!&a{I4B(d9;8y)3%KiZ*k zO8S&}OSloCq_eTtEqb80?;iVX=@$(T#BaX$VLfy>$St-UbI{Fb(5{u-*w}#-1~K}? zeR+P)3*P7~@4hqpMoIO!2K(8kE_f&GjaoYJ>DB5YRY48E#v!12QFPtuB7Iv&(Ph^n zW9Y-LVphFYZ#ejqXm`{K2L0BqCSONE)LTu*vs5hq`?k{`?fo${JJ>VQ@m)8&0{?BD zgH?~(&7V

Ny3&Gp#a1vq`r3;p@5Im;KU%w`vbV4`bV3>H573j=7!PPeo?9*;Kby z)+R<~52T%+6VosMz`j0f2;CNLo9uH`w*)%!T8#edUrvVz%8C>y5QW~KjH8264P-=Wh!RhY$HfH8XF0<=SponwqzPjtYt&k! zBw5O`;!421WthWaT1`yxQdX2AjOnj4kW7?~vJp5SnNH%dmNS^%27;1=%U&LV08dg@ zoXMn@a5!eOnQi8?b%t0DS1cBD5FUregMkHXOwpRKWLRsQZ-E%bkda2*KN3B1-g!UEuflZ@#(TsFedXgH%ijHZAj05THLA9@&-piMd9 zq*0e>z{!9lQfrz&8iK%|`0Eo5YHKGAYZlzJ$=>G$FCx;#?I< zip2t0B&IMJMQ{-;rbq!yQ39Ng@_DGpOEd~ft~Hu4ElygX063clI9wI3LixZ)CBg+T zs=|e^NJXk(3ge1}7($70L^ui})IbAOV(QURS)d32g-{qOMucLRLMaMHDHH*q7!Ss9 zF^}MSAp}MZLlL;-Wt~BTfpXFsESBWxwXxPUEQCw^!sJpGkBvMX2~%Sx3OIlsptXd~ zYev|HKf4^v}i%)B5eLJC6>ZSKstb0%%W5P zVD$jmNc;^XX3`myI-Od|vINDncs`j{fQBM46DGqa0*5&i6pFX z0<7UFJPy;wlHmO@BG|{{^dE=;5fBtkpnOB&b-zM_HV|K0OiG8QdoW~W2U=k;VFv?fqu$YUH zFv%5xH-SJX3Svxp2_&Ry8bk}7*9WiNiF#Q zY6c&=sfY6T;3IjGDmYLERYDOE8tvjW2u5u6L9ZGi$Zn?Pw1M{LxPZaQCb=SD^391( z)0|u~mz51b(0F^f%ugBg&l8cauIco(&%Pu2M*qU+ysJege(OE7m2?@*&Hj1G`|$bT z@z4U>ivGx`-TlAb39PVLelm02hD{qEa?X3)dT{Sl+s@yvhgLP@I=3HAySBM)+#|ce zz+CrnnR$gm_=D%~_7og z_kQJt&aBfn{A_~6bChc0MDs+?sKy&j2MzJ!&l9S+&6`<)jl>U3?AE~}hEL#--m>EF zeo&RWUo~7j^JTTlF2lBQ&vh5S6BCx$1#f-bqqyqs7Y(i+C&SOaNPIiFIv~Avz#}>K z(2Gqzi{ErA(=S||`r$HLseMdObBx`rMa=0?wWm>b)xazP~2%|%a-;m=act0{7Z1`Q~HX3WmVqE>rR*J_Ma?UGpTn5 zu`$c2K01%F>mzDaS!MZ}UI*&kV_U!KIAgky+kR=s?=$c3%j=om-0R@1S+cah<<`}v z&Kb)KTly9-epD(#R;==OY*v)^(H|E&`>a_PUM?uuMXCT1#|gHOl(+*LKRz zMVW<}zZP{}3Rh$kt4qY)aeEZI3-|pks;gK${oL_FwhfW9Oc5TsH}Sn=ts(FHY<8$w zdUI}M68=-c?AntP5*l_cJRNAeqZ2d7<=)uYe0NHw?Z@BWIHc=JpBrDkNPIBGZ|%y3 zQuvg8NO$qe$A`k2+rMeK7vUHG-KweW9f^781`(d@sAq;p*wDn8vvXySDzQY+Dv&%N KL{_{aCjH;Z_26Lu delta 483 zcmbQQ^@(|cWIZzj14CH%jzd6-u{g-xiSg!1oq8aLv%n*=n1O*?7=#%aX3dcR3eFGk z332^Defs|oAO1Hr0R{e-l>A?^_ zZTo-!{(l99|0hoTU$Nr9fdNQ=K*0Zmg#WvD|37o)e|7c$wQK+P^nk2cycno)zaD1? z&}pV6L4Lt||J5?|uKV-9s`~%mfALw7e?uexnmhdY|Nobc>CgW^#edZQ|7!U4|NqY) zK^}PbzNK&dzxB*UZ+DghO<3*e;uumf=k1A1u_gl^*N0(OG#=Rmxc6{H&AIq@{n;r| zEN_H%*ncXrJ63U4GxRy{HI@v~t#6&$85^#j%|5Rj#ItAqWkv}$I}Wz0Qy zV1s_fbMB?5MfW;o#A)AWSrQ$yG&|mS**@-X?6VA<4omE0IW8<4{-}SecCX=ijji)G zo{&h7N+|l?^uH%)QSWB0bvF(f($M~PwOx_Uksj8mA=uGg(%Htty QKzB2Ey85}Sb4q9e030y`8vp;N7mD8tQQwX3O6+Dx_#KG`To1CAe(}$ee&wA zeCI>Ut5f6n7p+|%-LhJ}aMM#13CdbI`KH&5yIL@C#{ats{ie`swmp0@9_183iIsA zwCHws@wY_>+LP_ta4y-J_aqLNtqFr4A4aDCHdHmC3THMouSIVe7id922a@uw>!3Meap!Xw=?;dYvw^^E8?`@J~>pi`LYchw32ocvdOI#?>PFMutRvEy}c$L zefJJJI7@fxfRd*Ljh8}#28)(0Mim+r9m6$pf^Jd)2RQuvO!1{ zkxkd=;u%bVK)^s)3>J$95Hx+N+JKp8YW=5Xia`!Bp;zcgt%202VKXNt*CZQ+R4VYp z@AFe>WwK#kenKTZM z$EFE5ayCtYa1bt2fDVe2d3CF(@bpNQ;>}6%bhLpc+)9 zBQS$T7pc)C3906!U~}ZKTLu;sju|j9W*`75!s4I^7iF;`nLL!qMG^Mz5EhDzz-w?) znfkxb=H&zX4Nkh0)PwO;EvCUW6+x^Td>edCA}xyvhAqni#T0`j=&=+6x8w=923?8- zOdU^v{bQ(M-`mMwXa-+j4imHuXdqm`qj9)O9u4EOnP5Ws80L#9**q3!G`n7-G#D`* z5fBe_1X_UxwP*#;9hxfd(RgD5VV(yd84cmmMo30w3>C{T?-=i^^<(^(9)1?Uh%E-h z4cfrg1$IKl@K!jamwD6q6_25L_!UP0)MJBul)htfjmh;<3ValJth>hK`X~iH3Ov?b z|2MhpKYUCPYVZ%p2tJhpllxbK&n#>Cq98HUW&WMGD31jeJFPTE4?zyD=F`f;)qTH;5jgnbzb`MH(tHvAlM>N+q{eA6Pk$slv?&0kERCI4<(B*Pk+Xa4P z=$(7T*T1~9?d_V0wmma6{cHSBpX>>A+?A2E{FuXz$C(o4R@cU_XccMR^%`7<|khn4JRL3frckc>MhtSIIBWS$z zcpviJwyE-xs6Vvl4>-Q8@!3b#b7Yhyt+%yl&i_)0Y%_QK5aYw$R&gx@!!PeSg?#xm zQBN9u;PZEkCFtw!)w0GNq>Ki-j&b|5TYDzO!@3zmE(bFM6>egl3`f^JPzGeSkj`U2JsVwQJ&ivDS7jLh1 z6BnC`vSTQ!&Zep$EyX6pJGR)rWDRk99j8eA6It4S@Aor0YMh!6K}DJ2_9_4Dj%|%P zf7-|W{2rf%>)61#OAA!#4*!T1=C*l;he*B43itSQBR7a6zMgXzZz{)Q%8t`nd+XP= z1TsyF{yf{E3@OZRbj>-s<#cwL&t45S*I~nTaCx}8f)3yb>91>CCr?zqDb4QPJ#(P` z)WPjmrHYLcq3`D>OiwOyi9KFqy}^H(>*O3O$oHPtK<@ficNOW){S#aYm~lJuDLT+( NP_Sf)xH2#<>p#D%@znqT literal 605 zcmeAS@N?(olHy`uVBq!ia0vp^JwU9)!3-pKaU7fkq!^2X+?^P2p46!aaySb-B8wRq zxP?KOkzv*x383Ko0G|+7AkFX}2iniTkifv8z`!8Dz)--zaG!zUJxDo20|Nul(DMuo z{R|B285jZ>7z`K~9B>$d%W&evU9>K%0Btla3GxeOnECnthiCa0KK(}n`!1g0zj|Fn zTKtZ@UA1kby|+L*}F2vnM~h zp&;ryp?k#x*4FR!W*NCz9;K(=9jKq?_iOE%B`384mrJvLJ$Fc5z3ZH#{y*Ja4%~ZQ z2qm zf`n?`Q>nlVo^ENW#5t;SB(*K2CSS=`JG_48mE1)$RNa#KW_xTg4cok-FQM$HDza=yVWrB?8=;v9mjR%uXwey{g_VtioB~oGz+87{F=JwUV&6qznxjhmFMC- io8P|E$k@!5_$|}a@f;UJ*9~A0GkCiCxvX0hKsx7Nlakx1aa5%@M=hksR?LO-^!zaguj;-@WYQ?)JFd zfJA|I@DNj z_Q3}}zqoE=X?E$<&PV>*$z|2No@k{z>s#l4Sx23l)jn_c#O@itgik)%*Z*Z{&1SK6 z*&F!1&C=?*ce_7Z*YbVo2R{+pPPXpI&N;F4(gyoB-@clC#o*`l8{eHN_;3EW`k400 zjXgax?*fY#Snl^la`C?UO%pr19xcBqWHDyVUDxY>b<_HLg}k>veRfqr_4Ll~Ff8i< z)#It~dptw&peUZXuftu|eP_Xu+NyRU|DoA=YmU7qeC+cTl;^kCJ-;`upO zV3GA#Ee!_`K7M3JYx|zvxw~8ND_Lj0KK;@;;bme_D_3`TdDL*Mm>Ia2(rKRuFy@ z!VwC=_~pV)%{}i@x<1@IX8!vSk$&n@86kk3$?w!qeCP- zS97KfJpK8KE#(WV^B*mkyxp_$?3IH9r;~3eYV#igmW3O-+N0~e_xIoP+{wM)T#$NV z+pzxd>1AL2>npPE{FX~fb$dZpcTd-m#_BDXH@tIe-6j81Q;v6h&u^^ENfp1S-GM#7 zx-S0iH?Qn@{Lk5V={@9USoT9*-rv0T7xyXmdp$h|!a`pkwzDwt)(*uU$FOOQEdy*fw%|Ot7XjzSk=5d zC^a`oE}1A^Y$-|!h#(3LfTyC7m@cH;M4DGX=cbt=@HE6|a1)_G1@6%j5a+GDl_q^D zwTUGbTkxWUtO%9frGpgc%1zW8MqHq%WHM<@a#k%7rWlvYMbRw9vLr%~`r4QQQe;e@ zZ&GA9yik`CYTQt@7;bU`QEN2Z1cAo!A^)QBKwy|YrVpxs^q^88PBB)RibkoCGjzk( zgh&P*`oS4`5Va{)33aV8Awgdgj2ZJsQpnQq{CHy`k`70fC>ViJ1l7^1%%~+x{eg<% z8KwkbH5yOPLSm0X8me+ltWmz1Bk6EPI)bJT^NvCf#hwNuR3IRDHL1~b&+l~;=K6xH zNvbSlPI-qzfhY@-&8d()3uO{0HjZ@3tc`_|BdGi_-2gEOnpB9~sv;h{Btr*K zAjtvVPVzM4Bt^T;K?1CY3I|CG%t}QB zX*-HW@FXBGv_w$TB5uNT0XJt34+l^~$-n?!U_eAlv%Emt1eOgl4uNqBwBx5VD-6bJ z(gieGRo4DDwAns*5yGRSm#I2he{I^7>8UEXCUcd!jHu~m!tr!l2tdk&po1nTr~O1+ znIWkj#KI8WKL!hS$gciSF))gg=YWk=93oHhB1e;=QwF5SBUSA#7w1xx(d@dW7)g+T zC1Io^(h3!5S}Xka!Bj08jZfA?GY?2IlD3hw)0B*51%@Z6>mMFqC0=&OH0fepBFWpJ zLb^}`k-!0X)@gQ&{G*0vRs<(-HuU{}gl7YQ<3$#d4$cWl9@s<@wF6C})X561pa!&O zYIwLd{lp$89oj#0x8vcYmdzFyC5u#2we z5;#7-$e8pUmupg067v~&}-hgeM vwM_W+-#^+qW5UXswhwZjD7^CFcbz#oh2?+BUf5HGXfeNUxp()Hx|V+f0Jn7i literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*BOf?|1kgU{J8W|9--If%^G2H;n{= zl6jskjv*CuTKm0)4k&Oq2YPPRy83(mwiRDCzckT~W8)C;wUn3Hd-TA!)FV&innlYJ z%1?JlemKJFu+HHWlgHJ4E#8y*wx&m3;(3{2G&d*Ww5^fZhU;1{0$xW|EL$LtqN$?F zDifn<#L!i(9-!9R2tYwhQxPQgPN+0Ly$7AudF2VuqMW4TX8$|>8{Iqertkjo-j&B2 zvMz4k^xl<6n+uZ*XSY4^ejA;%>WHzCXsg|r{jVCl_VHgYd}~I}+(*DuPYn)zmi_K_ zY2yP=qd#eqJKg)6{y2Es=UeuaoS4&@{KMPl?)*i6QfO(bal}}6ys`H#wxmA?D7zLN zJ2J0cFCm&g-@5p=c`xwmuRfQ*z&DL{iZ!Qu9SvOFJyoZUd9Y3RIcDW|r%yMQAxP3D z&Fd}od%dH4AdB{O+dM@*%d$>Zm$y1HADfr4=2WlnkAi}%;>^~X-G?(*H4v{{O>1Lv zmN=i>P}kkP<>da2tsRHb4{boNCtdisZ%@DDdqen=!z}}SFE6}&$#dy^(((hZRdnF# z``UoAJ%y~U%DhpX(KU0!%tiN-4{4`&AX&A8*zVb%ynrEu+yY~BYJqM+I zC+HIy1%F*!eX8?dy?cFEYv`xGpAD^k_T9suT$ay< zcOgT;z6U<~;v=l)(vGWYWouSa&)Ke%4V62tt$+Qlnydb&XPw^mAEvo1C6@P`elN27 z;hM;spFH2OwtwyAgF~sj?10L9H^#v9F?vB5r}v}tya`zfbyml z6>?LZ%qxz(rK!0w0Rn`8C8DuVeb^LY9!DHkfbVTH?m*)%R-MOD6(~i$x&cte$v6qD zAf`1^j-{z+uA!(xneYA)2zcdj)LK?V!0~7_>WtD(-3a0&&+|Az;S_~I56oN}w!|0~ zHnVMr1cncovY|yRO%J0srYPwRmdD|M>*#2Gp-3Pw1|K#@RDgQmF)@OZP67{w@bM9* zRnQ1QMhg1U2(to?DP9Ily}^({K_duT+2bJ;c`QECVARLyC^8P}K?u5C|5Y$4EcoYP68I`CUhPmxrbmMI!jTs()t z*`P5=;dl(lF2E}+s}ejrvE2WUp4|})YzM)`e-rd*f^xe=QN$EZQZR<6046b%3v=;6 z=17&56p{J5>A{941sD5G(4%MD&QF^(! zeVmPsVlMta!9^O-g}DIZt)h*Cto$&0qQ;48NX7;qUmp8SM|k{{Uu4#f3g(*uFn|bngym zNr@D#G!Z224*QXWw6%W+8j~%5pdh*bTl3QI`F4Kqa2T3a`+fNp-0LT|Ka}2u&h(}Y z4863e&Z;hcqdm173}$bx+>I2ZAX}A}^L<~e>UdIR+sNM~{WI&S~e~{6Whhsr9}FetFI|Gun6QdcpkFb3-kAi$7?Fi4cFm3g4mSH5>j5{SLhQ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/chat_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/chat_config_icon.png index 43166090474496767d5328abdde73623c7a318aa..8138e2e095cbac5ca897d60d4c02b39abdc107b1 100644 GIT binary patch literal 4508 zcmeHKYj6|S6<#pGAQ$Rl3W?*wW*x^(V5NOX+D9#evHVbi9M#C!CZurpA$fzO7235W ziv(~C#9-nyJOaaz6eyYS7{JX;APuFp2V5qhOr{xP(qIaqnG`0|I3z7N41;@D@lx;!~WQwcYSqbl%#x-do{GI)6KY+J0ac_-Y z38H8?qWYA8jOvYH8I@y-4?$v|20fRioJN0e*T1Q4c_7V~^U?lF=6avw#f=L--uiss zo2MJt!rtnb9=@>WV9il3Yfsf2hAmC|$LHnox6`e!=gmGkJ~uBWuY2v(nlEzkCx6rV z6!XZcICv(b>e(x+*WJy%kwxyly#7$eCmIK3eM@waZ}ee>{& z&VSunx1X3jZG8u3pZLpA_Wn-S^3tq{rNzxv;cdTtV(K@&6@Cx0mUX^!_3BySh$WO%)7|ShH$0+>a_kH)0doyg?nC!-kufhMfTRphyIe4 z<~>h+wDH}Y=Z+P?E(KHXXyYdf~8uP;9Hv)aG@{a#Mg4>x;L??|$1n5a z?ta*@z5C|HT^&97H(qX=Q8<3X@ut=<+aBv3x8r9W*SDG<+LHU7V(P-aUR`=+TlxmI z>7MPxiCcvgv)9h8f9LtMoSgAn^FH{+?O1eKRPBF5xqUnBMj+BXt6?>YAXBRpsIMCL zLS9sZW+178Y>oxPPxvpe4NM@Y^|}MY;5a&%Uoh-;55b4D0Tv)1mKX?INHbvx1}&)( znqJZXK?V}~-U!VLm#L*v*3|llD3>(IAw4%0LK27K!}XCsq8v%I$N@PBT{So>IbzB( zm)kQGVNl>#g5g9IBzuIXuK0$@8j+hZk|-xN5g0y%JHmUg_JlL^a=Uq_D%Kn6xttEn zn4gzaQIYt>qmQr(G$5@w1y~BV5`e~8nqhD&CrA<_a2zH1QlMNRO$Q-SHlQH5S%Em5 zNZAFF@!^ah2)Na11vo3&Y`7>=w4Eem8_jYl5Kl)Gs7eq>&B}n1AQVf}0!!H#+{PI> z*hxDsFc6Bc0fD4#j7VE;2`EYAOVvmaz;-G@;Fm4okUueC5Y88QTn>yf6T=oy0O&p# z0M~#LlGLa+Jmgh^@**7=e3A@lhsAR?8^Lfa#|%3ymLnR}qJc^hW|~cm7>(g!Ignal zC=~)E?64ZXI3fdGjd)cx;J}QeP$P0^*bNty1a#m8x(q=H%E}Wqo}#=Y&C?uD+U5`x zPo(&(lHzOpZ{Ei8K?{;iFIO};e`CUwTvLnWmC3i{Yd}dXCKOF93m%Bc5;V{tONl%o zR&q$J10lZ*_m2U=4%(IP6@$dEtW4pI#BjKk1|kmZB)|blOLn_R5e%K|;1If|`t&G> z$VGn0BjgGSG{F`6(}7k!J~EqVoow_0QU+y#6RelC^H!R-k(lNFmnX^sCs+l5b20}7 zN>c*Pv8;#-uv&@|DJvAv$aMd=@=_ErSYCm}*boPsSz!5(b|)QDc2G!5(gt^CxY1jN zcKQLnU@PwDXFz86a|#q4n`Bh{j?pzn*Qgj6mGhXo#^@Rq1EX>tQ`i5EF4OQ?Q4YaB zcu{x~Y}M7}V-@BLX=1}&4r<+U1uWMmoFIAquE2ca=tcezW_uRky& zBmalzSN~IiraG6i$jhGV+EO&F1D%v6Z&>zq|64bw#`iVjndaj?7o@DRi+5HX;5}7e zZpJF(d%5R6Vg3}L9T%P39(%iWPSFHk_E(iZzmu_c$^7}jY`0gtzqa~6@!FNP(ENXW?p{Zi hEcvz9_sfbI6%6OTu(L-e?hgQY!_(EzWt~$(698BJSiArL diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/combat_config_icon.png index 3c6dc0343cf0686edbd92e45760db6da0c7abd6d..4e5d76f557a35c4e5f9f432ada38c83be9bee6c7 100644 GIT binary patch literal 4488 zcmeHKeQ?v}8CRN;fT1kotF)JatMJuZWJ|In%UT>r<9xWq!And+I9ho1VMoKZ97(aA zYy$#IE)bfQQVOMv&vjktfb4+6)@DoEX0&Blf$Qj+m98^_>aBjWZ z^#!{Blq->-7=IEX8F%g2a16-h#>L4~&2HUz_sN(x&hEIC{dp_ROa-U-T$5w>CS2 zL@(ZYb>+pg8xCZ6y49X%vz8xM(}|sDGm6hO?mpw5;aoAUdCp1cr_Xc@yqklS{i5;t z=e9UI+7C4yysj)P?tk(h8)u5K1Ai%g?P%78y*!JQ@S2uq)u6Ip!R`Bla(-9=? zM{;4I*IigR6c3DI*AKTiOJ84<-MzA+b^r9t))rR$Sy}W&wC(v#MeW{R(;;rhihqvt z-2c?HdrP{GfArBQ{tsQ<)m52Q1zBGqwb4kqzGce5_G!!Ch(|tnB6f3DtPj~&EggJ+ zYPzq7Jh$=Wj?+grbsQPL>hAQcZ*JT1;(S|cb-eA!_ix>5xc6f9pFi!--tcgjxNgau zHsV5ii@haa$9{YxzqV!D+@@Q*;&1PrIAx*wX!Og+wYNZHpm}q!VK?i_edbrouJe_Q z@6vsj+V_9&Y3t<`m8?=*`BL5aU(a6)+V>t3PnK!f6LKHeIIV8Zfi}~@_N;wNbGltS zzxa4oKXGagx_$9s(@e(I?T=(%3C()OW;o*o_hHL zm-f{=o!icT{@%{c59VKeylqDQUCl2yw*IwkUSHbw?{r?-YPs*JoG)clH~QI{;t!wB zY*rfk=@Tcu$S<3{F1POZ57M)<@7g-|?ZxU|8egPBekb!Fxk&Ma>BneYF!^=JA>f6;(1* z7RrKSMR7SwqWLCso+|pea#!&n1blL$HM$<*tkzg8W{KG>iW;yI4u`{vlU9<%pa!PZ zhjkFg!di|2k;HIGnxM)NT~@+o0~7E{o$f?YxNaWuFBI{3hT+57APbNWYaB$Zgax;T zLe^9ZO)rWp7_qqA+Y9sZ)cAa74i>1*H&F)!?qg zh%HOp9`CS)K|w$cMG{t!>=Bx}?7vOc2;YpAL^!FAK=WbT5!yqsCzPR<$HTc4q0Vs6 z?Q){V{+y@?vdATF{eTtixWkT#yq(7=mM1ZXjbbrcbkKfQVsQZwDNydPrh~8`8Bh@1 zB10TM!HW)(q%pglpfJi#^O%Ezh`b<(c9CKkJ4vTNEKy}xl^~evl>sF}D8}KCaDwz> zKqPRC;t4Sz;&>6K#F~Gsw~yPlyaAu(U`sxJ2_jH4v59~IBi;Sq!b_=$q44so#y}iOW}fvw(w$UDnV^uCqzq1G zIOwgzlYWpdW2WB0&tRF|!5tv<*e0XmcZ{wvx<TXX_ z=9O_XCN5ae_qRuTpvdQT75LcG!m61youxm2Z2*2s&c69(>9NNq^(@(w-*n^Imb07R zVdgzdZM_@}{{Dr-pA3|)%YCj^p40pO$w~Wu>7Tc0*Y7$zJJ)*-96LtkJlH%b7eRWj WEX_Dq|BWh$kGPAX8=RZ&@enAN z;OXKRQZXkvAt50oje*fEby|SIWK|KChdc`;qAjB>BYK?o?3tu3apH!Ql+=-v#ac5Q zO-(|c=DetuW4l_wRu{fNbP0l+XkKTYg0n diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/commands_config_icon.png index 64208bb1c627023c0261384d0b33c957fbc1b930..9c09de04cda32f5d8b155228fd94f00c74fe3d8a 100644 GIT binary patch literal 4661 zcmeHLdu$W;9lxwQ(A)p8qx~+5*fdGPa6|hGqmKGvFZKsx3mn~f(WWTfX)GAHU z%Kpk(zQ_0R`F+2i@ArG>^SbKA3nshnc3~JcIUEYqpyM6Rcj9emfA8P>0XiINiPqaS zAcLpUrfxJr++Lo7ILsP4hGqYnsP3BFi5FduKeN7jYQxbPkvYvP*T+_FnH}}5JAeHo z*u4J4wHNQXW!1)+b>y3O(xLYGAFXQLS~dUq;szPma>@`Wq%t zI_&okW`lCr{Nx5-sPmz+BeB{xqGZio#Y>N!lurkPWeZE%8eZR5@>nzdPS2!G{LFIq z`qsvS2cJ8#V`bak-M8;<#lI{#_j&iWPl@|)Q04p9UhV$%y_YZfE}bcuxASOpFLnF& zO;Fod$i(VPuEmNwCbmwTF^8$Gf>W(4WwG8XSO4KYy7xCH`n*4V;f>?itD&;^eo$=Q zaU%Jc{K=E&=$#?gRqxepl~ZRvbz%SKUzC3GR_C`)6qUa7`--Kn)IZR>=floj%J#$D z;o{(*XUC4cyDN3(+^!Gq-epzYIMnd)-lRqYFB)s;M3Hfg(m^@T4F_IGD~r5i23i@0Vz-O-j<5%|fCCtmw#-^I&nSMpWt zM!fq6pMCWi*>I`7N3UxuE9mU%IMQ6#-uv`>(;IriFBcu(aGhUWQ<$B*)trO9{&+*` z{flqzeeRDF@C8qhXR!%uIs!j?>o2}DzLQ;D2jX&HAGUKw`nNlDF@<4Mcms7;ePofW znh7`1Oa;2L38X+<#oTNPsEyFZ6&N>?KH~Db2MFBId_}Hap>k13to8U)D_3 z(B#~yB&OAkfRWV9 zj5Vx^8VOiy1BXw>!-$+jOM>L}cm=O8Z1f0BTc{TuREBnQQcmL(Mn>r%YJt>x=l;LI8BXiRCXjZ02*qfT6 zFaK}W&iLRJ`J#sm3$4FAC(6%MEnJ$v%3n4axnaWb+*rs!&8J|2Wl+n-iLml2bqPqu zA-aDIH0+?<_?l)=R8bNYz>~U)cD$sc3ThsKlpw9EP!vT@&1W@)Zkf8B0cltnM?4~~ zP=n^U!e8V~_kp$68iUL$gp7wGmJyjz) zjn+ktrD@1`M~C~rrRQ`6C-aQV@&AwX6c1o%$f9zoBDx#UXs9KY)6qP8Je;mMJMc}X zH_-5d=~Yn9{eG}lE2#hI=Dfj(2L!5mUWOh#=s89WJ;(;y0d?BV+y_9 z`%ft`Bq>aV9`QR%FIrEXb)L^H#I%Bb|7+AwY6 xm439{+4$5~J%8(e`2DS$*0k%>UJG&eV_5GS>ejkRyVoImEF4@M*gdbI_21rGY-a!f literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVag8LcH|4(puFR=gqe1!mmg7x+H_FN4B zO2&J-IEGZr2|XXk*Py_|e4+PIThoER{@Oxz*Xkxt59sR9a1}B-%o@X@WuShc>Cgjn zIi|G^$`{14%u*tHKS)_kRcqP$+G2u@6F+P9uA5btZ+phhpZzP|+Hhud>h{SW8CCO{ Ue!h5XtPXO!r>mdKI;Vst0C0Rs_5c6? diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png index 120fd015d098ed45eada17b6ce32063ce3117e06..335d3c843fbbc864ee0479e68871201686acbc5d 100644 GIT binary patch literal 4452 zcmeHKeQ*@z8Q+jX%+Xko7!#YqvXN3Pd;4*FcY8}N5bi>9Ef>ykd<3=d?(Tb+mAl(x zcXM|{1w$|s2*iQ#)eI_1wFN}-hlof~KvSv?tZd*s$k^`A^O=S{$!e9a?;7B{2Q)N1C4Iz0sD0!Q#d$%XFc9^Op-?ZE}Sx_rUj#?!A)T?M*#?vr1w)l2iIOCw>^U?O`syWz^!!!4S zv*%8{@`;f1^&gLJIsN&ET}MBjdU-=fQN^g%SDM@Z(edLeIoqZmz0_$f*;IBzvGfrC zSvmXM=Db$5`KJBg!K)RulOCVec;M08($Z0#Q{MT-wN!FRQtf?Oxppo0azr~lF|iWI zu-oS=NMMWna|B6^T7j&J(3*pZ3Q+ zutBM5(%`(N+Mv|5OmfM@j0#J6N18HF2Ez+=NmJs6qQ-C&6NqY~;U)+)j`!ymjr;ur@G-rQ1;huH0&$A5 z(o{4`Wk={nRRV$ZCG@QkdJy#~RR?voQIlX*0>+H8YzSEzh>tgFk#sq-M8OD*B3B*F z$_$yZ+UE}pM3@wWm1sO2g~%S_X(*vVvWDblj-<=UP6UMy;12QbuRZOIy!?K_t4fV# zdOok4Fy|L!RZ?Uj{m4Ow4533JX~^424%#_Vq&bF!cE&E+fynU=CJV|J(+v=lpb3S* ztqQ^s8OdgMuptsUMV915yNeWM2Sd^}mII=bl^Isbf|#o*NR=Rxos|hCBPdA(veUsz zqyuu0>4CZCLxaoC(ZV{^JVj z2&f!HEijde0Md3;jo{HBFjOt5su4F~CWV`k1H*pQP%E%BTg2e7g?NVzh$Itoi6j?7Jq|z!DT|ko(1659Ql_c_ zbX^S@Nua^XFyaw$g#?=B3jaypQr$Z=n`8qt*8x#R(sq*OgN#F;2Rk)&Nt$cPMT17}7x-%)v4is&z|oH94W{>3b(zOmdHhpZhG(UP&D zof&QP)WA;P#}~@=RvvvayOmSm_{b!~;&+6u5xR!Oz_6T0)HOoauoxJY^N6~>GrBB; z--W7yaU=9za z2NdMESV9xFI<8Z=x_040#dQl8PUM;G>)4Z!&Bm4{pv;gW(6N#6L=0T)M;%y s*qD8v_Dngs_isTKBlB^$2}dvSGVBzWuXZ-?j0O3|)78&qol`;+0HDrJegFUf diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/discard_settings_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/discard_settings_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..904f27fcedab753fdbc86441fe8fc25803d5acd2 GIT binary patch literal 5168 zcmeHLeNYtV89$O#J~h&mm=SE&Q~ZeC+wZ;IEf>W*gwq@lxE7Q+upjRoTeuJJ7CC9P z5v$R{Gy?gO&`C^~mQit1u~W&%h@h!f9n7TmBP7bGqiGT}pdC^p(s%FpoMxuOB>ES7 zb9cMX`@FyR`TgGKd2Vla0M zMEn7tODzY8w#g3=5K>(RL+B$&;(yY0aZBx``Tu(44>gwBpFI}a{lND0S1)!x)B5qzx8@z`yt*|zZ^s}QNG|K| z>pRuZ`HPrXq2?bcD{eo%`>K&|GykWfetnJ8J-3yfGvLcv+#CPN>b1z`%dO`PhNxeu zR%@=^Y8~YRSu|~~vt)IxNI6lQUt>&q?$N{zC(jB0%*aStlT=f(_i)m>3cUSRd?USZ zsp&V>Wyg*^e`4RZnznRoK<;hp`xM;^a%-E#dx)XM$uJKL~X zEsa2_k0pu=lfEua?1-t3ng0Zlp9AIuzf36}{IdVwruW<4?H=NHyzs^;!)sY7?zhE6 z-|TMhI^o*pOZfh*xPHFBIepH;Emz+DVj%h2p{@tI6O!A{q-}Vm@JEAhecW|GYB^3F zPs}*Kr1<1J2mBW<9r)Ya1HqiToh45foeKQ+Dpy~)GEUvO`-2rpOySNC_SH#7>({Xl z55ICbr(w;af~4A%_!jH-D_k1~fzhZq;is-gxJz5m6P3v4C;l4!;$Ys##S5kYAPUl&i{Q zUNJ6zGA=D7KmZTWL?q-X_XdTK#TdpF;JI$bj7Zo;E3+629l40r7XS!tqD?rO5mGmj z#wX*Dw1DCg@@%U{AmEk7SgL7$0mCXQD@~P@$ro^A1kdvrPGTg9LJu^!$*YMW)Eiu& zLqsraASee^zoz=Uh>j^rz6#A^G{SLYG(L~t;TVJW21itYdSD^Zj}ayu^LVg{GlE*i zMhG$z&^OKqI$@b&c_8Sk2*@B~Bk*bqCPFCk*nEFQpgc@RkugvXJkT`=S0yGbnQ3?A zj?K^|aH}4Fcor0UlBcG+#>JWxn?4ezGcgc2eGGS!_bB(UGxTye1e;H;(8IIaEJl5O zLGj6|B7{#_#l_JaOQ5X8$|#MCE>z@20;M?GOi_|cqGf6Vl-(QDM6V2VC+mpG&J0 z10dZEb%a{M1PyD2EE(CVrIYeDQbhW@rUw(A5E%A;&;vLr5fZJS3QNQG;=(1Ar*VK%q?wl)GmkT7a1ZF21)RPg z^k`8b2ug%yN5Ub4by+EM>|a#_CLKS z;xOUo9oB5b25%eST?jUI8!}SNFxGo{jP$^JxdehtFES;4r{$WKYf1`C$$2`vrsbNF z0#kCH&aUrFuDJ0B8NdtweN@876bsMFBz(j%Lt2w*GYspm*Wden1GL2Yv(^R;hWJPH zca)*A=`m=G*6faq=uf}*=&Z%xZ)sas1Wmp9tBn4S31XA9rVIn)!Cy0$aBe#eW=3CnhEOZNWt-91+> y3{ksZI`Znv^=G=aq`uhF+}wCGbiMBQ56|C-JKX)?-iP2)275-f?cmCi>i+^!^$NZK literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/embellishments_config_icon.png index 74d5ea441e39258b86e57cdbd158107284a67433..7b6429bd0a7fc1168b87215ea58fdef09086a5d4 100644 GIT binary patch literal 4500 zcmeHKdvFuy5kK1nfn10Sj$^{p%o|EZ|P7_in^Z_(elEPrS6L7ziY$H!I)A6+Y z=aWu%x8Lq>cYnM4jc${ts&brpvKfM)aW1E$8eFrCbIfS)JM~5%4=!Cz-bH#fAA>_- zO;P zZrwb6Bxm2T_ipF*ZhdL~8Tj~=1=b1q8?KBFyk7p!;&%>oK6vQ#2bp#!dji{jVM*rx zqlL|w%|wdYT^iQ{5l`b|-J$)4`y2(?At zOOq~jzW9?J*q@iw+O!q5uQi@~x9}OhbI%*n+f|Xgv9qUb%5Hq<=dI>_omqPq6m&V- zZ(Yv6L!5m9X`8p-oXh5T)|o&0c3t18>%q@1>A!WGKUjORCGgBV=*02IUgN*KaQ4Vo zT-tY^pWJ!w+uygJJYRVA+18wr^o>W>w*0+y#`UzeM^9eaZke>LpjS0_A>XX7xUj>t zQCoY5IePR~N!8Rfvl|bu%E-%0-#-20C%faZWihSqd9}Mcgv=>17sojO5Ri2qjtBg~2p6{_30w}`8)6KB6DoRx9a-e|z-3xkhG`3J z!O`-#8YPhuGh7^&6t3D)(GLNh>`1+?hd2z2#bTBiWzoVuj9^(7!%2)JQJ{fFRt9xG zjs_zI21F9WAxFfp8q!rQ2pgEZpf&1t1Oe;tKzxCa+dT*$jP$br_`u?P2qP>w76@Re z77@KX3PAb;`d*8O7tASEEl0G*uqc;D<)B`W3L%Mu_MyhGKaq|kVzOTj0M!WaN(^yX z>2iApEer~LY9N%b0%Q--)K%p!SwmtoRubu?1_I0naffIRz+_DNz3j!se48hPSEwMDpGdPRNR#FipRu(BjNP%(%BRU@xWdjO;TU3A} z(ln{ad=bj6}2G62O%n!_26B)tU1(Im%E zvv88bQ}i`SRaX8tZDV}k;$+dCY6SRSnGhvsszzRsd`dq0)xNy@;^ z3^safaHsF*3zXts9{p{0FI~X!h?8OQJ3`k8UBhBvSjr>aHA2_07#NoFNO%3;=rZ4Z zSCoU`4_*ws3Fcq^Wfgdf94-8~(gFR|_#FF{unb7XhMaW~2+EvjoM}*dM=lVWbeFr_ zbY)ad<|E9z=WBKW(K45#)NA`hT)t;|&wZn$hK&bbD0zDGZ?a~zvkxx)VcV>SqiF?2 zQzn7q;LM8HhC_$wf~vxa>A6oLU0EFm=WdyHrG4gj$F(!*pZ0#ZcPn*fZx}DhwDe7D efOmA5av+Fa_qa)2m~|Dnf?VZQj{S3&|McIgJvOBP literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF+kmqoPQhZAPAJp z@N{tushE?TAYfFKz!R37knnzvB5je)m)^X0QasHZvVh zLVj5qNxSEs^WAg4`<;6w{k&k&{FI~zk`M$*@#MJ*;pZgtHEs-ipZ3o?BK&BtEiN$% z#RwV<>8e%(%^UUP`IE0S)U17Q)vldC+WXVQ z^Vv#n>u237TlcShX^gi$^zQS>fzsxjDJf0cXMFtLcTP^wvYmdexEp|Ly$Kccl%dpWZh$aZ|3bmVMpbT-v-+JX7)1(`ka|OiO;l z&l*Q}EJ@qk`kLq7QFZT6nfJvhG{y47{oW}hNye7sNB7Q2ocw9i?t9Ko{6KgNB@@?G zAxOfLn$ua}aXR}7f@N%byxx)5HZP;Stfg|BCn-MW6`U)Hw{y>{X@|J0V>97kTr z%kUi*Q}szF0;R&G$IlV_^OA1xH+JUSm$~x7;me;+z4UV1s1wOkoBx~NH|aN1-KS@jy?vxH*mtz3)AOt3k1R2b6?W4 zkR40PgYRBBaA?z?$D;F>Vjm)7*B^B~|MFiQosN?o9dG!A+qaSZ(?c!$R5l33mZm|0 zm3V(B$hzMuD!K%$Q9m4jkL70cW?N!d{W0{DR;qEUZkAS^^3mKd%8uT3*}4<88kvH(wC{xNAVbm@ybak^AF=)uGB*If{&fO5lgCVK^%} zWXky-Z$W>ANr6xE2V+r?>>-|prVfxbBsX&;R?gr=V0b_75bwU)W6sda>lIwOTy3W3 zaXBpJ{DPv(nj*w5Sw-a-jwLZxVr7gWL=_Wxk;G_@vD37qN{mbog7O5yh8U262?fEe z8pI)3J8dIm65{|XVGOO%7;lGf6s=Mmu(3SL+6F=7hcu{4v2t)$CX`}A*+j<10vcl} zl7&!&g28AzMo7ReE2_eCbUYhH79Q3^ei1IG<`;bc4+ea(IZVQZoC1%-LRpCcOF^Y* zs4xKbfEG~nNO)kVSo4D-Lp1p$?IcU{Bth^b&k+ne;Pfa6g`pNrRFbgLTx`T#7y*_8 zsTED7LV%bZRwFn=Ks5AFv94D-EM`)u8QDMVg$<>MhUgLv06__gfwc=1RZQ9ik`);K zdjusAgZyS?D(SRX<<13@|Y>!Q$?UEeiy&3)MCwqqOrCRL^)nUSgZj` zEKi6PACfD?fDgd^qgSwfcI_*~K-(xFQH+Q&Dh0*B+Uyvw@K75ZX_I(X6lKXi6g{k~ zMnnvO93SKnas>q%;|iVCyHvA>`bR2&xekyrjIdz@XHrH{0!do%yI-CnsWdH9G^W^i z4uicxW0J!07?5p%S6Egh__%8N$@_ZcnTlWpiV$r4w^1I&t13Zpuy<`TTtbRrF^M5m zjD<}JL_(rD?!UD0^~+-gniMGZTPcrI6uX_4;Z8-s@??_4cus*=3M`f8DY$>dx0i2l z^?Licue@yBJkI)BF&qD%W{o=xI{%=k<2HD%!ebimKc{=u4s*SmkKRq&+r4It|>v;tJj(=~@tW@|Pz!+)ad>3-Z ze7@MSy8&7fgL#jI5oCOt`AR^xZkqy)V-1hjJ@%u~lP69hf1P?Z3z~F~E2o%yr)Bda z6IP?i&JQ>4Ufn(Iz>n`)#nhLix4(blcdu6~*Vq3e>lW)6osy7|S-XpKyE2fLi;m3B ztqBWeU%}_r?-T-KE_OucE!eyF(zf%#OkWz3dFJrwS7&-USG>~t6Yqsn3%|^m)bWg? bYWw7~9j8BTUs1UOPK|ini(ChD%h&t|sE@~H literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/import_settings_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/import_settings_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b252652f4076fb400c8a92ece046a1cf00de5331 GIT binary patch literal 4736 zcmeHKeNYtV8DF%De3?)~;s@6CjA^vl+wZ;IEf;aUmC!hXDaZs0z=TeyQZ z8bl2(CPv64#xY|Pozx=QP9)P3LxU1BT5CnqG*PT&BvWnUXKOW$5&P~PAWSpUVH*1v zJF~aD&-*;T=Xrkb@7?$I$AwFmq$STxMi3;;mFFyi*L%%#%4GOE=O4EvcGgqmbM(+p z(iX1Rc;VuDVD(h3*+1i7juYRM8$NulWmeLr9HXB5O>TQ>`)cXr$_>v=6I~}e3Yve| zI;nU0w5EgaxbB@F*Av}8PcfBLFJJ>tpS+|2xp#`4$NGD@q6_G>9y znFkkGpI=*X;J~Ktmioqhd#CPQi++}H_Cnvz^OpGo_=2{Et9`$obNQ0}(wT&u-S2z$ z;Zt{Q1!_|gSyqy9vn;)H%GxP&7m~#V;DPX!%(5F-uKv^d{=RpP-4Zsu`1)aFdtRpZ zZ7Dr)?=gR=c<$-5#O}Q0tHRZt*$+Ip`jfXW{C(EBH@hYrOP$sJyR21PN*=lK%hO%0 z@~-#j_tJAee7Nk;{?_1`v#o!e*%~ewI9UGO<%dJB{)KNU$w}55UO2uugDq(|-m+P? zIBq80b9+mFL392?%Q7}*rtEU8|Kzg+xBDW$()8Njx|1JzrnAwv##uM8;-`OVyLegY z^>0T8ynT;<`uV3=`K9J-+Oo#Xgs$Gs?y6O}K*&uu{*f4T0j? zr5>fWLJ?HUqDPanq9O$F0YgHgzDj>sjM^hQg+UK2T;n&S zDCQ5(Ga=#_P7qc?deG1Ve$>R2zz1E!Fe^DK za5%!Gz^nU$u_#FPC{IJz?vORAHghD_&d5Sw_%QA$@1fpf&d|&47M%g5$}G?2 zv|G&lq8dU-sM`E1JDHuaY8YT%6iP1b`qiI=_8HFAJq(fCol_RS%p;QP(uo43!XpEys z4r6FS#RQJCVT259imIssPsgiK74fk^$S1++)P0f{;6cAPmct}m%r11cafqzBq!3O z$a3EzD3KW9A5e9z=D&HH%LmPhPkNpnhWTq^rudpF2CL#v@yAL%wwO>fwk$+RiMJ4z zs(~7-6Jo`Ol$Da-3*h@>P_RRG{Y%6^vlNgiM#314k}-y3ZJ3}6BoqV5$^s`zifkK= z9u8O~Ve{0WF1S3*}$O`|D_Gp5#v63WVDle-TBTxX7 z8H&YN0Vq7Fak45gUv+zff*)!x3pd~QLt4$k|3l4jhY=eDob|X3Zai=w!-qGrK{=RP z#$7xHSJ7R}0HMc|jEUcIy2j}m69Z#%9#_{mU1MTkOwQx#`pW1^zVj&z{P6#41b*nI zceo1RNAhGje~A<6K=P4C$|lxKhnA#Z-VX`k91y=@k%&+Ll-+ZE=bi&{E*U9};Cb~}5wQ$G_tsiec znmVcR3#I4AHmYIW@mtq9rs;Kc!=l@q<8p$h>IbI}Z+Wu&tox}wKYPiZP5FOO5NZ@o kOlj;FzoiCLRSg8PtdPXx1rx@-(3gjcA&;vu9bi& z9ttZy*$;7Tc?jY#Ci^ff)*bLXGHyRU_R0sdB2T`(I+U>|axB>K1v%&8R(XBs?$kd_ z53T4SV;VK9>b~_$-#_q>~FNTc~T2%UnyU)JN@hRy=6Yxe*T5r&s$ta7w#GP zsX6^b_qO!Q7bmC9Zpodv_itI-=Kbm$zvtFBFK55^@!=mvpQydxpLuQul$K0?cjuH- zJzGwuoply|SaIMicI=ro?9@XWe`pz>{f|xc&OgzO(m6n9ST?yi{B{K@-UF>J(> zveW4)ayt9#K~-%2`Lm9~{c|$9mXtQVbVq7a11D`Oj=XAY{_Ruw9iDE(cE0V=??<}R zThgW$?Av+z^g-d{eO(o0sbzT+u42m~p%U%cN!K@|J$xV*I{8fWQfBl5wzUGbe>yqE zdz3lWxV!Dhj;G$)G3v2fQzlGoZF_a5xv3)7yyJ=9-kPbOSM>b-T1MRi`=r$iW;D~E zbu`!-Ds9B`-{mfAXuanby_;i)UmP=Oc6f2*@>=x}sI9Dj+F!GUb7imJQ+{4pWc8l8 z>rBT>k3UC#`RF1}S+?l4>f?W$xe9c=xLw*^tY(bPp5B;NJ>%tOLwm=BtqZfdT$?U_ zk$H_i_=0i6{MQY4+NXHx42Qn0yT0#2@aP%suWrMiYdf0)tL9_x?49!(IC1LWuFv=p zS3l@%J^t+{n>tU<{Az9Ul-yhDchxriv-u|%Mr`qI zsl8@->#d8q#nV=2SMOYrl96%Cx_b`)>{2YcB&uBBB44_c@|8b)JTtNq$FOk=Wi(&q z?)ki^1WZ6u1Zau{LTKd*3zUvg9z9S=^L65M;K$S0nZ6bKEA{?uMYyfIgC}B7UD@V8jYHwW|I=GBx$?dPEriXFa)w7)a5}9 z#E77pr9&hzTu>Fma!8YvAg*HqL8;apMkCVW{rLq#ZubCuQ0-#@@j=Ewh@?#v83>Tc z9;%ifK_Gnz{iuiPMaz^dfvQp+7GZt_2DPkY2uU394^@Z#@p2@Qgnk%6rYed`-w?8( z$n6>M&?%^t1EIJVBKrnQP4*3vbwh5tCSFc*BFKFJ_Xg|!+T+H^%I)S|ide0uSLAXS z_4vG`h_b}TA8j@p%~7n6pasrGuvWWB00BybnKLuAg^{d4@FhVN1yv0MMW{m|aFdL1 zL_24*TWxj%+RS!>6>N~;tQ19^>m+GdF22s)qu_?ZKJJbj-qMCY^Q089W+`5!z!9Z9hIg`W-hML8^fb= z5Vb&`R0I&0qiT3(7y?ZRdlkj+FzQL+y61q}jTV#yG~fanM4%MI@|1;V7%$E8w1uac z`zeN}lI#^p_AUQ!*81|na}rH2lvNaed0doOQ>AcO;w|y&m*a~G$K%U_2V$ZG6+~cy zV}zAZiB%w23DN%1H?aM3`A3Gq25c5PC5nXI&PoJJ+c^SQ1c?x7k!A%BiZ<|X=&It= zq96?ODiM!}D>R^SuJC*NS~V-q+CVnZDya7XQASV}g5tciRp-uZHIg^KJlbldpoOCd zMi9*e3w&0>Ze;->iDsLRqX87Gi5VD3_kSxdX(IZ|%OUj*vA>x){xjBRV1n^a^-osBVFqr8rO-Ba-LXRcV*gIwPRYv)1|fkBj5k>Hw)I> z(fh#hH`^CyxXbFKRcCj$r(+GHe$Nzy3%SUl%^QCw?aB-G%zfjDwz>B``1SOIe|h`r u_?WG*{qc_;dF2f%W&7#(dLmbH+%v(-`YWd=p3g)vv7-E9*Xwg1Tk|jPU`($7 literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF+H}sz`a8MAK|Kj2SIiOUS zr;B4q#hm1X1OX#6vqXl*3tP4*7#yC{xKP5SI-;yZ#oWlCK(e`!p;@>k@sI#dqJ*J@ zGvkDZyly<1nE@rwctj+n;~A6{9m~w+FaRmdz4ng_V=9;I|Ku+~^^>bP0 Hl+XkKZ2dlr diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png index 17badfe1340dca17fa446e9262fadc575c85c72e..1f8c741c216dd718c2646bf1d1a9052960953b18 100644 GIT binary patch literal 4496 zcmeHKYj6|S6<%YEv0NB}UE*X6tk(vTz-k}TuB62>7|UQ$%V>-MnvE@1FCWbM9!jxoeh8GTd*#Fl>^u%2A81Q}oZo3Fv#~=luX(IvYK8 zS}lm<;fUgs0}$6Xh9M3UvJb-&9|YYGPks~s)|a2=&tKHA&^r0i`LgAY*ZfOYpLl;B zm^z0olD|B&rjNk`=OX{=URurUcZvRnlPlcwKv*V$%wEV}*ozJ<5OT`H^3f8KK@ z2g5R+lq)LS&Weh`gisp$9@}BBdUIi6=bGg$hrgZO(rlG}QWHBuBwv1}vd#U0;h3=J zky}}=`*-HwyQJg9M;~>0f8WtrzbboG`IN7)4Y6>owqt7l?)=riPK0}Y5WhYneieJM z9=`ggyiCt|wtL&@J?|WU=Irr_YsY6!xo6j&BXdkG^@-&1@7=i3c<-OtHf9v)@;{mH<-Vc9K z_Ydz%-gD)?D{Y6r`yBO`M^;*u4J(gEFaC1QCeU{1m~^^EEzFr$v@Jhc@>0_9YTJ|- zR}^%{PXd} zz0YNDRhn*dr%ruQRx@++yy%JVXBHNYYn}CW!}UabOIExtaL#l48-+N!@bZihwQ}F*WVy;S+WzWI2Y{-SHN|0 zRbvD$Z>;f%jq635L@X#XlqLj35QG}Q6Tv`86%uwL#VerSx|t&I6hvEZC+b{oyh4dU z+-x)(X|ggQ$5^7wfR{!jpHS;qJV1f&?8G`v3kwt#kH?L1lTnHIDaK~AQ8Y`jEQt`L zx-q1I1Q}9`b&52H1FB*~4r{U!!gWsIRic`mAkaEK7+)~#at+ak)BzQc9#jH^DaJ@s z!5}r=8&!_T3R{L~Qy>DxKkhAon5O5$M6(Q(%O0xdewIM)mNV z4m+XmFGz|gOG4_W*T$P^lZ_`C#>S9ls|k<*TD+vmECSBPTP0ES4Wn{~R1Jhgs8b+LY^Q4(KTS*{UInp9p%#4>~crOEoQ7ntds4GEWcvL!-gs8002Lbe& zNR!ASDqvwqtA*uAhLc1FNG6su(J3lP6c#IyAVB4mgTN1|aLAup&;=LD-A+5f8q?5} z#T@{e4>_P2kVBFZSMPv5au6=pfUYNFVR)0pYGW9hV{ANs2ecAKRMd+)D?=Mi*3^n# z7y+e&qy>7XB7&41Wg}EXAkdVEM^OTHLJtAgJ%^TEXrLsZ0SC|^BBfcgKyw1idKiV{)T4Y8QKhh4U%Sy7gdmf7SakKAbFlQn{8GGGMslL zyQ=uKIEcV0LsU94OkFSGz9gt)s&5^X#!|(z}3yhVZ?tXd}FYuWd z2~7%XV@b2m!jXV8n@A|xB;Eo!3G(Tp4T<-^r8lf22Gc90^aF9Qn5ER$%AE!bJ3)~w zX&XA3(LqlQo%92Gp;+(cYoN{U<`y_Uw#lgU9g}NJu2Cs4D)3l$jmb4C1x5uP>#qNs zT!uT(iZF!!;Kk9C;426CO!O2v!TX&h4y<2)A3FQvR%FQuSJkT+mYb)4GO)e-3Xm~d zbGj6_zx4lKgj?9 literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFEaktF()}8AtWpzA%QbFVNJ&ykCctC5>CA6c=N*J-HU`53rrW!Uif&!;j?{D-f{Cp h%SuShke_A1z#t@OacZN$_nRR1c)I$ztaD0e0sv!CJ9p6i80tdtpF-9kaWrJd;+1tlGcg+RTyM&z0#WOhqX{oS}-yU1;Zjal| z-I10@1Tus`N_Yr^fJl8HOdvBwp$a8wK@@5$Z9%I+1R0ffAa!(1v^42&?~;&Ao#|wh z|8h6``u@J(&+q&Fd>^yh%3WZVdI*>^jAxszPxWiTi40~q5h+&QF za``+i*I+y_ie1ZFo#lU+oqu{^b@RS^Gn>~r#Ql}Am#~)S*O#{Y-ZQqbI~II>m-m6q zQ|_D7`SOP!p5ZTap01sjIjsRrfsqt>)*;;Vm@Astp z-=hE0bZp1D!|P8R9=GUw>DiOF?RaUXxw$sca`+d$z4iB9sr}%SzWmjXc8aSWo6$mD zYF}qx7qH{IKQCUoZrg)vdv_(y?wyb`EBdq8R~ywgxrRXFhG6|3hr95pSLfg4Yi$0j z_g`(__w%j9wFNZ}Woga9x{JS?xsq$&+a?~XRP)CdPH&o0H{;hW#slry&(1A4?cVw2 zM^pQ#GtXe#D-Id+m|Wj#l<5gi_;okX=wgu%R}9U?T>VPy2W(==7O(e<7w<)E6Of!&1_T} z`m9Hfepy^OZB=32%fC#|&rjR(;Mpg767hv`rGJmy)02KZ7`-?(wgN?vthq9*ule2z zR!~AFPE>ecN`xY?@DQYERwBX)OMr&*ARvdGSodouF;o_v*gUJ3^hR7@v0Pps1=aPH zexZJez=+taVq;N)g#aO-acCkG46AIyi6wDac(02I3{9$NOPttzuMc%8QGi-Z788k= zCgd266&ul_s3@^j?y><0_~gVEYg&XQhJ;aCKQ&;}UpS zEzluS7;c~nQ8}W?N*L8KIbNyLoEQez(Lw)05wCX$KCBL~0Qn#iT!f%ZBoPV`!!1;; zGzLKi9QsBJ)eqa0r~;}|7ZpHh41~3U;Si!QWFM)E29x240s(>`1XWeID>Y)vIUcWX z$U>(eAcrDJD@gVTO-+_=lQqIOeI*&ra7Uo|5bg-=!Pt|^P|NFO-HK4ByXSE`F@1kl zR0LUMleczJqDeCiaLOv!aSLrGah|c!xJ6=kj%0wHw3&xNdBUp3g$1BPL2#1{acpM6 zB9an?J4BlWxA3%xb7s;GPn5&Ka2C5w8V>PTREAZ_1&4d3Lx~W|AyH4=%amw{gXxq*TmTS}a3Hy$6V8_SJWh-@k+&tjAg4*t z0QP_!7L~Yqd&w_{K()r{d{TDGX0|hwg?3mSW-8@%60rtERalEUDn**iDJS&AurM4* zEvHv11W3ZdXjoSiaGDbJD@xFb=@6)HIkfDB4JC3K=jJp3K}p)el2(?c{gj!tGAv2| zkfd31n7$&)(z5@jt+x+aluCNJtit`5B}J*8ss>9_PpQYCoNOi(O|}Kg38@fNE(XM; zpAajxBrN8_0RZR6K*0{mkkKr#}rQ9N$5OFS$Fs~u-3K;dSa83??@z!MmWt}2oi z=c1q_0C|L5!2(Tkg+4rxsvnHhk1qy#9w22nX~jv0pR%zO%~E!ZxbxwW3`Lnq3x$hz zGl1bq0C!kO3g>ydV1sSMkQ6=A-ESA(u!b~x<pP>%c>7xs zgy9Qb9DWH_>>|#>ugDDk$8+3Bzy9BQ;>9gcGCopXt0KsRd-TJA?A(_vlmz(&Gpzr=U*Y|E0cAe5OrThlr;B4q#hlVp zhI|bQBFq;aDOjs3s3tz+kjQ_)*r0>D#>Hf7vgvFiNzJ2%E%_(#+42f7eay zid~Gba(FY_7k()dZYi~@R_$**Iv>UTk9c|?%$xg)`?)1=|BEL-EI>~3boFyt=akR{ E0K(Qk*8l(j diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png index 76f7ee61af10347b196d2e77ed0f07e07b9601f1..2c7e2ae9f31348949ad22fb398530194cf6f99c0 100644 GIT binary patch literal 4530 zcmeHKYj6|S6<)_7#v(9ah{5178{w3;VYM$kR$I%)NXAxzjA{#mlQgi8E3qJHg?44h zPHG@H)X2pxBs}U;$B?#3NCTcc2m?d02`(imX=xkUI;2hsq-ILuGM)h(GNyMWKjcYf zI-Zt)mS(lP=brQ3bH4N4JG$H4<)u?~b9D%UOm&tyD&T#(c1^wy{?6~e!@=9>I?pP# zf{UV|urV0|G4L| zctBq6eP&?sy*cS@#^R!^KP<}^jy!56MCOAzzb)K`UG8ZuZ@@2BRnJ2T-jop}twFNe z-A=oGxE@%=zVGj_mA$h#w`+A}(}4#vni?7LuYwpfj zvr9YQ`uO8B{0E&~)hjbr7Ek{Y*-#UzPDiv1s?PRiE=!X3wRZ zOYH~NJ&#|0qKc6>RJ|Ix@au&ex%Rf##G~a(Zswu~x6O*=zu2rh*gk##iUnPcmK&es z4U%VG(C=AxNH@ot?cSn0dwt8D&c5KeOX{Cpy5DT>XbNmxhMYLQ_*L%1o-;>2V$;6- zeaEf~*Zlh}?mf>v^zM^4W6{-7`A(~J^Je;0fA~UPO+AVr(^g1OU#ncp zSV0aLI8o+-Ar=Th;UP#tQ7ps>>w${$z$XQ5`o7~Q^{6D;^eas+!WFWEwNhDK7*y7k zdxX06f>qQP73vCNECdJul|y3ze^6m#Hhlt@h0mH9*P{s+b-hi$%H>Awau}dSgV8`> zB{8Xn(iiH`g0SdiD;!IQAmE!#zgAU4ERIK`QA3nA$YCE&TCG-`pm2)9pa-VZ230PG z1(gLFL=wXR6d^2yR7nn^8Yaif5!I&G!*O&tzd*?48i5ZgLo7f(@E8}uNdtig0(feK zqL$P^kfDUWHbU{hWr|k-MUI38P*MYe>Vi}VQ5cC2MZ*3>Iii3AKL|iq1-cho~U zMy~~6jLAY`7KX7}c>ri5;Y~n^0=rZW2RPVHDZu#v9t!#r0~+CMvD<0WQwCzx;`Vc@ z7Y4vJAO%G^s*DbKqyVT?IgL-!LYird)nYM|G-0%oqfS*ItUxVls3c*anZ$_J7#5ZT zspT}KLV$!FR>RuEfK%nLN0$9Iy_OWJMUD)+;DQo4m2+?^fS?3rWC;^XQ63ULSXtWq zFhQ|IioYyM-rE1>tt}t4AldXXNrCg%CQQjSRS7mE-;%F>DY2MPG_fpLPDqxZa5X?o z+=p;mosY&OxgK^#33S~5dr)e3@4nW zg^?AJr`83tXQXw+121K_$iF&rXcpU3R?*jT_IKxY^nusA2>N0BwHanQB3UCoswjWj znx9NUmICCj-yV1)ZP#}B{iFTdZu$J2G9PhGFy|5@>lAHYlyXGyu^ J(2_OJ{0A<@Q0)K! literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6toHO32_C|WP=O(Y6d{fA|*k7!3^{7D+ugg|G&SW{=GxMc>|pUIjhdI zzte#7Q#@T9Ln`Lj_D2dGR^V}Njbt&LV6yjrY+>GgHf&F}h$bN;jUlWCd;V+bLdX$)#YqEi+7-8+69lgxCO z*8kX>{q?@@ecpSY_uhAIx8&tyPfxrr5rUxUE~g_O+-K_N)G6S)@atPFxE-zb6lwWv z2o3}lNiG**ttueGVpx_SDEy%>uQ<62PP%?!&Vw1wJL*3@{fFktx&@o2yxY3Et$xD~ z$wi-Bd!yu&Go5SdUgnORUtP0y|5^Cyr62Y>nGfz{y0^_Je4^=|v!wmRxlQL6qdBjp z@BVd@t^Jk#4Xp#p%B-QSgIn(9LOcJJ^>*9Lk6KPDYYwa(DET0H9s6~CPX3cu#joa< zb$!H-{l7dDg<*B)|HoSA1`DbQk>Z+8+(w7dUtgFC}3{Kl_ zTC&XWOl?_b=d<0db&YKYk`L6v*W&sv_U`%|`Oy%z?9k>by?6izgReP96`X)D74mM;@Em=nFS--cXz{VfER1shUmcH{1VU0g3atAk=eb&iLx zF5_tdS-B!HEzAG_pQy2L*jMgXnXnCs;4t6^lOV_Aq0NZK2Q-XkEA2;m{>0QfT{|-660KEyWDxB z7CHr9*%ydd0kX$wYO*v&*0|X8l}I|VfdKPS+;Q3?xkr?NmfOuZ6uv?a&*iWox_?Gc zcv)Z~kCY%;O;(CPDURY%6V6H~OS1%Ow3;kNBPVet-WUVr@~ax_=S3X~fE#3hW9H0) zC|XEV;3W%cqG<}HDGP_1SPRV?an?jhWDG=ZPzGJemd8e=LkR#1H?t-)B^ptRBq-Em z#03CFSx}r4ExaHJwAC1mM&Ow&CFo;8Ib|Q~6|sQd8}XqN&ZOtLYzS$<$0T{>tR?{i zFaxq*P(te1l1KK51sbdKNmvNVXvIxtnzRzMl^#=CD+X22i#jTS8;sV-ie4B7qywmB z^-cu<5jn_)u?Iy~Q-U5vDYqedP_S+}y6gr6C9oRnU^Nkd;-m@W&XA;sFfk;~nCS;_ zlEGv26+xD&{+qTwK5$yJ=uTM${;MLQ=u8!e8=`N~*K#>BOfVc73x?&RDX46vC`94} zSkWbZJ?r<1VE-6y*b%w>JM~MV+aDlZhv|LCmD@AX+#Ax zZAHOs7*S5J(x}LrMOvUJ38$&?;r?&w#dO3-dTE%xA&wL?4f{^HqY5!QD4-=O13NR= z=&{kAewZ(PPrZ%DaGTvm4*+`7$%Ocwq-&C{2{AAs<;m`vq-#P9Oh|dMyZ&!+aLSvB>0M)!mY}7K)3W?OZ)Gefg~Z|d_;wyX|we+4%+_Wy+9bRx!jrY zpWi(e{0xn0o$9kf@pg6GuPkQ&&;=!Tp6ZF9y6+-t4=bvxLvpsXx_0G8V z3$!l$^7Q8tvis*X3H?W_mj8Bl#vec4d3^K9i+2(=YQtU7?m6#oY!A&o)W;nDx!mHE z&gZAKw)8!ay5z_=e|z}($IgCMa$(@jp9SN7Y^&+JYt!^&z>|%yAsZD6Rbu868;y literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*ID&|G!@#prHP}LVv=22ZQs)@6SB| zN+x@{IEGZriR};MYf#{E?sna-*!A6ht-}O^-_G|=2bn$azVX2M*!~%5_Aa58y%OoO z1lM(XJZpJaa;E3>#s%FK(}Se4->wl&l&>~9=6vsO`Qw}Sqi(TJNL}NpR_~nlWA4gr Zm$>6Xm=*?ZnGptZzo)C8%Q~loCICy2QO^JX diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png index 0cd3dd0af545c1716d3d986375df147b57c8cad7..270912df0be17a838ffb89073e82cbe07b20390e 100644 GIT binary patch literal 4696 zcmeHKeQXow9lk)D5R>pRmXbmyjw9=!+xb5Ib&E-YZ4x(_c!_CDSe3kY_u9E(`;6~` zoouBvDQ(uEwZOzm)Q+-M8v=?ZVCsNX1OgSTt5Sy6ji#lHvXZI=%3z`zP1t*OKDA0y zw6ec))_wgxp7;Gd@AJF!{n)>R{d`i?Q~aD`=XB@GNl#=3KG5`h_LlC=RfR#l|JvdySBitDk2znO*6^Nx_55Au@>gM4)>Deh z<@dT=!}XvlUVMCuv$ChG=u|^(CsFXs1GCqiep@*2@f1}RbT;lfR8ZecAHFrci!WYc z{z==~%&bD4%^(m`^4QR zxs$U!e_q^h`slv+g-iS1nYT}?9z4lI-WmUR$vKsoZYiUBwTlL zXWo6`!|H8S57iZHE}FjEwdwNb$M0TDz7|qi|KKw{w6VK0`h@$*!N*>H|IpRzQeSK* zHWlulrPU-L~5s-~2}7E$`3r&TRRD-&B*ED*dJUFt%$= zWBjeFuO58vTn=9G82JH~^GvsU$AP~%FF4=s>pK<}1_rRb3lp#J30dP9Hj`J7zJk6L zf}}>xKvqR)PDPOeZ6&3tIFQyt9T#C(i8+buM~@M>B0GsXi;wojU9d^1Y)!!0)|CON zb*`aRqd3m?;8Jhv;jaM9}BQU1|d2yqP!Cq$j1U zXNjdIyd)uqgc|qqAqaHmB${+RE>Ki5nKUOkvziD~jKkreXqIAG5=D?&OH2nTGNvsu zATk(ks7VPWt}AK`H!y*yHtSA;Kz@99e$lwkHv%8ihFCy+P$>|n7&A>pqtw_8P4}!v zAVU-S(hMzt+LWq+n%bO@pl3ad>5Ilf$kIrDyg3m`mm^CQjKC-g)zGNSxFIXNKL1FD zK|xrF#?x7d>~WF05*j6I+}sRLx}32SLFps7Z;b{WW4S%emm8v{|DP>?D?WbCXAC>cRRfdfGSNIG~1 zk}|{6bjTq=PLk75vLq~56H$PcQ;C8wq~ft~+F=kbl>5C-f;H2l7JmfjA(Vi6K#9p} zQX6#zlqjs#fx#zZW2~H=w(&L_&!9p^gC2zm4QbIpWoR>JPkW4o5l}gZT3{#@0i^Ay z8o`x-Kvxq1RgE|aV^X-0IpX%AhLV8}+(3s2lxBH>wg@a6V0eMG2)ymvG%L_!;#FA* zwfwheqkZs_%%WE+8XCVPZOZgiEnJtm%iKnkbTi?2x-A4CWlGS%dYIuDVP#xW6NrT& zdVUNEcG#|bi5Mg+EwUmFkdz!8$xEC}B2`#PUbNe77S17A>=}|q&^0xrCqV+1hY^p6 zDe=9Ge2!<9c-2bCIMuapUk~xwU9gyVh93<_s19c)#+aP1J zTNy<2IN5v^<)sBbTwV!fJnx6KT0;GYnlk}oUJz*2GdA?%LGLkYPxed{A zFNeVK$w4N>?<8H5bWMnX2?bB8Ym%-BF)*RvNp*c?beTp!g<%Z+e@&tfU2gl;&FCXJ zTdb;ZV;>p6BWJ}1WXX+JuGTPY`W$1=!n$58M8+K5>+|IF-~T|~gVcep^Q)1`<8_w@ z>~BhP*_69z>n*#lQI_SCvx*<(rcRyObMDvGfBV6X!o~Nk`0MxE@?Y*N>3E%*Wr literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFlFzshFeMYskkK$lwyMy85QmbB?NBW(}D{Ypsi!+k-u)9CDK@yEt)2gWtl77R`%) z+@GHomu4in;Ih0QXH?%6!<6k0aehE=IY{VfNxE$fOI zFIBJGE^HX diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png index b3bcb883edebe0672e3f4845ec37f5adaa363b35..98b2fe82a5154f26aaf0d5727d7ca5e9d4eddd45 100644 GIT binary patch literal 4493 zcmeHKe{2)?6+Z}&)D*;kL1;6$UVv;`&iC6tu5rMNP2v^@FBnLoZt4AWuGl`ucd?!H z2MM$g$eM`+N{Rvtow^PXB-_*<8e?_FQU(ZB+PX|ISlhHxsaTsLBm#_*eb3GhN2@eN z8~?@D`R?BLz0Z5^^WOK#-`&3Q(s`ywOb`Uk^OU(Nz>o?BuueLSps~)`naY0vmg|;7a z-fer2w5~^LROgNSFBk1?WwsY??_8JfUi;|#f8eWoHdI==j(oDV;N-KnmPLDBzk6%o zpQ{&zx^fS_TK{nJ>zs(T_s}`)PO|Wgj!XQ)nm_&J@ciV8E6-HrH5J3VA!x>nN=b>& zQ&KXP4oITw`Mr*^Gi&quYc{sN_U-J}7Mu9X^4L+N?e#tGUf*TY3AXd8yR*HIv@c#- z+V|#1AD!j@+SgyTC3}l=!9A!h7OBwpE*v?qxcZNY$d#YQhnL5Ppd(e%u}h1x{1?eT z?|!HALeHMlJvmR$%3AQP{hdb(sMe}PThFt%Z#ORexauFD-Ot|gcL?XJZ6?zs!sM1K^!^Rjl1YYy!ENwD#-%~klyZ!5p#H(UIJ%LaR2 zduAW@=~J6+YTf4J^#i{z*v9pCpAg?E*YX}Jd~EmP`jtO#Gac()aAZ?{zw6+wPnO>& z&i)KJu>Pbe*S^HJ!*uS(j*-5h@Wny>1Fz}5=45MV+j{8qskO(szkhi4t*h*ed+#Ur z58U|M!Q_>K&tGm^Qap3#Tg|Q4+g19MN?t@o6lwC<<0C^b^gc0iFi$19XYHF4`+QIj1DZ1y#Pbd{7njIuS)NFR!~D` zPE>ixoCrlg-$78(nnZ*Xwn{q8O93V9K!#4ei@=KLK(;Vm+#4y8YL&9asI;-M+%Gh4 z73?Cirr1=JU;#i#(m6O03WhZ{;XqQjEO<7=7y_qM^sNr0((8ju)Tjj0X4;IS?t~H} zkzx~E6cuH*!nJM`0=zkpT3wH@7#5Gm&2h@CMgtgOx7#tC#7Gha8mQI~*0}^4*76OA zG=@vkgs2kH6*UYSm>jRx>kb3~>+o27p@`Qz4jXQ$_kJ@NmEzk39=@|W~`*r$qWRTkK<0#9?LzY479vn)};#dMtB~V12O!wqADmN zn|j3Ul1N)b0u=;`LTL);P@9#ZQGq079Jlipo+2`!JYh}e!h&Q#0dTVdaBQMXk|IH% zJcUarEn9JvBV-=sXhI@rhO+UDoB^>Rs(`NKf|*enP$Gb`%T`*pSt-;aQx=rAaSUpc zX&Z=(Fyi599;Z@JqQI_GqahBIQweba35$dSsRe^@*6H&&5YmiKNPIy~mw^G;14>v_ zPDRTlzJqq&5=_r?v&l3F#CxE+&boI006ANvP$* z0SU~H(S{w9E8oxz3}>@gX%0szf&u*`SZI{93L+}txL~Cv5w~*o$>^FY>v1kBIRk)4 zz!hlF6j$(fM@#j+$@=kH$*2RM48<7~xA_SROED~AN3aK<9%&_co1NrQ(F)p}78x1k z84^bcinqx!CGs3YPY(BgOE04%#?mXojDa{-%p&YR%AHoon4o}`vT3X^YLCn5w_Ui{-Zw9a=VTq(+B;I)yYuF8|EgF?@ridMyJmGh|D7#vsJr`=xT@>b z_!sXD8zi5g4D>R2(;jH;x S1?vS~AdkD;b@B&KZ~r&0^Fglw literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_R-32_C|q=Ln)ZYP0y1WSVaf*Bmn?>7+WfB%2J!u^Ex0R{En_?l&a zk|CZhjv*Cu*7jZGYfunz+Bvi7?wWu9vyJa&eY@hEzUP1hbH)vkG@BzXo|TesTwmp0 z=M7iLR#4c(d}N~4qn_3@odw%N!*y=0*>-e))7+%L_eyIjs+jg@vTn@CoZSy{u&1k^ J%Q~loCIB?gNc;c* diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png index 6029861fe8a80723371a6bbc8bda9cecd7bfd049..694940b7bce0298bd1160fe34a65a2ddec15608b 100644 GIT binary patch literal 4281 zcmeHKe{d639$y$~Ay>R|phZMjw;+15Np|ylZ76M$wh>Z7=@kl`^=0>Mx-`kAyW1wM zo&~8tP=uC_wSy>#pari`j`L0iI~0rODV{_9i9ivCqBqVJoWVOgR}1%c)0TA3nVZg> z|23J-?tb6r`+48*=Y8LI@;3Pk^QY=&=`akN>Md{=p?kV|O-@0-bFbY1=ysyEc$HEF zVt7;%c_9RGr6vk-7#Da9i=PSm*WB8Lrwx2Fh~`_Twghd zzWZYT+hrHKk1yZ&THwgnOV^jQox?Y$oO!?Td+wLz&&;2DU}EO{w_ts9N8Q(%WZ|Kl zy)QO8JKEcx*ndUL&b!|5{id0L*sI^>z4K~%&#vdh z$NT!Gc)_B1x(%LC8a`OwkkZ(>`JS|ey1VwSZ~D;N-ca|*_Q_@E^rf?uDGxSd*o1n) z6V{Hy<^f9xi{9s$|qlH<*sY#pW9?>8D@h?Yu+jjW6iR=7#J0ANkyT7NcbjQn5(>s-Tf8gxgON+}h$}ORRfzy9l zvtaRsJKp-3xxRXO%fP&j?rtK#v(p-_?CI`xUXW5})_gqQCGEj{b%!Ruy|dePdBZDf zc8P!MYwOthNh-eNx8zq?>QkNWO@H{pdA{dt&)H+aGlPRz%}QzC0{PDKsP3u-R9~xn zOBq%S>j5VQpgtasqQb+ltn7FcuoY0j128B=oW#|m#|T{DoWx3t&*+P~V7X9GE5Q}D zg~e=b1?%95>_xh)ID-hnPyu*69E!+H+(~G>40=}01_IY0N`;eH<@4h%QG&QxZ`K=0 zPh6;`iA6d*OX7H@$elMtf!>@%xuQfFgCQ1+>0>6nCV#_{3!!cm`Zggzn5YbP*pTcY zE1qgZG8E8HddS6Sn;MFsELKS@^i;!$l9^1wu_OM`Dk-F;!?6Y!f?))e(X7;{Df7KP z|A>bwK~M-sH7_LgD5N6rH^mwin>wPUlN<AJJQicX zPT8yul6KH6qJV&O@OGADDM$lA*(qQRBvCAr1XPtElpK{x#UUz+GukX>tC{41i6YIE z!-lAAJV~*3#0|_g$Qm^&j%D&hDGbnZ3Skh0hG-V$@oRyd@W+H`)#&(J#jj58qW@kz#{@3>s!a*auWF@eXcYh11|DKIARcy;~X zi_Au8!B6kY!4=pj5`NUrbl83E1`>Gm$Y> z@%lWef1h-F+BEB&dj}ekiSxR1itQ)+nodsb#M4}Tzi%AOKRNr#6D6&>bobVOPT7;S zavKteNki3o~2y-PpQ$;l?jNJ=k{C rWIB}g^5uvAwXQnjjt|#eY`vBd+?gA#J$=H1=EJ<6Lid5(hadkB^NI?7 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFqA+A6g57@4ep9PfWDhcunPPqU7eZYB!{SF12-)~|Bikf)3IEGZr zNlpl1Vismo^m%p5(W&d>X}TOZCgZ?7c@vun8+CPa2gxK{)1|* T3a{HjL6&;D`njxgN@xNAVka=u diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/uncategorized_config_icon.png index 5f8bc4143a6ac1356aabf5bc984227d421dfd946..35ce6fc1246ae4b9135da082b59d2bacb3d4d440 100644 GIT binary patch delta 535 zcmV+y0_gp#0=fi{8Gi-<001BJ|6u?C0fcEoLr_UWLm+T+Z)Rz1WdHyuk$sUpNW(xJ z#a~m4A}xXz5pl>+o$R6_j-`r4uu$3xtvZ-o`UOoIk`xz5!L{Jv$70pN#aUMeS3wZ` z0C9G3Qgo3L|Cbb6#CUMrk9YSTckck9S!Jr(69ZJuGSZ2-n19Q!ioLH0U>HFRA|x?W zPi7Xg@El+F@bUF7%Co%B{W(HP!DN6>B#trNu!uK^XE!aK^FDEyl_iDvoOsfp3lcwa zU3U46bIDy{D6rE*M`2bV*G`2j~SB3=<8V6>v8I000?u zMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0000INklT7QMRaq+k zRxm939CytY7LPI~_|5DCf_ip;6?XznOF1*@#TX)KW*1u%0-&OX*!B;-)Z1(Ou zWEXy^>+nzhUJcBFSc6$E~FX8w) z>5k!DAFpm$d0%NpeP;4L$JS52JUZMPea$D=yyG_9x4FG8_=I!I(4)Wo=!n%s^ zUoRbOdG<^qUhpV+4oiHx-MRbKzuV8+PxbU1@e4O^Vh0vR-rVoAgfT4jAsMw-nfphA zs058bQoPU@3nB$NvX{leK&*lq?uC9iWGAk?afHBS$xf7VZrUAoz)HEWCIU-pR(Zsl zDv_6nWe*s#V*&yQLJi=tU?8LlF*^~*70|OTrU*Q4qE*?6GItT~P$Cd#jjWL-^J4M_ z6Y+on&yGkwq1c%}3W472M5U&M1&WGBqsFM&s6_k}!}B~vn<$fsL>8pFF{FVQ8B!PN z5F;2)sEQFetjS6U*D--tsn+ZSf%N!Te8I5WJq{mIM_E98P%#ju7$Z#ugVbaXRmESaCIaQPe&3d7=S@!s-jhyDN7c(+(qLa zIt6|?7>;`(vZq*TvTuT{DY5CAcsi2@2wj~gQ^w_9*3VznNg%V{U{^#w^0 zWl4xXLK|d7v&lm8tdA#I$t;q@dMfd&yMZDIwQ6HF!#!wM!wU~E62O#(g1 zUXf(q#{Xumj}M+bQuIPuMeA>ji$-Ru1g;->8+i@L@nOR8_*e))97#b18=w@A6Jd?0 z#7YqIL$rU4Htd*O{+4E7AmC_d1*GJ&qGsTLiS%+DO9Dppu?)wU%)B@iT~&Nq6hvT- zAMuE|LJb<{3STl>s-;uyqm@vv1EP$iIg++{7^^_D0%IkpTb~|;kP}6YCPf}i3QMyh zX#*TXS~#A!Nmkax^1i9z{%`3`>WH!QvMGH-94lrv^^J0m7);th5iKJ!v@@fPo*Lij zNBPqC)LVFrw%ILQ0YT3!GA({*=$fHxS`19fc&58%=$aM-(=wjvuKycdhKX-Q7(##W zqUcNTi}!1{qp!$W-jxMTtWW>7o%WU^Nm97*VHLxY)Acg}Yizn32@^G!J1_Cm+vlZZ z+?ikSffI>->~iLKY$xB{xzf;%r#PP(nAbXdx-avO2Ug5Yd-3H{&7WV}y}LN||*$%>+A09Zg2Ze+hb?`xpwQK=ZBuqy8f2Gxw4e%9cbL7zSFj+> diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png index 78eb080f2e2f49c4f2eef03cae60c90abd5e2a1e..908dbef449764ad5b989d4e10865ff2d3fd0190d 100644 GIT binary patch literal 4492 zcmeHKe^3yJv(z5Q`}KX%K-;N9U}@c`i>sFQ*H@x5aQ?)JP} zxRV*9B19cBjX-CbQadq?Z7u$oMC`QwYCt3tYcpapZLFXrn!!vpD27I-M(B6%0FP;A zI?TlX*qi>ZJYi{>)N)u z%|D=*eE#5c>F1X^*6sYQaH42q?Ir*U0Pvx|2$KHE#%E?nEzzZB1V zKl?YoY_y(v??`>?fU+uQc<<1j=Y+_+|H?VrHs|X8kCk;t*AJ9lPTk0VU6)t*`h9S3 zVMWI`-_#u-7e8Cyj+v78zQ#CrI?HnAPM^Q1rF~s%er^4?J)iEm`*cs%hIFF6s~16% z>SUX(z-6(SjNJ5wvUiTBZ>%Cu49#p| zmSyUHT3gZ4@n%=+&W5(5sYh$k2T9j&_Z|2WTRu!=9^XCK_ou~o2CM_ul2#x3(9=ew z9&7S``r;$@^`HIvJo2_P!*`NT zQ|4R@Y~*fky-pr->IT`t1KA6fz4pb)+xHgUJl6Tt#aRna{55OyTO~ib|6XtBVd3C8 z!?`ra-&U4>bn0;M+V#VKfBtYdfB0 z#jocjMF9G!9}3`+wJI9q#R{OJ0`SQJD|YA92N)_#R;<|QCfz|BD3_fzAy8D4=Mifv zL{`F9y`;;EauC1|R344`D+6IJYQ9DLT62@H*?s1;VM#9e^eln_7}J)52j%2hSU5kw>s(MJq=CFCP0mSqW&CTJRm8hCh1K;@%&AiPwA zh-276SPaQQRaOG1hRF*`m1@N>C`ZTQ^9SATari)Zlm*BK5#@sfr6&o$pGdR_tBz_2 zG8)i#T7*4tn-YZ}tW}gmB0^G!_X@=!Q~p4yI|Zx zqrfNogE1>e_5@8;_C6+SLTs8OmQG?I(0m+sg7#SMF=eRbc5`+`tkS}B*{zu7pOX|( zmblm>?WHUtX(4f*1uV{x5`(iAfyPM-ZKk{eE3pPk0+cHdR{4MkG$;tJmmv;s1fto( z3b@h0k~kv@UYxfWO*k;}j0La^?In!~5cwe)b|qh#7?lPkK`4gjy(ZDiLlg^*GbUQX zd4XndiWUtfRupMTG{vAKk;_p+ejb)n_VYeK1OvX9KqH*XE^t{fT2DS+DX8RCFEoIA zKn_SsB>Y(9k^P`Z|4f5PHhVr1+hpYl^N(F)%6RsqUJhYf=nMN_ncgzBjsbkG~Z`0RF*? zz%RkU+@-&VUy;*=+%r{~X_ zH+SWx9!;;rWzY6lE?jMTKdqgdF|F~lvXM*7uHFOpcGzlPEUJyF+cy~IEMJ~EZ`$Qg zhV1KqnAvoUC^B^4=})Im=AK5n|9qBBer3U}+54*Q_G4Rb=$2LFRJEMibtT1e+fiCw S9vFr`5SJs*espzN?SBEElt`EW literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fXMsm#F#`j) zFbFd;%$g$s6f_I)32_C|WPt5u8AU*CLM1_d!3+ZR=l47GzyH5JVE%oDf&_zx!`6yf zK-p4H7srr_IlleTLPr!hSR9iirtY};JKpSv*BgG#TScc7vkE3C8|Xe-nX$w||M#?R zd9e;5HkWYI2MX1#pFgkMy`%P&o>9xW*gt_Wbxpi8!(LS^yfb-uf@4P9vIi`$@9%GW tz|_0hTR3n*<<{NR8}{rD_I-zU;uumfNA}!C-Ub5!=fHFp_mvrv5A~QYEZHw9(a0&$*t>D^sj5r0tZ#YtzDfA5 z@n}&-k%I5hRsqhu77qcAi3gN5Kg@Wt+5KXB!Q)WwydA9OcMd%l7UaoWc1a6@#a%pUXO@geCwXDOXAW diff --git a/common/src/main/resources/assets/wynntils/textures/icons/generic/next.png b/common/src/main/resources/assets/wynntils/textures/icons/generic/next.png index 806b3e43695e5d8c38aa719915177896c0a62c47..cbfacfc26c0aa695ad3a45fb9dd8a834e277d180 100644 GIT binary patch literal 4262 zcmeHKe{dA_72il9aDY-m31A@G4Hg~P+aLF9Z^;G2U6MPS3rBJgqNw@a?sqRMcej_@ z&D{|#5TOxBP34y`l+sA+C^$&kso<2MO~i=EFgljTUx0`mi_?xlGZJ7J;&<=z<1%%| z$&CD$z1d&y``+ih_xZl}=5~v(qHL;Rjse54sUEkh65Xfi=fnxn7>wY5=*!=x->Sn}hr?~|z~@hP{0TU$5eZE~JJnTzYcc)(b3uI>G^ zZ|{HX!|tUk`i|untasmZP5JZjg=ki&aN(=b_=VIM=P~$)BAVNc=*j^^!#rVee)7M*b6oA&__Ar{Abzs zx4gdR%#p1pj!dlm$+&4h-L>c70#i#(vh~Q5*RMC`epYkwKezKXKGZ30ST?_vxzN7Z zwmE1cf8SeFzj@bvzrMaN`A*y9=}Tgd#&0~Uo(4_9=HG-G_j9gA&;M=JSAmsQ|K-`2 z+Ydakllu4Sm7G$)@|A|}zb{x1+S?9`uUDvflNSAa%Z!Hke{3}zYM=JPih?fJ-fN%F zyUm>X1F^gORl_X%Oy5Ss>905TclJciUe?Ze4R1Adw1n4}V<(P3_zL*s(^E$;@L9Ls z?by}*^#^-9&M)}#+18mwcQqevYWZ*LFM6_eFYdUq!#I0;!428aMOW~J%2 z<=C-nMHTrQ7B#%~)VRF7yLR07&SQPa#N!F2f4|(POO9RCM_%c6s*ws>i8)CuckcVi4zHCFhA z#x;UnB$gBz3X?nn2ty6v$#5v5@<|7g!sXGkE~W@PrJ}8I5UadC+^NJMZZ?{YG+C0A z<1A5Rzzbud#8+wOXa$)NqA+A1ZHR?Z>4*XaLokd~RpgZ!;j+x*^$l6* z6a?jPG-ZXz9-*np(lA*gV$)Yr>0}0i%!hDCXb20c8F%R%V=c~KE$ zkxxA`R%n$3$dL?Zvyo=2oh5-lTS&oTXYHKX451`tKzSmn1|kB~p%A!HMmUh+0+8nH zBxG4LX_hPj5-`91fk5RbSM!)ne3b-nXDEvV6uy(nX}kQ zV3rt?4u~9WGn*_TV@g4Z0$-}c!T@cj90oy1MI*t~f=)PJ?DIGX)<_Rad?BDo$N=?# z91)d-I=tkU!>~#NI-iV>C=qDD1vH32Y1Yis7M^AOjET1}yqQ}_vpk)l zuZXg=_J_3f_Q4C&o9>oX2pjhhjURYlSgAO?$r zh)2W~D$o>H`27Q0^}tB|L><)k0Z~SxI?bSrpaznq^ocQ;Z6Wo4d=#b>GDZxtOUuyc zLX(gh8ifOV=|krZ9s_jTK@SLe%*m+u9iwZEu2C^CD&?{28l!7e42(*7th#qe(sD=J8Sl(est8IW|luOG3P}iIB;%p`OfA^IptV>hxGP8 zUs~3m6aF0CmQQhYm;WVqzvIcbaFRUhem?8UUJr}?PTKxP?bR=Gu&XDlcRgy~O(Ss3 NQ&Qo2b!qL>-vJTT_6Gm} literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFpALq~h=6zI;H5YjD^YwaT%kI@via!_UXZKD&b5l)j#_Hoa2r}Uj z(c$pA9gd-TU==%8KW2BmF}tvD*@CubZp&_KwFxg&#`a+Ce_mhF<^4prpWS}{H(8!L zw&dMDx98xwbI1H2_Vm>(&R$$L`8#A)ELx>LHf5kQZ^@g9=%<_F*QUiUA-ik9-qX36 zz7y2Rb+2rH=fL`-2X0<|Q|9Dbw{71u!_-!jXg}~!e}BX6|E&4P7dHx9e%~WB&A+?d zc($vRZVl4-lV6vvYTb6vqy0M*Z|};PGE06Sc73CAoNErQ-4JSc%H}M7{IAvj^)Ise z&KI2TdS=B|;`93#*`!sA_SKzwZN?g|YuA3^l}e>>Qt@5u^6Kt>wq3WkYx3@eMSad4 zS1(MvVLbLU);aGbT|P6_+oC&urDdS!Qsl&W^#hOYt>*5w@S1tZ(Id0>ac4d|_VQVF z!gqh~-gfHBM?1PdopEtv`_$5mwJ$ff{k#3%OA|V0c7NGnDA-bTUDWkqmmBANwl#aL z)O^Eo=+M>D%IQtTbq62LEG*3ExaaK$uO;Hk;?lrV;$Y4Q3 zrH^k|$uj~rt5jE#U?D&ls2rLIhaw7_uwzMF7T#-O0z;D~>PkCS?eU@xNd~CdU^b9= zMM8{GSg8&zk%a(T<(xAJ0iWzxt*S;@f{4fChPcTf$w9)%FbqLb1V!P{0$1uIDwn_` zN|6SU!f*nGm&K?mN)c4U!Z7>KAv=@0@x>>sU@L&oQA0J722)C-Z43*`fz)zZ zr$T_F2dsv5$beHN*(XUMJEkRtYM#St4;(0gQ#mK60tiY{W|p+D6y-CTSPR7(O}`^4 zmQ1sk1Tj$mW7gXEpe3nIcZmv&U!N4EW@-Ugm3m4&hQ#DBp=fd}SdLGXpl~rDB=dw= zDHUJKMS=jHAA=1$Bo}|683KN*Ex;H7E|@GdZniOgoDr-7F3kVnWBY|tcE=&uL2>Nlh9#`3@+V6m``o2$GYlT@#QUJM*D1 zTXlOXvcJrlnq$_NKmEZ+P*m-9micV&oZZ}`Zz6BWJaF66#K8L}ExkGG_LgnFT-IN3 z{l$+jFFSl>)|LO!(frNLolV6hS-#~>`tEnj`~TJGs(Rwx;Mt!0vfSYfW%Vs9T$>se fmb!o0f9F@7j+uu{<-1rI194YWI$tVZ{)hhqMf3j= literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFFVdQ&MBb@0OhFHHlZyP>gkTVOxe#N Date: Wed, 22 May 2024 17:42:41 +0200 Subject: [PATCH 26/28] Optimize new textures --- .../settings/WynntilsBookSettingsScreen.java | 26 +++++++++--------- .../resources/assets/wynntils/lang/en_us.json | 4 +-- .../config_categories/all_config_icon.png | Bin 4702 -> 4913 bytes .../config_categories/apply_settings_icon.png | Bin 4943 -> 5147 bytes .../config_categories/chat_config_icon.png | Bin 4508 -> 4707 bytes .../config_categories/combat_config_icon.png | Bin 4488 -> 4709 bytes .../commands_config_icon.png | Bin 4661 -> 4908 bytes .../config_categories/debug_config_icon.png | Bin 4452 -> 4688 bytes .../discard_settings_icon.png | Bin 5168 -> 5396 bytes .../embellishments_config_icon.png | Bin 4500 -> 4710 bytes .../export_settings_icon.png | Bin 4962 -> 5165 bytes .../import_settings_icon.png | Bin 4736 -> 4943 bytes .../inventory_config_icon.png | Bin 4508 -> 4716 bytes .../config_categories/map_config_icon.png | Bin 4496 -> 4716 bytes .../overlays_config_icon.png | Bin 4500 -> 4711 bytes .../config_categories/players_config_icon.png | Bin 4530 -> 4716 bytes .../redirects_config_icon.png | Bin 4516 -> 4723 bytes .../tooltips_config_icon.png | Bin 4696 -> 4913 bytes .../trade_market_config_icon.png | Bin 4493 -> 4703 bytes .../config_categories/ui_config_icon.png | Bin 4281 -> 4486 bytes .../uncategorized_config_icon.png | Bin 570 -> 4297 bytes .../utilities_config_icon.png | Bin 4497 -> 4715 bytes .../wynntils_config_icon.png | Bin 4492 -> 4708 bytes .../wynntils/textures/icons/generic/next.png | Bin 4262 -> 4478 bytes .../textures/icons/generic/previous.png | Bin 4269 -> 4480 bytes 25 files changed, 15 insertions(+), 15 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index d8bd30da11..ef5ddfd218 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -64,7 +64,7 @@ public final class WynntilsBookSettingsScreen extends WynntilsScreen { private static final int CONFIGS_PER_PAGE = 4; private static final int CONFIGURABLE_SCROLL_X = (int) (Texture.CONFIG_BOOK_BACKGROUND.width() / 2f - 12); private static final int CONFIG_SCROLL_X = Texture.CONFIG_BOOK_BACKGROUND.width() - 23; - private static final int MAX_DISPLAYED_CATEGORIES = 7; + private static final int MAX_DISPLAYED_CATEGORIES = 10; private static final int SCROLL_AREA_HEIGHT = 186; private static final int SCROLL_START_Y = 21; @@ -101,7 +101,7 @@ private WynntilsBookSettingsScreen() { searchWidget = new SearchWidget( 60, - Texture.CONFIG_BOOK_BACKGROUND.height() + 5, + Texture.CONFIG_BOOK_BACKGROUND.height() + 6, 100, 20, (s) -> { @@ -149,7 +149,7 @@ protected void doInit() { .withStyle(ChatFormatting.GRAY)), 150), Texture.TAG_BLUE, - Texture.ADD_ICON)); + Texture.IMPORT_SETTINGS_ICON)); yPos += 15 + Texture.TAG_BLUE.height() / 2; @@ -169,7 +169,7 @@ protected void doInit() { .withStyle(ChatFormatting.GRAY)), 150), Texture.TAG_BLUE, - Texture.SHARE_ICON)); + Texture.EXPORT_SETTINGS_ICON)); yPos += 15 + Texture.TAG_BLUE.height() / 2; @@ -190,7 +190,7 @@ protected void doInit() { .withStyle(ChatFormatting.GRAY)), 150), Texture.TAG_BLUE, - Texture.SAVE)); + Texture.APPLY_SETTINGS_ICON)); yPos += 15 + Texture.TAG_BLUE.height() / 2; @@ -208,14 +208,14 @@ protected void doInit() { .withStyle(ChatFormatting.GRAY)), 150), Texture.TAG_BLUE, - Texture.CLOSE)); + Texture.DISCARD_SETTINGS_ICON)); // endregion // region Category tags - int xPos = 18; + int xPos = (int) (Texture.TAG_RED.width() * 0.85); allCategoriesButton = this.addRenderableWidget(new SettingsCategoryTabButton( - 18, + xPos, (int) -(Texture.TAG_RED.height() * 0.75f), Texture.TAG_RED.width(), Texture.TAG_RED.height(), @@ -227,7 +227,7 @@ protected void doInit() { selectedCategoryButton = allCategoriesButton; } - xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75; + xPos += Texture.TAG_RED.width() * 2 + 1; this.addRenderableWidget(new SettingsPageTabButton( xPos, @@ -238,7 +238,7 @@ protected void doInit() { List.of(Component.translatable("screens.wynntils.settingsScreen.previous")), false)); - xPos += (Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75) * (MAX_DISPLAYED_CATEGORIES + 1); + xPos += (Texture.TAG_RED.width() * 1.25) * (MAX_DISPLAYED_CATEGORIES + 1) - Texture.TAG_RED.width() * 0.25; this.addRenderableWidget(new SettingsPageTabButton( xPos, @@ -674,12 +674,12 @@ private void populateCategories() { this.removeWidget(widget); } - int xPos = (int) (18 + Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75); + int xPos = (int) (Texture.TAG_RED.width() * 2.85 + 1); categoryButtons = new ArrayList<>(); for (int i = 0; i < MAX_DISPLAYED_CATEGORIES; i++) { - xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.75; + xPos += Texture.TAG_RED.width() + Texture.TAG_RED.width() * 0.25; int categoryIndex; @@ -890,7 +890,7 @@ private void renderBg(PoseStack poseStack) { } private void renderSearchBar(PoseStack poseStack) { - RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 2); + RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 5); } private void renderTags(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { diff --git a/common/src/main/resources/assets/wynntils/lang/en_us.json b/common/src/main/resources/assets/wynntils/lang/en_us.json index 190dc13012..5e76467a25 100644 --- a/common/src/main/resources/assets/wynntils/lang/en_us.json +++ b/common/src/main/resources/assets/wynntils/lang/en_us.json @@ -2320,7 +2320,7 @@ "screens.wynntils.settingsScreen.apply.description": "Save changes", "screens.wynntils.settingsScreen.booleanConfig.disabled": "Disabled", "screens.wynntils.settingsScreen.booleanConfig.enabled": "Enabled", - "screens.wynntils.settingsScreen.close": "Close", + "screens.wynntils.settingsScreen.close": "Discard", "screens.wynntils.settingsScreen.close.description": "Close without saving changes", "screens.wynntils.settingsScreen.export": "Export Settings", "screens.wynntils.settingsScreen.export.all": "- Left click to export settings from your clipboard for all settings.", @@ -2445,7 +2445,7 @@ "screens.wynntils.wynntilsGuides.screenDescription": "Here you can see all the guides Wynntils has. These guides usually show all the items of a specific category.", "screens.wynntils.wynntilsGuides.tomeGuide.name": "Tome Guide", "screens.wynntils.wynntilsMenu.configs.description": "Change the settings the way you want.", - "screens.wynntils.wynntilsMenu.configs.name": "Configuration", + "screens.wynntils.wynntilsMenu.configs.name": "Settings", "screens.wynntils.wynntilsMenu.crowdSourcing.description": "Help us collect data about Wynncraft.", "screens.wynntils.wynntilsMenu.crowdSourcing.name": "Crowd Sourcing", "screens.wynntils.wynntilsMenu.leftClickToSelect": "Left click to select", diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/all_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/all_config_icon.png index acbd1d4b47c92c0155704af9106dc8e2fb9b9b10..c57cca3f482003de02a2cb790ee4f0c1b4704072 100644 GIT binary patch delta 739 zcmV<90v!F`B(Wxt7zqIb0000bJ#8Y9Avpt~YNwH1A%AFzn;*^w!xDUDmX`hg@*~}n zVuMPTAbWaayEm$OzWoIGkEBn;5W5Fe4-%e@=mBj$i*mJceZqFo9X3zsBxPiuA-}a2 zY;R96h53*u1QxM5fb^q58bks!E@5CP&?0&GYbRL9zdbF4FWZV)6_!0p?f?J*glR)V zP)S2WAd&qP3R_D>Djh5;;t;Tt8v#Fm-e#34Mo$b-R8vnU;zBOJDg<8P#~?x&!;r`f zEty%&!gYMz!^79RD9>^~_vh%B3kCx`0&$FKx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z z>ypE7oJ%%)d1hG8rss*n#6qcyr7mV=T_K(!j>w8i`QDtvGUqMMO0~|~_v9~s3>MUt z4A*InB7r3&k%9mTbyQG=i72fqDF)KCA9wMO*!~o`Byv^2$gzML6o|GT{11M2YZRxa zoTOkJ@V{8r$2bt!1zHWu`aZU-)(PNy2CmeOzt#liK1pwMw8#+<+6FGJJDRiyTL;#2d9Y~YY z5h6n*0CD9K=KufzB}qgdcnZJ0Y-d4wE(#y V2ZL0ZgMk15002ovPDHLkV1nu@D5(Gd delta 694 zcmV;n0!jU`Cf+2F7zqdl0000V^Z#LyAvptSRi=?$A%Ex;iyy8A!xDUDmX`hg=|@_U zVuMPzAbWaaTN_n9-+qGpN75%^h~0y#2MNzc^nf;>MY&qJKVds)h0PN>Ng3H!$ZxF$ z+uIXNVLl`ZfkkW%ApK~N29dywOBh%RbQBwY@ky|de|tI+zTBQ!99IyU`2YX`glR)V zP)S2WAd&qP3R895vM1lTYpxw0X?_=9;p8)=6;7aTI>n&jJlk{d+iyQ&N+rY(jSCjXE%N=0! zNtX=Ck^D4;QVDoJqi-qzp<7@raLw(lvyamUAV*y--v9@Pz(kp{*FD}n(A(R;XFC1; z0IMN#y{cw5Z~y=gG_!>QiUK4yV`ODFVP<75Ghs9~Ei^DOI4xo}H8(9`VKO!`VPQ2f zG-ET9GX<;)F)%ncGcqy{D6t%n~AL5(j3T7BK(-082?kK~y-)wUIFr03is(SjPW< zIW`t|HmJaM6bvD2RvCcX9WTGWQ$$p00&kJ`oue1VZ36(36iPak>eihS0#;gx(hig% c_|^HE2?-%f&IcyjQvd(}07*qoM6N<$f~yWBvj6}9 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/apply_settings_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/apply_settings_icon.png index 808f88459fe7ec662a62def7baa4a177f2d0e2e3..7211d6cc7f694e7356c3a28f93531f96368dab9d 100644 GIT binary patch delta 822 zcmV-61Ihf)CYvab7zqLc0001DofqYWDt_kF+?& zW-8r`^y!6dEmU!T{W0=~&?jOOyBk$E0*^v;gEqcJxoWw8VLNDrjuSeeoZgqoZ!9jw zwznrsg84uM83Q^7KtB@DOeABrCL0*VG?0x2b0@Zte|wq;U)(ZT8Etc9rIGO<3R_D> zDjh5;;t;Tt8v#Fm-e#34Mo$b-R8vnU;zBOJDg<8P#~?x&!;r`fEty%&!gYMz!^79R zD9>^~_vh%B3kCx`0&$FKx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z>ypE7oJ%%)d1hG8 zrss*n#6qcyr7mV=T_K(!j>w8i`QDtvGUqMMO0~|~_v9~s3>MUt4A*InB7r3&k%9mT zbyQG=i72fqDF)KCA9wMO*!~o`Byv^2$gzML6o|GT{11M2YZRxaoTOkJ@V{8r$2bt! z1zHWu`aZU-)(PNy2CmeOzt#liK1pwMw8#+<+6FGJJDRiyT>EKH###mIy94G1}FwMIx{vpG_#Qgs{@n323#aGGdMC~G-5R^VlZN2 zEi`5~V=ZDbWjHN0Vm2@~IW#afWMngwKnF|;GBQ*#H###mIyAF03TX&`GVhl900009 zP)t-s0080T<>mkX|6vvpk delta 756 zcmVishO!0a~?kgD{$CgCpr+FKCIIAI=8D5`1Nrmi_+nBi)i> zgG!emdwOHLH>!HR{RH`sq))^Uy9ZSd5}u9d0c}2uaYbRL9zdbF4FWfX)83O}yK#}nv3R895vM1lTY zpxw0X?_=9;p8)=6;7aTI>n&jJlk{d+iyQ&N+rY(jSCjXE%N=0!NtX=Ck^D4;QVDoJ zqi-qzp<7@raLw(lvyamUAV*y--v9@Pz(kp{*FD}n(A(R;XFC1;0IMN#y{cw5Z~y=h z6SIW^iUK4#IW}c6V=*x;F)%YZEi^b`G%YwZVKpr|GdE*qGdE>2H!wMqGX<*)I5;;p zFfueUIW#kq=>>EKHaasoIx>@E1}FwLIx{&sGP98es{^we3t$KqrxBb?00006VoOIv z0RI600RN!9r<0Se6Cr#KClo=@|84*P09{E$K~y-)#gb7Dz#s@i3-SK9gllwPOU#@K z!Dam;hF75gMF{|qWVk^@`dYJ&W;U8JsR7bI&YWiutuC>>Ib{IlAAAdVW}X7v%{z#$ mVv8(wIYK0nb9dnG_(d085^ad5OXh_D00002i_ld)-EXu^^#FIK*kob}7lEZJD zOE!CXW?0Xr=ZV9_LaB?TE@ow2A)XIO`ldWEa0~RUIlZ;_aryvcsjKB1;NTFLC{gyh%e#BKd;9lHyT2c|zH-82 z+MtdA01q^2R9JLaO-wptvyK9R0wgyxH)b+nF=8z+F*h(RG-NPiEjVH_Vl6c^IW#ji zGcYqZIWUtm1*;1=GBPnSFfcMUH8qpz1#|~DIx{vpH87K81}6tMIx{vpH88W12J8Wo zzy@3-WimE2He@g~Ej2heGc7b?G&wCeHf3WiGG<|8I5IFbW@KS7lRyVd3o(!*bZ7@!$K!1r}icC8*47X z_4b6MFdq_yz#=vVkZu~J!AW3769z^@gH>>pxhf9w?@klp3*0tY8i$7n_>u7-e^ZO1 z6$gumIAo|!cBvwcrHVzcP}&NuI+$Gg1x*@~6cK5>YZC58B$c*>v)55YySJ_3fefs5;oChq~4JHY6ZE*X*| z`DqHpBJh4j-;@W2Z-M?bx3~5_P9K0Qb+vp092^3ZCCXm+cz0iSZ~vZY_xA(oY;x8f zc77lL01j1YR9JLaO-wptvyK9R0wg(OGB#o{H)bt2Vq#(~G&D3}EjVN~H7#RfGBY+Y zFl99}I60Fu1*;1;H#s#mFgH0kIX9E(1#|~9Ix{&sF*TE91}6tIIx{&sF*UQ22J8W| zT?t?a7LK8-DgXcg24YJ`L;&Uh<^blp(PCed@DU+@3nvfFe)MSo003x7L_t(I%f*sG z62Kq`17(I^@c*ar4tk=4Ef6lY+|*x?2&dZ9UL*f-2Pv|sDJzNb&N${1KTK4;AJ<>vo4KCe4_FMGEwl=Cd-+n;;Bk2<{ z%2i_ld)-EXu^^#FIK*kob}7lEZJDOE!CXW?0Xr=ZV9_LaB?TE@ow2 zA)XIO`ldWEa0~RUIlZ;_ zaryvcsjKB1;NTFLC{gyh%e#BKd;9lHyT2c|zH-82+MtdA01q^2R9JLaO-wptvyK9R z0wXjvHa9ajHDxU@WHvc1G&VV9En;RiH7z$YV>e}HIWRdnWRo%ltP43ZGBP(eF)}bU zGn45BbO$#&GdDUgH;aR&23#azG&eFgV=-baV>LN9Ei^DU zWi2^1WH~J~H)UaEWHB*gH#udKKnF|lr7|Np?x6|w*T00DGTPE!Ct=GbNc0004EOGiWihy@);lk^ZFQx7Ev_L{Z@ z0000qNkl5T9N+J0FOYy_7T0004mX+uL$Nkc;*aB^>EX>4Tx0C=2zkv&Mm zKpe$iQ;VV%2Y-u*IAo|!cBvwcrHVzcP}&NuI+$Gg1x*@~6cK5>YZC58B$c*>v) z5#(#mpi*0{Q0KL0Ft6|&U$F|)%0sPOvmDcgsn!wyA>5YySJ_3fefs5;oChq~4 zJHY6ZE*X*|`DqHpBJh4j-;@W2Z-M?bx3~5_P9K0Qb+vp092^3ZCCXm+cz0iSZ~vZY z_xA(oY;x8fc77lL01j1YR9JLaO-wptZ*4ANWV4h4d;%k8F=AvnGBPzSH#adfEi^YZ zVl6o|IX5k0V`F4DWHdN7H!_nm1*{7y{D6t@ev_&3n(b>>|M-1=D_r$EGOk?$Z1 zTT4YM9V{y15U`UO0Y872i_ld)-EXu^^#FIK*kob}7lEZJDOE!CX zW?0Xr=ZV9_LaB?TE@ow2A)XIO`ldWEa0@N;tvS85_i_3FWT~s=8{ps&m?%;9y34zJyL;M1&2~bQ_MF0T5<>lr7|Nj#FgAV`z00DGTPE!Ct=GbNc0004EOGiWihy@);lhF|& zJr5-j0!{-|0000UNkl&(E`Lw0ziVp0Z1qkFT?^f1^|Zr10vWv&1V1r N002ovPDHLkV1j}ULvjEB delta 702 zcmV;v0zv((CbcAx7!3#p0000V^Z#K0006>~B_Ds=4Z|P|{AY@e;1^)VAx$cEgN|Q= zohVd2iR1jxVVsW7`;{I8gpwpzEv*zVNRvk0go2|_Mv%!7z$un|x(Z||wwpcF68&c$ zVR6E4D&LIs8HH^vGzowGF^Y$HOhhL3Flu4M+isr#{%7Dy>-y_0VD6LjW>2Q)e|H###olVb)a2Q)e|H###ovyleN0<${`UFGS|NsC06l;F^^y&Xm k&7+!!lV%v8NHZk>0QaI}qgM;Ai2wiq07*qoM6N<$f{11^LI3~& diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png index 335d3c843fbbc864ee0479e68871201686acbc5d..5c97886cf2b94a37468fe8918641134f65b0ecbf 100644 GIT binary patch delta 872 zcmV-u1DE{dBG4p|7!3jg0001Dofq-|006>~B_Dr54g(gGx6edwOA83sv3UevJGh=^Zh|?nc#(ghwH|K^tRHu2$|NYzM8daY834r}t&@ z8*6{T_V$FNFdq_yz#=vpkbX2sgGgY;BQz`pTAb&oSjfLUO@uGp{#hP(*t3QJ00D$) zLqkwWLqi~Na&Km7Y-Iodc$|HaJxIeq9K~N-OGPRjEGpsnNgNw7S4z7YA_yK?7?BJy6A|?JWDYS_3;J6>}?mh0_0p4bn zDMn8WP*hV-C*ndbzbXV?;m06C7{idr3@w>i%))hi-NVDzyC~0cKlkV8mkS01JOXiy zX}U?gK|H%@YMl3p!>laI#OK75I$ez!^A?Vi={4RWnF(E zo*|CNic0z3oWnBbEzU}{&f53nFANscl?>Nujv|32B$0vu33XIZg^4JwDk%oiv>$iz zkJ$bcxg>H`z{s(H8Wf1OAN&t~cWV@8TUppF0l4>Yre0*V48WHvKnGcz`0 zEi+>?H!U>HMH###n zIx{tsWd5PEP_mMF$Gj1#?TN3H~;`yfdZ3rpe~I70000v}YyBYaI(kEhw)s3nf36DZ_gEqcJxmvk?VcBSgjT1Ua*}YGb zd#o=7+glTo!n{co0*lxfK>E=j4I+UVO&AyrO%zdsEEUV9D_>1WPnd3j(;)Tu!uK^XE!aK^FDEil_iDvoOsHh3lcwa zU3U46bID|FXUWSIB#)Qt991CCx2nEpsi%M zPIDXyEFp;$btI#X3aYRWp;aTrM4I;F9{w@MpCXq`t_m1A7Epr<$?=2#!S8O(;(v71 zO$x?=z>95vOaQ&RK&xTf-^aGyIsyF8z?IhV*P6iGC+Urj7Cr)owt1=Y=9(H~p000hEX;fHrSWQeiW3!9`fdV9AF=I0|HZo={WjA6nEi_^^IW1yjHZd(Q zGcq(`VmC5mF*0M5F$Jp%H#jjfH#sykG&7Ut1$75AIy5pmF*lQ91}6tIIy5pmF*mc2 z2J8W|TM1wY7J`JS=l}o!24YJ`L;&Uh<^blp(PCed?hzqQ3n~$U-?v8q001vZL_t(I z%VS`m7Wn`F|Nl`#hNU5+nu!C9$eI}$85xl!pFVwx*Fb4$X-0+t2LP47H`3Em|78FG N002ovPDHLkV1mIJQ3wD4 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/discard_settings_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/discard_settings_icon.png index 904f27fcedab753fdbc86441fe8fc25803d5acd2..e100ae87a27f100709e1e1de22fdbdf74b5d4371 100644 GIT binary patch delta 853 zcmV-b1FHP6D3mIY7=Ho-0001Dofq-|006~$R9JLUVRs;Ka&Km7Y-J#Hd2nSQWq4_3 z004N}ZIEFO!ypKS|9grZ0Ra_{W7jU(4R-uJl{R%5iLVbZUy*Qp-mmcJ!BK;zV!7r_ z2(4PV!5GbGLnG->Pv|sDJzNb&N${1KTK4;AJ<>vo4KCe4_FMGEwl=Cd-+n;;Bk2<{ z%Djh5;;t;Tt8v#Fm-e#34Mo$b- zR8vnU;zBOJDg<8P#~?x&!;r`fEty%&!gYMz!^79RD9>^~_vh%B3kCx`0&$FKx=Fl2 zJiBRXocD>ttSrjJ=fsmbU6A;Z>ypE7oJ%%)d1hG8rss*n#6qcyr7mV=T_K(!j>w8i z`QDtvGUqMMO0~|~_v9~s3>MUt4A*InB7r3&k%9mTbyQG=i72fqDF)KCA9wMO*!~o` zByv^2$gzML6o|GT{11M2YZRxaoTOkJ@V{8r$2bt!1zHWu`aZU-)(PNy2CmeOzt#li zK1pwMw8#+<+6FGJJDRiyT_H7#N`GiEI{H!)@~FgY+bG&wnwGX<*)IWjUfH#smgI507j=>>ELH###nIy5(v zWCkY(H###nIy5)4k_L$clfVXCBsn!SF=1vkVJ&7fWnwKfGG#X{VKHVlEiz+bGi5nr zH8(gjGLt|DObaqHR53R?GdDUkH?tE9Xb3Z^_Tp^-000S4OjJbx0K?_w<^TWxIW##? z00001bW%=J06^y0W&i*H0b)x>L;#2d9Y~Xr6Cq^}B`?D-9{&IU07gkfK~xCWV_*OQ z4G_{|U|7Py)xb1?foTDk0|UbfO`wd{5+K1f0Y+%10Es1%3=B*Y*c=$R92h4s09Bo delta 820 zcmV-41IzrBDzGS!7=H)`0000V^Z#K0006{#R9JLUVRs;Ka&Km7Y-J#Hd2nSQWq4_3 z004N}ZBW|{!ypX&_Y@t$FTjjLnpElr9lr*gC{#U(-~yRA(BkG#B!3Pbc6D-AY*?edDdw0004mX+uL$Nkc;*aB^>EX>4Tx0C=2zkv&Mm zKpe$iQ;Q-MhXoc9amdh<905OnLaWA9vo8*)nq_2?2{B(-75iTizzBi}Au2IbPh}T# z@El+F@bUF7#95vM1lTYpxw0X?_=9;p8)=6;7aTI>n&jJlk{d+iyQ&N+rY(jSCjXE%N=0!NtX=C zk^D4;QVDoJqi-qzp<7@raLw(lvyamUAV*y--v9@Pz(kp{*FD}n(A(R;XFC1;0IMN# zy{cw5Z~y=h^0S5liUK4sV>dHmHZm|RWH2x?Ei`3hH!V3hIW;XfH#K54HZ(9fWo2TM zGzF^*I5;;oI50RdH#j+y>IHNMHaasoIx#qtWdK@I>R2m>4c z|IP9Z_p&Bt)2(2XE6flmaH9HKJM-<^$iM&)5!&h`qffHi0VP?&PLhU|qzo&GgBxzt yyqVqm8hhon)7(>k;ER=?+Ucf1EB-}0000Djh5;;t;Sp*+oShOBIV?p|llR zbuhW~3z{?}DK3tJYr(;f#j1mgv#t)Vf*^nR0pjf7r060g{x2!Ci1FaKAMfrx?%o03 zW|b*MPYh60Q%@)2LN3251YY6CAVL_!kjM-znOV%jb$s2!!`Hhg&vHNa=jfLU1_L|- zag1rYNxVTkyJ>2i_ld)-EXu^^#FIK*kob}7lEZJDOE!CXW?0Xr=ZV9_LaB?TE@ppa zT_K(!j>w8i`QDtvGUqMMO0~|~_v9}O7Sxpt*J+L-fh8o7f&dA1R8WP9D6J|f2GX=2 zckz$d{uH?+a#g^{v49#Bh_)a64}N!R6sM=0q+lHIzgX7CI1tzcS`EwkKDMmZ3E+DM zuGEgd)&%B0NpEzt$Pp0Q1}?5UnzTg+TtvS85 z_i_3FWT~s=8{ps&m?%;9y34zJyLWi2#iHe)R~W;Z!4 zW@cnCG&eY6H8){4lR*be3oishO!0a~?k12GzCXN;t0^n@l^^l%jzlHe;Nwe0;< zkF+?&29|C{_VmKG7OJ|x{TTU=q))^kyBk$E5*~%<25qcGxmvleupP9*#tS`2IlV8F z-&`*XuD2(M!hA>+LKLwvfb^$98c0H9G+|&gG*M&?>Rbs2`FE#@@CDm^Sr(|svxJfH zAb(Sfq7?^=h&W`ZPIjpxj-`r4uu$3xtvZ-o`UOoIk`xz5!L{Jv$70pN#aUMeS3wZ` z0C9G3Qgo3L|Cbb6#CUMrk9YSTckck9S!Jr(69ZJuGSZ2-n9HwEUV9D_>1WPnd3j(;)Tu!uK^XE!aK^FDEil_iDvoOsHh3lcwa zU3U46bID|FXUWSIB#)Qt991CCx2nEpsi%M zPIDXyEFp;$btI#X3aYRWp;aTrM4I;F9{w@MpCXq`t_m1A7Epr<$?=2#!S8O(;(v71 zO$x?=z>95vOaQ&RK&xTf-^aGyIsyF8z?IhV*P6iGC+Urj7Cr)owt1=Y=9(H~p000hEX;fHrSWQeiW3!F|fdV9BG&C}1WnnfgHDO^hEi`5|Gc95_Wo9io zG+{I`Vl!i7I5lCDGX<*)H#jjjGdD6aGBGfd=>>ELGdeUfIyEzsWCkY(GdeUfIyE!1 zk_PMnvt0>b2o@gWyiNcB00v@9M??VT0OkPZy3t}^lkgECehVr!zT8um0001ANkl%=yTnk2A!faxgv%F8?8GAe5X3761S=gGvW!R}kp{0000< KMNUMnLSTZ;IbV7J diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/export_settings_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/export_settings_icon.png index f997864490cbcd42518a3d2a14769bfdde513e8c..d216004f5bdfc865f0680e863895352b2abd89ee 100644 GIT binary patch delta 816 zcmV-01JC^8Caoxt7!3jg0001Dofq-|006|1B{Y8q(yC0egmE4+A>sJEU*XZgQG=#p zx#moOR;}D1j3(OPNIKX9I>nL?SAmfd+%iMU-hbvJEl#mPrJIpGy|Ar?s_t(;M*fiW zi5Oycqv}S&vk={&&2LezR_EX>4Tx0C=2z zkv&MmKpe$iTT4YM9V{y15U`UR0Y872i_ld)-EXu^^#FIK*kob}7 zlEZJDOE!CXW?0Xr=ZV9_LaB?TE@ow2A)XIO`ldWEa0@N;tvS85_i_3FWT~s=8{ps&m?%;9y34zJyLI4w0ZVmCQ7F*z_{ zWnq&v1*{4(GB`OhF*h+dH%y7#LQqTEM`xYSjt`u2rj6GH9(@wFD@% uY68QmrCAOPt0qVSRXB)%2nJ+A6o>)SauUO#uC#an0000 delta 753 zcmVoN7!3#p0000V^Z#K000702B{YAgq*bYE3FACuLc;d@e!{DRqXtdI za?P0lty;N37!9^OLI17xF;Fb|u_WmOuX>y7UDqW21?S*A7RCRy58Tmuf zCt`@zjj9_7k3w{VHoirX zff*W27+4B)lnhp>J_#1`w5J2%58XOhATbGragp&L3R895vM1lTYpxw0X?_=9;p8)=6;7aTI z>n&jJlk{d+iyQ&N+rY(jSCjXE%N=0!NtX=Ck^D4;QVDoJqi-qzp<7@raLw(lvyamU zAV*y--v9@Pz(kp{*FD}n(A(R;XFC1;0IMN#y{cw5Z~y=h6SIW^iUK4sHa9ahFk>+- zIAu0sEi^M^Gc7qcWHT)?GiEY4Wi>WAHa0brGX<;)F)%PWF*!IeG&Ymz1$G26Haawu zV+JY&F*Z6hvyld?1G5_oUp#n{iWzI9~qhw3W#Ha!Im0URWH zrZ`1J900xMJtW?m0ZJ+DFF%o_I&KE$+ju}qsj26j<8UNr696RHx&^oDjh5;;t;Tt905On-e#34 zMo$b-R8vnU;zBOJDg<8P#~?x&!;r`fEty%&!gYMz!^79RD9>^~_vh%B3kCx`0&$FK zx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z>ypE7oJ%%)d1hG8rss*n#6qcyr7mV=T_K(! zj>w8i`QDtvGUqMMO0~|~_v9~s3>MUt4A*InB7r3&k%9mTbyQG=i72fqDF)KCA9wMO z*!~o`Byv^2$gzML6o|GT{11M2YZRxaoTOkJ@V{8r$2bt!1zHWu`aZU-)(PNy2CmeO zzt#liK1pwMw8#+<+6FGJJDRiyTlr7|Ns3o z^)mnf00DGTPE!Ct=GbNc0004EOGiWihy@);lhhF*Uk@e`DPvHV0000$NkluM)2dY~8Mr`%)~Z!Y7_wHan!q5nYLx>6+tN@521bxhh7=GX b!TW za=of%HgEs{4>Yrd0*eA8WHmT4HaIseH8?jkEi_|cIW0M1I4~_ZI5;&pH8y26G&V4k zGX<*(I5;ygHZnIeH8_*#1$75DIx{gkH8zuE1}6tLIx{gkH8!)72Fn7oJPKe477@Kk zPXGV_24YJ`L;$@2O8_ii19=#e&k`Yj4j(vVmoIhz003-BL_t(I%e9ir4Zt7_Lmkv9 z@cyGEYtT!P(ob3f>brqr;|K#u+JUMz0FbQMpUn&fi~M8I_nb0_gwg%>HZ+o=WQITg zHbd_LRCQk5$(UTl;!SF;rPEt|5Z$27Z&9vR?qAprT4D2qPEv;VW%3(q!S?oqq%bHS z5{1AbHV2S?G)RL;U`7)LmI95YkujeH3;DOF6X6TpdRZYQxO-cX@gRR&OGPRjEGps< zusYdAMI1{Ni(sL&6nNgNw7S4z7YA_yOYV;H2mxCH^ld zw21NGxF7HCJ?`EC-e#34Mo$b-R8vnU;zBOJDg<8P#~?x&!;r`fEty%&!gYMz!^79R zD9>^~_vh%B3kCx`0&#zgX}U?gK|H%@YMl3p!>laI#OK75I$ez!^A?Vi={4RWnCejA&$t3O8MTL!!qYB&Puh;+V|uy3>MUt4A*InB7r3&k%9mT zbyQG=i72fqDF)KCA9wMO*!~o`Byv^2$gzML6o|GT{11M2YZQN{r<|l<9Pqzb*2g#y z*acb*%lbaHtkwzOdj_u5j=$Cf<~~VpbhOA35ZVSVt~;8v2VCv|!%v#1i?-yW=`9w4 z_cQvYJTPzz^sPC)wfAxQ0A#7F>ELH###oIx;wuWCkY(H###oIx;x3k_PMnlfVXCBr;() zG&nh7Gc7YQWHT)^G&M9WVP<1wEjVFiVKHK5Gc#f`G?PFFObaqHR53R?GdMajIJ0&L zXb3a%)zh8;000S4OjJbx05Rp|<^TWx%GDB}00001bW%=J06^y0W&i*H0b)x>L;#2d z9Y~Y(5FuL+CLCANEGhs106a-VK~xCWV_*OSE-nTJrUeTE7&sUh1Q?ha7#tWF6c~XL xT}vDom_TAc2^K7b00W}~NU;bjP%&cw0|5NS1y#6x{3!qc002ovPDHLkV1m^lXqEr~ delta 830 zcmV-E1Ht_4B%C9V7zqdl0000V^Z#LyAt`^)DRzXsfN&hTcG7OJ<1av3m1&l69S6A~ zaD3h`cyur+XeyR#&gjspm75F0i8h!}2Su){R!KFD{LO1q~8j=(jN5Qq=;KyRs!Nplu2UkH5`~Y!wa8h)U691PJ zTEuv8+>dwn9(V5mp;=|B*%Jd)%`(!7xR}eYioLH0U<3mY5tW#!Co_v#c#f}o`1pDk z;aT42{v3l!!DN6>B#wVE-LQx^h-Wt~o%23%h?OOU_?&pkpbHW|a$R=$jdRIifoFz{ zYlrQ95Ryc2QR;zW^z9)ZSu%NAExK48%2`nLr6m=w{ zjtZ)<5TR8g#YCF+;~xGo$DbmXOs)zTITlcZ3d!+<|H1EW&EkJ_)J+P;fxwGxe@py9Sx0hc?#=#wrPk|X(P3dJJu zen#Jv2ZnEf{x!F^_C8J@fGl;jd;=UD0+S`mUiWx+Uw3c+o@w{@1L1Ffc7MV=^=~V>mHnWim38 zGX<*)I506WGBY_bF)%cf=>>ELG&(UgIx#YnWCkY(G&(UgIx#Y{k_PMnvt0>b2o?`O zAejIF00v@9M??VT0OkPZy3t}^lkgECe+&-{3}qes0001JNklX!;LP53`#eo2VSa}D;1TW~000002uVdw IM6N<$f@AY=RsaA1 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/map_config_icon.png index 1f8c741c216dd718c2646bf1d1a9052960953b18..7a54147edcd83db552d4adc694d8b67ef0ea1b34 100644 GIT binary patch delta 891 zcmV->1BCpLBkUxQ7!3jg0001Dofq-|006|1B`JSM0)*qxwUc&(9e)Nw)lRd7>pbKp z3CHLC3Xcws8Z;HlHD>~}YUKuDG|>h}(!n0k61RLf3yhTDD>Jn0{VN~o<`f%Lx)|Bh z3){U=)&1?q$bTe#B8J%AsJfBxEJQbGb1ll%%5{b9pgU~7&`HYhK23gOEx6vEkQC-a zq7Z*r#O46fp9X0V3Cw81z*3;mGnNgNw7S4z7YA_yOYV;H2mxCH{XeDYS_3;J6>}?mh0_0p4bnDMn8WP*hV- zC*ndbzbXV?;m06C7{idr3@w>i%))hi-NVDzyC~0cKlkV8mkS01JOXiyX}U?gK|H%@ zYMl3p!>laI#OK75I$ez!^A?Vi={4RWnCejA&$t3O8I}@ zoWnBbEzU}{&f53nFANscl?>Nujv|32B$0vu33XIZg^4JwDk%oiv>$izkJ$bcxg>H` zz{s(H8Wf1OAN&t~cWV@8TUppF0l4>Yre0*V48FgIp1Gc_|bEn_q>H7zt{ zH)Ab1Vl!baH8f>8GB`FkFf=(ZlQadZ3pp|~F*P$eH#0Fblj;R@2RAx1I65;mlVt`c z2RAx1I65;mvy%qw0h7T7Tq8MQH#RXjHD)bgWH4bZG&5l|Ejck|F)d^^HZn3{VKg{7 zIFmpJO$#zIR53R?GdMakHM4gJXb3YwOqM4A000S4OjJbx0KMhq<^TWxg=3N?00001 zbW%=J06^y0W&i*H0b)x>L;#2d9Y~Y)5FuL+CL`gr0T%!O06a-VK~xCWV_<-Q1whQi z1td5a8W1ywsRzO1UEgM1%afvb*5gT|InFkPTUdYi;+L0 zu-psH!ry<4;vpRq34%3@S{SL!0*67L-=fmIUcazxbcfHA25H^BPm|x=Dz>*~h$^xv zD}g0deGZ`GSkjIlg9S|(7!4iyP*^!8!9xD+=|K7d+df$onN++9k?|mZQ;VV%2aAX} zWT;MdsUnW0ibb$c+6t{Ym|Xe=O&XFE7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx z6k5c1aNLh~_a1le0HIlBs@W3*RLwHdiMW`{uZq2|2w(&Q5D}G_sV6gwS$K}Gd-(Wz z7vWjn=l&dnO2K4+Pb7|iG2O6;H;899EuHf|afp>Ah4`F!%AgApKXP4m`HgeQVS#6c zjBI+II7BR#x>)XFRyI`P8RD>_YLqYJTvj-5aaOB!*1jiyVX&aBWVlXq90@ETi4=7t zqmBxyun?hDBgI6T_TwJ@F~^@GmrSk-7&#VDg9^##(}_#ZGTJv zy}LlGVcXxww%s}b{LjFZ*74Vxz}zS4jgA&R0*1DMi|dXi?*W%P!03}M8ImLUX$r+6 z@P0<$lm~`yf&MkOxAs0xAAl@%wR{5{90HRi%3k+)cVBmJ|DI|0_XFu{a@HPpejoq< z4pnJXSaeuTOgdw;jsk%KBxEyTV`4dBGA%MNFg7hTHZ(XbVPrTpEjME~G%;c|F*af` zWs@@ns|z;bb~31A2o zrk*wf00006VoOIv0RI600RN!9r<0TL5g~dDHw%E#A|U_(09#2!K~y-)wUfaK05J#z zv&VH||D|mm<`a%1VAO^9cE(k3jN9d_WLOqO%_T|JbWGEUNz$Jk27u0;-v87t+>X4* wmjxfJ9!_2*ge#I1jwB@g1S6YfX1MyT6SseDGy$J0Q~&?~07*qoM6N<$f>O3*A^-pY diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/overlays_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/overlays_config_icon.png index 26cd33b2352ef97fd62d15f28d68e04d78e66a2c..9c10b004dd3ff7ac67257a51699ebbe853b9069f 100644 GIT binary patch delta 876 zcmV-y1C#ueBj+TL7!3jg0001Dofq-|00702B_DrV4#OY}`{xupLP!FHv}YyBYaI(kEhw)s3nf36DZ_gEqcJxmvk?VcBSgjT1Ua*}YGb zd#o=7+glTo!n{co0*lxfK>E=j4I+UVO&C}TG@8IF)hEG1p7wMg`~lteStR4Pp@Wg} zAb(p+MJgRED&i2ZI@v`<97`38V4<`XT6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)= z0pjf7r060g{x2!Ci1FaKAMfrx?%o03W|b*MPYh60Q%@)2LN3251YY6CAVL_!kjM-z znOV%jb$s2!!`Hhg&vHNa=jfLU1_L|-aes_yx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z z>ypE7oJ%%)d1hG8rss*n#6qcyr7mV=T_K(!j>w8i`QDtvGUqMMO0~|~_v9}O7Sxpt z*J+L-fh8o7f&dA1R8WP9D6J|f2GX=2ckz$d{uH?+a#g^{v49#Bh_)a64}N!R6o03u zoTOkJ@V{8r$2bt!1zHWu`aZU-)(PNy2CmeOzt#liK1pwMw8#+<+6FGJJDRiyTtvS85_i_3FWT~s=8{ps&m?%;9y34zJyLrvvvq*2s469t-JsL00~e`R7C&)dFAEh|NsBJF)6+P0004WQchC){upP9*<_Vpo4DZY2 zH`jlH?d=JoFdq_yz#=vWkbX2sLy*9XCJc;*hP)1)eG)9>-=0o{FWdB47&SWBR{#J3 zglR)VP)S2WAaHVTW@&6?004NLeUUv#!$2IxUsH>s6$gumIAo|!cBvwcrHVzcP}&Nu zI+$Gg1x*@~6cEUV9D_>1WPnd3 zjxpV^h&PC5H!Yp>K5>YZC58B$c*>v)5|FXUWSIB#)Qt991CCx2nEpsi%MPIDXyEFp;$btI#X3aYRWp;aTrM4I;F z9{w@MpCXq`t_m1A7Epr<$?=2#!S8O(;&jwa3dVuJi*0{Q0KL0Ft6|&U$F|)%0sPOv zmDcgsn!wyA>5YySJ_3fefs5;oChtW7mpj1dlP(#OBl&3x#Uk*2M&FbNhHruXHMh6+ zK29HiEOoVf0~{OzlO@Vt_jq?-cW?imY4`U7>1=Y=9(H~p000hEvxWkT0wXhHG-NPl zF)cV`HZ(0XVlrecVKXo{Enzb;I5;_BG&eS8Gm|t0s|z;bc031A2oOq?&u00006VoOIv0RI600RN!9r<0TM z5g~sII|5a>)rkNA0ANW(K~y-)-IBo#z#t3*)2dr!|Iuy^_X83|EhMNf{0laLQ(`ud ziY%-CVz|*P_~~cA`p7Ra76Cf#4*>$Sly4Dcjd~x@)dt-CsK%%cBZSU3K*)?UJnlEv d%$}rPya8k=+>wQS58?m-002ovPDHLkV1jX*bu0h? diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/players_config_icon.png index 2c7e2ae9f31348949ad22fb398530194cf6f99c0..65f0aa8a10ed6fd4f0db801af8d91da4035d99e3 100644 GIT binary patch delta 877 zcmV-z1Cso*BkUxQ7zqLc0001Dofq2i_ld)-EXu^^#FIK*kob}7lEZJD zOE!CXW?0Xr=ZV9_LaB?TE@ow2A)XIO`ldWEa0~RUIlZ;_aryvcsjKB1;NTFLC{gyh%e#BKd;9lHyT2c|zH-82 z+MtdA01q^2R9JLaO-wptvyK9R0wXhJHZ?LcH!v+ZIW;gXG-Wt4En+w~G%YqcIc798 zWi>T1Ig>I4tP43ZGc_;aR& z23#aEW;r)DWHV+hFfnE|Ei_^>H!Wc@HeoF}V>viAVl!eeW-&ICKnF|lr7|NnlU>OKGf00DGTPE!Ct=GbNc0004E zOGiWihy@);lk^ZFTMs7+x*e!G0000yNkl zvIaCVh%8_gVQ6e%bYy5`V1N-0K(0stP=Y};gaH8negp|&ws0Tw00000NkvXXu0mjf DS0BKdG zS;BQ3C+qA+Nk3B`V-_oLZ66D>>gA-2s|6n1KNBR<*McWgzcaeI#1|?GP19b-&!t; zZEsIzg84uM83Q^8KtB@DOeABrOExfMIMo=)K8Y>l-=0o{FWgpH8vs1CZ;|mJe^ZO1 z6$gumIAo|!cBvwcrHVzcP}&NuI+$Gg1x*@~6cK5>YZC58B$c*>v)55YySJ_3fefs5;oChq~4JHY6ZE*X*| z`DqHpBJh4j-;@W2Z-M?bx3~5_P9K0Qb+vp092^3ZCCXm+cz0iSZ~vZY_xA(oY;x8f zc77lL01j1YR9JLaO-wptvyK9R0wXbGWn^YJH83qTVKy->G-GBnEn;J0IW1#2F=jF| zV>dWCWRo%ltP3|eH#ashGcYtcF_Y;9bO$s#FgZFiHj`uqCkHe-FgZFiHnWlj>;bb~ z31A2oUW<8-00006VoOIv0OkPZ0Oq>UVqcT+5g~sJ2_$cd5`X{z0DehCK~y-)#gb7D zz#s@i!FUVqf3%*X`xyxmbS^F#zdoQXiX4{C9!PQkRdsu6ZWa*%z>00B7MgFYwyqR9 z-$+vLn#s(~k?&=)#V|7~L+lYYGj(Y>b!Rd^Bo1Ji1pr260N5(|vjLTjZ_c>$VU};v kTlOCL#ORw%vs3i%))hi z-NVDzyC~0cKlkV8mkS01JOXiyX}U?gK|H%@YMl3p!>laI#OK75I$ez!^A?Vi={4RWnCejA&$t3O8MTL!!qYB&Puh;+V|uye+(AXl?>Nujv|32 zB$0vu33XIZg^4JwDk%oiv>$izkJ$bcxg>H`z{s(H8Wf1OAN&t~cWV@8TU zppF0l4>Yrd0*eA8V>dW3VmM>ELH###pIy5+wWCkY(H###pIy5-5k_PMnlfVXCBspU+F)%q| zI4xr^IW{dcH#9RXVq`WsEjeK@IAk_CV_{}DVUs`yObaqHR53R?GdVgmIJ0&LXb3Zj zR`^N)000S4OjJbx043$+<^TWxSwyOR00001bW%=J06^y0W&i*H0b)x>L;#2d9Y~Y( z5Fug@Cop^wafko_07FScK~xCWV_<*)4G^IOA`}`J7*;J%U|?ck-~d7(t-!#*!T=N% zU}#_saA0T<5M*Fza1a3zAoU=ELjXuHEn#2)018Wa=of% zHgEs{4pp;-0*eA8Vl`xCWj8V{WMgJGEi^efHZ3_eH)1U`VK+HrGcaK^HfA!DGX<*) zI50FdIWjmgIXF3!=>>ELG&(XcIyE_yWCkY(G&(XcIyE`7k_PMnvt0>b2o}9w<;?&9 z00v@9M??Vs0RI60puMM)lkgECe+(2m9qw~!0001RNkl;o}?bA}C|;ySl`X`o1E=2ASWpyDeWB)Rp@Rh3@c#sB~S M07*qoM6N<$f>gZ}g#Z8m diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/tooltips_config_icon.png index 270912df0be17a838ffb89073e82cbe07b20390e..615dbee81385673046e6e7efc5cf79cc59493b00 100644 GIT binary patch delta 767 zcmV3R_D>Djh5;;t;Tt8v#Fm-e#34 zMo$b-R8vnU;zBOJDg<8P#~?x&!;r`fEty%&!gYMz!^79RD9>^~_vh%B3kCx`0&$FK zx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z>ypE7oJ%%)d1hG8rss*n#6qcyr7mV=T_K(! zj>w8i`QDtvGUqMMO0~|~_v9~s3>MUt4A*InB7r3&k%9mTbyQG=i72fqDF)KCA9wMO z*!~o`Byv^2$gzML6o|GT{11M2YZRxaoTOkJ@V{8r$2bt!1zHWu`aZU-)(PNy2CmeO zzt#liK1pwMw8#+<+6FGJJDRiyTM=zGX<*(IWjabHZwRfH93>$1$75EIy5jk zFgBB91}6tMIy5jkFgCN22Fn7Izy@3-WMyV!Fl0G3EoL`nWGyr{GGr}cWHvA@I5smj zVP!QrH)J?ClRyVd3o$juS}1_bB~pwrG}M6s1ORM@2iq=`&o2M~002ovPDHLkV1gGnJW&7u delta 744 zcmV4kT9RUeO1B_;dShD~RXyK+g8WC) zCt`@*gQ^D!&qnlsHlIbgTDd=AJ7|T?6FNy5*;mMKtp(fL6HH+~Bnp8=Yz`p(Xpjbx zz>Gsn7+7@Z?kEE1Bv{D5J)H<&+)!B?q0EX>4Tx0C=2z zkv&MmKpe$iQ;Q-MhZYfW$k3A<0Y862tHxBbFAk`hWn_{GF<)2}`(F{j2!aS9Dlt<} zWfybs9AEeF@%1jov%Js!Ifj&?$pD{79A~;=5pNLBZdy9$ec~{yNDA>e@uWc)B!1+& z?D8Auvcm$;3>&%3JaL#nSc#52SZMb#)@$h)j?-r}s*8mx0q{=$D?QCrD! zo#r@_SV9VEh>+1h6*X9h(W;SRB18KL5C53sPm@a~R~3vL3#dbdEUg+uOfqI{p0s zt08i|s%AED000j(vxWkS0wgqKGh{YnVmB=`VPZEeG%+@2En;J0I4xv2WMO1BWMXAC zVl$I81*-};FgG+eH#9LcF_Y;9bq6#$GBr9hHUVqcTc5+P&^885P$*;xPp07XeeK~y-)V`M-A|NsC0 z&p-rVWMpK-5F}PJ0|NuY)2C12YMB@)1Wedmf(@YCJczw88U`aW3>a~lj1NdlOEWT1 a3jhE>XL)}Y7}h}m0000! diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/trade_market_config_icon.png index 98b2fe82a5154f26aaf0d5727d7ca5e9d4eddd45..feff43089aac9aabbb48e60b0c4fbc9e38009fd3 100644 GIT binary patch delta 869 zcmV-r1DgDeBi|&D7!3jg0001Dofq-|006|1B_Dr54#OY}yYq@YAtV99bLiSh`@x<+ zQ_`wbwS?<9$PEeG@B0a_4vrc$70Wee0<>!724OVNc8;VwdqIbo{BSlHmf$O+wCwi} zKhl&G8&tXk+1ne-+^FjLb_?2i_ld)-EXu^^#FIK*kob}7 zlEZJDOE!CXW?0Xr=ZV9_LaB?TE@ow2A)XIO`ldWEa0~RUIlZ;_aryvcsjKB1;NTFLC{gyh%e#BKd;9lHyT2c| zzH-82+MtdA01q^2R9JLaO-wptvyB3Q0wgssFflV^GBPbRHaKN1G-G8rEn;IgH7zw` zW;Zc8IAt(lGBcAh1*;1=GBhzaGC46eG&Gaw1#|~DIy5jkF*lQA1}6tMIy5jkF*mc3 z2J8WozXn_+WH&W1Gcz(|EoCq_WGyr^VlXW@V>vM`V`MTmW;Qr7I5=iwlRpPc3o0004WQchCwMn{hnN^O7m5RI=Y+Cz6nKcqhqFO$v444#TH^lU zC!CT}bCoYa`i{mjH%ua5Z$a@R?h}!VHG(XHm_{Q-KpW4(Vp^|HST>xY<3J~_d-fS} zuca;e_SWns6K$LrotbqE!2JktbCI3NFZsYMr<2)Y5?{#Eo({kt+-g}IfIc9Jk?|mZ zQ;VV%2aAX}WT;MdsUnW0ibb$c+6t{Ym|Xe=O&XFE7e~Rh;NZt%)xpJCR|i)?5c~jf zc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@W3*RLwHdiMW`{uZq2|2w(&Q5D}G_sV6gw zS$K}Gd-(Wz7vWjn=l&dnO2K4+Pb7|iG2O6;H;899EuHf|afp>Ah4`F!%AgApKXP4m z`HgeQVS#6cjBI+II7BR#x>)XFRyI`P8RD>_YLqYJTvj-5aaOB!*1jiyVX&aBWVlXq z90@ETi4=7tqmBxyun?hDBgI6T_TwJ@F~^@GmrSk-7&#VDg9^# z#(}_#ZGTJvy}LlGVcXxww%s}b{LjFZ*74Vxz}zS4jgA&R0*1DMi|dXi?*W%P!03}M z8ImLUX$r+6@P0<$lm~`yf&MkOxAs0xAAl@%wR{5{90HRi%3k+)cVBmJ|DI|0_XFu{ za@HPpejoq<4pnJXSaeuTOgdw;jsk%KBsgSdGBRW_F)d;;bb~31A2oS|R8}00006VoOIv0RI600RN!9r<0TL5g~aD1v^eRPE>jWm~z>}a0 zKLjT*-N8}R*4YKx0t)X4B;0u%`pN)MRm-M`aQkfrG9N)-yiz(%00000NkvXXu0mjf Dimqyq diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/ui_config_icon.png index 694940b7bce0298bd1160fe34a65a2ddec15608b..34baae644ee5171f093e91b4d8ab1ae9cbbfbad4 100644 GIT binary patch delta 849 zcmV-X1FrnJA%-K67!3jg0001Dofq-|00702B{hGfRjFzT<2+CPU|A*Osd3yhTDmJwR^{v#i0a*7QqU5xDQg=H>Ob$`1V`9snt zVu;m^sv8N9LUe;RzD2oOxqe~UXoigwI!W2RPm_DB1>0K_lES=66atIb7(n{bAPpjc z8BG}&SPHZv*U%b$5-j9tPY1#u+e}#$o|4suk?|yd9V{y15U@JgMMWG-6^me@v=v%) zFuC*#nlvOSE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3;J6>}?mh0_0p4bn zDMn8WP*hV-C*ndbzbXV?;m06C7{idr3@w>i%))hi-NVDzyC~0cKlkV8mkS01JOXiy zX}U>&yg@v>X=t?9!*85RHhXzySkI>CiNnM~sf(p9W@TL= zo*|CNic0z3oWnBbEzU}{&f53nFANscl?>Nujv|32B$0vu33XIZg^4JwDk%oiv>$iz zkJ$bcxg>H`z{s(H8Wf1OAN&t~cWV@xwjSk}il5ZDD;4a@pIwyf3(;ClwH z)Q-Q_1m-?TZ*;WC5fIu2F0MP8v8TUppF0l4pnJXSaeuTOgdw4Z7yN6 zk^+4KBr!2HG%;poG%YkUVqq;bV>UD`IASm|En{RkWHV(pW;A0tF_SX|s|z_YG&3lr7|Nr9}`~?6200DGTPE!Ct=GbNc0004EOGiWihy@);lNAslQx7N~P*_kN z0000qNkl9e`RiGk`>+BLf2yqXUrNzzF1u bhA;pC5M>7Y-x)(h00000NkvXXu0mjf8$4XT delta 843 zcmV-R1GM~xBe@}v7!3#p0000V^Z#K0006|1B{hG9s!X$laUL=u;rP5?;nBfSgQjA+ z=1hQAt=u4t2HMGy^kffciX|Ve0wX23WrUW!f94}CPO(9yn~^=eu&srv?r%Rv{*d&E z7-Dy$>PEt&5Z$1SZ&9vR?qAprT4CdaPEt1`%<{P@U|eB95hsMX*rX3avVr zT>1q~8j=(jN5Qq=;KyRs!Nplu2UkH5`~Y!wa8h)U691PJTEuv8+>dwn9(V5mf3wO| zvnK|qnq{ODaWR))6+^EGVi;izLXeoLCo_v#c#f}o`1pDkE!DN6>B#trN zu!w&*h-Wt~o%24iz{-+Bd`>)R&;^Mfxh}i>#<}FMpJxh2Ha$-)5R0WQmb;jh4V8F? zIHIT;<@<9kE1b7DtJOMd-;=*ET+miBT&FpP1eTCQ3L<3GQ9%_JqO@wHm`Kxp+`~WW z_*3MP$yEU(#{z0lAvu2VKlt6PS)877lfr*-Aoyb2ALBr17icwX`}^3oTPHx^8Mx9q z{#p~5`y{>5(IQ8{z&3Dk-O=Pd;Bp5TdD10Aa-;xFf3XO>pV2qvfuUQVZ_Vwky^qre zAWK~>-v9@Pz(k3%*FE0d+uhs0XWIS!0C`t(sV8$A-T(j%c4<^tbXZMHI%98bE@88i z0(}A`H85g0F*i0jEiySWV=Xi?WnnEjW;kOlV=-kiVPP>iF<~}hlQadZ3pg+`H#9gj zGdMFjlj;R@2Q)e{H##*mlVt`c2Q)e{H##*mvy%o50keMyUm01y!Z z06UHF8+>5E_gFisa(9+yy)sTCsHy*tj4XrM)UU0(Gc&Oap5+Py1pY-xpd zWyyB>up3fb69>XDq12P669{>L(}$sPoYW11!6BW{M+Os5VGK=U+B&2(p$5`ndUyRm zo@S=wndYB0BkkUE&-v~--#zEdz3TLC-nb}ZX$FEIi`*5?8u-l7zJ>+xceNvk!N*6f zzB;vri=p9&EJ{rPRa?RU1#wA4kod@x4?dEeK(js@%UxGmaaa4FfA>t^vhf>AWy7$0 zZ(jP|C4bw`9C>vt@BX&%rRUz>)N8x9^p%G~6&cs}XYV?g)>^W%|Jo&cy|-gq>(=*g zF1G*kO7!|yw*M)=G;sKdwcFB;+KMmSd^@H8vCRGjoo|}(+wGa@11mqeKHeR{o7+a{ zKRV7F^X*d3{66=^DzP6Usvg}x_KRhU*NyPy7p0u%@85FYv+;ce3v&xE92&1Y#8q#| z%YJRiDR05hichHciB}&_xqI07hME1rP1}zf%Zo4nB(TG>dO`HNyFXdF3qcHzOJ!wV zcUjqV;4s{tZ|`wbBsMHR^{q!LU29gXU2{3-XYBhf*Ye86UG+chTl{d8?Ef_L0JEyl z*xk|i)>}`VdincZzwFKK?LcoBE{~5Myn?O1O%(R+yf*q;{>N7xS1%eaiu(%7tFyem z+Ul=fE;SCWS@_LMr_s_SiQPk4_>Z>!_C)lt3yH+=K*8Ba@x<7bXEIY4*zelDOM2b? zMu~kudbDSvGjU|?nUiBD_p;k|-`Ml_rxS8dWl>v;SaW+E=gI(}AQ%ecm0N1xMEurv9NXKX&b@ z^S5*RS4F=5o1ve7Z)xt% zwx#yI*FAV{;fL$pvf4NFrJRveWAC~HeQDpgiX^HJyx4X8gXjN>=e19mZoOb9!9!EsBPWs z<69efn}8Ls&#=c?2oMA+hsJ|VA%%@QFddhL@0ysvP+diBbYOKJFIpx?0LmB{BZ<4> zQZtRM&p_=FL1b&3!FTEQ@G0h&M%sw!|*YSxk)-5&3Z zg+@U@3WjwnNcJpERTA%zHOn_`Mh_?15okVxJ4<^yc3l~2c|5FB=A)W>Zl?p&)@KEo zmjqUSHCq`gZ8KYO%4B13hO&~l%@6!I$zN4khqxxf}^{a66?S7XU;!6woI$!r2n9+kw$W@{YvY#Hk`Q zfHfe61UaVMnes_NP^)qppOl3vGTCT`DPpWvl9~)$M|=oG6qt(|Dn%MiR^43N7#4;D zspYgxg#fx7M#Gjx0H?|kpDZ^yFbx9LEN7-Yu%HA^<(!-fASg*QENNzG+DBPfhGdzd zuaPuMCh5z9B)0r7ZLNGz`{brqND5rPMHfxhR4v#(Ihq_cNqRA%s9qK<$4`c!aLqu_ z{e)PPQ+xv#3INzYrV@5qE`3fim_*(}GJZ2ok|KpOz((VKznQ`X-pW93fgqas+31Qa zsxdACN&=8a$Q4Xboh!6pYO4xo>&F^^whxdpoHXM}lwrhFu!PnzrlYkJ|HX%0S4e6x z&~8!&TNmtv#7rxk;!A5fU*KnIAHKj9AoTnqbK-ZNu6erV#K4@C=d){`t~oIgIA^T(XLzYnw9FU^11X27jh`je-^$O)SAt;$c7Kk!#@KMgTHd4 z6WN)vq5=-m!xdW<1j)Qt`x=k~Jxic4O?7)*X;)J6?kO-Dp75@MqWe@=omwUbwbMGH zA0dH&#w4`?)sB!`+Oxk5m9pH<65rj!d_B4dj!49C`sE$)N{AqC*JfvLX?@3k0IWv+ A*#H0l delta 493 zcmV1q~8j=(jN5Qq=;KyRs!Nplu2UkH5 z`~Y!wa8h)U691PJTEuv8+>dwn9(V5mp;=|B*%Jd)%`(!7xPO?-uZq2|2w)gN3?d{k zQ%`0Vv+x{W_we!cF3PjK&;2<sH1`^EJSJ5NHLM7{kVsJ)bXdtC6lWHMvev4ph9x|;D7MDTeCPl zDjh5;;t;Tt8Ua6l-e#34Mo$b-R8vnU;zBOJDg<8P#~?x&!;r`fEty%&!gYMz z!^79RD9>^~_vh%B3kCx`0&$FKx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z>ypE7oJ%%) zd1hG8rss*n#6qcyr7mV=T_K(!j>w8i`QDtvGUqMMO0~|~_v9~s3>MUt4A*InB7r3& zk%9mTbyQG=i72fqDF)KCA9wMO*!~o`Byv^2$gzML6o|GT{11M2YZRxaoTOkJ@V{8r z$2bt!1zHWu`aZU-)(PNy2CmeOzt#liK1pwMw8#+<+6FGJJDRiyTF)cJQF*Yq?WHe(fGGk_AW@a~JWimCBJ_k(;GBQ*#H##&iIxsM^bqHt(GvfmH zIsgCw2~bQ_MF0Q*<>lr7|Nq3nyhZ>300DGTPE!Ct=GbNc0004EOGiWihy@);lk*TE zS`R4z#7k_d0000xNkllQWH0nhW{2rxWl6+d^3ta>hcvk?|l3 zQ;Q-MhZYfW$k3A;0Y862tHxBbFAk`hWn_{GF<)2}`(F{j2!aS9Dlt<}Wfybs9AEeF z@%1jov%Js!Ifj&?$pD{79A~;=5pNLBZdy9$ec~{yNDA>e@uWc)B!1+&?D8Auvcm$; z3>&%3JaL#nSc#52SZMb#)@$h)j?-r}s*8mx0q{=$D?QCrD!o#r@_SV9VE zh>+1h6*X9h(W;SRB18KL5C53sPm@a~R~3vL3#dbdEUg+uOfqI{p0st08i|s%AED z000hEvxNeR0wiNFFg7qTHDxU~IW=Z2G&E&3En#6fHZ3$|VlreoH!x&3WjT{G1*;1< zFf=zfG&V3cHZhaw1#|~AIx;ajF*uWC1}6tJIx;ajF*vi52J8W|T?t?a7WLSIi2wiq z24YJ`L;&Uh<^blp(PCed@DU+>3>6YaN7_UH003S|L_t(I%hi%g3cw%?M2++ox&P7T z9IvZN5D}xL(5&u}xqTN2N}x&yj<)8Sf$Bb5Gsbjj34 sfM{1Q;Pje)bIQ7(!pCtPrR&qW0c@gR6Ghe&m;e9(07*qoM6N<$f+lEH0RR91 diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/wynntils_config_icon.png index 908dbef449764ad5b989d4e10865ff2d3fd0190d..adbaf1cf8c52b1230d45cc9ac287903ad9d08d41 100644 GIT binary patch delta 489 zcmeBCexfo#f|H4vfq@}uuK1^kipuqle1{cyc7N`&Ra9X-RQ%$W=kJ5_?3pt|mqi{b zm3h+E^7wOIt2?_p@2sw;vy2&|wiY!T%*tq1ewm>ELZn-M9ou1{n$&62{{DOE9yKYc z*=xH(byae-bg1q9x~4zwm(-Iw?l!Mt=REKBrNL~z>&~d1_KDURt!IU;JSA_2pU7XU z$9ns=uur0$3Rk0R4xhr`j0tQL5A=9TL~w24S# zjSLOUEsab}jEpD0WG!Jgw=y=hGBBT%%wpe8&W0PcaOAFnUv=kFv zlT_n0U5n&2GhNHnL^D$p3j@QnRLjW@>^|H^Mj?h!gEp6OWN;YID_A@S7_giHJ|V6Q z3|&v3KK=jy|BL0Ezkq^_B|(0{3=Yq3q=7g|-tI089jvk*lfMWk2JZA!u6{1-oD!M$1#|~AIx;XiF*%cD1}6tJIx;XiF*&o62J8W|T?t?a7V%3XsQ>@~24YJ` zL;(K){{a7>y{D6t@DU+*3=|V6TicTW003A?L_t(I%iWT(5x_7A1CiHY|Isvu+@$h> zLxL+)f_QX*Su+qNB`FjG*wXYwRwpTvvM*CJ(C_9IGP+B=0MNd|IR{l2>kpiD@a7_Y i;|e5eMs=FIhuR4^>_uO8Xm0)h0000gGx6edwOA83sv3UevJGh=^Zh|?nc#(ghwH|K^tRHu2$|NYzM8daY834r}t&@ z8*6{T_V$FNFdq_yz#=vpkbX2sgGgY;BQz`pT5)%tBVi%`_B0W`+w@r&Zj2JD0004n zX+uL$Nkc;*aB^>EX>4Tx0C=2zkv&MmKpe$iTT4YM9V{ZnAwv}eyQqj`sbUcX~Fh$QM?Hz$^S1MhFv#h|JJZ*~J`O$JaePe7%eDEcbJNjzPI-Fu)@a z$C;*^#2du3o2JHjpE%4aqD*{FJgL(Ki66NxIsC@CY_peVhV@)#o;XY_lzUj}VOD?9 z72+AA(Ki)VL3E7WHx3sFq1O{s|z_YH83+YIWRRfHlr7|NmyV z9tHpa00DGTPE!Ct=GbNc0004EOGiWihy@);lNAslOb;n5X!n)s0000jNklN^H>=T>t<807*qo IM6N<$f(-m<$^ZZW delta 836 zcmV-K1H1hGBBmjb7!3#p0000V^Z#K0006|1B_Ds=4Z|P|{AY@efFFPvhcv0w4LW`g zaH3H4B#!e#hjBPQ?^k$qFlo?KEZ3YPpj9h32#XVKFhw2gK|IBh4_ASa65KLF%ie$H zDK1Xbpwi9Ao?h72LRI&-A0vNA`a}$|yHRx`;aMOzX!Bb!S1b1~Y)4#S^Mp=PhWBOi z8*6{T_V$FNFdsq^!6G&XkbX2sgGgXT69z^@Lrh>Dtuz<%Z%-$}7u+0K8ho_DQvd(~ zglR)VP)S2WAaHVTW@&6?004NLeUUv#!$2IxUsH>s6$gumIAo|!cBvwcrHVzcP}&Nu zI+$Gg1x*@~6cEUV9D_>1WPnd3 zjxpV^h&PC5H!Yp>K5>YZC58B$c*>v)5|FXUWSIB#)Qt991CCx2nEpsi%MPIDXyEFp;$btI#X3aYRWp;aTrM4I;F z9{w@MpCXq`t_m1A7Epr<$?=2#!S8O(;&jwa3dVuJi*0{Q0KL0Ft6|&U$F|)%0sPOv zmDcgsn!wyA>5YySJ_3fefs5;oChtW7mpj1dlP(#OBl&3x#Uk*2M&FbNhHruXHMh6+ zK29HiEOoVf0~{OzlO@Vt_jq?-cW?imY4`U7>1=Y=9(H~p000ekvxNeS0wXavVr4Km zIW1)}GBhnTW;J3hVKHGhEipGTH!)*5WnnisIFmC4s|z8^p7lrp9@nILs=dOngo}snZ3CAGt0${KmO#vzKRv^;~A2I7}>* zdsymWR?!vW8RDp{sFd%`J1leF;;hsftaE=){=#5UUCDBt<|vX_LJDaJkkCLCHJFIe zs*++LL;DFAf5i5u$t97i3Pz3v)S*DM{osG_yIZ3)J>?_?6M+B4vOdOuz%I~kTGscm zWwlQL-!pKfcK!7hF!xD%v#UjqfY3H@aoyFVJ>YT&7e0Lyr0oG6@W0I zTVP<#>8-Pm(+40&T`k`L2Zz9TnX=bi-re8Z+rMWz{rv#WFLKMTO2*v)01j2Ng#wBK zBw{xEhH!);lVK_1|Gcsb6KnG9lr7|NqT<9YX*B00DGTPE!Ct=GbNc0004EOGiWihy@);lNAslOb;m}_(+I*0000j zNkl3WyK^5iH2s0n@AnY*Sa5 QIRF3v07*qoM6N<$f`yqRX#fBK delta 693 zcmV;m0!saWBdsBj7!3#p0000V^Z#K0006|1CAEJT4Gl4ap?wl8B#trNu!uK^XE!aK^FDEil_iDvoOsHh3lcwaU3U46bID|FXUWSIB#)Qt991CCx3rou%NAExK48%2`nLr6m=w{jtZ)<5TR8g z#YCF+;~xGo$DbmXOs)zTITlcZ3d!+<|H1EW&Ej;_O$x?=z>95vOaQ&RK&xTf-^aGy zIsyF8z?IhV*P6iGC+Urj7Cr)owtjiWNGdeXgIx#boW(Fq*GdeXgIx#b|lm-m}vw#R-2o^8#Lr4Gs00v@9M??Vs0RI60 zpuMM)lM@jkcMCKPLZ8&v00013NklhiK;=6@Im+) z`K;LRU%9(K@%1-w7?6RNfGj)(RA7J&z|2DU>V8O4o6Kk3!Ak{6ZHz&AgK9{RdR0D2 b5BMGJmqR Date: Thu, 23 May 2024 16:47:12 +0100 Subject: [PATCH 27/28] feat: Separate Search Widget --- .../settings/WynntilsBookSettingsScreen.java | 13 ++++------ .../widgets/SettingsSearchWidget.java | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java diff --git a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java index ef5ddfd218..ad39858820 100644 --- a/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java +++ b/common/src/main/java/com/wynntils/screens/settings/WynntilsBookSettingsScreen.java @@ -24,6 +24,7 @@ import com.wynntils.screens.settings.widgets.ConfigurableButton; import com.wynntils.screens.settings.widgets.SettingsCategoryTabButton; import com.wynntils.screens.settings.widgets.SettingsPageTabButton; +import com.wynntils.screens.settings.widgets.SettingsSearchWidget; import com.wynntils.screens.settings.widgets.SettingsSideTabButton; import com.wynntils.utils.MathUtils; import com.wynntils.utils.StringUtils; @@ -99,10 +100,10 @@ public final class WynntilsBookSettingsScreen extends WynntilsScreen { private WynntilsBookSettingsScreen() { super(Component.translatable("screens.wynntils.settingsScreen.name")); - searchWidget = new SearchWidget( - 60, + searchWidget = new SettingsSearchWidget( + 55, Texture.CONFIG_BOOK_BACKGROUND.height() + 6, - 100, + 120, 20, (s) -> { configurablesScrollOffset = 0; @@ -262,8 +263,6 @@ public void doRender(GuiGraphics guiGraphics, int mouseX, int mouseY, float part int adjustedMouseX = mouseX - (int) translationX; int adjustedMouseY = mouseY - (int) translationY; - renderSearchBar(poseStack); - renderTags(guiGraphics, adjustedMouseX, adjustedMouseY, partialTick); renderBg(poseStack); @@ -889,10 +888,6 @@ private void renderBg(PoseStack poseStack) { RenderUtils.drawTexturedRect(poseStack, Texture.CONFIG_BOOK_BACKGROUND, 0, 0); } - private void renderSearchBar(PoseStack poseStack) { - RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 5); - } - private void renderTags(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { for (Renderable renderable : renderables) { renderable.render(guiGraphics, mouseX, mouseY, partialTick); diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java new file mode 100644 index 0000000000..180cb8e5bf --- /dev/null +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java @@ -0,0 +1,24 @@ +/* + * Copyright © Wynntils 2024. + * This file is released under LGPLv3. See LICENSE for full license details. + */ +package com.wynntils.screens.settings.widgets; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.wynntils.screens.base.TextboxScreen; +import com.wynntils.screens.base.widgets.SearchWidget; +import com.wynntils.utils.render.RenderUtils; +import com.wynntils.utils.render.Texture; +import java.util.function.Consumer; + +public class SettingsSearchWidget extends SearchWidget { + public SettingsSearchWidget( + int x, int y, int width, int height, Consumer onUpdateConsumer, TextboxScreen textboxScreen) { + super(x, y, width, height, onUpdateConsumer, textboxScreen); + } + + @Override + protected void renderBackground(PoseStack poseStack) { + RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 5); + } +} From e9c5f6c1a3e3b2cf0d247a910d9a9207cfc28ebc Mon Sep 17 00:00:00 2001 From: Rafii2198 Date: Fri, 24 May 2024 00:01:53 +0200 Subject: [PATCH 28/28] Final touches --- .../widgets/SettingsSearchWidget.java | 2 +- .../com/wynntils/utils/render/Texture.java | 2 +- .../textures/content_book/tag_search.png | Bin 4764 -> 4990 bytes .../commands_config_icon.png | Bin 4908 -> 5139 bytes .../config_categories/debug_config_icon.png | Bin 4688 -> 4928 bytes .../embellishments_config_icon.png | Bin 4710 -> 4942 bytes .../config_categories/map_config_icon.png | Bin 4716 -> 4952 bytes .../uncategorized_config_icon.png | Bin 4297 -> 4548 bytes 8 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java index 180cb8e5bf..99dcce2343 100644 --- a/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java +++ b/common/src/main/java/com/wynntils/screens/settings/widgets/SettingsSearchWidget.java @@ -19,6 +19,6 @@ public SettingsSearchWidget( @Override protected void renderBackground(PoseStack poseStack) { - RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 5); + RenderUtils.drawTexturedRect(poseStack, Texture.TAG_SEARCH, 30, Texture.CONFIG_BOOK_BACKGROUND.height() - 3); } } diff --git a/common/src/main/java/com/wynntils/utils/render/Texture.java b/common/src/main/java/com/wynntils/utils/render/Texture.java index c1e83c9827..1f644e555d 100644 --- a/common/src/main/java/com/wynntils/utils/render/Texture.java +++ b/common/src/main/java/com/wynntils/utils/render/Texture.java @@ -29,7 +29,7 @@ public enum Texture { TAG_BLUE("content_book/tag_blue.png", 44, 22), TAG_RED("content_book/tag_red.png", 22, 44), TAG_RED_SELECTED("content_book/tag_red_selected.png", 22, 44), - TAG_SEARCH("content_book/tag_search.png", 140, 34), + TAG_SEARCH("content_book/tag_search.png", 140, 30), // endregion // region Icons diff --git a/common/src/main/resources/assets/wynntils/textures/content_book/tag_search.png b/common/src/main/resources/assets/wynntils/textures/content_book/tag_search.png index c376c04b79ae8a441c5c3436a147f7c4caa263f0..6a310c045e6d73f6c3c6b0ecc15bcb6fc8e275ec 100644 GIT binary patch delta 1407 zcmV-_1%UdTCH^Lm7YZH-1^@s6{%-bmks%|0!4bnC4EuYEj)1WNGY)CeyKd0&E5PKM zT*V=b3<8^u&-+D>j>t-yishPf0JLh24S|J;HkgAB9 z!CV@m^kcMM;O&~I>i%{!@`t4VC?eS1sJfBFnP4|)v#gM-mERJ!Rl$PINu8t&@6+Ue zzSn~8?Fpj9cnC`Xi`e{t^r<8bK>}lggMD;`hq8KthWzW(0(}8{5?Ody$=<9000D$) zLqkwWLqi~Na&Km7Y-Iodc$|HaJxIeq9K~N#OGPRjEGXiTp*q>Y55!TbSOg2DtS}bq^n3?_xa5``n+SUn!Uj@QK88 zOgAjz4dR(iOXs{#9ARZiAwDM_H|T=Ik6f2se&bwnSm2ovBb%Nlju4BbE|$B0n3WBc zc$zq>s2b%9IhPgATb$Kuowe`DUl=NAD;ciS96HBwBZX+Q4a zA9nmHa>?YXfRSSXHK>prKlmT~?$#_$O}a^;I1qTT?T=9)xC^uzw*7r<+pQD8{|sDd z9e=F}%zl#I=xEU+AiND+Tz51^c@MbU0fwG*$&eh$Pg5usf%h}|raUlk3-qnIy|wpo z`T%69tK}Qu;1C!qQTDpWyL-EP`}a({zaQ0%a?bTs6d(Wq4pp;;0*V48Fk&)eHZWvl zEoEdeH!U<{Vm2)}F=IF_V_`BjI5;>oGht$3lQadY3^gz@HaIXjH8(agG?VHDaSAk4 zFfckWF*-6ZlVt`Z3N%zOFgh?XIx;Y`lLid|lfedDBsnxNF*0LjVJ$T|GdV3ZGGs9= zIAUcsEn{XkW;iiqVmC8nF_S?DO$szrFfckWF*-6ZvzP~H2o?on9;E;P00v@9M??Vs z0RI60puMM)lNJyle-{=36ex%3=Kuf#Nl8RORCwC$nXyY7Q5?s=C)a{Vv^)xjXa-$M zz@bz~H!WnULPuS6P>{B6l6Gi8ItcC12LFHz9dzm_oK6mAv!FNxj#^N{*&z)aYG|bz z`Z}b!Cb@)Ml17ia?+1>9caP)o`+a!7cfV862C=Y^%h6%SfB4GhBW#rXP#8jC2!$bjr{%At@v$*k0FeAqIlj3iD5v=ZlNTWHQKRvlY)Gkq9OxC$XsmFjI_f(1od%C6Pz~0G2-O004~L z4OHBm*X{-`^3Dd`f7{3R5s%01^9u>EFbh3r`0(zP zLz>c6E{hNX>uYQ5`uY$h78Y`DB;0V~%9n3=@$3;YW)7jj2?!xz7)HgM($2D}>y*WZ zd`z3}8h7Qgqz}Kt(BEVJ>C2j>hqCw^wP{(t=CFKk07+f1Te?UA{eDVXkXuX|yQf;gWQESzs9=t~k9c6nB`z^Irf^A1^@s6jn*-sks%|0+YQ4Y4E*;L9lINOZ227Mx zJ&D7d;jj(I=lz052a|%PV!7sw4y{_bd0;rv1{3Pw0eeP{?m93>f?X2dB_8CszjQhc z=GHt)7o+t9ZTCdg@V6hM_(*z1y@)-GY8VO61cgDHZDFoft}Sc_-eGe=Cn>}GH2FP$ zYw_vr$wgs4gan;MY!)DWDM<4mIkR8#f+c%QLqSnNgNw7S4z7ZKAou~|?BJy6A|?JWDYS_3;J6>}?mh0_0YaWa=of%HgEs{4R*7J0*V48I5cB6Wi>W9 zEif`OGc7bZVKOaYH!@}|FlAz7VPiKnF*IQ|lQadY3^O=4GcYqaI5;sjGn48CaSAe2 zF*Z6eH99aelVt`Z3NlnNHaamiIxsV{lLid|vwsL+2o^$h_+0=100v@9M??VT0OkPZ zy3t}^ll2fFe-;i81D{^h0{{R5MoC0LRCwC$n=xn;Q5eVn7wTY2EIgEl)C_eg4>|}! zIx1wcg^s#3Lx+N^#6=+#3Fx4QvjlXgQ^&x?se^+<3W7uAu!X{TI;4R|)1xic&^T02 z#%mC};@e-H@o9&h-6Kfb%~LJXXMY+AGnnd^b|f8yFER$Xm?oEfK8n*^gJQ5ZSt z0pIq1GR1SsY1D=thENznVF-mG6ozn0I*!)F6iU0@4t1IAAPbXCi*_7Y=5x8gy4D&M z3&^6@X1wQbuI#ZoXGpjAFxQe7 zVxL!Bf7^`y4D-J%rfI@7O&m_o;c$8mwrxWQftlG^EH#p>+JIqX)1tjFmF{bEX?H9j z%j0*SI`-^)O(d#iD5U@ZZ|f7U%f2iX%c3m9 z++qI8(m-u}3$I^2ht?WWN=PZ8l%g!`Fx_RbHyS8Rj-zB*p|>tFq{4*BLNRztiX;o6 zYA}?A#1n?HkiLbXETnH?C<}?)VJHjfd#o-@j-zOO_P-Mn5N7+Jh4q~u{=&VhmjR$- zjSv9XK4=|vm=9mKm%Qa_oXw}Ni1H*|nm{12tf@iSka241k@mpqUIr>kXaB-sMQMwt~GYZ>U zs2cwEV-!D5cw1Z!JTin8X+IZ%-%S3)?_h6gXTKSds7`e^X0EDjh5+;*g;_ z*})IQQL0!33#F~ls)Na;U(lo>NpW!$Tni3IfbAYN@MmiA}bNN*<_=*4q5kVLe5;OH=W-$xT@pTU$U+-c( z%lq7)qhBeQ4DgA>e{)PXEaDB~nN3UQyiXiqWl14ECmuKGg2azpmtB72Tyj|8nGqwK zo+pkFi={4>yO@;?m3W#ss;C;}3ptk+&Rd+-YMr(3$zK>MXe$}6(;PtpOGqLG5i;ti zpb85yS~XHkq-j6y;U9MVDRRl=s(_JW0X3+Q96$IU{O;B)e@;!hNuf9pc(Lt|Q6RVr zv>LYkeQevU6TtrrTxlJDtqIJ2lHTZO(IX(d4P0DzGIO z`ldWEa0~RUxxKabaryvcsjKB1;NTD#D^d2k$GdyGd;9lHyT2dRjB?KPR1_cp01)zN zR9JLaO-wptvyB3Q0wgmxHa0OgW-=`_G&5!`G&N>2EjVF0H!UzRVrDR7IWsphFffxc z1*!}*IW;siF*7kVIWjYo=ml{KGgLA%Ix#moGBJ~51|$kIR5CI;F*iCgF|&~dssoe1 z23#aFVqrEiV>n_hVKO&mEi_^_IW0LdGcqkOWHB*iFflb{V=!ZrKL<<;GBZ>%GCDCg zIx;b{GYV)391ha#&;S4c3{Xr|MF0Q*006(`<>mkX|D<+ZS(CI9Izkr|5fv83A5H)O z03u05K~xCWV_*OQ9uUC{W*z_$23Q1{;bI1;LQJbxFu(x-iR=V1tD-$400000NkvXX Hu0mjfXaPtx delta 764 zcmV-1=D_r$EGOk?|mZTT4YM9V{y15U@Jg zMMWG-6^me@v=v%)FuC*#nlvOSE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3 z;J6>}?mh0_0p4bnDMn8WP*hV-C*ndbzbXV?;m06C7{idr3@w>i%))hi-NVDzyC~0c zKlkV8mkS01JOXiljA^<_yg@v>X=t?9!*85RHhXzySkI>C ziNnM~sf(p9W@TL=o*|CNic0z3oWnBbEzU}{&f53nFANscl?>Nujv|32B$0vu33XIZ zg^4JwDk%oiv>$izkJ$bcxg>H`z{s(H8Wf1OAN&t~cWV@Xr>C5xU>xwjSk}il5ZDD; z4a@pIwyf3(;ClwH)Q-Q_1m-?TZ*;WC5fIu2F0MP8v8TUppF0l5EE%s zSaeuTOgdw;jsk%KBrr5&Vq#%AWGysdGB+(WVK*}^VK8AcEo5dmW;tXvVK`zpWs@@n zsthwZGBPtaIW#aiHaL^%1#t>8R53R?GdDUhHJVa diff --git a/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png b/common/src/main/resources/assets/wynntils/textures/icons/config_categories/debug_config_icon.png index 5c97886cf2b94a37468fe8918641134f65b0ecbf..1c6e39a00929cd96f479f8e8afb68c33ee2f261b 100644 GIT binary patch delta 840 zcmV-O1GoIpB)}$+Bmu#ZB_Mwi!ypK}`-(mRSyX(EY0{bgpwBNxlEzHeab3V!k+6N< zukh&LC_z%uTyrLaRH@udC=IloBgxJl&>^OLI16kk*ohHp_WMUZ(&QAIsdO>Yrx%vF zP{sZAX5z#~9);)zZG4Mz)pGs9ve673J9I+Xy-$;SEX69OwNpW!$Tni3IfbAYN@MmiA}bNN*<_=*4q5kVLe5;OH=W-$xT@pTU$U+-c(%lq7) zqhBeQ4DgA>e{)PXEaDB~nN3UQyiXiqWl14ECmuKGg2azpmtB72Tyj|8nGqwKo+pkF zi={4>yO@;?m3W#ss;C;}3ptk+&Rd+-YMr(3$zK>MXe$}6(;PtpOGqLG5i;tipb85y zS~XHkq-j6y;U9MVDRRl=s(_JW0X3+Q96$IU{O;B)e@;!hNuf9pc(Lt|Q6RVrv>LYk zeQevU6TtrrTxlJDtqIJ2lHTZO(IX(d4P0DzGIO`ldWE za0~RUxxKabaryvcsjKB1;NTD#D^d2k$GdyGd;9lHyT2dRjB?KPR1_cp01y*tR9JLa zO-wptvy1|P0wgvuFflh_GB7PUWHB%;G%{i_EjT$fI4w9dHexkoIW=Z8G-Z=91*!}* zIW;#lGB`CeFgY-j=LK;JGgLA%Ix;dkGBT551|$kIR5CI;GBP?cGP95d%L0?W23#aH zGchnRGB`9XWMesIEi^eWIW1y1GdC?WG%_?aHe+HiVl^?7J_k$-GBZ>%GCDFcIx;e| zQweAY9QVpIjsO4v3{Xr|MF0Q*000l=<>mkX|AYe)`IFQUI#CxC78byc*fRhC05M5K zK~xCWV_*OS{trOHfCGpPI5-%1{=ZUSU}j)wKqvk%Flb?w;90dwfx&=*fdc@W@(Qzd SM#&cd0000JgfHCwSsr)TvxbrGAb(p+MJgRED&i2ZI@v`< z97`38V4<`XT6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)=0pjf7r060g{x2!Ci1FaK zAMfrx?%o03W|b*MPYh60Q%@)2LN3251YY6CAVL_!kjM-znOV%jb$s2!!`Hhg&vHNa z=jfLU1_L|-aes_yx=Fl2JiBRXocD>ttSrjJ=fsmbU6A;Z>ypE7oJ%%)d1hG8rss*n z#6qcyr7mV=T_K(!j>w8i`QDtvGUqMMO0~|~_v9}O7Sxpt*J+L-fh8o7f&dA1R8WP9 zD6J|f2GX=2ckz$d{uH?+a#g^{v49#Bh_)a64}N!R6o03uoTOkJ@V{8r$2bt!1zHWu z`aZU-)(PNy2CmeOzt#liK1pwMw8#+<+6FGJJDRiyTtvS85_i_3FWT~s=8{ps&m?%;9y34zJyLlr7|Nk&WM+}K$j7_N57k?|mZQ%glE9V{r~kfA!+ z!4Jeys#pXIrLEAagUO{|(4-+rad8w}3l4rPRvlcNb#-tR1i=pwX9p)m7b)?7NufoI z2gm(*ckglc4iK7ErkXu-fT~$WIuRFh`BgFaiU0-?K^PMfGxcOS}bq^n3?_xa5 z``n+SUn!Uj@QK8Kb4)iZ;tk@NO-tvzPaI)oNg+Nb9yjQM#E)E;U4G+Sa#-M*5hI(P zCyo${r7o7cn3WBcc$zq>s2b%9IhPgATb$Kuowe`DUl=NAD;ciS96HBwBZX+Q4aA9nmHa>?YXfRSSXHK>prKlmT~?$#`SPEEQ=p*RqDvF(phAh-*( z8n*p?Y}>69!2b+fX&ry93CwL5 zstYtZHZUEoT4#*5&2p|NsAVnv$-Q))6{g7Ze&gUgP`R0000z zNklk07*qoM6N<$g8cbsH2?qr delta 788 zcmV+v1MB?GCgvoNBmu;cB_DrV4#OY}`{xupLP!FH2i_ld)-EXu^^#FIK*kob}7lEZJDOE!CXW?0Xr z=ZV9_LaB?TE@ow2A)XIO z`ldWEa0~RUIlZ;_aryvcsjKB1;NTFLC{gyh%e#BKd;9lHyT2c|zH-82+MtdA01q^2 zR9JLaO-wptvyB3Q0wgwMI5II}F=j1gW-~Y~G+|{hEjTh|I4xr`H!?RkG&VOfWi*pA z1*!`(IWjUhGBGhSF)@?p1#${9R53R?GdMahGLvHlBnmQAF*iChI65#gvyleN0<${` zUy7UDqW21?S*A7RCRy5 z8TmufJ7S2{jj9_7k3w{VHoirS}bq^n3?_xa5``n+S zUn!Uj@QK8Kb4)iZ;tk@NO-tvzPaI)oNg+Nb9yjQM#E)E;U4G+Sa#-M*5hI(PCyo${ zr7o7cn3WBcc$zq>s2b%9IhPgATb$Kuowe`DUl=NAD;ciS96 zHBwBZX+Q4aA9nmHa>?YXfRSSXHK>prKlmT~?$#`SPEEQ=p*RqDvF(phAh-*(8n*p? zY}>69!2b+fX&ry93Cw9R5CI;GB`RhHGGs7eIFmmIO$#zJR5CI;GB`RhH?vg< zXb2oY>uYiV000b7OjJbx00000z2)WQ|Ns9p=}d5w))6{p7Ze;3qy?oK0000+NklE;w0RJs`1(+k_ZP}TkI z$H;#qeIka~-Ke^e@GL|(Xmc&f)yj2+?VvkszR*d^@IFm`V=gVY-ky*Y=0l} z?mh0_0p4bnDMn8WP*hV-C*ndbzbXV?;m06C7{idr3@w>i%))hi-NVDzyC~0cKlkV8 zmkS01JOXiljA^<_yg@v>X=t?9!*85RHhXzySkI>CiNnM~ zsf(p9W@TL=o*|CNic0z3oWnBbEzU}{&f53nFANscl?>Nujv|32B$0vu33XIZg^4Jw zDk%oiv>$izkJ$bcxg>H`z{s(H8Wf1OAN&t~cWV@Xr>C5xU>xwjSk}il5ZDD;4a@pI zwyf3(;ClwH)Q-Q_1m-?TZ*;WC5fIu2F0MP8v8TUppF0l4>W01SaeuT zOgdw;jsk%KBrrE-Gcz?aG%aH^F*PkTWjA9jIbt(mEj2V{IWjmlI50FhFq1O{sthwZ zGBYtXGdVXiF*K9u1#t>8R53R?GdMakHIrlpBnmQAF*iChI65;mvyukO0<$~{U)q51#bj(MmF-NGfK7O+taqE z+^tw#%aAoKDQ2TLm7G&$TvRMm&+Q%WnRR>;sIlsk8UY}GQ%glE9V{r~ zkfA!+!4Jeys#pXIrLEAagUO{|(4-+rad8w}3l4rPRvlcNb#-tR1i=pwX9p)m7b)?7 zNufoI2gm(*ckglc4iK7ErkXu-fT~$WIuRFh`BgFaiU0-?K^PMfGxcOS}bq^n3 z?_xa5``n+SUn!Uj@QK8Kb4)iZ;tk@NO-tvzPaI)oNg+Nb9yjQM#E)E;U4G+Sa#-M* z5hI(PCyo${r7o7cn3WBcc$zq>s2b%9IhPgATb$Kuowe`DUl=NAD;ciS96HBwBZX+Q4aA9nmHa>?YXfRSSXHK>prKlmT~?$#`SPEEQ=p*RqDvF(ph zAh-*(8n*p?Y}>69!2b+fX&ry93CwXas7z+LA}>s8nCG$^6+7BvM&4-ttSrjJ=fsmbU6A;Z>ypE7oJ%%)d1hG8 zrss*n#6qcyr7mV=T_K(!j>w8i`QDtvGUqMMO0~|~_v9}O7Sxpt*J+L-fh8o7f&dA1 zR8WP9D6J|f2GX=2ckz$d{uH?+a#g^{v49#Bh_)a64}N!R6o03uoTOkJ@V{8r$2bt! z1zHWu`aZU-)(PNy2CmeOzt#liK1pwMw8#+<+6FGJJDRiyTtvS85_i_3FWT~s=8{ps&m?%;9y34zJyLL;#2d9Y~WO z5g-T_4=64HhEODvM-eC?3`s;mR0!8&U?2?u001xm0mrI^jsO4v07*qoM6N<$f~w|N A{Qv*}