Screen Operation API
Add controller compatibility to GUIs.
You can add explicit controller support to your UI if necessary with the various APIs in Controlify.
To make sure that your GUI classes don't depend on Controlify to load, all controller handling is done in a separate class, namely the ScreenProcessor
, that is registered in Controlify's pre-init entrypoint.
Making a screen
Before we get to handling a Screen, first we need to make an example screen:
In this basic example, there is a screen with two buttons that execute a function upon pressed. Even without a custom ScreenProcessor
, this screen will work well out of the box.
However, we can enhance the experience using shortcuts using the GUI Abstract Actions 1 and 2 provided in the Controlify bindings.
To do this, we need to add create said ScreenProcessor
.
Creating a ScreenProcessor
ScreenProcessor
If a custom processor is not provided for a screen, the parent class ScreenProcessor
is just used. This provides the basic functionality for controller operation for screens. You can choose to completely override this functionality, or extend from it using super
calls.
The above screen processor doesn't actually do anything, so let's add some functionality:
In the above example, I removed most of the methods and just left handleButtons
, then added a simple if statement to check if the bindings were pressed, then told the button to press. You could even use your own bindings using BindingSupplier
that you learnt about in the other wiki page.
Attaching the ScreenProcessor
ScreenProcessor
There are two ways to attach a processor; you can do it through a mixin, or the registry.
Using the registry
Inside of the pre-init entrypoint, add the following code...
Using Mixin
You can make your screen implement the ScreenProcessorProvider
interface which does as it says on the tin.
Make sure to not initialise the processor inside the getter function, as it could be ran multiple times per tick.
It is not inherently bad to mixin into your own classes, so don't feel that this in an 'improper' way. However using the registry is probably better. This method is useful when adding processors to vanilla screens, where you have easier access to fields and functions with @Shadow
that you can pass into your processor.
Using ComponentProcessor
ComponentProcessor
The screen processors work great for handling global actions within the screen, but don't provide any way to control the interaction behaviour of individual GUI components. This is where component processors come in.
For the example, we will create a processor for the vanilla button widget. For all intensive purposes, all we need to know about AbstractButton
is that it has an abstract onPress()
method:
Now we create our component processor:
Notice how both the 'override' methods return boolean. The return value dictates whether or not the corresponding screen processor methods are ran. This processor doesn't do much, so let's add the functionality to run the onPress()
method.
Here we added a constructor so we have access to the button, removed the unneeded overrides and added yet another quick binding check to press the button. Again, this can be switched out for your own binding that you created in the other wiki page.
The use case of a component processor shown above will actually not behave any differently to if it wasn't there. This is because if there is no component processor, GUI_PRESS
will just emulate the enter key, which buttons already handle for. However, it is always best to have explicit compatibility to not rely on emulation.
Attaching a ComponentProcessor
ComponentProcessor
You attach a component processor no differently from how you attach a screen processor. You have two options: the registry, or a mixin.
Using the registry
Inside of the pre-init entrypoint, add the following code...
Using Mixin
You can make your component implement the ComponentProcessorProvider
interface which does as it says on the tin.
Make sure to not initialise the processor inside the getter function, as it could be ran multiple times per tick.
Using button guides
The screen now fully works with a controller, but it is not clear what buttons press what on your screen. This is where the button guide API comes in; you can easily add binding previews to buttons.
To add a button guide, we need to modify our screen processor and add an override for the onWidgetRebuild
method. Since this runs after our buttons have initialised.
If you want to use a custom binding, remove the 'builtin' suffix and replace the lambda with your BindingSupplier
.
More examples
If you want to see some more advanced examples, have a look at the Controlify source in your IDE. The following packages will be very helpful:
dev.isxander.controlify.screenop.compat
dev.isxander.controlify.mixins.feature.screenop.vanilla
dev.isxander.controlify.mixins.compat
Last updated