Skip to content

Commit

Permalink
Calculate and store widget parent id and position when the interfaces…
Browse files Browse the repository at this point in the history
… are rendered

This removes the need to calculate widget bounds and parent on demand by
traversing up the widget tree.
  • Loading branch information
Adam- authored and johannajennekvist committed Jul 1, 2018
1 parent ae8b3b0 commit 06d5c9c
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 111 deletions.
9 changes: 0 additions & 9 deletions runelite-api/src/main/java/net/runelite/api/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,13 @@
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
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;
Expand All @@ -61,6 +62,7 @@
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;
Expand Down Expand Up @@ -321,9 +323,9 @@ public Widget[] getWidgetRoots()
{
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);
}
Expand All @@ -343,7 +345,7 @@ public Widget getWidget(WidgetInfo widget)

@Inject
@Override
public Widget[] getGroup(int groupId)
public RSWidget[] getGroup(int groupId)
{
RSWidget[][] widgets = getWidgets();

Expand All @@ -352,15 +354,7 @@ public Widget[] getGroup(int groupId)
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
Expand Down Expand Up @@ -564,7 +558,7 @@ public List<GraphicsObject> getGraphicsObjects()

for (Node node = head.getNext(); node != head; node = node.getNext())
{
graphicsObjects.add((GraphicsObject)node);
graphicsObjects.add((GraphicsObject) node);
}

return graphicsObjects;
Expand Down Expand Up @@ -1099,4 +1093,45 @@ public void methodDraw(boolean var1)
{
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);
}
}
}
}
}
}
161 changes: 74 additions & 87 deletions runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
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;
Expand All @@ -42,8 +42,6 @@
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)
Expand All @@ -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()
Expand All @@ -74,34 +110,27 @@ public Widget getParent()
@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];

// It looks like the first node in the bucket is always
// a sentinel
Node cur = node.getNext();
while (cur != node)
// 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

// 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
Expand Down Expand Up @@ -153,42 +182,7 @@ else if (parent.isHidden())
@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
Expand Down Expand Up @@ -285,9 +279,9 @@ public Widget[] getDynamicChildren()
}

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);
}
Expand All @@ -300,50 +294,39 @@ public Widget[] getDynamicChildren()
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
Expand Down Expand Up @@ -373,7 +356,9 @@ public void broadcastHidden(boolean hidden)
{
// if the widget is hidden it will not magically unhide from its parent changing
if (child == null || child.isSelfHidden())
{
continue;
}

child.broadcastHidden(hidden);
}
Expand All @@ -386,7 +371,9 @@ public void broadcastHidden(boolean hidden)
for (Widget nestedChild : nestedChildren)
{
if (nestedChild == null || nestedChild.isSelfHidden())
{
continue;
}

((RSWidget) nestedChild).broadcastHidden(hidden);
}
Expand Down
Loading

0 comments on commit 06d5c9c

Please sign in to comment.