Cycle particle settings with up to five options

Choices with up to five options cycle forward on left click and backward
on right click, listing all options in the lore. Two-option choices still
read as a toggle; longer choices keep their list.
This commit is contained in:
2026-10-26 09:49:07 +01:00
parent 5e81081620
commit c3eda01e20
3 changed files with 19 additions and 10 deletions
@@ -54,6 +54,7 @@ class EntryEditor {
private final int BACK = BottomBar.position(SIZE, BottomBar.BACK);
private final int COST = BottomBar.position(SIZE, BottomBar.COST);
private final int DELETE = BottomBar.position(SIZE, BottomBar.DELETE);
private final int MAX_CYCLED_OPTIONS = 5;
private final Map<Parameter<?>, Material> ICONS = Map.ofEntries(
Map.entry(COUNT, Material.GLOWSTONE_DUST),
@@ -154,13 +155,13 @@ class EntryEditor {
Player player = context.player();
Object value = context.entry().getValues().get(parameter);
List<String> lore = new ArrayList<>();
if (parameter instanceof ChoiceParameter<?> choice && isToggle(choice)) {
if (parameter instanceof ChoiceParameter<?> choice && isCycled(choice)) {
lore.addAll(optionLines((ChoiceParameter<Object>) choice, value, player));
} else {
lore.add(msg("PARTICLE_VALUE", player, valueText(parameter, value, player)));
}
lore.add("");
lore.add(msg(isToggle(parameter) ? "PARTICLE_VALUE_TOGGLE" : "PARTICLE_VALUE_CLICK", player));
lore.add(msg(isToggle(parameter) ? "PARTICLE_VALUE_TOGGLE" : isCycled(parameter) ? "PARTICLE_VALUE_CYCLE" : "PARTICLE_VALUE_CLICK", player));
Material icon = ICONS.getOrDefault(parameter, Material.PAPER);
if (parameter instanceof BooleanParameter) icon = (Boolean) value ? Material.LIME_DYE : Material.GRAY_DYE;
@@ -184,8 +185,8 @@ class EntryEditor {
ValueEditors.editColors(player, () -> context.entry().getValues().get(gradient), gradient.getMaxColors(),
colors -> apply(context, gradient, colors), context::reopen);
} else if (parameter instanceof ChoiceParameter<?> choice) {
if (isToggle(choice)) {
toggle(context, (ChoiceParameter<Object>) choice, value);
if (isCycled(choice)) {
cycle(context, (ChoiceParameter<Object>) choice, value, clickType.isRightClick() ? -1 : 1);
} else {
pick(context, (ChoiceParameter<Object>) choice, value);
}
@@ -193,12 +194,17 @@ class EntryEditor {
});
}
// Booleans and choices with exactly two options switch on click instead of opening a screen
private boolean isToggle(Parameter<?> parameter) {
return parameter instanceof BooleanParameter || (parameter instanceof ChoiceParameter<?> choice && choice.getBuildableValues().size() == 2);
// Choices with a few options cycle through them on click instead of opening a list
private boolean isCycled(Parameter<?> parameter) {
return parameter instanceof ChoiceParameter<?> choice && choice.getBuildableValues().size() <= MAX_CYCLED_OPTIONS;
}
// Both options of a toggle, the current one highlighted
// With two options both click directions lead to the same value, so it reads as a plain toggle
private boolean isToggle(Parameter<?> parameter) {
return parameter instanceof BooleanParameter || (isCycled(parameter) && ((ChoiceParameter<?>) parameter).getBuildableValues().size() == 2);
}
// All options of a cycled choice, the current one highlighted
private <E> List<String> optionLines(ChoiceParameter<E> parameter, E current, Player player) {
List<String> lines = new ArrayList<>();
for (E option : parameter.getBuildableValues()) {
@@ -208,9 +214,10 @@ class EntryEditor {
return lines;
}
private <E> void toggle(Context context, ChoiceParameter<E> parameter, E current) {
// Left click moves forward, right click backward
private <E> void cycle(Context context, ChoiceParameter<E> parameter, E current, int direction) {
List<E> values = parameter.getBuildableValues();
apply(context, parameter, values.get(values.indexOf(current) == 0 ? 1 : 0));
apply(context, parameter, values.get(Math.floorMod(values.indexOf(current) + direction, values.size())));
context.reopen();
}