diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java index 26e2612955..8f2dbfc23e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java @@ -292,6 +292,8 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis int intStackSize = client.getIntStackSize(); int stringStackSize = client.getStringStackSize(); + tabInterface.handleScriptEvent(event); + switch (eventName) { case "setSearchBankInputText": diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java index 51e179b143..bcf03fd585 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java @@ -31,6 +31,7 @@ class MenuIndexes { static final int NEW_TAB = 2; static final int IMPORT_TAB = 3; + static final int OPEN_TAB_MENU = 4; } static class Tab diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index 45d71fb94c..82a19b4f3d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -68,6 +68,7 @@ import net.runelite.api.VarClientStr; import net.runelite.api.Varbits; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.vars.InputType; import net.runelite.api.widgets.ItemQuantityMode; import net.runelite.api.widgets.JavaScriptCallback; @@ -110,6 +111,9 @@ public class TabInterface private static final String REMOVE_TAG = "Remove-tag"; private static final String TAG_GEAR = "Tag-equipment"; private static final String TAG_INVENTORY = "Tag-inventory"; + private static final String TAB_MENU_KEY = "tagtabs"; + private static final String TAB_MENU = TAG_SEARCH + TAB_MENU_KEY; + private static final String OPEN_TAB_MENU = "View tag tabs"; private static final int TAB_HEIGHT = 40; private static final int TAB_WIDTH = 39; private static final int BUTTON_HEIGHT = 20; @@ -117,6 +121,13 @@ public class TabInterface private static final int SCROLL_TICK = 500; private static final int INCINERATOR_WIDTH = 48; private static final int INCINERATOR_HEIGHT = 39; + private static final int BANK_ITEM_WIDTH = 36; + private static final int BANK_ITEM_HEIGHT = 32; + private static final int BANK_ITEM_X_PADDING = 12; + private static final int BANK_ITEM_Y_PADDING = 4; + private static final int BANK_ITEMS_PER_ROW = 8; + private static final int BANK_ITEM_START_X = 51; + private static final int BANK_ITEM_START_Y = 0; private final Client client; private final ClientThread clientThread; @@ -209,6 +220,7 @@ public class TabInterface newTab = createGraphic("", TabSprites.NEW_TAB.getSpriteId(), -1, TAB_WIDTH, 39, bounds.x, 0, true); newTab.setAction(1, NEW_TAB); newTab.setAction(2, IMPORT_TAB); + newTab.setAction(3, OPEN_TAB_MENU); newTab.setOnOpListener((JavaScriptCallback) this::handleNewTab); tabManager.clear(); @@ -342,6 +354,11 @@ public class TabInterface { notifier.notify("Failed to import tag tab from clipboard, invalid format."); } + break; + case NewTab.OPEN_TAB_MENU: + client.setVarbit(Varbits.CURRENT_BANK_TAB, 0); + openTag(TAB_MENU_KEY); + break; } } @@ -379,6 +396,7 @@ public class TabInterface { iconToSet.setIconItemId(itemId); iconToSet.getIcon().setItemId(itemId); + iconToSet.getMenu().setItemId(itemId); tabManager.setIcon(iconToSet.getTag(), itemId + ""); } }) @@ -528,6 +546,60 @@ public class TabInterface scrollTab(0); } + private void setTabMenuVisible(boolean visible) + { + for (TagTab t : tabManager.getTabs()) + { + t.getMenu().setHidden(!visible); + } + } + + private boolean isTabMenuActive() + { + return TAB_MENU.equals(client.getVar(VarClientStr.INPUT_TEXT)); + } + + public void handleScriptEvent(final ScriptCallbackEvent event) + { + String eventName = event.getEventName(); + + int[] intStack = client.getIntStack(); + int intStackSize = client.getIntStackSize(); + + switch (eventName) + { + case "setBankScroll": + if (!isTabMenuActive()) + { + setTabMenuVisible(false); + return; + } + + setTabMenuVisible(true); + + // scroll height + intStack[intStackSize - 3] = (((tabManager.getTabs().size() - 1) / BANK_ITEMS_PER_ROW) + 1) * (BANK_ITEM_HEIGHT + BANK_ITEM_Y_PADDING); + + // skip normal bank layout + intStack[intStackSize - 2] = 1; + break; + case "beforeBankLayout": + setTabMenuVisible(false); + break; + case "isTabMenuActive": + if (!isTabMenuActive()) + { + intStack[intStackSize - 1] = 0; + return; + } + + // Must set the bank title because we are skipping it in scripts + client.getWidget(WidgetInfo.BANK_TITLE_BAR).setText("Showing items: " + ColorUtil.wrapWithColorTag(TAB_MENU, Color.red)); + intStack[intStackSize - 1] = 1; + break; + } + } + public void handleWheel(final MouseWheelEvent event) { if (parent == null || !canvasBounds.contains(event.getPoint())) @@ -556,7 +628,6 @@ public class TabInterface } MenuEntry[] entries = client.getMenuEntries(); - MenuEntry entry = entries[entries.length - 1]; if (activeTab != null && event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId() @@ -678,7 +749,7 @@ public class TabInterface // is dragging widget and mouse button released if (client.getMouseCurrentButton() == 0) { - if (draggedWidget.getItemId() > 0 && draggedWidget.getId() != parent.getId()) + if (!isTabMenuActive() && draggedWidget.getItemId() > 0 && draggedWidget.getId() != parent.getId()) { // Tag an item dragged on a tag tab if (draggedOn.getId() == parent.getId()) @@ -687,7 +758,8 @@ public class TabInterface updateTabIfActive(Lists.newArrayList(Text.standardize(draggedOn.getName()))); } } - else if (parent.getId() == draggedOn.getId() && parent.getId() == draggedWidget.getId()) + else if ((isTabMenuActive() && draggedWidget.getId() == draggedOn.getId() && draggedOn.getId() != parent.getId()) + || (parent.getId() == draggedOn.getId() && parent.getId() == draggedWidget.getId())) { // Reorder tag tabs moveTagTab(draggedWidget, draggedOn); @@ -746,6 +818,28 @@ public class TabInterface return !config.tabs() || widget == null || widget.isHidden(); } + private void addTabActions(Widget w) + { + w.setAction(1, VIEW_TAB); + w.setAction(2, CHANGE_ICON); + w.setAction(3, REMOVE_TAB); + w.setAction(4, EXPORT_TAB); + w.setAction(5, RENAME_TAB); + w.setOnOpListener((JavaScriptCallback) this::handleTagTab); + } + + private void addTabOptions(Widget w) + { + int clickmask = w.getClickMask(); + clickmask |= WidgetConfig.DRAG; + clickmask |= WidgetConfig.DRAG_ON; + w.setClickMask(clickmask); + w.setDragDeadTime(5); + w.setDragDeadZone(5); + w.setItemQuantity(10000); + w.setItemQuantityMode(ItemQuantityMode.NEVER); + } + private void loadTab(String tag) { TagTab tagTab = tabManager.load(tag); @@ -753,12 +847,7 @@ public class TabInterface if (tagTab.getBackground() == null) { Widget btn = createGraphic(ColorUtil.wrapWithColorTag(tagTab.getTag(), HILIGHT_COLOR), TabSprites.TAB_BACKGROUND.getSpriteId(), -1, TAB_WIDTH, TAB_HEIGHT, bounds.x, 1, true); - btn.setAction(1, VIEW_TAB); - btn.setAction(2, CHANGE_ICON); - btn.setAction(3, REMOVE_TAB); - btn.setAction(4, EXPORT_TAB); - btn.setAction(5, RENAME_TAB); - btn.setOnOpListener((JavaScriptCallback) this::handleTagTab); + addTabActions(btn); tagTab.setBackground(btn); } @@ -771,17 +860,33 @@ public class TabInterface Constants.ITEM_SPRITE_WIDTH, Constants.ITEM_SPRITE_HEIGHT, bounds.x + 3, 1, false); - int clickmask = icon.getClickMask(); - clickmask |= WidgetConfig.DRAG; - clickmask |= WidgetConfig.DRAG_ON; - icon.setClickMask(clickmask); - icon.setDragDeadTime(5); - icon.setDragDeadZone(5); - icon.setItemQuantity(10000); - icon.setItemQuantityMode(ItemQuantityMode.NEVER); + addTabOptions(icon); tagTab.setIcon(icon); } + if (tagTab.getMenu() == null) + { + Widget menu = createGraphic( + client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER), + ColorUtil.wrapWithColorTag(tagTab.getTag(), HILIGHT_COLOR), + -1, + tagTab.getIconItemId(), + BANK_ITEM_WIDTH, BANK_ITEM_HEIGHT, + BANK_ITEM_START_X, BANK_ITEM_START_Y, + true); + addTabActions(menu); + addTabOptions(menu); + if (activeTab != null && activeTab.getTag().equals(TAB_MENU_KEY)) + { + menu.setHidden(false); + } + else + { + menu.setHidden(true); + } + tagTab.setMenu(menu); + } + tabManager.add(tagTab); } @@ -815,6 +920,7 @@ public class TabInterface final String coloredName = ColorUtil.wrapWithColorTag(newTag, HILIGHT_COLOR); tagTab.getIcon().setName(coloredName); tagTab.getBackground().setName(coloredName); + tagTab.getMenu().setName(coloredName); tabManager.removeIcon(oldTag); tabManager.setIcon(newTag, tagTab.getIconItemId() + ""); @@ -978,6 +1084,10 @@ public class TabInterface y -= (currentTabIndex * TAB_HEIGHT + currentTabIndex * MARGIN); } + int itemX = BANK_ITEM_START_X; + int itemY = BANK_ITEM_START_Y; + int rowIndex = 0; + for (TagTab tab : tabManager.getTabs()) { updateWidget(tab.getBackground(), y); @@ -993,6 +1103,23 @@ public class TabInterface } y += TAB_HEIGHT + MARGIN; + + Widget item = tab.getMenu(); + item.setOriginalX(itemX); + item.setOriginalY(itemY); + item.revalidate(); + + rowIndex++; + if (rowIndex == BANK_ITEMS_PER_ROW) + { + itemX = BANK_ITEM_START_X; + itemY += BANK_ITEM_Y_PADDING + BANK_ITEM_HEIGHT; + rowIndex = 0; + } + else + { + itemX += BANK_ITEM_X_PADDING + BANK_ITEM_WIDTH; + } } updateWidget(newTab, y); @@ -1008,9 +1135,9 @@ public class TabInterface downButton.revalidate(); } - private Widget createGraphic(String name, int spriteId, int itemId, int width, int height, int x, int y, boolean hasListener) + private Widget createGraphic(Widget container, String name, int spriteId, int itemId, int width, int height, int x, int y, boolean hasListener) { - Widget widget = parent.createChild(-1, WidgetType.GRAPHIC); + Widget widget = container.createChild(-1, WidgetType.GRAPHIC); widget.setOriginalWidth(width); widget.setOriginalHeight(height); widget.setOriginalX(x); @@ -1037,6 +1164,11 @@ public class TabInterface return widget; } + private Widget createGraphic(String name, int spriteId, int itemId, int width, int height, int x, int y, boolean hasListener) + { + return createGraphic(parent, name, spriteId, itemId, width, height, x, y, hasListener); + } + private void updateWidget(Widget t, int y) { t.setOriginalY(y); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java index 004e5f45ed..403fc9dddf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java @@ -37,6 +37,7 @@ class TagTab private int iconItemId; private Widget background; private Widget icon; + private Widget menu; TagTab(int iconItemId, String tag) { @@ -55,5 +56,10 @@ class TagTab { icon.setHidden(hide); } + + if (menu != null) + { + menu.setHidden(hide); + } } } diff --git a/runelite-client/src/main/scripts/BankSearchLayout.rs2asm b/runelite-client/src/main/scripts/BankSearchLayout.rs2asm index c6a34565ba..067e8fcbe1 100644 --- a/runelite-client/src/main/scripts/BankSearchLayout.rs2asm +++ b/runelite-client/src/main/scripts/BankSearchLayout.rs2asm @@ -3,6 +3,18 @@ .string_stack_count 0 .int_var_count 35 .string_var_count 1 +; callback "beforeBankLayout" +; Fired before the bank starts its layout +; Used by the TabInterface to hide fake bank items for tag tabs +; +; callback "setBankScroll" +; Fired before bank is calculated +; Used by the TabInterface to show fake bank items for tag tabs +; +; callback "isTabMenuActive" +; Used by the TabInterface to skip setting the bank title + sconst "beforeBankLayout" + runelite_callback get_varbit 5102 iconst 1 if_icmpeq LABEL4 @@ -385,6 +397,15 @@ LABEL339: sub istore 29 LABEL343: + iconst 0 ; Scroll height variable + iconst 0 ; Compare variable + iconst 0 ; + sconst "setBankScroll" ; Show fake bank items for tag tabs + runelite_callback ; If tag tab menu search isn't active + if_icmpeq CONTINUE_SEARCH ; continue to normal bank search + istore 27 ; Load scroll height into variable + jump GetTabRange ; Skip normal bank layout +CONTINUE_SEARCH: iload 30 iload 29 iconst 1 @@ -822,12 +843,12 @@ LABEL740: invoke 514 iconst 1 if_icmpeq LABEL744 - jump LABEL747 + jump GetTabRange LABEL744: iconst 1 iconst 1 invoke 299 -LABEL747: +GetTabRange: iconst -1 istore 31 iconst -1 @@ -844,7 +865,7 @@ LABEL759: iload 19 iconst 816 if_icmplt LABEL763 - jump LABEL843 + jump SetTitle LABEL763: iload 2 iload 19 @@ -936,12 +957,17 @@ LABEL838: add istore 19 jump LABEL759 -LABEL843: +SetTitle: + iconst 0 ; Compare variable + iconst 0 ; + sconst "isTabMenuActive" ; Check if tag tab menu + runelite_callback ; is active and skip setting + if_icmpne FinishBuilding ; the bank title if it is get_varbit 4170 iconst 2 - if_icmpeq LABEL847 - jump LABEL857 -LABEL847: + if_icmpeq SetTitleRomanNumeral + jump SetTitleNumber +SetTitleRomanNumeral: sconst "Tab " iconst 105 iconst 115 @@ -953,8 +979,8 @@ LABEL847: runelite_callback ; iload 5 if_settext - jump LABEL863 -LABEL857: + jump FinishBuilding +SetTitleNumber: sconst "Tab " get_varbit 4150 tostring @@ -963,7 +989,7 @@ LABEL857: runelite_callback ; iload 5 if_settext -LABEL863: +FinishBuilding: iload 0 iload 1 iload 2