This tutorial is part of a series on 317 interfaces. For some of the other entries, see the list below:
In this guide, we’ll cover the creation of non-standard, containerless hover buttons. These allow you to avoid the clipping issues when nesting hover buttons inside of scrolling containers. Please reference my interface class for any naming confusion: Interface.java
Standard hovers require three interfaces:
- The unhovered interface (typically a sprite that acts a button, for example)
- An invisible container interface that is only to be shown when moused over
- A child interface of the aforementioned container which will be used as the hovered state of the first interface
However, due to the use of a container, these sorts of hover buttons will result in weird clipping issues when nested inside of a scrolling container. A quick fix for that is to remove the need for the container all together.
Start by adding a method to grab a free index in the interface array:
Code:
private static int getFreeIndex() {
for (int i = 0; i < instances.length; i++) {
if (instances[i] == null) {
return i;
}
}
return -1;
}
Next, create a method to parent a child to a given interface:
Code:
private static void addChild(final int x, final int y, final int child, final RSInterface parent) {
final int[] childX = new int[parent.childX.length + 1];
final int[] childY = new int[parent.childY.length + 1];
final int[] children = new int[parent.children.length + 1];
System.arraycopy(parent.childX, 0, childX, 0, parent.childX.length);
System.arraycopy(parent.childY, 0, childY, 0, parent.childY.length);
System.arraycopy(parent.children, 0, children, 0, parent.children.length);
childX[childX.length - 1] = x;
childY[childY.length - 1] = y;
children[children.length - 1] = child;
parent.childX = childX;
parent.childY = childY;
parent.children = children;
}
private static void addChild(final int x, final int y, final RSInterface parent, final RSInterface child) {
addChild(x, y, child.id, parent);
}
Add a method for creating a sprite interface:
Code:
public static Interface createSprite(final int parentIndex, final int index, final String disabled, final String enabled) {
final Sprite spriteDisabled = Sprite.fetchSprite(disabled);
final Sprite spriteEnabled = Sprite.fetchSprite(enabled);
final Interface sprite = instances[index] = new Interface();
sprite.index = index;
sprite.parent = parentIndex;
sprite.type = 5;
sprite.width = spriteDisabled.myWidth;
sprite.height = spriteDisabled.myHeight;
sprite.spriteDisabled = spriteDisabled;
sprite.spriteEnabled = spriteEnabled;
return sprite;
}
public static Interface createSprite(final int parentIndex, final String disabled, final String enabled) {
final int index = getFreeIndex();
if (index < 0) {
throw new IllegalStateException("Interface cache full; expand the size of the array before attempting to create a component!");
}
return createSprite(parentIndex, index, disabled, enabled);
}
Then, add a method for creating the hover buttons:
Code:
public static List<RSInterface> createContainerlessHoverButton(final int x, final int y, final int parentIndex, final String unhovered, final String hovered, final String tooltip) {
final RSInterface unhoveredButton = createSprite(parentIndex, unhovered, unhovered);
final RSInterface hoveredButton = createSprite(parentIndex, hovered, hovered);
unhoveredButton.buttonType = 1;
unhoveredButton.tooltip = tooltip;
unhoveredButton.hoverParentIndex = hoveredButton.index;
hoveredButton.hoverParentIndex = hoveredButton.index;
hoveredButton.hidden = true;
addChild(x, y, instances[parentIndex], unhoveredButton);
addChild(x, y, instances[parentIndex], hoveredButton);
return Stream.of(unhoveredButton, hoveredButton).collect(Collectors.toList());
}
Next, go into your `Client` or `Game` class, depending on your client's naming, and rename the following:
Code:
anInt1048 -> sidebarHoveredInterfaceIndex
anInt1026 -> viewportHoveredInterfaceIndex
anInt886 -> hoveredInterfaceIndex
Finally, in your drawInterface method, where it draw the child interfaces, add the following code to prevent drawing of the hovered sprite until the interface is hovered:
Code:
if (childInterface.hidden && viewportHoveredInterfaceIndex != childInterface.id && sidebarHoveredInterfaceIndex != childInterface.id) {
continue;
}