Calculate and store widget parent id and position when the interfaces are rendered
This removes the need to calculate widget bounds and parent on demand by traversing up the widget tree.
This commit is contained in:
@@ -412,15 +412,6 @@ public interface Client extends GameEngine
|
|||||||
*/
|
*/
|
||||||
Widget getWidget(WidgetInfo widget);
|
Widget getWidget(WidgetInfo widget);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an array of widgets that correspond to the passed group ID.
|
|
||||||
*
|
|
||||||
* @param groupId the group ID
|
|
||||||
* @return the widget group
|
|
||||||
* @see net.runelite.api.widgets.WidgetID
|
|
||||||
*/
|
|
||||||
Widget[] getGroup(int groupId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a widget by its raw group ID and child ID.
|
* Gets a widget by its raw group ID and child ID.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -36,14 +36,13 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.HashTable;
|
import net.runelite.api.HashTable;
|
||||||
import net.runelite.api.Node;
|
|
||||||
import net.runelite.api.Prayer;
|
import net.runelite.api.Prayer;
|
||||||
import net.runelite.api.WidgetNode;
|
import net.runelite.api.WidgetNode;
|
||||||
import net.runelite.api.events.ConfigChanged;
|
import net.runelite.api.events.ConfigChanged;
|
||||||
import net.runelite.api.events.DraggingWidgetChanged;
|
import net.runelite.api.events.DraggingWidgetChanged;
|
||||||
import net.runelite.api.events.GameStateChanged;
|
import net.runelite.api.events.GameStateChanged;
|
||||||
import net.runelite.api.events.WidgetMenuOptionClicked;
|
|
||||||
import net.runelite.api.events.WidgetLoaded;
|
import net.runelite.api.events.WidgetLoaded;
|
||||||
|
import net.runelite.api.events.WidgetMenuOptionClicked;
|
||||||
import net.runelite.api.widgets.Widget;
|
import net.runelite.api.widgets.Widget;
|
||||||
import static net.runelite.api.widgets.WidgetConfig.DRAG;
|
import static net.runelite.api.widgets.WidgetConfig.DRAG;
|
||||||
import static net.runelite.api.widgets.WidgetConfig.DRAG_ON;
|
import static net.runelite.api.widgets.WidgetConfig.DRAG_ON;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import net.runelite.api.Friend;
|
|||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.GrandExchangeOffer;
|
import net.runelite.api.GrandExchangeOffer;
|
||||||
import net.runelite.api.GraphicsObject;
|
import net.runelite.api.GraphicsObject;
|
||||||
|
import net.runelite.api.HashTable;
|
||||||
import net.runelite.api.HintArrowType;
|
import net.runelite.api.HintArrowType;
|
||||||
import net.runelite.api.IndexedSprite;
|
import net.runelite.api.IndexedSprite;
|
||||||
import net.runelite.api.InventoryID;
|
import net.runelite.api.InventoryID;
|
||||||
@@ -61,6 +62,7 @@ import net.runelite.api.SpritePixels;
|
|||||||
import net.runelite.api.Tile;
|
import net.runelite.api.Tile;
|
||||||
import net.runelite.api.VarPlayer;
|
import net.runelite.api.VarPlayer;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
|
import net.runelite.api.WidgetNode;
|
||||||
import net.runelite.api.WorldType;
|
import net.runelite.api.WorldType;
|
||||||
import net.runelite.api.coords.LocalPoint;
|
import net.runelite.api.coords.LocalPoint;
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
@@ -321,9 +323,9 @@ public abstract class RSClientMixin implements RSClient
|
|||||||
{
|
{
|
||||||
int topGroup = getWidgetRoot();
|
int topGroup = getWidgetRoot();
|
||||||
List<Widget> widgets = new ArrayList<Widget>();
|
List<Widget> widgets = new ArrayList<Widget>();
|
||||||
for (Widget widget : getWidgets()[topGroup])
|
for (RSWidget widget : getWidgets()[topGroup])
|
||||||
{
|
{
|
||||||
if (widget != null && widget.getParentId() == -1)
|
if (widget != null && widget.getRSParentId() == -1)
|
||||||
{
|
{
|
||||||
widgets.add(widget);
|
widgets.add(widget);
|
||||||
}
|
}
|
||||||
@@ -343,7 +345,7 @@ public abstract class RSClientMixin implements RSClient
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Override
|
@Override
|
||||||
public Widget[] getGroup(int groupId)
|
public RSWidget[] getGroup(int groupId)
|
||||||
{
|
{
|
||||||
RSWidget[][] widgets = getWidgets();
|
RSWidget[][] widgets = getWidgets();
|
||||||
|
|
||||||
@@ -352,15 +354,7 @@ public abstract class RSClientMixin implements RSClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> w = new ArrayList<Widget>();
|
return widgets[groupId];
|
||||||
for (Widget widget : widgets[groupId])
|
|
||||||
{
|
|
||||||
if (widget != null)
|
|
||||||
{
|
|
||||||
w.add(widget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.toArray(new Widget[w.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -564,7 +558,7 @@ public abstract class RSClientMixin implements RSClient
|
|||||||
|
|
||||||
for (Node node = head.getNext(); node != head; node = node.getNext())
|
for (Node node = head.getNext(); node != head; node = node.getNext())
|
||||||
{
|
{
|
||||||
graphicsObjects.add((GraphicsObject)node);
|
graphicsObjects.add((GraphicsObject) node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return graphicsObjects;
|
return graphicsObjects;
|
||||||
@@ -1099,4 +1093,45 @@ public abstract class RSClientMixin implements RSClient
|
|||||||
{
|
{
|
||||||
callbacks.clientMainLoop();
|
callbacks.clientMainLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MethodHook("gameDraw")
|
||||||
|
@Inject
|
||||||
|
public static void gameDraw(Widget[] widgets, int parentId, int var2, int var3, int var4, int var5, int x, int y, int var8)
|
||||||
|
{
|
||||||
|
for (Widget rlWidget : widgets)
|
||||||
|
{
|
||||||
|
RSWidget widget = (RSWidget) rlWidget;
|
||||||
|
if (widget == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.getRSParentId() == parentId)
|
||||||
|
{
|
||||||
|
if (parentId != -1)
|
||||||
|
{
|
||||||
|
widget.setRenderParentId(parentId);
|
||||||
|
}
|
||||||
|
widget.setRenderX(x + widget.getRelativeX());
|
||||||
|
widget.setRenderY(y + widget.getRelativeY());
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||||
|
WidgetNode childNode = componentTable.get(widget.getId());
|
||||||
|
if (childNode != null)
|
||||||
|
{
|
||||||
|
int widgetId = widget.getId();
|
||||||
|
int groupId = childNode.getId();
|
||||||
|
RSWidget[] children = client.getWidgets()[groupId];
|
||||||
|
|
||||||
|
for (RSWidget child : children)
|
||||||
|
{
|
||||||
|
if (child.getRSParentId() == -1)
|
||||||
|
{
|
||||||
|
child.setRenderParentId(widgetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ import java.awt.Rectangle;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.runelite.api.Node;
|
import net.runelite.api.HashTable;
|
||||||
import net.runelite.api.Point;
|
import net.runelite.api.Point;
|
||||||
import net.runelite.api.WidgetNode;
|
import net.runelite.api.WidgetNode;
|
||||||
import net.runelite.api.events.WidgetHiddenChanged;
|
import net.runelite.api.events.WidgetHiddenChanged;
|
||||||
@@ -42,8 +42,6 @@ import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
|
|||||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||||
import net.runelite.api.widgets.WidgetItem;
|
import net.runelite.api.widgets.WidgetItem;
|
||||||
import net.runelite.rs.api.RSClient;
|
import net.runelite.rs.api.RSClient;
|
||||||
import net.runelite.rs.api.RSHashTable;
|
|
||||||
import net.runelite.rs.api.RSNode;
|
|
||||||
import net.runelite.rs.api.RSWidget;
|
import net.runelite.rs.api.RSWidget;
|
||||||
|
|
||||||
@Mixin(RSWidget.class)
|
@Mixin(RSWidget.class)
|
||||||
@@ -57,6 +55,44 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
@Inject
|
@Inject
|
||||||
private static int rl$widgetLastPosChanged;
|
private static int rl$widgetLastPosChanged;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private int rl$parentId;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private int rl$x;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private int rl$y;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RSWidgetMixin()
|
||||||
|
{
|
||||||
|
rl$parentId = -1;
|
||||||
|
rl$x = -1;
|
||||||
|
rl$y = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Override
|
||||||
|
public void setRenderParentId(int parentId)
|
||||||
|
{
|
||||||
|
rl$parentId = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Override
|
||||||
|
public void setRenderX(int x)
|
||||||
|
{
|
||||||
|
rl$x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Override
|
||||||
|
public void setRenderY(int y)
|
||||||
|
{
|
||||||
|
rl$y = y;
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Override
|
@Override
|
||||||
public Widget getParent()
|
public Widget getParent()
|
||||||
@@ -74,34 +110,27 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
@Override
|
@Override
|
||||||
public int getParentId()
|
public int getParentId()
|
||||||
{
|
{
|
||||||
int parentId = getRSParentId();
|
int parentId = rl$parentId;
|
||||||
if (parentId != -1)
|
|
||||||
{
|
|
||||||
return parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
int groupId = TO_GROUP(getId());
|
if (parentId != -1 && getRSParentId() == -1)
|
||||||
RSHashTable componentTable = client.getComponentTable();
|
|
||||||
RSNode[] buckets = componentTable.getBuckets();
|
|
||||||
for (int i = 0; i < buckets.length; ++i)
|
|
||||||
{
|
{
|
||||||
Node node = buckets[i];
|
// if this happens, the widget is or was nested.
|
||||||
|
// rl$parentId is updated when drawing, but will not be updated when
|
||||||
|
// the widget is no longer reachable in the tree, leaving
|
||||||
|
// parent id potentially incorrect
|
||||||
|
|
||||||
// It looks like the first node in the bucket is always
|
// check the parent in the component table
|
||||||
// a sentinel
|
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||||
Node cur = node.getNext();
|
WidgetNode widgetNode = componentTable.get(parentId);
|
||||||
while (cur != node)
|
if (widgetNode == null || widgetNode.getId() != TO_GROUP(getId()))
|
||||||
{
|
{
|
||||||
WidgetNode wn = (WidgetNode) cur;
|
// invalidate parent
|
||||||
|
rl$parentId = -1;
|
||||||
if (groupId == wn.getId())
|
return -1;
|
||||||
{
|
|
||||||
return (int) wn.getHash();
|
|
||||||
}
|
|
||||||
cur = cur.getNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
|
return parentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -153,42 +182,7 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
@Override
|
@Override
|
||||||
public Point getCanvasLocation()
|
public Point getCanvasLocation()
|
||||||
{
|
{
|
||||||
int x = 0;
|
return new Point(rl$x, rl$y);
|
||||||
int y = 0;
|
|
||||||
RSWidget cur;
|
|
||||||
|
|
||||||
for (cur = this; cur.getParent() != null; cur = (RSWidget) cur.getParent())
|
|
||||||
{
|
|
||||||
x += cur.getRelativeX();
|
|
||||||
y += cur.getRelativeY();
|
|
||||||
|
|
||||||
x -= cur.getScrollX();
|
|
||||||
y -= cur.getScrollY();
|
|
||||||
}
|
|
||||||
|
|
||||||
// cur is now the root
|
|
||||||
int[] widgetBoundsWidth = client.getWidgetPositionsX();
|
|
||||||
int[] widgetBoundsHeight = client.getWidgetPositionsY();
|
|
||||||
|
|
||||||
int boundsIndex = cur.getBoundsIndex();
|
|
||||||
if (boundsIndex != -1)
|
|
||||||
{
|
|
||||||
x += widgetBoundsWidth[boundsIndex];
|
|
||||||
y += widgetBoundsHeight[boundsIndex];
|
|
||||||
|
|
||||||
if (cur.getType() > 0)
|
|
||||||
{
|
|
||||||
x += cur.getRelativeX();
|
|
||||||
y += cur.getRelativeY();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x += cur.getRelativeX();
|
|
||||||
y += cur.getRelativeY();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Point(x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -285,9 +279,9 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> widgets = new ArrayList<Widget>();
|
List<Widget> widgets = new ArrayList<Widget>();
|
||||||
for (Widget widget : children)
|
for (RSWidget widget : children)
|
||||||
{
|
{
|
||||||
if (widget != null && widget.getParentId() == getId())
|
if (widget != null && widget.getRSParentId() == getId())
|
||||||
{
|
{
|
||||||
widgets.add(widget);
|
widgets.add(widget);
|
||||||
}
|
}
|
||||||
@@ -300,50 +294,39 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
public Widget[] getStaticChildren()
|
public Widget[] getStaticChildren()
|
||||||
{
|
{
|
||||||
List<Widget> widgets = new ArrayList<Widget>();
|
List<Widget> widgets = new ArrayList<Widget>();
|
||||||
for (Widget widget : client.getGroup(TO_GROUP(getId())))
|
for (RSWidget widget : client.getGroup(TO_GROUP(getId())))
|
||||||
{
|
{
|
||||||
if (widget != null && widget.getParentId() == getId())
|
if (widget != null && widget.getRSParentId() == getId())
|
||||||
{
|
{
|
||||||
widgets.add(widget);
|
widgets.add(widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return widgets.toArray(new Widget[widgets.size()]);
|
return widgets.toArray(new RSWidget[widgets.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Override
|
@Override
|
||||||
public Widget[] getNestedChildren()
|
public Widget[] getNestedChildren()
|
||||||
{
|
{
|
||||||
RSHashTable componentTable = client.getComponentTable();
|
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||||
int group = -1;
|
|
||||||
|
|
||||||
// XXX can actually use hashtable lookup instead of table
|
WidgetNode wn = componentTable.get(getId());
|
||||||
// iteration here...
|
if (wn == null)
|
||||||
for (Node node : componentTable.getNodes())
|
|
||||||
{
|
{
|
||||||
WidgetNode wn = (WidgetNode) node;
|
return new RSWidget[0];
|
||||||
|
|
||||||
if (wn.getHash() == getId())
|
|
||||||
{
|
|
||||||
group = wn.getId();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group == -1)
|
int group = wn.getId();
|
||||||
{
|
|
||||||
return new Widget[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> widgets = new ArrayList<Widget>();
|
List<RSWidget> widgets = new ArrayList<RSWidget>();
|
||||||
for (Widget widget : client.getGroup(group))
|
for (RSWidget widget : client.getGroup(group))
|
||||||
{
|
{
|
||||||
if (widget != null && widget.getParentId() == getId())
|
if (widget != null && widget.getRSParentId() == -1)
|
||||||
{
|
{
|
||||||
widgets.add(widget);
|
widgets.add(widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return widgets.toArray(new Widget[widgets.size()]);
|
return widgets.toArray(new RSWidget[widgets.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -373,7 +356,9 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
{
|
{
|
||||||
// if the widget is hidden it will not magically unhide from its parent changing
|
// if the widget is hidden it will not magically unhide from its parent changing
|
||||||
if (child == null || child.isSelfHidden())
|
if (child == null || child.isSelfHidden())
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
child.broadcastHidden(hidden);
|
child.broadcastHidden(hidden);
|
||||||
}
|
}
|
||||||
@@ -386,7 +371,9 @@ public abstract class RSWidgetMixin implements RSWidget
|
|||||||
for (Widget nestedChild : nestedChildren)
|
for (Widget nestedChild : nestedChildren)
|
||||||
{
|
{
|
||||||
if (nestedChild == null || nestedChild.isSelfHidden())
|
if (nestedChild == null || nestedChild.isSelfHidden())
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
((RSWidget) nestedChild).broadcastHidden(hidden);
|
((RSWidget) nestedChild).broadcastHidden(hidden);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,6 +156,15 @@ public interface RSClient extends RSGameEngine, Client
|
|||||||
@Import("widgets")
|
@Import("widgets")
|
||||||
RSWidget[][] getWidgets();
|
RSWidget[][] getWidgets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an array of widgets that correspond to the passed group ID.
|
||||||
|
*
|
||||||
|
* @param groupId the group ID
|
||||||
|
* @return the widget group
|
||||||
|
* @see net.runelite.api.widgets.WidgetID
|
||||||
|
*/
|
||||||
|
RSWidget[] getGroup(int groupId);
|
||||||
|
|
||||||
@Import("region")
|
@Import("region")
|
||||||
@Override
|
@Override
|
||||||
RSRegion getRegion();
|
RSRegion getRegion();
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ public interface RSWidget extends Widget
|
|||||||
@Override
|
@Override
|
||||||
int getId();
|
int getId();
|
||||||
|
|
||||||
|
void setRenderParentId(int parentId);
|
||||||
|
|
||||||
|
void setRenderX(int x);
|
||||||
|
|
||||||
|
void setRenderY(int y);
|
||||||
|
|
||||||
@Import("parentId")
|
@Import("parentId")
|
||||||
int getRSParentId();
|
int getRSParentId();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user