| title | Bindings API |
|---|
Learn how to register new controller bindings.
The custom input bindings must be registered inside the Controlify pre-init entrypoint. Read more in [Controlify Entrypoint](controlify-entrypoint#using-the-entrypoint).Controlify allows users to configure different buttons on their controllers to actions in-game. You may want your own mod's actions to be able to be invoked from the controller too.
To register a controller binding, use the ControlifyBindApi.get() method:
private InputBindingSupplier actionBinding;
@Override
public void onControlifyInit(InitContext ctx) {
final ControlifyBindApi registrar = ControlifyBindApi.get();
registerInputBindings(registrar);
}
private void registerInputBindings(ControlifyBindApi registrar) {
actionBinding = registrar.registerBinding(
builder -> builder
.id(ResourceLocation.fromNamespaceAndPath(MyMod.MODID, path))
// The category of the binding, this is used to group bindings together in the settings.
.category(Component.translatable("mymod.binding.category"))
// A context is where the binding can be used. Multiple contexts can be used.
.allowedContexts(BindContext.IN_GAME)
// Allow using the binding in the radial menu.
// You can't use a custom modded item directly in here, since it's not registered yet
// and a runtime error will be thrown. Continue reading for a better alternative.
.radialCandidate(RadialIcons.getItem(Items.BARRIER)))
// Prevents Controlify from auto-registering controller bindings for Epic Fight's
// vanilla key mappings due explicit native support.
// You could also use ".keyEmulation(MyModKeyMappings.ACTION) to emulates
// the vanilla KeyMapping behavior, which may not always work well.
.addKeyCorrelation(MyModKeyMappings.ACTION)
);
}To add a name and description to the binding, you need to define the language keys controlify.binding.<namespace>.<path> and controlify.binding.<namespace>.<path>.desc respectively, alternatively, you can set .name(Component) and .description(Component)
Registering the binding provides you with a InputBindingSupplier, where you can then access the binding with actionBinding.on(controller);
You may have noticed that in the above code, we did not define a default binding, such as the A button. This is because default bindings are data-driven and defined by resource packs. If you want to define a default binding, you can do so by creating a JSON file in your mod's resources.
{
"defaults": {
"mymod:action1": {
"button": "controlify:button/south"
}
}
}This will set the default binding for mymod:action1 to the south face button on all controllers. You can also define defaults for specific controller namespaces by creating a file in assets/<namespace>/controllers/default_bind/<path>.json.
For more information on how to define default bindings, see the Default Binds page.
Once you have access to a binding through bindingSupplier.on(controller), you can access many properties of the binding:
| Property | Description |
|---|---|
inputGlyph() |
Returns the input glyph for the binding, which can be used in text. |
digitalNow() |
Returns true if the binding is pressed this tick. |
digitalPrev() |
Returns true if the binding was pressed in the previous tick. |
analogueNow() |
Gets a float value between 0 - 1 which describes its analogue state. |
analoguePrev() |
Gets a float value between 0 - 1 which describes its analogue state in the previous tick. |
justPressed() |
Returns if the binding is pressed this tick, if it returns true, the state is consumed and will return false for the remaining tick. |
justReleased() |
Returns if the binding was just released this tick, if it returns true, the state is consumed and will return false for the remaining tick. |
justTapped() |
Returns if the binding was just tapped this tick, if it returns true, the state is consumed and will return false for the remaining tick. |
guiPressed().get() |
Returns true if the binding is pressed this tick in the GUI context. |
There are more properties available inside of InputBinding which you can look at in the sources, but the above are the most notable that you will use the most.
There is nothing special about rendering glyphs for controller bindings, as Controlify utilises custom fonts.
This means you can use the glyphs within localised text, or just render it with graphics.drawString(myBinding.inputGlyph(), x, y, -1);
When registering a radial menu candidate, you must provide an icon to render it in the GUI.
You can use RadialIcons.getEffect(...) or RadialIcons.getItem(...) (for example, RadialIcons.getItem(Items.REDSTONE)).
However, do not reference modded items directly (e.g., RadialIcons.getItem(ModItems.CUSTOM.get())),
as item registration is deferred — meaning those items are not yet registered at this stage.
What you can do instead, is to reference the texture image file in the bundled resource-pack of your mod, using the following approach:
private enum MyRadialIcons {
CUSTOM(MyMod.rl("textures/item/custom.png")),;
private final @NotNull ResourceLocation id;
MyRadialIcons(@NotNull ResourceLocation id) {
this.id = id;
}
public @NotNull ResourceLocation getId() {
return id;
}
}
@Override
public void onControlifyPreInit(PreInitContext context) {
final ControlifyBindApi registrar = ControlifyBindApi.get();
registerCustomRadialIcons();
// Must be called after registerCustomRadialIcons
registerInputBindings(registrar);
}
private void registerCustomRadialIcons() {
for (MyRadialIcons icon : MyRadialIcons.values()) {
final ResourceLocation location = icon.getId();
// For consistency with the current Controlify radial icons,
// this code is equivalent to:
// https://github.com/isXander/Controlify/blob/f5c94c57d5e0d4954e413624a0d7ead937b6e8ab/src/main/java/dev/isxander/controlify/bindings/RadialIcons.java#L106-L112
RadialIcons.registerIcon(location, (graphics, x, y, tickDelta) -> {
var pose = CGuiPose.ofPush(graphics);
pose.translate(x, y);
pose.scale(0.5f, 0.5f);
Blit.tex(graphics, location, 0, 0, 0, 0, 32, 32, 32, 32);
pose.pop();
});
}
}
private void registerInputBindings(ControlifyBindApi registrar) {
actionBinding = registrar.registerBinding(
builder -> builder
.radialCandidate(MyRadialIcons.CUSTOM.getId())
);
}