feat(ui/button): implement more events & simulators

This commit implements events onHoverEnter/onHoverExit.

Simulators have .click() to simulate click, .hoverEnter()/.hoverExit() and so on.
This commit is contained in:
2025-10-01 10:17:04 +07:00
parent 63c81f98c2
commit affa81a3e8
2 changed files with 123 additions and 4 deletions

View File

@ -10,9 +10,12 @@ import org.vibecoders.moongazer.managers.Assets;
import org.vibecoders.moongazer.ui.UITextButton;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.video.VideoPlayer;
import com.badlogic.gdx.video.VideoPlayerCreator;
@ -20,8 +23,10 @@ public class MainMenu extends Scene {
private VideoPlayer videoPlayer;
private FileHandle videoFileHandle;
private Texture titleTexture;
private UITextButton[] buttons;
private float titleY, titleX, titleWidth, titleHeight;
private boolean videoPrepared = false;
private int currentChoice = -1;
public MainMenu(Game game) {
super(game);
@ -55,6 +60,7 @@ public class MainMenu extends Scene {
UITextButton loadButton = new UITextButton("Load", font);
UITextButton settingsButton = new UITextButton("Settings", font);
UITextButton exitButton = new UITextButton("Exit", font);
buttons = new UITextButton[] { playButton, loadButton, settingsButton, exitButton };
int buttonWidth = 300;
int buttonHeight = 80;
@ -77,6 +83,7 @@ public class MainMenu extends Scene {
exitButton.setSize(buttonWidth, buttonHeight);
exitButton.setPosition(centerX, startY - spacing * 3);
// Mouse click handlers
playButton.onClick(() -> log.debug("Play clicked"));
loadButton.onClick(() -> log.debug("Load clicked"));
settingsButton.onClick(() -> {
@ -95,9 +102,65 @@ public class MainMenu extends Scene {
root.addActor(settingsButton.getActor());
root.addActor(exitButton.getActor());
// Keyboard navigation handling
initKeyboardHandling();
game.stage.addActor(root);
}
private void initKeyboardHandling() {
for (int i = 0; i < buttons.length; i++) {
final int index = i;
buttons[i].onHoverEnter(() -> {
log.trace("Button hover enter: {}", index);
if (currentChoice != index) {
if (currentChoice != -1) {
buttons[currentChoice].hoverExit();
}
currentChoice = index;
}
});
buttons[i].onHoverExit(() -> {
if (currentChoice == index) {
currentChoice = -1;
}
});
}
root.addListener(new InputListener() {
@Override
public boolean keyDown(InputEvent event, int keycode) {
log.trace("Key pressed: {}", keycode);
switch (keycode) {
case Input.Keys.UP:
currentChoice = (currentChoice - 1 + 4) % 4;
break;
case Input.Keys.DOWN:
currentChoice = (currentChoice + 1) % 4;
break;
case Input.Keys.RIGHT:
case Input.Keys.ENTER:
if (currentChoice != -1) {
buttons[currentChoice].click();
}
break;
default:
break;
}
if (currentChoice != -1) {
log.trace("Current choice: {}", currentChoice);
for (int i = 0; i < buttons.length; i++) {
if (i == currentChoice) {
buttons[i].hoverEnter();
} else {
buttons[i].hoverExit();
}
}
}
return true;
}
});
}
private void startVideoOnce() {
if (videoPlayer == null || videoPrepared)
return;

View File

@ -1,12 +1,15 @@
package org.vibecoders.moongazer.ui;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.EventListener;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
public abstract class UIButton {
protected Actor actor;
protected Button button;
public Actor actor;
public Button button;
public Actor getActor() {
return actor;
@ -24,12 +27,65 @@ public abstract class UIButton {
actor.addListener(eventListener);
}
public void click() {
// Thx ChatGPT
InputEvent down = new InputEvent();
down.setType(InputEvent.Type.touchDown);
down.setButton(Input.Buttons.LEFT);
down.setStageX(button.getX());
down.setStageY(button.getY());
button.fire(down);
InputEvent up = new InputEvent();
up.setType(InputEvent.Type.touchUp);
up.setButton(Input.Buttons.LEFT);
up.setStageX(button.getX());
up.setStageY(button.getY());
button.fire(up);
}
public void hoverEnter() {
InputEvent e = new InputEvent();
e.setType(InputEvent.Type.enter);
e.setPointer(-1);
button.fire(e);
}
public void hoverExit() {
InputEvent e = new InputEvent();
e.setType(InputEvent.Type.exit);
e.setPointer(-1);
button.fire(e);
}
public void onClick(Runnable action) {
button.addListener(new com.badlogic.gdx.scenes.scene2d.utils.ClickListener() {
button.addListener(new ClickListener() {
@Override
public void clicked(com.badlogic.gdx.scenes.scene2d.InputEvent event, float x, float y) {
public void clicked(InputEvent event, float x, float y) {
action.run();
}
});
}
public void onHoverEnter(Runnable action) {
button.addListener(new ClickListener() {
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
if (pointer == -1) {
action.run();
}
}
});
}
public void onHoverExit(Runnable action) {
button.addListener(new ClickListener() {
@Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
if (pointer == -1) {
action.run();
}
}
});
}
}