Merge pull request #4025 from Adam-/widget-optimizations
Widget optimizations
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>
|
||||
@@ -692,7 +683,7 @@ public interface Client extends GameEngine
|
||||
* @return the widget node component table
|
||||
* @see WidgetNode
|
||||
*/
|
||||
HashTable getComponentTable();
|
||||
HashTable<WidgetNode> getComponentTable();
|
||||
|
||||
/**
|
||||
* Gets an array of current grand exchange offers.
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Collection;
|
||||
* A data structure that uses a hash function to compute an index into an
|
||||
* array of buckets from which node objects can be quickly obtained.
|
||||
*/
|
||||
public interface HashTable
|
||||
public interface HashTable<T extends Node>
|
||||
{
|
||||
/**
|
||||
* Gets a node by its hash value.
|
||||
@@ -38,12 +38,12 @@ public interface HashTable
|
||||
* @param value the node value
|
||||
* @return the associated node
|
||||
*/
|
||||
Node get(long value);
|
||||
T get(long value);
|
||||
|
||||
/**
|
||||
* Gets a collection of all nodes stored in this table.
|
||||
*
|
||||
* @return the nodes stored
|
||||
*/
|
||||
Collection<Node> getNodes();
|
||||
Collection<T> getNodes();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -339,10 +338,9 @@ public class ReorderPrayersPlugin extends Plugin
|
||||
|
||||
private PrayerTabState getPrayerTabState()
|
||||
{
|
||||
HashTable componentTable = client.getComponentTable();
|
||||
for (Node node : componentTable.getNodes())
|
||||
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||
for (WidgetNode widgetNode : componentTable.getNodes())
|
||||
{
|
||||
WidgetNode widgetNode = (WidgetNode) node;
|
||||
if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID)
|
||||
{
|
||||
return PrayerTabState.PRAYERS;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -299,51 +293,52 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
@Override
|
||||
public Widget[] getStaticChildren()
|
||||
{
|
||||
List<Widget> widgets = new ArrayList<Widget>();
|
||||
for (Widget widget : client.getGroup(TO_GROUP(getId())))
|
||||
if (getRSParentId() == getId())
|
||||
{
|
||||
if (widget != null && widget.getParentId() == getId())
|
||||
// This is a dynamic widget, so it can't have static children
|
||||
return new Widget[0];
|
||||
}
|
||||
|
||||
List<Widget> widgets = new ArrayList<Widget>();
|
||||
for (RSWidget widget : client.getGroup(TO_GROUP(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;
|
||||
|
||||
// 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)
|
||||
if (getRSParentId() == getId())
|
||||
{
|
||||
// This is a dynamic widget, so it can't have nested children
|
||||
return new Widget[0];
|
||||
}
|
||||
|
||||
List<Widget> widgets = new ArrayList<Widget>();
|
||||
for (Widget widget : client.getGroup(group))
|
||||
HashTable<WidgetNode> componentTable = client.getComponentTable();
|
||||
|
||||
WidgetNode wn = componentTable.get(getId());
|
||||
if (wn == null)
|
||||
{
|
||||
if (widget != null && widget.getParentId() == getId())
|
||||
return new RSWidget[0];
|
||||
}
|
||||
|
||||
int group = wn.getId();
|
||||
|
||||
List<RSWidget> widgets = new ArrayList<RSWidget>();
|
||||
for (RSWidget widget : client.getGroup(group))
|
||||
{
|
||||
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 +368,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 +383,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();
|
||||
|
||||
@@ -30,6 +30,7 @@ import net.runelite.mapping.Import;
|
||||
public interface RSHashTable extends HashTable
|
||||
{
|
||||
@Import("get")
|
||||
@Override
|
||||
RSNode get(long value);
|
||||
|
||||
@Import("size")
|
||||
|
||||
@@ -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