diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 2fb818721c..5ff159ff96 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -152,6 +152,9 @@ public class Widget { x += cur.getRelativeX(); y += cur.getRelativeY(); + + x -= cur.widget.getScrollX(); + y -= cur.widget.getScrollY(); } // cur is now the root @@ -196,6 +199,30 @@ public class Widget } public Collection getWidgetItems() + { + int[] itemIds = widget.getItemIds(); + + if (itemIds == null) + { + return null; + } + + List items = new ArrayList<>(itemIds.length); + + for (int i = 0; i < itemIds.length; ++i) + { + WidgetItem item = getWidgetItem(i); + + if (item != null) + { + items.add(item); + } + } + + return items; + } + + public WidgetItem getWidgetItem(int index) { int[] itemIds = widget.getItemIds(); int[] itemQuantities = widget.getItemQuantities(); @@ -205,43 +232,26 @@ public class Widget return null; } - List items = new ArrayList<>(itemIds.length); - - assert itemIds.length == itemQuantities.length; - int columns = getWidth(); // the number of item slot columns is stored here int paddingX = getPaddingX(); int paddingY = getPaddingY(); + int itemId = itemIds[index]; + int itemQuantity = itemQuantities[index]; Point widgetCanvasLocation = getCanvasLocation(); - for (int i = 0; i < itemIds.length; ++i) + if (itemId <= 0 || itemQuantity <= 0 || columns <= 0) { - int itemId = itemIds[i]; - int itemQuantity = itemQuantities[i]; - - if (itemId <= 0 || itemQuantity <= 0) - { - continue; - } - - Rectangle bounds = null; - - if (columns > 0) - { - int row = i / columns; - int col = i % columns; - int itemX = widgetCanvasLocation.getX() + ((ITEM_SLOT_SIZE + paddingX) * col); - int itemY = widgetCanvasLocation.getY() + ((ITEM_SLOT_SIZE + paddingY) * row); - - bounds = new Rectangle(itemX - 1, itemY - 1, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE); - } - - WidgetItem item = new WidgetItem(itemId - 1, itemQuantity, i, bounds); - items.add(item); + return null; } - return items; + int row = index / columns; + int col = index % columns; + int itemX = widgetCanvasLocation.getX() + ((ITEM_SLOT_SIZE + paddingX) * col); + int itemY = widgetCanvasLocation.getY() + ((ITEM_SLOT_SIZE + paddingY) * row); + + Rectangle bounds = new Rectangle(itemX - 1, itemY - 1, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE); + return new WidgetItem(itemId - 1, itemQuantity, index, bounds); } private int getPaddingX() @@ -253,4 +263,45 @@ public class Widget { return widget.getPaddingY(); } + + public Widget[] getChildren() + { + net.runelite.rs.api.Widget[] widgets = widget.getChildren(); + + if (widgets == null) + { + return null; + } + + Widget[] children = new Widget[widgets.length]; + + for (int i = 0; i < widgets.length; ++i) + { + children[i] = getChild(i); + } + + return children; + } + + public Widget getChild(int index) + { + net.runelite.rs.api.Widget[] widgets = widget.getChildren(); + + if (widgets == null || widgets[index] == null) + { + return null; + } + + return new Widget(client, widgets[index]); + } + + public int getItemId() + { + return widget.getItemId(); + } + + public int getItemQuantity() + { + return widget.getItemQuantity(); + } } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 0b7ec01b9e..5d15e45870 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -26,10 +26,9 @@ package net.runelite.api.widgets; class WidgetID { + static final int BANK_GROUP_ID = 12; static final int INVENTORY_GROUP_ID = 149; - static final int PESTRCONTROL_GROUP_ID = 408; - static final int CLAN_CHAT_GROUP_ID = 7; static class PestControl @@ -56,4 +55,9 @@ class WidgetID static final int NAME = 3; static final int OWNER = 5; } + + public static class Bank + { + static final int ITEM_CONTAINER = 12; + } } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 1366feeccd..bc14e93284 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -43,7 +43,9 @@ public enum WidgetInfo CLAN_CHAT_TITLE(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.TITLE), CLAN_CHAT_NAME(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.NAME), - CLAN_CHAT_OWNER(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.OWNER); + CLAN_CHAT_OWNER(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.OWNER), + + BANK_ITEM_CONTAINER(WidgetID.BANK_GROUP_ID, WidgetID.Bank.ITEM_CONTAINER); private final int groupId; private final int childId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java index bcb3586f20..09b884e8b1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java @@ -54,6 +54,7 @@ public class DevTools extends Plugin private int widgetParent = -1; private int widgetChild = -1; + private int widgetItem = -1; private Font font; @@ -185,6 +186,11 @@ public class DevTools extends Plugin widgetChild = id; } + void setWidgetItem(int id) + { + widgetItem = id; + } + int getWidgetParent() { return widgetParent; @@ -195,4 +201,9 @@ public class DevTools extends Plugin return widgetChild; } + int getWidgetItem() + { + return widgetItem; + } + } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java index d1ea94dbec..76ac0219ab 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java @@ -60,6 +60,9 @@ import net.runelite.client.ui.overlay.OverlayPosition; public class DevToolsOverlay extends Overlay { + public static final int ITEM_EMPTY = 6512; + public static final int ITEM_FILLED = 20594; + private static final Color RED = new Color(221, 44, 0); private static final Color GREEN = new Color(0, 200, 83); private static final Color ORANGE = new Color(255, 109, 0); @@ -116,7 +119,7 @@ public class DevToolsOverlay extends Overlay renderInventory(graphics); } - renderWidget(graphics); + renderWidgets(graphics); return null; } @@ -393,23 +396,92 @@ public class DevToolsOverlay extends Overlay } } - public void renderWidget(Graphics2D graphics) + public void renderWidgets(Graphics2D graphics) { int parentID = plugin.getWidgetParent(); int childID = plugin.getWidgetChild(); + int itemIndex = plugin.getWidgetItem(); if (parentID == -1) { return; } - Widget widget = client.getWidget(parentID, (childID == -1) ? 0 : childID); - if (widget != null && !widget.isHidden()) + Widget widgetParent = client.getWidget(parentID, 0); + if (widgetParent == null || widgetParent.isHidden()) { - Rectangle bounds = widget.getBounds(); - graphics.setColor(CYAN); - graphics.draw(bounds); + return; } + + Rectangle parentBounds = widgetParent.getBounds(); + graphics.setColor(YELLOW); + graphics.draw(parentBounds); + + if (childID == -1) + { + return; + } + + Widget widgetChild = client.getWidget(parentID, childID); + if (widgetChild == null || widgetChild.isHidden()) + { + return; + } + + Rectangle childBounds = widgetChild.getBounds(); + graphics.setColor(CYAN); + graphics.draw(childBounds); + + if (itemIndex == -1) + { + return; + } + + Widget childComponent = widgetChild.getChild(itemIndex); + if (childComponent != null && !childComponent.isHidden() + && childComponent.getItemId() != ITEM_EMPTY + && childComponent.getItemId() != ITEM_FILLED) + { + Rectangle componentBounds = childComponent.getBounds(); + + graphics.setColor(ORANGE); + graphics.draw(componentBounds); + + renderWidgetText(graphics, componentBounds, childComponent.getItemId(), YELLOW); + } + + WidgetItem widgetItem = widgetChild.getWidgetItem(itemIndex); + if (widgetItem == null) + { + return; + } + + Rectangle itemBounds = widgetItem.getCanvasBounds(); + + graphics.setColor(ORANGE); + graphics.draw(itemBounds); + + renderWidgetText(graphics, itemBounds, widgetItem.getId(), YELLOW); + } + + private void renderWidgetText(Graphics2D graphics, Rectangle bounds, int itemId, Color color) + { + if (itemId == -1) + { + return; + } + + String text = itemId + ""; + FontMetrics fm = graphics.getFontMetrics(); + Rectangle2D textBounds = fm.getStringBounds(text, graphics); + + int textX = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2)); + int textY = (int) (bounds.getY() + (bounds.getHeight() / 2) + (textBounds.getHeight() / 2)); + + graphics.setColor(Color.BLACK); + graphics.drawString(text, textX + 1, textY + 1); + graphics.setColor(color); + graphics.drawString(text, textX, textY); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java index d398c9803c..ac258febef 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java @@ -25,6 +25,7 @@ package net.runelite.client.plugins.devtools; import java.awt.*; +import java.util.Collection; import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.tree.DefaultMutableTreeNode; @@ -32,7 +33,10 @@ import javax.swing.tree.DefaultTreeModel; import net.runelite.api.Client; import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetItem; import net.runelite.client.RuneLite; +import static net.runelite.client.plugins.devtools.DevToolsOverlay.ITEM_EMPTY; +import static net.runelite.client.plugins.devtools.DevToolsOverlay.ITEM_FILLED; import net.runelite.client.ui.PluginPanel; public class DevToolsPanel extends PluginPanel @@ -174,6 +178,7 @@ public class DevToolsPanel extends PluginPanel Object[] path = e.getPath().getPath(); plugin.setWidgetParent(Integer.parseInt(path[1].toString())); plugin.setWidgetChild((path.length > 2) ? Integer.parseInt(path[2].toString()) : -1); + plugin.setWidgetItem((path.length > 3) ? Integer.parseInt(path[3].toString()) : -1); setWidgetInfo(); }); @@ -266,6 +271,7 @@ public class DevToolsPanel extends PluginPanel plugin.setWidgetParent(-1); plugin.setWidgetChild(-1); + plugin.setWidgetItem(-1); int idx = -1; @@ -286,14 +292,50 @@ public class DevToolsPanel extends PluginPanel DefaultMutableTreeNode parent = new DefaultMutableTreeNode(idx); root.add(parent); - for (Widget child : children) + for (Widget widgetChild : children) { - if (child == null || child.isHidden()) + if (widgetChild == null || widgetChild.isHidden()) { continue; } - parent.add(new DefaultMutableTreeNode(child.getId() & 0xFFFF)); + DefaultMutableTreeNode child = new DefaultMutableTreeNode(widgetChild.getId() & 0xFFFF); + parent.add(child); + + Widget[] childComponents = widgetChild.getChildren(); + if (childComponents != null) + { + int index = -1; + for (Widget component : childComponents) + { + index++; + if (component == null || component.isHidden() + || component.getItemId() == ITEM_EMPTY + || component.getItemId() == ITEM_FILLED) + { + continue; + } + + child.add(new DefaultMutableTreeNode(index)); + } + } + + Collection items = widgetChild.getWidgetItems(); + if (items == null) + { + continue; + } + + for (WidgetItem item : items) + { + + if (item == null) + { + continue; + } + + child.add(new DefaultMutableTreeNode(item.getIndex())); + } } } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/Widget.java b/runescape-api/src/main/java/net/runelite/rs/api/Widget.java index 8a92b2f14b..e68676285f 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/Widget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/Widget.java @@ -118,6 +118,9 @@ public interface Widget @Import("borderThickness") int getBorderThickness(); + @Import("itemId") + int getItemId(); + @Import("itemQuantity") int getItemQuantity();