diff --git a/src/itdelatrisu/opsu/states/OptionsMenu.java b/src/itdelatrisu/opsu/states/OptionsMenu.java index f4810c4c..8c02d96c 100644 --- a/src/itdelatrisu/opsu/states/OptionsMenu.java +++ b/src/itdelatrisu/opsu/states/OptionsMenu.java @@ -22,39 +22,32 @@ import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.Opsu; import itdelatrisu.opsu.Options; import itdelatrisu.opsu.Options.GameOption; -import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.audio.MusicController; import itdelatrisu.opsu.audio.SoundController; import itdelatrisu.opsu.audio.SoundEffect; -import itdelatrisu.opsu.ui.Colors; -import itdelatrisu.opsu.ui.Fonts; -import itdelatrisu.opsu.ui.MenuButton; import itdelatrisu.opsu.ui.UI; -import java.util.*; - -import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; -import org.newdawn.slick.Image; 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.ItemList; -import yugecin.opsudance.ui.RWM; +import yugecin.opsudance.ui.OptionsOverlay; +import yugecin.opsudance.ui.OptionsOverlay.OptionTab; /** * "Game Options" state. *
* Players are able to view and change various game settings in this state.
*/
-public class OptionsMenu extends BasicGameState {
+public class OptionsMenu extends BasicGameState implements OptionsOverlay.Parent {
+
/** Option tabs. */
- private enum OptionTab {
- DISPLAY ("Display", new GameOption[] {
+ private static final OptionTab[] options = new OptionsOverlay.OptionTab[]{
+ new OptionTab("Display", new GameOption[]{
GameOption.SCREEN_RESOLUTION,
GameOption.FULLSCREEN,
GameOption.ALLOW_LARGER_RESOLUTIONS,
@@ -67,7 +60,7 @@ public class OptionsMenu extends BasicGameState {
GameOption.LOAD_HD_IMAGES,
GameOption.LOAD_VERBOSE
}),
- MUSIC ("Music", new GameOption[] {
+ new OptionTab("Music", new GameOption[] {
GameOption.MASTER_VOLUME,
GameOption.MUSIC_VOLUME,
GameOption.EFFECT_VOLUME,
@@ -77,7 +70,7 @@ public class OptionsMenu extends BasicGameState {
GameOption.DISABLE_SOUNDS,
GameOption.ENABLE_THEME_SONG
}),
- GAMEPLAY ("Gameplay", new GameOption[] {
+ new OptionTab("Gameplay", new GameOption[] {
GameOption.BACKGROUND_DIM,
GameOption.FORCE_DEFAULT_PLAYFIELD,
GameOption.IGNORE_BEATMAP_SKINS,
@@ -94,7 +87,7 @@ public class OptionsMenu extends BasicGameState {
GameOption.MAP_END_DELAY,
GameOption.EPILEPSY_WARNING,
}),
- INPUT ("Input", new GameOption[] {
+ new OptionTab("Input", new GameOption[] {
GameOption.KEY_LEFT,
GameOption.KEY_RIGHT,
GameOption.DISABLE_MOUSE_WHEEL,
@@ -103,7 +96,7 @@ public class OptionsMenu extends BasicGameState {
GameOption.NEW_CURSOR,
GameOption.DISABLE_CURSOR
}),
- CUSTOM ("Custom", new GameOption[] {
+ new OptionTab("Custom", new GameOption[] {
GameOption.FIXED_CS,
GameOption.FIXED_HP,
GameOption.FIXED_AR,
@@ -113,7 +106,7 @@ public class OptionsMenu extends BasicGameState {
GameOption.DISABLE_UPDATER,
GameOption.ENABLE_WATCH_SERVICE
}),
- DANCE ("Dance", new GameOption[] {
+ new OptionTab("Dance", new GameOption[] {
GameOption.DANCE_MOVER,
GameOption.DANCE_QUAD_BEZ_AGGRESSIVENESS,
GameOption.DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR,
@@ -130,7 +123,7 @@ public class OptionsMenu extends BasicGameState {
GameOption.DANCE_CIRLCE_IN_LAZY_SLIDERS,
GameOption.DANCE_MIRROR,
}),
- DANCEDISP ("Dance display", new GameOption[] {
+ new OptionTab("Dance display", new GameOption[] {
GameOption.DANCE_DRAW_APPROACH,
GameOption.DANCE_OBJECT_COLOR_OVERRIDE,
GameOption.DANCE_OBJECT_COLOR_OVERRIDE_MIRRORED,
@@ -146,94 +139,31 @@ public class OptionsMenu extends BasicGameState {
GameOption.DANCE_ENABLE_SB,
GameOption.DANCE_HIDE_WATERMARK,
}),
- PIPPI ("Pippi", new GameOption[] {
+ new OptionTab ("Pippi", new GameOption[] {
GameOption.PIPPI_ENABLE,
GameOption.PIPPI_RADIUS_PERCENT,
GameOption.PIPPI_ANGLE_INC_MUL,
GameOption.PIPPI_ANGLE_INC_MUL_SLIDER,
GameOption.PIPPI_SLIDER_FOLLOW_EXPAND,
GameOption.PIPPI_PREVENT_WOBBLY_STREAMS,
- });
+ })
+ };
- /** Total number of tabs. */
- public static final int SIZE = values().length;
-
- /** Array of OptionTab objects in reverse order. */
- public static final OptionTab[] VALUES_REVERSED;
- static {
- VALUES_REVERSED = values();
- Collections.reverse(Arrays.asList(VALUES_REVERSED));
- }
-
- /** Enum values. */
- private static OptionTab[] values = values();
-
- /** Tab name. */
- private final String name;
-
- /** Options array. */
- public final GameOption[] options;
-
- /** Associated tab button. */
- public MenuButton button;
-
- /**
- * Constructor.
- * @param name the tab name
- * @param options the options to display under the tab
- */
- OptionTab(String name, GameOption[] options) {
- this.name = name;
- this.options = options;
- }
-
- /**
- * Returns the tab name.
- */
- public String getName() { return name; }
-
- /**
- * Returns the next tab.
- */
- public OptionTab next() { return values[(this.ordinal() + 1) % values.length]; }
-
- /**
- * Returns the previous tab.
- */
- public OptionTab prev() { return values[(this.ordinal() + (SIZE - 1)) % values.length]; }
- }
-
- /** Current tab. */
- private OptionTab currentTab;
-
- /** Key entry states. */
- private boolean keyEntryLeft = false, keyEntryRight = false;
-
- /** Game option coordinate modifiers (for drawing). */
- private int textY, offsetY;
-
- // game-related variables
private GameContainer container;
private StateBasedGame game;
private Input input;
private Graphics g;
private final int state;
- private GameOption selectedOption;
- private final ItemList list;
- private final RWM rwm;
+ private OptionsOverlay optionsOverlay;
public OptionsMenu(int state) {
this.state = state;
- list = new ItemList();
- rwm = new RWM();
}
@Override
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
- list.init(container);
- rwm.init(container);
this.container = container;
this.game = game;
@@ -243,319 +173,53 @@ public class OptionsMenu extends BasicGameState {
int width = container.getWidth();
int height = container.getHeight();
- // option tabs
- Image tabImage = GameImage.MENU_TAB.getImage();
- float tabX = width * 0.032f + (tabImage.getWidth() / 3);
- float tabY = Fonts.XLARGE.getLineHeight() + Fonts.DEFAULT.getLineHeight() +
- height * 0.015f - (tabImage.getHeight() / 2f);
- int tabOffset = Math.min(tabImage.getWidth(), width / OptionTab.SIZE);
- for (OptionTab tab : OptionTab.values())
- tab.button = new MenuButton(tabImage, tabX + (tab.ordinal() * tabOffset), tabY);
-
- // game option coordinate modifiers
- textY = (int) (tabY + tabImage.getHeight());
- //int backHeight = GameImage.MENU_BACK.getAnimation(1).getHeight();
- offsetY = (int) ((Fonts.MEDIUM.getLineHeight()) * 1.1f);
+ optionsOverlay = new OptionsOverlay(this, options, 5, width, height);
}
@Override
- public void render(GameContainer container, StateBasedGame game, Graphics g)
- throws SlickException {
- int width = container.getWidth();
- int height = container.getHeight();
- int mouseX = input.getMouseX(), mouseY = input.getMouseY();
-
+ public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
// background
GameImage.OPTIONS_BG.getImage().draw();
- // title
- float marginX = width * 0.015f, marginY = height * 0.01f;
- Fonts.XLARGE.drawString(marginX, marginY, "Options", Color.white);
- Fonts.DEFAULT.drawString(marginX + Fonts.XLARGE.getWidth("Options") * 1.2f, marginY + Fonts.XLARGE.getLineHeight() * 0.9f - Fonts.DEFAULT.getLineHeight(),
- "Change the way opsu! behaves", Color.white);
-
- // game options
- g.setLineWidth(1f);
- GameOption hoverOption = (keyEntryLeft) ? GameOption.KEY_LEFT :
- (keyEntryRight) ? GameOption.KEY_RIGHT :
- getOptionAt(mouseY);
- if (selectedOption != null) {
- hoverOption = selectedOption;
- }
- for (int i = 0, j = 0; i < currentTab.options.length; i++) {
- GameOption option = currentTab.options[i];
- if (!option.showCondition()) {
- continue;
- }
- drawOption(option, j++, hoverOption == option);
- }
-
- // option tabs
- OptionTab hoverTab = null;
- for (OptionTab tab : OptionTab.values()) {
- if (tab.button.contains(mouseX, mouseY)) {
- hoverTab = tab;
- break;
- }
- }
- for (OptionTab tab : OptionTab.VALUES_REVERSED) {
- if (tab != currentTab)
- UI.drawTab(tab.button.getX(), tab.button.getY(),
- tab.getName(), false, tab == hoverTab && !list.isVisible());
- }
- UI.drawTab(currentTab.button.getX(), currentTab.button.getY(),
- currentTab.getName(), true, false);
- g.setColor(Color.white);
- g.setLineWidth(2f);
- float lineY = OptionTab.DISPLAY.button.getY() + (GameImage.MENU_TAB.getImage().getHeight() / 2f);
- g.drawLine(0, lineY, width, lineY);
- g.resetLineWidth();
-
- if (list.isVisible()) {
- list.render(container, game, g);
- }
- if (rwm.isVisible()) {
- rwm.render(container, game, g);
- }
-
- UI.getBackButton().draw();
-
- // key entry state
- if (keyEntryLeft || keyEntryRight) {
- g.setColor(Colors.BLACK_ALPHA);
- g.fillRect(0, 0, width, height);
- g.setColor(Color.white);
- String prompt = (keyEntryLeft) ?
- "Please press the new left-click key." :
- "Please press the new right-click key.";
- Fonts.LARGE.drawString(
- (width / 2) - (Fonts.LARGE.getWidth(prompt) / 2),
- (height / 2) - Fonts.LARGE.getLineHeight(), prompt
- );
- }
-
- UI.draw(g);
-
- // current hovering option
- if (hoverOption != null && !list.isVisible() && !rwm.isVisible()) {
- String optionDescription = hoverOption.getDescription();
- float textWidth = Fonts.SMALL.getWidth(optionDescription);
- Color.black.a = 0.7f;
- g.setColor(Color.black);
- g.fillRect(mouseX + 10, mouseY + 10, 10 + textWidth, 10 + Fonts.SMALL.getLineHeight());
- Fonts.SMALL.drawString(mouseX + 15, mouseY + 15, optionDescription, Color.white);
- Color.black.a = 1f;
- }
+ int mouseX = input.getMouseX(), mouseY = input.getMouseY();
+ optionsOverlay.render(g, mouseX, mouseY);
}
@Override
- public void update(GameContainer container, StateBasedGame game, int delta)
- throws SlickException {
- rwm.update(delta);
+ public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
UI.update(delta);
MusicController.loopTrackIfEnded(false);
- int mouseX = input.getMouseX(), mouseY = input.getMouseY();
- UI.getBackButton().hoverUpdate(delta, mouseX, mouseY);
+ optionsOverlay.update(delta, input.getMouseX(), input.getMouseY());
}
@Override
- public int getID() { return state; }
+ public int getID() {
+ return state;
+ }
@Override
public void mouseReleased(int button, int x, int y) {
- selectedOption = null;
- if (list.isVisible()) {
- list.mouseReleased(button, x, y);
- }
- if (rwm.isVisible()) {
- rwm.mouseReleased(button, x, y);
- }
+ optionsOverlay.mouseReleased(button, x, y);
}
@Override
public void mousePressed(int button, int x, int y) {
- if (list.isVisible()) {
- list.mousePressed(button, x, y);
- return;
- }
- if (rwm.isVisible()) {
- return;
- }
-
- // key entry state
- if (keyEntryLeft || keyEntryRight) {
- keyEntryLeft = keyEntryRight = false;
- return;
- }
-
- // check mouse button
- if (button == Input.MOUSE_MIDDLE_BUTTON)
- return;
-
- // back
- if (UI.getBackButton().contains(x, y)) {
- SoundController.playSound(SoundEffect.MENUBACK);
- game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
- return;
- }
-
- // option tabs
- for (OptionTab tab : OptionTab.values()) {
- if (tab.button.contains(x, y)) {
- if (tab != currentTab) {
- currentTab = tab;
- SoundController.playSound(SoundEffect.MENUCLICK);
- }
- return;
- }
- }
-
- // options (click only)
- final GameOption option = getOptionAt(y);
- if (option != null) {
- selectedOption = option;
- Object[] listItems = option.getListItems();
- if (listItems == null) {
- if (option.showRWM()) {
- rwm.show();
- } else {
- option.click(container);
- }
- } else {
- list.setItems(listItems);
- list.setClickListener(new Observer() {
- @Override
- public void update(Observable o, Object arg) {
- option.clickListItem((int) arg);
- }
- });
- list.show();
- }
- }
-
- // special key entry states
- if (option == GameOption.KEY_LEFT) {
- keyEntryLeft = true;
- keyEntryRight = false;
- } else if (option == GameOption.KEY_RIGHT) {
- keyEntryLeft = false;
- keyEntryRight = true;
- }
-
- // ctrl+click to reset slider options
- if (selectedOption != null && selectedOption.isDragOption() && (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL))) {
- selectedOption.setValue(selectedOption.getDefaultVal() - 1);
- // trigger update
- selectedOption.drag(container, 1);
- }
+ optionsOverlay.mousePressed(button, x, y);
}
@Override
public void mouseDragged(int oldx, int oldy, int newx, int newy) {
- if (list.isVisible()) {
- list.mouseDragged(oldx, oldy, newx, newy);
- return;
- }
- if (rwm.isVisible()) {
- return;
- }
-
- // key entry state
- if (keyEntryLeft || keyEntryRight)
- return;
-
- if (selectedOption == null || !selectedOption.isDragOption()) {
- return;
- }
-
- // check control keys (reset to default value on ctrl+click)
- if (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL)) {
- selectedOption.setValue(selectedOption.getDefaultVal() - 1);
- // trigger update
- selectedOption.drag(container, 1);
- return;
- }
-
- // check mouse button (right click scrolls faster)
- int multiplier;
- if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
- multiplier = 4;
- else if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON))
- multiplier = 1;
- else
- return;
-
- // get direction
- int diff = newx - oldx;
- if (diff == 0)
- return;
- diff = ((diff > 0) ? 1 : -1) * multiplier;
-
- // options (drag only)
- selectedOption.drag(container, diff);
+ optionsOverlay.mouseDragged(oldx, oldy, newx, newy);
}
@Override
public void mouseWheelMoved(int newValue) {
- if (list.isVisible()) {
- list.mouseWheelMoved(newValue);
- }
- if (input.isKeyDown(Input.KEY_LALT) || input.isKeyDown(Input.KEY_RALT))
- UI.changeVolume((newValue < 0) ? -1 : 1);
+ optionsOverlay.mouseWheelMoved(newValue);
}
@Override
public void keyPressed(int key, char c) {
- if (list.isVisible()) {
- list.keyPressed(key, c);
- return;
- }
- if (rwm.isVisible()) {
- rwm.keyPressed(key, c);
- return;
- }
-
- // key entry state
- if (keyEntryLeft || keyEntryRight) {
- if (keyEntryLeft)
- Options.setGameKeyLeft(key);
- else
- Options.setGameKeyRight(key);
- keyEntryLeft = keyEntryRight = false;
- return;
- }
-
- switch (key) {
- case Input.KEY_ESCAPE:
- SoundController.playSound(SoundEffect.MENUBACK);
- game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
- break;
- case Input.KEY_F5:
- // restart application
- if ((input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) &&
- (input.isKeyDown(Input.KEY_RSHIFT) || input.isKeyDown(Input.KEY_LSHIFT))) {
- container.setForceExit(false);
- container.exit();
- }
- break;
- case Input.KEY_F7:
- Options.setNextFPS(container);
- break;
- case Input.KEY_F10:
- Options.toggleMouseDisabled();
- break;
- case Input.KEY_F12:
- Utils.takeScreenShot();
- break;
- case Input.KEY_TAB:
- // change tabs
- if (input.isKeyDown(Input.KEY_LSHIFT) || input.isKeyDown(Input.KEY_RSHIFT))
- currentTab = currentTab.prev();
- else
- currentTab = currentTab.next();
- SoundController.playSound(SoundEffect.MENUCLICK);
- break;
- }
+ optionsOverlay.keyPressed(key, c);
}
/**
@@ -569,7 +233,6 @@ public class OptionsMenu extends BasicGameState {
public void enter(GameContainer container, StateBasedGame game)
throws SlickException {
UI.enter();
- currentTab = OptionTab.DANCE;
restartOptions = "" + Options.getResolutionIdx() + Options.isFullscreen() + Options.allowLargeResolutions() + Options.getSkinName();
}
@@ -578,56 +241,19 @@ public class OptionsMenu extends BasicGameState {
if (!("" + Options.getResolutionIdx() + Options.isFullscreen() + Options.allowLargeResolutions() + Options.getSkinName()).equals(restartOptions)) {
container.setForceExit(false);
container.exit();
+ return;
}
+ SoundController.playSound(SoundEffect.MENUBACK);
}
- /**
- * Draws a game option.
- * @param option the option
- * @param pos the position to draw at
- * @param focus whether the option is currently focused
- */
- private void drawOption(GameOption option, int pos, boolean focus) {
- int width = container.getWidth();
- int textHeight = Fonts.MEDIUM.getLineHeight();
- float y = textY + (pos * offsetY);
- Color color = (focus) ? Color.cyan : Color.white;
-
- Fonts.MEDIUM.drawString(width / 30, y, option.getName(), color);
- Fonts.MEDIUM.drawString(width / 2, y, option.getValueString(), color);
- g.setColor(Colors.WHITE_ALPHA);
- if (option.isDragOption()) {
- float availableWidth = width / 2 - width / 30;
- g.fillRect(width / 2, y + textHeight, 20, 10);
- g.fillRect(width / 2 + availableWidth - 20, y + textHeight, 20, 10);
- availableWidth -= 40 + 100;
- float optionPercent = (float) (option.getIntegerValue() - option.getMinValue()) / (option.getMaxValue() - option.getMinValue());
- g.fillRect(width / 2 + 20 + optionPercent * availableWidth, y + textHeight, 100, 10);
- }
- g.drawLine(0, y + textHeight, width, y + textHeight);
+ @Override
+ public void onLeave() {
+ game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
}
- /**
- * Returns the option at the given y coordinate.
- * @param y the y coordinate
- * @return the option, or GameOption.NULL if no such option exists
- */
- private GameOption getOptionAt(int y) {
- if (y < textY)
- return null;
+ @Override
+ public void onSaveOption(GameOption option) {
- int index = (y - textY) / offsetY;
- if (index >= currentTab.options.length)
- return null;
-
- for (GameOption option : currentTab.options) {
- if (option.showCondition()) {
- index--;
- }
- if (index < 0) {
- return option;
- }
- }
- return null;
}
+
}
diff --git a/src/itdelatrisu/opsu/ui/Colors.java b/src/itdelatrisu/opsu/ui/Colors.java
index 7f00603a..c43d0893 100644
--- a/src/itdelatrisu/opsu/ui/Colors.java
+++ b/src/itdelatrisu/opsu/ui/Colors.java
@@ -26,6 +26,7 @@ import org.newdawn.slick.Color;
public class Colors {
public static final Color
BLACK_ALPHA = new Color(0, 0, 0, 0.5f),
+ BLACK_ALPHA_75 = new Color(0, 0, 0, 0.75f),
WHITE_ALPHA = new Color(255, 255, 255, 0.5f),
BLUE_DIVIDER = new Color(49, 94, 237),
BLUE_BACKGROUND = new Color(74, 130, 255),
diff --git a/src/yugecin/opsudance/ui/OptionsOverlay.java b/src/yugecin/opsudance/ui/OptionsOverlay.java
new file mode 100644
index 00000000..81c711a0
--- /dev/null
+++ b/src/yugecin/opsudance/ui/OptionsOverlay.java
@@ -0,0 +1,243 @@
+/*
+ * opsu!dance - fork of opsu! with cursordance auto
+ * Copyright (C) 2016 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