add options menu as overlay

This commit is contained in:
yugecin 2017-01-19 16:03:53 +01:00
parent 04449abe62
commit e7eec14341
8 changed files with 297 additions and 190 deletions

View File

@ -92,7 +92,7 @@ public class Opsu extends StateBasedGame {
addState(new Game(STATE_GAME)); addState(new Game(STATE_GAME));
addState(new GamePauseMenu(STATE_GAMEPAUSEMENU)); addState(new GamePauseMenu(STATE_GAMEPAUSEMENU));
addState(new GameRanking(STATE_GAMERANKING)); addState(new GameRanking(STATE_GAMERANKING));
addState(new OptionsMenu(STATE_OPTIONSMENU)); //addState(new OptionsMenu(STATE_OPTIONSMENU));
//addState(new DownloadsMenu(STATE_DOWNLOADSMENU)); //addState(new DownloadsMenu(STATE_DOWNLOADSMENU));
} }

View File

@ -415,8 +415,7 @@ public class Options {
SHOW_FPS ("Show FPS Counter", "FpsCounter", "Show an FPS counter in the bottom-right hand corner.", true), SHOW_FPS ("Show FPS Counter", "FpsCounter", "Show an FPS counter in the bottom-right hand corner.", true),
SHOW_UNICODE ("Prefer Non-English Metadata", "ShowUnicode", "Where available, song titles will be shown in their native language.", false) { SHOW_UNICODE ("Prefer Non-English Metadata", "ShowUnicode", "Where available, song titles will be shown in their native language.", false) {
@Override @Override
public void click(GameContainer container) { public void click() {
super.click(container);
if (bool) { if (bool) {
try { try {
Fonts.LARGE.loadGlyphs(); Fonts.LARGE.loadGlyphs();
@ -468,8 +467,7 @@ public class Options {
}, },
NEW_CURSOR ("Enable New Cursor", "NewCursor", "Use the new cursor style (may cause higher CPU usage).", true) { NEW_CURSOR ("Enable New Cursor", "NewCursor", "Use the new cursor style (may cause higher CPU usage).", true) {
@Override @Override
public void click(GameContainer container) { public void click() {
super.click(container);
UI.getCursor().reset(); UI.getCursor().reset();
} }
}, },
@ -1131,9 +1129,8 @@ public class Options {
* Processes a mouse click action (via override). * Processes a mouse click action (via override).
* <p> * <p>
* By default, this inverts the current {@code bool} field. * By default, this inverts the current {@code bool} field.
* @param container the game container
*/ */
public void click(GameContainer container) { bool = !bool; } public void click() { bool = !bool; }
/** /**
* Get a list of values to choose from * Get a list of values to choose from
@ -1697,7 +1694,7 @@ public class Options {
* sends a bar notification about the action. * sends a bar notification about the action.
*/ */
public static void toggleMouseDisabled() { public static void toggleMouseDisabled() {
GameOption.DISABLE_MOUSE_BUTTONS.click(null); GameOption.DISABLE_MOUSE_BUTTONS.click();
UI.sendBarNotification((GameOption.DISABLE_MOUSE_BUTTONS.getBooleanValue()) ? UI.sendBarNotification((GameOption.DISABLE_MOUSE_BUTTONS.getBooleanValue()) ?
"Mouse buttons are disabled." : "Mouse buttons are enabled."); "Mouse buttons are disabled." : "Mouse buttons are enabled.");
} }

View File

@ -18,35 +18,14 @@
package itdelatrisu.opsu.states; package itdelatrisu.opsu.states;
import itdelatrisu.opsu.GameImage;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.Options.GameOption; import itdelatrisu.opsu.Options.GameOption;
import itdelatrisu.opsu.audio.MusicController;
import itdelatrisu.opsu.audio.SoundController;
import itdelatrisu.opsu.audio.SoundEffect;
import itdelatrisu.opsu.ui.UI;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.EmptyTransition;
import yugecin.opsudance.ui.OptionsOverlay; import yugecin.opsudance.ui.OptionsOverlay;
import yugecin.opsudance.ui.OptionsOverlay.OptionTab; import yugecin.opsudance.ui.OptionsOverlay.OptionTab;
/** public class OptionsMenu {
* "Game Options" state.
* <p>
* Players are able to view and change various game settings in this state.
*/
public class OptionsMenu extends BasicGameState implements OptionsOverlay.Parent {
/** Option tabs. */ public static final OptionTab[] normalOptions = new OptionsOverlay.OptionTab[]{
private static final OptionTab[] options = new OptionsOverlay.OptionTab[]{
new OptionTab("Display", new GameOption[]{ new OptionTab("Display", new GameOption[]{
GameOption.SCREEN_RESOLUTION, GameOption.SCREEN_RESOLUTION,
GameOption.FULLSCREEN, GameOption.FULLSCREEN,
@ -154,104 +133,4 @@ public class OptionsMenu extends BasicGameState implements OptionsOverlay.Parent
}) })
}; };
private StateBasedGame game;
private Input input;
private final int state;
private OptionsOverlay optionsOverlay;
public OptionsMenu(int state) {
this.state = state;
}
@Override
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
this.game = game;
this.input = container.getInput();
optionsOverlay = new OptionsOverlay(this, options, 5, container);
}
@Override
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
// background
GameImage.OPTIONS_BG.getImage().draw();
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
optionsOverlay.render(g, mouseX, mouseY);
UI.draw(g);
}
@Override
public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
UI.update(delta);
MusicController.loopTrackIfEnded(false);
optionsOverlay.update(delta, input.getMouseX(), input.getMouseY());
}
@Override
public int getID() {
return state;
}
@Override
public void mouseReleased(int button, int x, int y) {
optionsOverlay.mouseReleased(button, x, y);
}
@Override
public void mousePressed(int button, int x, int y) {
optionsOverlay.mousePressed(button, x, y);
}
@Override
public void mouseDragged(int oldx, int oldy, int newx, int newy) {
optionsOverlay.mouseDragged(oldx, oldy, newx, newy);
}
@Override
public void mouseWheelMoved(int newValue) {
optionsOverlay.mouseWheelMoved(newValue);
}
@Override
public void keyPressed(int key, char c) {
optionsOverlay.keyPressed(key, c);
}
/**
* This string is built with option values when entering the options menu.
* When leaving the options menu, this string is checked against the new optionstring with the same options.
* If those do not match, it means some option has change which requires a restart
*/
private String restartOptions;
@Override
public void enter(GameContainer container, StateBasedGame game)
throws SlickException {
UI.enter();
restartOptions = "" + Options.getResolutionIdx() + Options.isFullscreen() + Options.allowLargeResolutions() + Options.getSkinName();
}
@Override
public void leave(GameContainer container, StateBasedGame game) throws SlickException {
if (!("" + Options.getResolutionIdx() + Options.isFullscreen() + Options.allowLargeResolutions() + Options.getSkinName()).equals(restartOptions)) {
container.setForceExit(false);
container.exit();
return;
}
SoundController.playSound(SoundEffect.MENUBACK);
}
@Override
public void onLeave() {
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
}
@Override
public void onSaveOption(GameOption option) {
}
} }

View File

@ -71,6 +71,7 @@ import org.newdawn.slick.gui.TextField;
import yugecin.opsudance.core.DisplayContainer; import yugecin.opsudance.core.DisplayContainer;
import yugecin.opsudance.core.inject.InstanceContainer; import yugecin.opsudance.core.inject.InstanceContainer;
import yugecin.opsudance.core.state.ComplexOpsuState; import yugecin.opsudance.core.state.ComplexOpsuState;
import yugecin.opsudance.ui.OptionsOverlay;
/** /**
* "Song Selection" state. * "Song Selection" state.
@ -320,15 +321,21 @@ public class SongMenu extends ComplexOpsuState {
/** Sort order dropdown menu. */ /** Sort order dropdown menu. */
private DropdownMenu<BeatmapSortOrder> sortMenu; private DropdownMenu<BeatmapSortOrder> sortMenu;
private final OptionsOverlay optionsOverlay;
public SongMenu(final DisplayContainer displayContainer, InstanceContainer instanceContainer) { public SongMenu(final DisplayContainer displayContainer, InstanceContainer instanceContainer) {
super(displayContainer); super(displayContainer);
this.instanceContainer = instanceContainer; this.instanceContainer = instanceContainer;
optionsOverlay = new OptionsOverlay(this, displayContainer, OptionsMenu.normalOptions, 0);
overlays.add(optionsOverlay);
} }
@Override @Override
public void revalidate() { public void revalidate() {
super.revalidate(); super.revalidate();
components.clear();
// header/footer coordinates // header/footer coordinates
headerY = displayContainer.height * 0.0075f + GameImage.MENU_MUSICNOTE.getImage().getHeight() + headerY = displayContainer.height * 0.0075f + GameImage.MENU_MUSICNOTE.getImage().getHeight() +
Fonts.BOLD.getLineHeight() + Fonts.DEFAULT.getLineHeight() + Fonts.BOLD.getLineHeight() + Fonts.DEFAULT.getLineHeight() +
@ -460,8 +467,6 @@ public class SongMenu extends ComplexOpsuState {
@Override @Override
public void render(Graphics g) { public void render(Graphics g) {
super.render(g);
g.setBackground(Color.black); g.setBackground(Color.black);
int width = displayContainer.width; int width = displayContainer.width;
@ -711,6 +716,8 @@ public class SongMenu extends ComplexOpsuState {
UI.getBackButton().draw(); UI.getBackButton().draw();
UI.draw(g); UI.draw(g);
super.render(g);
} }
@Override @Override
@ -927,7 +934,7 @@ public class SongMenu extends ComplexOpsuState {
return true; return true;
} else if (selectOptionsButton.contains(x, y)) { } else if (selectOptionsButton.contains(x, y)) {
SoundController.playSound(SoundEffect.MENUHIT); SoundController.playSound(SoundEffect.MENUHIT);
// TODO d displayContainer.switchState(OptionsMenu.class); optionsOverlay.show();
return true; return true;
} }
@ -1166,7 +1173,7 @@ public class SongMenu extends ComplexOpsuState {
return true; return true;
case Input.KEY_O: case Input.KEY_O:
if (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL)) { if (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL)) {
// TODO d displayContainer.switchState(OptionsMenu.class); optionsOverlay.show();
} }
return true; return true;
default: default:
@ -1225,6 +1232,10 @@ public class SongMenu extends ComplexOpsuState {
@Override @Override
public boolean mouseWheelMoved(int newValue) { public boolean mouseWheelMoved(int newValue) {
if (super.mouseWheelMoved(newValue)) {
return true;
}
Input input = displayContainer.input; Input input = displayContainer.input;
if (input.isKeyDown(Input.KEY_LALT) || input.isKeyDown(Input.KEY_RALT)) { if (input.isKeyDown(Input.KEY_LALT) || input.isKeyDown(Input.KEY_RALT)) {

View File

@ -24,15 +24,17 @@ import yugecin.opsudance.core.components.Component;
import java.util.LinkedList; import java.util.LinkedList;
public class ComplexOpsuState extends BaseOpsuState { public abstract class ComplexOpsuState extends BaseOpsuState {
protected final LinkedList<Component> components; protected final LinkedList<Component> components;
protected final LinkedList<OverlayOpsuState> overlays;
private Component focusedComponent; private Component focusedComponent;
public ComplexOpsuState(DisplayContainer displayContainer) { public ComplexOpsuState(DisplayContainer displayContainer) {
super(displayContainer); super(displayContainer);
this.components = new LinkedList<>(); this.components = new LinkedList<>();
this.overlays = new LinkedList<>();
} }
public final void focusComponent(Component component) { public final void focusComponent(Component component) {
@ -47,11 +49,55 @@ public class ComplexOpsuState extends BaseOpsuState {
} }
public boolean isAnyComponentFocused() { public boolean isAnyComponentFocused() {
return focusedComponent != null; return focusedComponent != null || isAnyOverlayActive();
}
public boolean isAnyOverlayActive() {
for (OverlayOpsuState overlay : overlays) {
if (overlay.active) {
return true;
}
}
return false;
}
@Override
public boolean mouseWheelMoved(int delta) {
for (OverlayOpsuState overlay : overlays) {
if (overlay.mouseWheelMoved(delta)) {
return true;
}
}
return false;
}
@Override
public boolean mousePressed(int button, int x, int y) {
for (OverlayOpsuState overlay : overlays) {
if (overlay.mousePressed(button, x, y)) {
return true;
}
}
return false;
}
@Override
public boolean mouseDragged(int oldx, int oldy, int newx, int newy) {
for (OverlayOpsuState overlay : overlays) {
if (overlay.mouseDragged(oldx, oldy, newx, newy)) {
return true;
}
}
return false;
} }
@Override @Override
public boolean mouseReleased(int button, int x, int y) { public boolean mouseReleased(int button, int x, int y) {
for (OverlayOpsuState overlay : overlays) {
if (overlay.mouseReleased(button, x, y)) {
return true;
}
}
if (focusedComponent == null) { if (focusedComponent == null) {
for (Component component : components) { for (Component component : components) {
if (!component.isFocusable()) { if (!component.isFocusable()) {
@ -83,14 +129,25 @@ public class ComplexOpsuState extends BaseOpsuState {
component.updateHover(displayContainer.mouseX, displayContainer.mouseY); component.updateHover(displayContainer.mouseX, displayContainer.mouseY);
component.preRenderUpdate(); component.preRenderUpdate();
} }
for (OverlayOpsuState overlay : overlays) {
overlay.preRenderUpdate();
}
}
@Override
protected void revalidate() {
super.revalidate();
for (OverlayOpsuState overlay : overlays) {
overlay.revalidate();
}
} }
@Override @Override
public void render(Graphics g) { public void render(Graphics g) {
super.render(g); for (OverlayOpsuState overlay : overlays) {
for (Component component : components) { overlay.render(g);
component.render(g);
} }
super.render(g);
} }
@Override @Override
@ -98,6 +155,11 @@ public class ComplexOpsuState extends BaseOpsuState {
if (super.keyReleased(key, c)) { if (super.keyReleased(key, c)) {
return true; return true;
} }
for (OverlayOpsuState overlay : overlays) {
if (overlay.keyReleased(key, c)) {
return true;
}
}
if (focusedComponent != null) { if (focusedComponent != null) {
if (key == Input.KEY_ESCAPE) { if (key == Input.KEY_ESCAPE) {
focusedComponent.setFocused(false); focusedComponent.setFocused(false);
@ -112,6 +174,11 @@ public class ComplexOpsuState extends BaseOpsuState {
@Override @Override
public boolean keyPressed(int key, char c) { public boolean keyPressed(int key, char c) {
for (OverlayOpsuState overlay : overlays) {
if (overlay.keyPressed(key, c)) {
return true;
}
}
if (focusedComponent != null) { if (focusedComponent != null) {
if (key == Input.KEY_ESCAPE) { if (key == Input.KEY_ESCAPE) {
focusedComponent.setFocused(false); focusedComponent.setFocused(false);

View File

@ -0,0 +1,117 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state;
import org.newdawn.slick.Graphics;
import java.io.StringWriter;
public abstract class OverlayOpsuState implements OpsuState {
protected boolean active;
protected boolean acceptInput;
public abstract void hide();
public abstract void show();
@Override
public final void update() {
}
public void revalidate() {
}
protected abstract void onPreRenderUpdate();
@Override
public final void preRenderUpdate() {
if (active) {
onPreRenderUpdate();
}
}
protected abstract void onRender(Graphics g);
@Override
public final void render(Graphics g) {
if (active) {
onRender(g);
}
}
@Override
public final void enter() {
}
@Override
public final void leave() {
}
@Override
public final boolean onCloseRequest() {
return true;
}
protected abstract boolean onKeyPressed(int key, char c);
@Override
public final boolean keyPressed(int key, char c) {
return acceptInput && onKeyPressed(key, c);
}
protected abstract boolean onKeyReleased(int key, char c);
@Override
public final boolean keyReleased(int key, char c) {
return acceptInput && onKeyReleased(key, c);
}
protected abstract boolean onMouseWheelMoved(int delta);
@Override
public final boolean mouseWheelMoved(int delta) {
return acceptInput && onMouseWheelMoved(delta);
}
protected abstract boolean onMousePressed(int button, int x, int y);
@Override
public final boolean mousePressed(int button, int x, int y) {
return acceptInput && onMousePressed(button, x, y);
}
protected abstract boolean onMouseReleased(int button, int x, int y);
@Override
public final boolean mouseReleased(int button, int x, int y) {
return acceptInput && onMouseReleased(button, x, y);
}
protected abstract boolean onMouseDragged(int oldx, int oldy, int newx, int newy);
@Override
public final boolean mouseDragged(int oldx, int oldy, int newx, int newy) {
return acceptInput && onMouseDragged(oldx, oldy, newx, newy);
}
@Override
public void writeErrorDump(StringWriter dump) {
dump.append("> OverlayOpsuState dump\n");
dump.append("accepts input: ").append(String.valueOf(acceptInput)).append(" is active: ").append(String.valueOf(active));
}
}

View File

@ -29,16 +29,18 @@ import itdelatrisu.opsu.ui.Fonts;
import itdelatrisu.opsu.ui.MenuButton; import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.UI; import itdelatrisu.opsu.ui.UI;
import org.newdawn.slick.*; import org.newdawn.slick.*;
import yugecin.opsudance.core.DisplayContainer;
import yugecin.opsudance.core.state.ComplexOpsuState;
import yugecin.opsudance.core.state.OverlayOpsuState;
@SuppressWarnings("UnusedParameters") public class OptionsOverlay extends OverlayOpsuState {
public class OptionsOverlay {
private Parent parent; private final ComplexOpsuState parent;
private GameContainer container; private final DisplayContainer displayContainer;
private final Image sliderBallImg; private Image sliderBallImg;
private final Image checkOnImg; private Image checkOnImg;
private final Image checkOffImg; private Image checkOffImg;
private OptionTab[] tabs; private OptionTab[] tabs;
private int selectedTab; private int selectedTab;
@ -79,21 +81,26 @@ public class OptionsOverlay {
private int sliderSoundDelay; private int sliderSoundDelay;
public OptionsOverlay(Parent parent, OptionTab[] tabs, int defaultSelectedTabIndex, GameContainer container) { public OptionsOverlay(ComplexOpsuState parent, DisplayContainer displayContainer, OptionTab[] tabs, int defaultSelectedTabIndex) {
this.parent = parent; this.parent = parent;
this.container = container; this.displayContainer = displayContainer;
this.tabs = tabs; this.tabs = tabs;
selectedTab = defaultSelectedTabIndex; selectedTab = defaultSelectedTabIndex;
listHoverIndex = -1; listHoverIndex = -1;
}
@Override
public void revalidate() {
super.revalidate();
sliderBallImg = GameImage.CONTROL_SLIDER_BALL.getImage().getScaledCopy(20, 20); sliderBallImg = GameImage.CONTROL_SLIDER_BALL.getImage().getScaledCopy(20, 20);
checkOnImg = GameImage.CONTROL_CHECK_ON.getImage().getScaledCopy(20, 20); checkOnImg = GameImage.CONTROL_CHECK_ON.getImage().getScaledCopy(20, 20);
checkOffImg = GameImage.CONTROL_CHECK_OFF.getImage().getScaledCopy(20, 20); checkOffImg = GameImage.CONTROL_CHECK_OFF.getImage().getScaledCopy(20, 20);
width = container.getWidth(); width = displayContainer.width;
height = container.getHeight(); height = displayContainer.height;
// calculate positions // calculate positions
optionWidth = width / 2; optionWidth = width / 2;
@ -109,10 +116,12 @@ public class OptionsOverlay {
maxScrollOffset = Fonts.MEDIUM.getLineHeight() * 2 * tabs.length; maxScrollOffset = Fonts.MEDIUM.getLineHeight() * 2 * tabs.length;
scrollOffset = 0; scrollOffset = 0;
for (OptionTab tab : tabs) { for (OptionTab tab : tabs) {
/*
if (defaultSelectedTabIndex-- > 0) { if (defaultSelectedTabIndex-- > 0) {
scrollOffset += Fonts.MEDIUM.getLineHeight() * 2; scrollOffset += Fonts.MEDIUM.getLineHeight() * 2;
scrollOffset += tab.options.length * optionHeight; scrollOffset += tab.options.length * optionHeight;
} }
*/
maxScrollOffset += tab.options.length * optionHeight; maxScrollOffset += tab.options.length * optionHeight;
tab.button = new MenuButton(tabImage, tabX, tabY); tab.button = new MenuButton(tabImage, tabX, tabY);
tabX += tabOffset; tabX += tabOffset;
@ -127,7 +136,8 @@ public class OptionsOverlay {
optionStartY = (int) (tabY + tabImage.getHeight() / 2 + 2); // +2 for the separator line optionStartY = (int) (tabY + tabImage.getHeight() / 2 + 2); // +2 for the separator line
} }
public void render(Graphics g, int mouseX, int mouseY) { @Override
public void onRender(Graphics g) {
// bg // bg
g.setColor(Colors.BLACK_ALPHA_75); g.setColor(Colors.BLACK_ALPHA_75);
g.fillRect(0, 0, width, height); g.fillRect(0, 0, width, height);
@ -136,7 +146,7 @@ public class OptionsOverlay {
renderTitle(); renderTitle();
// option tabs // option tabs
renderTabs(mouseX, mouseY); renderTabs();
// line separator // line separator
g.setColor(Color.white); g.setColor(Color.white);
@ -159,7 +169,7 @@ public class OptionsOverlay {
UI.getBackButton().draw(); UI.getBackButton().draw();
// tooltip // tooltip
renderTooltip(g, mouseX, mouseY); renderTooltip(g);
// key input options // key input options
if (keyEntryLeft || keyEntryRight) { if (keyEntryLeft || keyEntryRight) {
@ -175,15 +185,10 @@ public class OptionsOverlay {
Fonts.LARGE.drawString((width - Fonts.LARGE.getWidth(prompt)) / 2, (height - Fonts.LARGE.getLineHeight()) / 2, prompt); Fonts.LARGE.drawString((width - Fonts.LARGE.getWidth(prompt)) / 2, (height - Fonts.LARGE.getLineHeight()) / 2, prompt);
} }
private void renderTooltip(Graphics g, int mouseX, int mouseY) { private void renderTooltip(Graphics g) {
if (hoverOption != null) { if (hoverOption != null) {
String optionDescription = hoverOption.getDescription(); UI.updateTooltip(displayContainer.renderDelta, hoverOption.getDescription(), false);
float textWidth = Fonts.SMALL.getWidth(optionDescription); UI.drawTooltip(g);
Color.black.a = 0.7f;
g.setColor(Color.black);
g.fillRoundRect(mouseX + 10, mouseY + 10, 10 + textWidth, 10 + Fonts.SMALL.getLineHeight(), 4);
Fonts.SMALL.drawString(mouseX + 15, mouseY + 15, optionDescription, Color.white);
Color.black.a = 1f;
} }
} }
@ -322,10 +327,10 @@ public class OptionsOverlay {
Fonts.MEDIUM.drawString(optionStartX + optionWidth - valueLen, y, value, Colors.BLUE_BACKGROUND); Fonts.MEDIUM.drawString(optionStartX + optionWidth - valueLen, y, value, Colors.BLUE_BACKGROUND);
} }
public void renderTabs(int mouseX, int mouseY) { public void renderTabs() {
for (int i = 0; i < tabs.length; i++) { for (int i = 0; i < tabs.length; i++) {
OptionTab tab = tabs[i]; OptionTab tab = tabs[i];
boolean hovering = tab.button.contains(mouseX, mouseY); boolean hovering = tab.button.contains(displayContainer.mouseX, displayContainer.mouseY);
UI.drawTab(tab.button.getX(), tab.button.getY(), tab.name, i == selectedTab, hovering); UI.drawTab(tab.button.getX(), tab.button.getY(), tab.name, i == selectedTab, hovering);
} }
} }
@ -339,7 +344,25 @@ public class OptionsOverlay {
Fonts.DEFAULT.drawString(marginX, marginY, "Change the way opsu! behaves", Color.white); Fonts.DEFAULT.drawString(marginX, marginY, "Change the way opsu! behaves", Color.white);
} }
public void update(int delta, int mouseX, int mouseY) { @Override
public void hide() {
acceptInput = false;
SoundController.playSound(SoundEffect.MENUBACK);
active = false;
}
@Override
public void show() {
acceptInput = true;
active = true;
}
@Override
public void onPreRenderUpdate() {
int mouseX = displayContainer.mouseX;
int mouseY = displayContainer.mouseY;
int delta = displayContainer.renderDelta;
if (sliderSoundDelay > 0) { if (sliderSoundDelay > 0) {
sliderSoundDelay -= delta; sliderSoundDelay -= delta;
} }
@ -352,7 +375,7 @@ public class OptionsOverlay {
UI.getBackButton().hoverUpdate(delta, mouseX, mouseY); UI.getBackButton().hoverUpdate(delta, mouseX, mouseY);
if (isAdjustingSlider) { if (isAdjustingSlider) {
int sliderValue = hoverOption.getIntegerValue(); int sliderValue = hoverOption.getIntegerValue();
updateSliderOption(mouseX, mouseY); updateSliderOption();
if (hoverOption.getIntegerValue() - sliderValue != 0 && sliderSoundDelay <= 0) { if (hoverOption.getIntegerValue() - sliderValue != 0 && sliderSoundDelay <= 0) {
sliderSoundDelay = 90; sliderSoundDelay = 90;
SoundController.playSound(SoundEffect.MENUHIT); SoundController.playSound(SoundEffect.MENUHIT);
@ -366,22 +389,23 @@ public class OptionsOverlay {
} }
} }
public void mousePressed(int button, int x, int y) { @Override
public boolean onMousePressed(int button, int x, int y) {
if (keyEntryLeft || keyEntryRight) { if (keyEntryLeft || keyEntryRight) {
keyEntryLeft = keyEntryRight = false; keyEntryLeft = keyEntryRight = false;
return; return true;
} }
if (isListOptionOpen) { if (isListOptionOpen) {
if (y > optionStartY && listStartX <= x && x < listStartX + listWidth && listStartY <= y && y < listStartY + listHeight) { if (y > optionStartY && listStartX <= x && x < listStartX + listWidth && listStartY <= y && y < listStartY + listHeight) {
hoverOption.clickListItem(listHoverIndex); hoverOption.clickListItem(listHoverIndex);
parent.onSaveOption(hoverOption); // TODO d parent.onSaveOption(hoverOption);
SoundController.playSound(SoundEffect.MENUCLICK); SoundController.playSound(SoundEffect.MENUCLICK);
} }
isListOptionOpen = false; isListOptionOpen = false;
listHoverIndex = -1; listHoverIndex = -1;
updateHoverOption(x, y); updateHoverOption(x, y);
return; return true;
} }
mousePressY = y; mousePressY = y;
@ -393,35 +417,37 @@ public class OptionsOverlay {
} else if (hoverOption.getType() == OptionType.NUMERIC) { } else if (hoverOption.getType() == OptionType.NUMERIC) {
isAdjustingSlider = sliderOptionStartX <= x && x < sliderOptionStartX + sliderOptionLength; isAdjustingSlider = sliderOptionStartX <= x && x < sliderOptionStartX + sliderOptionLength;
if (isAdjustingSlider) { if (isAdjustingSlider) {
updateSliderOption(x, y); updateSliderOption();
} }
} }
} }
if (UI.getBackButton().contains(x, y)) { if (UI.getBackButton().contains(x, y)) {
parent.onLeave(); hide();
} }
return true;
} }
public void mouseReleased(int button, int x, int y) { @Override
public boolean onMouseReleased(int button, int x, int y) {
selectedOption = null; selectedOption = null;
if (isAdjustingSlider) { if (isAdjustingSlider) {
parent.onSaveOption(hoverOption); // TODO d parent.onSaveOption(hoverOption);
} }
isAdjustingSlider = false; isAdjustingSlider = false;
sliderOptionLength = 0; sliderOptionLength = 0;
// check if clicked, not dragged // check if clicked, not dragged
if (Math.abs(y - mousePressY) >= 5) { if (Math.abs(y - mousePressY) >= 5) {
return; return true;
} }
if (hoverOption != null) { if (hoverOption != null) {
if (hoverOption.getType() == OptionType.BOOLEAN) { if (hoverOption.getType() == OptionType.BOOLEAN) {
hoverOption.click(container); hoverOption.click();
parent.onSaveOption(hoverOption); // TODO d parent.onSaveOption(hoverOption);
SoundController.playSound(SoundEffect.MENUHIT); SoundController.playSound(SoundEffect.MENUHIT);
return; return true;
} else if (hoverOption == GameOption.KEY_LEFT) { } else if (hoverOption == GameOption.KEY_LEFT) {
keyEntryLeft = true; keyEntryLeft = true;
} else if (hoverOption == GameOption.KEY_RIGHT) { } else if (hoverOption == GameOption.KEY_RIGHT) {
@ -435,27 +461,33 @@ public class OptionsOverlay {
if (tab.button.contains(x, y)) { if (tab.button.contains(x, y)) {
scrollOffset = tScrollOffset; scrollOffset = tScrollOffset;
SoundController.playSound(SoundEffect.MENUCLICK); SoundController.playSound(SoundEffect.MENUCLICK);
return; return true;
} }
tScrollOffset += Fonts.MEDIUM.getLineHeight() * 2; tScrollOffset += Fonts.MEDIUM.getLineHeight() * 2;
tScrollOffset += tab.options.length * optionHeight; tScrollOffset += tab.options.length * optionHeight;
} }
return true;
} }
public void mouseDragged(int oldx, int oldy, int newx, int newy) { @Override
public boolean onMouseDragged(int oldx, int oldy, int newx, int newy) {
if (!isAdjustingSlider) { if (!isAdjustingSlider) {
scrollOffset = Utils.clamp(scrollOffset + oldy - newy, 0, maxScrollOffset); scrollOffset = Utils.clamp(scrollOffset + oldy - newy, 0, maxScrollOffset);
} }
return true;
} }
public void mouseWheelMoved(int delta) { @Override
public boolean onMouseWheelMoved(int delta) {
if (!isAdjustingSlider) { if (!isAdjustingSlider) {
scrollOffset = Utils.clamp(scrollOffset - delta, 0, maxScrollOffset); scrollOffset = Utils.clamp(scrollOffset - delta, 0, maxScrollOffset);
} }
updateHoverOption(prevMouseX, prevMouseY); updateHoverOption(prevMouseX, prevMouseY);
return true;
} }
public boolean keyPressed(int key, char c) { @Override
public boolean onKeyPressed(int key, char c) {
if (keyEntryRight) { if (keyEntryRight) {
Options.setGameKeyRight(key); Options.setGameKeyRight(key);
keyEntryRight = false; keyEntryRight = false;
@ -475,16 +507,21 @@ public class OptionsOverlay {
listHoverIndex = -1; listHoverIndex = -1;
return true; return true;
} }
parent.onLeave(); hide();
return true; return true;
} }
return false; return false;
} }
private void updateSliderOption(int mouseX, int mouseY) { @Override
public boolean onKeyReleased(int key, char c) {
return false;
}
private void updateSliderOption() {
int min = hoverOption.getMinValue(); int min = hoverOption.getMinValue();
int max = hoverOption.getMaxValue(); int max = hoverOption.getMaxValue();
int value = min + Math.round((float) (max - min) * (mouseX - sliderOptionStartX) / (sliderOptionLength)); int value = min + Math.round((float) (max - min) * (displayContainer.mouseX - sliderOptionStartX) / (sliderOptionLength));
hoverOption.setValue(Utils.clamp(value, min, max)); hoverOption.setValue(Utils.clamp(value, min, max));
} }
@ -536,7 +573,6 @@ public class OptionsOverlay {
public interface Parent { public interface Parent {
void onLeave(); void onLeave();
void onSaveOption(GameOption option); void onSaveOption(GameOption option);
} }

View File

@ -112,7 +112,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
private final Game game; private final Game game;
private final MoveStoryboard msb; private final MoveStoryboard msb;
private final OptionsOverlay overlay; private OptionsOverlay overlay;
static { static {
for (OptionTab tab : options) { for (OptionTab tab : options) {
@ -124,7 +124,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
this.game = game; this.game = game;
this.msb = msb; this.msb = msb;
initialOptions = new HashMap<>(); initialOptions = new HashMap<>();
overlay = new OptionsOverlay(this, options, 2, container); //overlay = new OptionsOverlay(this, options, 2, container);
this.width = container.getWidth(); this.width = container.getWidth();
this.height = container.getHeight(); this.height = container.getHeight();
speed = 10; speed = 10;
@ -160,13 +160,13 @@ public class SBOverlay implements OptionsOverlay.Parent {
g.fillRect(curtime * width, height - 10f, 10f, 10f); g.fillRect(curtime * width, height - 10f, 10f, 10f);
} }
if (menu) { if (menu) {
overlay.render(g, container.getInput().getMouseX(), container.getInput().getMouseY()); //overlay.render(g, container.getInput().getMouseX(), container.getInput().getMouseY());
} }
} }
public void update(int delta, int mouseX, int mouseY) { public void update(int delta, int mouseX, int mouseY) {
if (Options.isEnableSB() && menu) { if (Options.isEnableSB() && menu) {
overlay.update(delta, mouseX, mouseY); //overlay.update(delta, mouseX, mouseY);
} }
msb.update(delta, mouseX, mouseY); msb.update(delta, mouseX, mouseY);
} }