From 4b64ed64612b65cb41fabda431bbd761b1c96c31 Mon Sep 17 00:00:00 2001 From: CADIndie Date: Fri, 20 Feb 2026 17:12:28 -0600 Subject: [PATCH 1/3] Make temp rebinding GUI --- .../screens/GuiGroupedListEditorScreen.java | 217 ++++++++++++++++++ .../client/gui/settings/GuiBindings.java | 104 +++------ .../assets/vivecraft/lang/en_us.json | 3 + 3 files changed, 247 insertions(+), 77 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java diff --git a/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java b/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java new file mode 100644 index 000000000..e54827dd3 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java @@ -0,0 +1,217 @@ +package org.vivecraft.client.gui.framework.screens; + +import com.google.common.collect.ImmutableList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.vivecraft.client.gui.framework.widgets.SettingsList; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public abstract class GuiGroupedListEditorScreen extends GuiListScreen { + private final Supplier> valuesSupplier; + private final Function categorySupplier; + private final Runnable loadDefaults; + private final Consumer> save; + + protected final boolean fixedEntryCount; + + protected List elements; + protected abstract T createNewValue(String category); + + public GuiGroupedListEditorScreen( + Component title, Screen lastScreen, boolean fixedEntryCount, Supplier> valuesSupplier, + Runnable loadDefaults, Consumer> save, @Nullable Function categorySupplier) + { + super(title, lastScreen); + this.fixedEntryCount = fixedEntryCount; + this.valuesSupplier = valuesSupplier; + this.loadDefaults = loadDefaults; + this.save = save; + this.categorySupplier = categorySupplier != null ? categorySupplier : item -> ""; + } + + @Override + protected void init() { + super.init(); + } + + @Override + protected void addLowerButtons(int top) { + this.addRenderableWidget( + Button.builder(Component.translatable("vivecraft.gui.loaddefaults"), button -> { + this.loadDefaults.run(); + this.elements = null; + this.reinit = true; + }) + .bounds(this.width / 2 - 155, top, 150, 20) + .build()); + + this.addRenderableWidget( + Button.builder(Component.translatable("gui.back"), button -> this.onClose()) + .bounds(this.width / 2 + 5, top, 150, 20) + .build()); + } + + @Override + public void onClose() { + this.save.accept(this.elements); + super.onClose(); + } + + @SuppressWarnings("unchecked") + protected List getCurrentValues() { + return this.list.children().stream().map(entry -> { + if (entry instanceof GuiListEditorScreen.ValueEntry valueEntry) { + return (T) valueEntry.getValue(); + } else { + return null; + } + }).filter(Objects::nonNull).collect(Collectors.toList()); + } + + @Override + protected List getEntries() { + List entries = new LinkedList<>(); + + if (this.elements == null) { + this.elements = new ArrayList<>(this.valuesSupplier.get()); + } + + Map> grouped = new LinkedHashMap<>(); + + for (T element : this.elements) { + String category = this.categorySupplier.apply(element); + grouped.computeIfAbsent(category, k -> new LinkedList<>()) + .add(element); + } + + int index = 0; + for (Map.Entry> group : grouped.entrySet()) { + + String category = group.getKey(); + List values = group.getValue(); + + SettingsList.GroupedEntry categoryEntry = null; + + if (!category.isEmpty()) { + categoryEntry = new SettingsList.GroupedEntry( + Component.translatable(category)); + entries.add(categoryEntry); + } + + for (T value : values) { + SettingsList.BaseEntry entry = this.toEntry(value, index++); + + if (categoryEntry != null) { + categoryEntry.add(entry); + } else { + entries.add(entry); + } + } + + if (!this.fixedEntryCount && categoryEntry != null) { + categoryEntry.add(createAddButton(category)); + } + } + + return entries; + } + + private SettingsList.BaseEntry createAddButton(String category) { + return new SettingsList.WidgetEntry( + Component.literal(""), + Button.builder(Component.translatable("vivecraft.options.add"), button -> { + this.addNewValue(category); + }).size(50, 20).build() + ); + } + + protected void addNewValue(String category) { + this.elements = getCurrentValues(); + this.elements.add(this.createNewValue(category)); + this.reinit = true; + } + + protected abstract ValueEntry toEntry(T value, int index); + + protected static class RemovableEntry extends ValueEntry { + protected final T value; + + private final int index; + private final Button editButton; + private final Button removeButton; + + public RemovableEntry(Component name, T value, int index) { + super(name, null); + this.value = value; + this.index = index; + + this.editButton = Button.builder(Component.translatable("vivecraft.options.edit"), + button -> {}) + .bounds(0, 0, 100, 20).build(); + this.removeButton = Button.builder(Component.literal("-"), + button -> {}) + .bounds(0, 0, 20, 20).build(); + } + + @Override + public void renderContent( + GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovering, float partialTick) + { + super.renderContent(guiGraphics, mouseX, mouseY, hovering, partialTick); + + int textY = this.getY() + this.getHeight() / 2 - Minecraft.getInstance().font.lineHeight / 2 + 2; + guiGraphics.drawString(Minecraft.getInstance().font, this.name, this.getContentX(), textY, + this.textColor()); + this.removeButton.active = this.isActive(); + this.editButton.active = this.isActive(); + + this.editButton.setX(this.getContentRight() - this.editButton.getWidth() - 20); + this.editButton.setY(this.getY()); + this.editButton.render(guiGraphics, mouseX, mouseY, partialTick); + this.removeButton.setX(this.getContentRight() - 20); + this.removeButton.setY(this.getY()); + this.removeButton.render(guiGraphics, mouseX, mouseY, partialTick); + } + + @Override + public List narratables() { + return ImmutableList.of(this.editButton, this.removeButton); + } + + @Override + public List children() { + return ImmutableList.of(this.editButton, this.removeButton); + } + + @Override + public void setActive(boolean active) { + super.setActive(active); + this.removeButton.active = active; + this.editButton.active = active; + } + + @Override + public T getValue() { + return this.value; + } + } + + protected static abstract class ValueEntry extends SettingsList.BaseEntry { + public ValueEntry(Component name, Supplier tooltipSupplier) { + super(name, tooltipSupplier); + } + + public abstract T getValue(); + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java index f88b9a63e..42c84b6af 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java @@ -1,94 +1,44 @@ package org.vivecraft.client.gui.settings; -import com.google.common.collect.ImmutableList; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.AbstractWidget; -import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.Tooltip; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; -import org.vivecraft.client.gui.framework.screens.GuiListScreen; -import org.vivecraft.client.gui.framework.widgets.SettingsList; -import org.vivecraft.client_vr.provider.control.ActionType; +import org.vivecraft.client.gui.framework.screens.GuiGroupedListEditorScreen; +import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.provider.control.InputAction; -import org.vivecraft.client_vr.provider.openxr.MCOpenXR; import java.util.LinkedList; import java.util.List; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -public class GuiBindings extends GuiListScreen { - +public class GuiBindings extends GuiGroupedListEditorScreen { public GuiBindings(Screen lastScreen) { - super(Component.translatable("vivecraft.options.screen.bindings"), lastScreen); + super(Component.empty(), + lastScreen, false, + () -> { + if (MCVR.get() == null) return List.of(); + List list = new LinkedList<>(); + for (var entry : MCVR.get().getInputActions()) { + var input = MCVR.get().getInputActionByName(entry.name); + if (input != null) { + list.add(input); + } + } + return list; + }, + () -> {}, + save -> {}, + action -> action.actionSet.name() + ); + + this.searchable = false; } @Override - protected List getEntries() { - List list = new LinkedList<>(); - for (var entry : MCOpenXR.get().getBinds().entrySet()) { - var input = MCOpenXR.get().getInputActionByName(entry.getKey()); - if (input == null) continue; - //list.add(new ResettableEntry(Component.translatable(input.name), input)); - } - return list; - } - - public static class ResettableEntry extends SettingsList.WidgetEntry { - public static final int VALUE_BUTTON_WIDTH = 125; - - private final Button resetButton; - private final BooleanSupplier canReset; - - public ResettableEntry(Component name, InputAction action) { - super(name, getBaseWidget(action, VALUE_BUTTON_WIDTH, 20).get()); - - this.canReset = () -> action.type != ActionType.BOOLEAN; - this.resetButton = Button.builder(Component.literal("X"), button -> { - action.setType(ActionType.BOOLEAN); - this.valueWidget = getBaseWidget(action, valueWidget.getWidth(), valueWidget.getHeight()).get(); - }) - .tooltip(Tooltip.create(Component.translatable("controls.reset"))) - .bounds(0, 0, 20, 20).build(); - } - - @Override - public void renderContent( - GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovering, float partialTick) - { - super.renderContent(guiGraphics, mouseX, mouseY, hovering, partialTick); - this.resetButton.setX(this.getContentRight() - 20); - this.resetButton.setY(this.getContentY()); - this.resetButton.active = this.canReset.getAsBoolean(); - this.resetButton.render(guiGraphics, mouseX, mouseY, partialTick); - } - - @Override - public List children() { - return ImmutableList.of(this.valueWidget, this.resetButton); - } - - @Override - public List narratables() { - return ImmutableList.of(this.valueWidget, this.resetButton); - } - - @Override - public void setActive(boolean active) { - super.setActive(active); - this.resetButton.active = active; - } + protected InputAction createNewValue(String category) { + return null; } - public static Supplier getBaseWidget(InputAction action, int width, int height) { - return () -> Button - .builder(Component.literal("" + action.type), button -> {}) - .bounds(0, 0, width, height) - .tooltip(Tooltip.create(Component.literal(action.name))) - .build(); + @Override + protected ValueEntry toEntry(InputAction value, int index) { + return new RemovableEntry(Component.literal(value.keyBinding.getName()), value, 0); } } diff --git a/common/src/main/resources/assets/vivecraft/lang/en_us.json b/common/src/main/resources/assets/vivecraft/lang/en_us.json index 949ab5435..1d89836a2 100644 --- a/common/src/main/resources/assets/vivecraft/lang/en_us.json +++ b/common/src/main/resources/assets/vivecraft/lang/en_us.json @@ -84,6 +84,7 @@ "vivecraft.options.screen.teleport": "Teleport Settings", "vivecraft.options.screen.controls": "Controller Settings", "vivecraft.options.screen.keyboard": "Keyboard Settings", + "vivecraft.options.screen.bindings": "Controller Bindings", "_comment4": "Buttons that lead to the screen", "vivecraft.options.screen.main.button": "VR Settings...", "vivecraft.options.screen.gui.button": "HUD and GUI Settings...", @@ -493,7 +494,9 @@ "vivecraft.options.once": "Once", "vivecraft.options.disabled": "Disabled", "vivecraft.options.editlist": "Edit List", + "vivecraft.options.add": "Add", "vivecraft.options.addnew": "Add New", + "vivecraft.options.edit": "Edit", "vivecraft.options.updatetype.alpha": "Alpha", "vivecraft.options.updatetype.beta": "Beta", "vivecraft.options.updatetype.release": "Release", From 7bc5eed0daf9ba4060dad5ed377d3166a696be7e Mon Sep 17 00:00:00 2001 From: CADIndie Date: Mon, 23 Feb 2026 04:17:35 -0600 Subject: [PATCH 2/3] Implement most of rebinding backend --- .../screens/GuiGroupedListEditorScreen.java | 90 +--- .../client/gui/settings/GuiBindings.java | 126 ++++- .../client_vr/provider/control/Action.java | 5 + .../client_vr/provider/control/Button.java | 3 + .../provider/openvr_lwjgl/MCOpenVR.java | 12 +- .../client_vr/provider/openxr/MCOpenXR.java | 218 ++++---- .../provider/openxr/control/XRBinding.java | 483 ------------------ .../openxr/control/XRBindingProfile.java | 168 ++++++ .../client_vr/settings/VRSettings.java | 2 + .../input/{ => openvr}/cosmos_defaults.json | 0 .../cosmos_defaults_reversed.json | 0 .../input/{ => openvr}/knuckles_defaults.json | 0 .../knuckles_defaults_reversed.json | 0 .../input/{ => openvr}/oculus_defaults.json | 0 .../oculus_defaults_reversed.json | 0 .../input/{ => openvr}/tracker_defaults.json | 0 .../input/{ => openvr}/vive_defaults.json | 0 .../{ => openvr}/vive_defaults_reversed.json | 0 .../input/{ => openvr}/wmr_defaults.json | 0 .../{ => openvr}/wmr_defaults_reversed.json | 0 .../input/openxr/cosmos_defaults.json | 148 ++++++ .../input/openxr/index_defaults.json | 144 ++++++ .../input/openxr/oculus_defaults.json | 271 ++++++++++ .../vivecraft/input/openxr/pico_defaults.json | 150 ++++++ .../input/openxr/simple_defaults.json | 93 ++++ .../vivecraft/input/openxr/vive_defaults.json | 155 ++++++ 26 files changed, 1376 insertions(+), 692 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/control/Action.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/control/Button.java delete mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/control/XRBinding.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/control/XRBindingProfile.java rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/cosmos_defaults.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/cosmos_defaults_reversed.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/knuckles_defaults.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/knuckles_defaults_reversed.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/oculus_defaults.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/oculus_defaults_reversed.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/tracker_defaults.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/vive_defaults.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/vive_defaults_reversed.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/wmr_defaults.json (100%) rename common/src/main/resources/assets/vivecraft/input/{ => openvr}/wmr_defaults_reversed.json (100%) create mode 100644 common/src/main/resources/assets/vivecraft/input/openxr/cosmos_defaults.json create mode 100644 common/src/main/resources/assets/vivecraft/input/openxr/index_defaults.json create mode 100644 common/src/main/resources/assets/vivecraft/input/openxr/oculus_defaults.json create mode 100644 common/src/main/resources/assets/vivecraft/input/openxr/pico_defaults.json create mode 100644 common/src/main/resources/assets/vivecraft/input/openxr/simple_defaults.json create mode 100644 common/src/main/resources/assets/vivecraft/input/openxr/vive_defaults.json diff --git a/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java b/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java index e54827dd3..5fef3751b 100644 --- a/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java +++ b/common/src/main/java/org/vivecraft/client/gui/framework/screens/GuiGroupedListEditorScreen.java @@ -1,11 +1,6 @@ package org.vivecraft.client.gui.framework.screens; -import com.google.common.collect.ImmutableList; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.framework.widgets.SettingsList; @@ -37,7 +32,7 @@ public GuiGroupedListEditorScreen( this.valuesSupplier = valuesSupplier; this.loadDefaults = loadDefaults; this.save = save; - this.categorySupplier = categorySupplier != null ? categorySupplier : item -> ""; + this.categorySupplier = categorySupplier != null ? categorySupplier : item -> "Empty"; } @Override @@ -101,26 +96,18 @@ protected List getEntries() { String category = group.getKey(); List values = group.getValue(); - SettingsList.GroupedEntry categoryEntry = null; - if (!category.isEmpty()) { - categoryEntry = new SettingsList.GroupedEntry( - Component.translatable(category)); - entries.add(categoryEntry); + entries.add(new SettingsList.GroupedEntry( + Component.translatable(category) + )); } for (T value : values) { - SettingsList.BaseEntry entry = this.toEntry(value, index++); - - if (categoryEntry != null) { - categoryEntry.add(entry); - } else { - entries.add(entry); - } + entries.add(this.toEntry(value, index++)); } - if (!this.fixedEntryCount && categoryEntry != null) { - categoryEntry.add(createAddButton(category)); + if (!this.fixedEntryCount && !category.isEmpty()) { + entries.add(createAddButton(category)); } } @@ -144,69 +131,6 @@ protected void addNewValue(String category) { protected abstract ValueEntry toEntry(T value, int index); - protected static class RemovableEntry extends ValueEntry { - protected final T value; - - private final int index; - private final Button editButton; - private final Button removeButton; - - public RemovableEntry(Component name, T value, int index) { - super(name, null); - this.value = value; - this.index = index; - - this.editButton = Button.builder(Component.translatable("vivecraft.options.edit"), - button -> {}) - .bounds(0, 0, 100, 20).build(); - this.removeButton = Button.builder(Component.literal("-"), - button -> {}) - .bounds(0, 0, 20, 20).build(); - } - - @Override - public void renderContent( - GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovering, float partialTick) - { - super.renderContent(guiGraphics, mouseX, mouseY, hovering, partialTick); - - int textY = this.getY() + this.getHeight() / 2 - Minecraft.getInstance().font.lineHeight / 2 + 2; - guiGraphics.drawString(Minecraft.getInstance().font, this.name, this.getContentX(), textY, - this.textColor()); - this.removeButton.active = this.isActive(); - this.editButton.active = this.isActive(); - - this.editButton.setX(this.getContentRight() - this.editButton.getWidth() - 20); - this.editButton.setY(this.getY()); - this.editButton.render(guiGraphics, mouseX, mouseY, partialTick); - this.removeButton.setX(this.getContentRight() - 20); - this.removeButton.setY(this.getY()); - this.removeButton.render(guiGraphics, mouseX, mouseY, partialTick); - } - - @Override - public List narratables() { - return ImmutableList.of(this.editButton, this.removeButton); - } - - @Override - public List children() { - return ImmutableList.of(this.editButton, this.removeButton); - } - - @Override - public void setActive(boolean active) { - super.setActive(active); - this.removeButton.active = active; - this.editButton.active = active; - } - - @Override - public T getValue() { - return this.value; - } - } - protected static abstract class ValueEntry extends SettingsList.BaseEntry { public ValueEntry(Component name, Supplier tooltipSupplier) { super(name, tooltipSupplier); diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java index 42c84b6af..b70cb23b4 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiBindings.java @@ -1,44 +1,130 @@ package org.vivecraft.client.gui.settings; +import com.google.common.collect.ImmutableList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.framework.screens.GuiGroupedListEditorScreen; -import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.control.InputAction; +import org.vivecraft.client_vr.provider.openxr.MCOpenXR; +import org.vivecraft.client_vr.provider.control.Action; +import org.vivecraft.client_vr.provider.openxr.control.XRBindingProfile; -import java.util.LinkedList; +import java.io.FileNotFoundException; +import java.util.ArrayList; import java.util.List; -public class GuiBindings extends GuiGroupedListEditorScreen { +public class GuiBindings extends GuiGroupedListEditorScreen { public GuiBindings(Screen lastScreen) { - super(Component.empty(), - lastScreen, false, - () -> { - if (MCVR.get() == null) return List.of(); - List list = new LinkedList<>(); - for (var entry : MCVR.get().getInputActions()) { - var input = MCVR.get().getInputActionByName(entry.name); - if (input != null) { - list.add(input); - } + super(Component.empty(), lastScreen, false, () -> + { + if (MCOpenXR.get() == null) return List.of(); + List actions = new ArrayList<>(); + try { + if (MCOpenXR.get() == null) return List.of(); + XRBindingProfile profile = XRBindingProfile.getCurrentProfile(); + if (profile == null) profile = XRBindingProfile.getDefaultBinding(MCOpenXR.get().getCurrentInteractionProfile()); + if (profile == null) profile = XRBindingProfile.getDefaultBinding(""); + actions.addAll(profile.actions()); + } catch (FileNotFoundException e) { + // Show error to user about missing profile } - return list; + + return actions; }, () -> {}, - save -> {}, - action -> action.actionSet.name() + save -> { + XRBindingProfile profile = new XRBindingProfile( + "Custom Profile", + new String[]{MCOpenXR.get().getCurrentInteractionProfile()}, + true, + save + ); + if (profile.saveProfile()) { + // Show success to user + } else { + // Show error to user + } + }, + action -> XRBindingProfile.getPrettyName(action.buttons().getFirst().path()) ); this.searchable = false; } @Override - protected InputAction createNewValue(String category) { + protected Action createNewValue(String category) { return null; } @Override - protected ValueEntry toEntry(InputAction value, int index) { - return new RemovableEntry(Component.literal(value.keyBinding.getName()), value, 0); + protected ValueEntry toEntry(Action value, int index) { + return new RemovableEntry<>(Component.translatable(value.key().substring(value.key().lastIndexOf('/') + 1)), value, 0); + } + + protected static class RemovableEntry extends ValueEntry { + protected final T value; + + private final int index; + private final Button editButton; + private final Button removeButton; + + public RemovableEntry(Component name, T value, int index) { + super(name, null); + this.value = value; + this.index = index; + + this.editButton = Button.builder(Component.translatable("vivecraft.options.edit"), + button -> {}) + .bounds(0, 0, 100, 20).build(); + this.removeButton = Button.builder(Component.literal("-"), + button -> {}) + .bounds(0, 0, 20, 20).build(); + } + + @Override + public void renderContent( + GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovering, float partialTick) + { + super.renderContent(guiGraphics, mouseX, mouseY, hovering, partialTick); + + int textY = this.getY() + this.getHeight() / 2 - Minecraft.getInstance().font.lineHeight / 2 + 2; + guiGraphics.drawString(Minecraft.getInstance().font, this.name, this.getContentX(), textY, + this.textColor()); + this.removeButton.active = this.isActive(); + this.editButton.active = this.isActive(); + + this.editButton.setX(this.getContentRight() - this.editButton.getWidth() - 20); + this.editButton.setY(this.getY()); + this.editButton.render(guiGraphics, mouseX, mouseY, partialTick); + this.removeButton.setX(this.getContentRight() - 20); + this.removeButton.setY(this.getY()); + this.removeButton.render(guiGraphics, mouseX, mouseY, partialTick); + } + + @Override + public List narratables() { + return ImmutableList.of(this.editButton, this.removeButton); + } + + @Override + public List children() { + return ImmutableList.of(this.editButton, this.removeButton); + } + + @Override + public void setActive(boolean active) { + super.setActive(active); + this.removeButton.active = active; + this.editButton.active = active; + } + + @Override + public T getValue() { + return this.value; + } } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/Action.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/Action.java new file mode 100644 index 000000000..8f7a5d43e --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/Action.java @@ -0,0 +1,5 @@ +package org.vivecraft.client_vr.provider.control; + +import java.util.List; + +public record Action(String key, List