runelite-api: fix widget children lookup logic

Also update dev tools panel widget tree to use show all widgets children,
and start from the root widgets.

Thanks to @rsbmatt for his assistance in explaining the logic
This commit is contained in:
Adam
2017-08-05 14:11:05 -04:00
parent b26ee3f193
commit 39f9cfbe70
9 changed files with 330 additions and 202 deletions

View File

@@ -26,6 +26,7 @@ package net.runelite.api;
import java.awt.Canvas;
import java.util.Arrays;
import java.util.Objects;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.rs.api.ItemComposition;
@@ -213,13 +214,14 @@ public class Client
return client.getBaseY();
}
public Widget[][] getWidgets()
public Widget[] getWidgetRoots()
{
return Arrays.stream(client.getWidgets())
.map(parent -> parent != null ? Arrays.stream(parent)
.map(child -> child != null ? new Widget(this, child) : null)
.toArray(Widget[]::new) : null
).toArray(Widget[][]::new);
int topGroup = client.getWidgetRoot();
return Arrays.stream(client.getWidgets()[topGroup])
.filter(Objects::nonNull)
.filter(w -> w.getParentId() == -1) // is a root
.map(w -> new Widget(this, w))
.toArray(Widget[]::new);
}
public Widget getWidget(WidgetInfo widget)
@@ -230,6 +232,21 @@ public class Client
return getWidget(groupId, childId);
}
public Widget[] getGroup(int groupId)
{
net.runelite.rs.api.Widget[][] widgets = client.getWidgets();
if (widgets == null || groupId < 0 || groupId >= widgets.length)
{
return null;
}
return Arrays.stream(widgets[groupId])
.filter(Objects::nonNull)
.map(w -> new Widget(this, w))
.toArray(Widget[]::new);
}
public Widget getWidget(int groupId, int childId)
{
net.runelite.rs.api.Widget[][] widgets = client.getWidgets();
@@ -258,11 +275,6 @@ public class Client
return client.getWidgetPositionsY();
}
public boolean[] getValidInterfaces()
{
return client.getValidInterfaces();
}
public String[] getPlayerOptions()
{
return client.getPlayerOptions();

View File

@@ -26,13 +26,17 @@ package net.runelite.api.widgets;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import net.runelite.api.Client;
import net.runelite.api.Node;
import net.runelite.api.Point;
import net.runelite.api.WidgetNode;
import net.runelite.api.XHashTable;
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
public class Widget
{
@@ -70,7 +74,7 @@ public class Widget
return null;
}
return client.getWidget(id >>> 16, id & 0xFFFF);
return client.getWidget(TO_GROUP(id), TO_CHILD(id));
}
public int getParentId()
@@ -81,7 +85,7 @@ public class Widget
return parentId;
}
int i = getId() >>> 16;
int i = TO_GROUP(getId());
XHashTable componentTable = client.getComponentTable();
for (Node node : componentTable.getNodes())
{
@@ -96,6 +100,70 @@ public class Widget
return -1;
}
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 Widget[] getDynamicChildren()
{
net.runelite.rs.api.Widget[] children = widget.getChildren();
if (children == null)
{
return new Widget[0];
}
return Arrays.stream(children)
.filter(Objects::nonNull)
.filter(w -> w.getParentId() == getId())
.map(w -> new Widget(client, w))
.toArray(Widget[]::new);
}
public Widget[] getStaticChildren()
{
return Arrays.stream(client.getGroup(TO_GROUP(getId())))
.filter(Objects::nonNull)
.filter(w -> w.getParentId() == getId())
.toArray(Widget[]::new);
}
public Widget[] getNestedChildren()
{
XHashTable componentTable = client.getComponentTable();
int group = -1;
// XXX can actually use hashtable lookup instead of table
// iteration here...
for (Node node : componentTable.getNodes())
{
WidgetNode wn = (WidgetNode) node;
if (wn.getHash() == getId())
{
group = wn.getId();
break;
}
}
if (group == -1)
{
return new Widget[0];
}
return Arrays.stream(client.getGroup(group))
.filter(w -> w.getParentId() == getId())
.toArray(Widget[]::new);
}
private int getRelativeX()
{
return widget.getRelativeX();
@@ -264,37 +332,6 @@ 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();

View File

@@ -89,4 +89,14 @@ public enum WidgetInfo
return childId;
}
public static int TO_GROUP(int id)
{
return id >>> 16;
}
public static int TO_CHILD(int id)
{
return id & 0xFFFF;
}
}