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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
|
||||
@@ -36,14 +36,13 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.HashTable;
|
||||
import net.runelite.api.Node;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.WidgetNode;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.DraggingWidgetChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.WidgetMenuOptionClicked;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.events.WidgetMenuOptionClicked;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import static net.runelite.api.widgets.WidgetConfig.DRAG;
|
||||
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.GrandExchangeOffer;
|
||||
import net.runelite.api.GraphicsObject;
|
||||
import net.runelite.api.HashTable;
|
||||
import net.runelite.api.HintArrowType;
|
||||
import net.runelite.api.IndexedSprite;
|
||||
import net.runelite.api.InventoryID;
|
||||
@@ -61,6 +62,7 @@ import net.runelite.api.SpritePixels;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.WidgetNode;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
@@ -321,9 +323,9 @@ public abstract class RSClientMixin implements RSClient
|
||||
{
|
||||
int topGroup = getWidgetRoot();
|
||||
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);
|
||||
}
|
||||
@@ -343,7 +345,7 @@ public abstract class RSClientMixin implements RSClient
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
public Widget[] getGroup(int groupId)
|
||||
public RSWidget[] getGroup(int groupId)
|
||||
{
|
||||
RSWidget[][] widgets = getWidgets();
|
||||
|
||||
@@ -352,15 +354,7 @@ public abstract class RSClientMixin implements RSClient
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Widget> w = new ArrayList<Widget>();
|
||||
for (Widget widget : widgets[groupId])
|
||||
{
|
||||
if (widget != null)
|
||||
{
|
||||
w.add(widget);
|
||||
}
|
||||
}
|
||||
return w.toArray(new Widget[w.size()]);
|
||||
return widgets[groupId];
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -564,7 +558,7 @@ public abstract class RSClientMixin implements RSClient
|
||||
|
||||
for (Node node = head.getNext(); node != head; node = node.getNext())
|
||||
{
|
||||
graphicsObjects.add((GraphicsObject)node);
|
||||
graphicsObjects.add((GraphicsObject) node);
|
||||
}
|
||||
|
||||
return graphicsObjects;
|
||||
@@ -1099,4 +1093,45 @@ public abstract class RSClientMixin implements RSClient
|
||||
{
|
||||
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.Collection;
|
||||
import java.util.List;
|
||||
import net.runelite.api.Node;
|
||||
import net.runelite.api.HashTable;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.WidgetNode;
|
||||
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 net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.rs.api.RSClient;
|
||||
import net.runelite.rs.api.RSHashTable;
|
||||
import net.runelite.rs.api.RSNode;
|
||||
import net.runelite.rs.api.RSWidget;
|
||||
|
||||
@Mixin(RSWidget.class)
|
||||
@@ -57,6 +55,44 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
@Inject
|
||||
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
|
||||
@Override
|
||||
public Widget getParent()
|
||||
@@ -74,34 +110,27 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
@Override
|
||||
public int getParentId()
|
||||
{
|
||||
int parentId = getRSParentId();
|
||||
if (parentId != -1)
|
||||
{
|
||||
return parentId;
|
||||
}
|
||||
int parentId = rl$parentId;
|
||||
|
||||
int groupId = TO_GROUP(getId());
|
||||
RSHashTable componentTable = client.getComponentTable();
|
||||
RSNode[] buckets = componentTable.getBuckets();
|
||||
for (int i = 0; i < buckets.length; ++i)
|
||||
if (parentId != -1 && getRSParentId() == -1)
|
||||
{
|
||||
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
|
||||
// a sentinel
|
||||
Node cur = node.getNext();
|
||||
while (cur != node)
|
||||
// check the parent in the component table
|
||||
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||
WidgetNode widgetNode = componentTable.get(parentId);
|
||||
if (widgetNode == null || widgetNode.getId() != TO_GROUP(getId()))
|
||||
{
|
||||
WidgetNode wn = (WidgetNode) cur;
|
||||
|
||||
if (groupId == wn.getId())
|
||||
{
|
||||
return (int) wn.getHash();
|
||||
}
|
||||
cur = cur.getNext();
|
||||
// invalidate parent
|
||||
rl$parentId = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
return parentId;
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -153,42 +182,7 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
@Override
|
||||
public Point getCanvasLocation()
|
||||
{
|
||||
int x = 0;
|
||||
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);
|
||||
return new Point(rl$x, rl$y);
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -285,9 +279,9 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -300,50 +294,39 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
public Widget[] getStaticChildren()
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
return widgets.toArray(new Widget[widgets.size()]);
|
||||
return widgets.toArray(new RSWidget[widgets.size()]);
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
public Widget[] getNestedChildren()
|
||||
{
|
||||
RSHashTable componentTable = client.getComponentTable();
|
||||
int group = -1;
|
||||
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||
|
||||
// XXX can actually use hashtable lookup instead of table
|
||||
// iteration here...
|
||||
for (Node node : componentTable.getNodes())
|
||||
WidgetNode wn = componentTable.get(getId());
|
||||
if (wn == null)
|
||||
{
|
||||
WidgetNode wn = (WidgetNode) node;
|
||||
|
||||
if (wn.getHash() == getId())
|
||||
{
|
||||
group = wn.getId();
|
||||
break;
|
||||
}
|
||||
return new RSWidget[0];
|
||||
}
|
||||
|
||||
if (group == -1)
|
||||
{
|
||||
return new Widget[0];
|
||||
}
|
||||
int group = wn.getId();
|
||||
|
||||
List<Widget> widgets = new ArrayList<Widget>();
|
||||
for (Widget widget : client.getGroup(group))
|
||||
List<RSWidget> widgets = new ArrayList<RSWidget>();
|
||||
for (RSWidget widget : client.getGroup(group))
|
||||
{
|
||||
if (widget != null && widget.getParentId() == getId())
|
||||
if (widget != null && widget.getRSParentId() == -1)
|
||||
{
|
||||
widgets.add(widget);
|
||||
}
|
||||
}
|
||||
return widgets.toArray(new Widget[widgets.size()]);
|
||||
return widgets.toArray(new RSWidget[widgets.size()]);
|
||||
}
|
||||
|
||||
@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 (child == null || child.isSelfHidden())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
child.broadcastHidden(hidden);
|
||||
}
|
||||
@@ -386,7 +371,9 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
for (Widget nestedChild : nestedChildren)
|
||||
{
|
||||
if (nestedChild == null || nestedChild.isSelfHidden())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
((RSWidget) nestedChild).broadcastHidden(hidden);
|
||||
}
|
||||
|
||||
@@ -156,6 +156,15 @@ public interface RSClient extends RSGameEngine, Client
|
||||
@Import("widgets")
|
||||
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")
|
||||
@Override
|
||||
RSRegion getRegion();
|
||||
|
||||
@@ -40,6 +40,12 @@ public interface RSWidget extends Widget
|
||||
@Override
|
||||
int getId();
|
||||
|
||||
void setRenderParentId(int parentId);
|
||||
|
||||
void setRenderX(int x);
|
||||
|
||||
void setRenderY(int y);
|
||||
|
||||
@Import("parentId")
|
||||
int getRSParentId();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user