Creating a custom skin
Creating a Custom Skin
This section guides you through creating a custom Skin
to define a unique context menu appearance.
Steps
Extend
Skin
:Create a new class extending
Skin
.Optionally implement
GroupableSkin
for option group support.
Register Renderers:
In the constructor, use
addRenderer
to registerSkinRenderer
instances for supported option types.
Implement
renderContextMenu
:Draw the menu’s background and layout.
Iterate over
getOptions
to render each option using its renderer.
Handle Input:
Override input methods (
mouseClicked
, etc.) for menu-level interactions.Delegate option-specific input to renderers.
Set Screen Behavior:
Use
setCreateNewScreen
to determine if the menu opens in a new screen.
Example:
public class SimpleSkin extends Skin {
public SimpleSkin() {
addRenderer(BooleanOption.class, SimpleBooleanRenderer::new);
setCreateNewScreen(false); // This will open this skin in the moveable screen itself. eg: classic skin
}
@Override
public void renderContextMenu(DrawContext drawContext, ContextMenu<?> contextMenu, int mouseX, int mouseY) {
this.contextMenu = contextMenu;
//Some padding and dimension definition
int yOffset = contextMenu.y + 2;
int width = 10;
// Draw background
DrawHelper.drawRectangle(drawContext.getMatrices().peek().getPositionMatrix(),
contextMenu.x, contextMenu.y, 100, contextMenu.getHeight(), 0x80000000);
// Render options
// You MUST use getOptions(contextMenu) so you avoid problems with setting groups
for (Option<?> option : getOptions(contextMenu)) {
if (!option.shouldRender()) continue;
option.render(drawContext, contextMenu.x + 2, yOffset, mouseX, mouseY);
width = Math.max(width, option.getWidth());
yOffset += option.getHeight() + 1;
}
contextMenu.setWidth(width + 4);
contextMenu.setHeight(yOffset - contextMenu.y);
}
public static class SimpleBooleanRenderer implements SkinRenderer<BooleanOption> {
@Override
public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) {
option.setPosition(x, y);
option.setHeight(10);
option.setWidth(mc.textRenderer.getWidth(option.getName().getString()) + 10);
int color = option.get() ? 0x00FF00 : 0xFF0000;
drawContext.drawText(mc.textRenderer, option.getName(), x, y, color, false);
}
}
}
Common Pitfalls
Not Setting Dimensions: Failing to update
contextMenu.setWidth
andcontextMenu.setHeight
can cause clipping.Fix: Calculate and set dimensions based on rendered options.
Ignoring Group Support: If
supportsGroups()
is false, groups are flattened, which may break hierarchical menus.Fix: Implement
GroupableSkin
if groups are needed.
Test your skin with all supported option types to ensure renderers are correctly registered.
Last updated
Was this helpful?