Merge remote-tracking branch 'orgin/master' into omaster
Conflicts: src/itdelatrisu/opsu/GameImage.java src/itdelatrisu/opsu/OsuGroupNode.java
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
package itdelatrisu.opsu.states;
|
||||
|
||||
import itdelatrisu.opsu.GameImage;
|
||||
import itdelatrisu.opsu.GameMod;
|
||||
import itdelatrisu.opsu.MenuButton;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.OsuGroupList;
|
||||
@@ -121,6 +122,95 @@ public class ButtonMenu extends BasicGameState {
|
||||
public void leave(GameContainer container, StateBasedGame game) {
|
||||
Button.CLOSE.click(container, game);
|
||||
}
|
||||
},
|
||||
MODS (new Button[] { Button.RESET_MODS, Button.CLOSE }) {
|
||||
@Override
|
||||
public String[] getTitle(GameContainer container, StateBasedGame game) {
|
||||
return new String[] {
|
||||
"Mods provide different ways to enjoy gameplay. Some have an effect on the score you can achieve during ranked play. Others are just for fun."
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBaseY(GameContainer container, StateBasedGame game) {
|
||||
return container.getHeight() * 2f / 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enter(GameContainer container, StateBasedGame game) {
|
||||
super.enter(container, game);
|
||||
for (GameMod mod : GameMod.values())
|
||||
mod.resetHover();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leave(GameContainer container, StateBasedGame game) {
|
||||
Button.CLOSE.click(container, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(GameContainer container, StateBasedGame game, Graphics g) {
|
||||
super.draw(container, game, g);
|
||||
|
||||
int width = container.getWidth();
|
||||
int height = container.getHeight();
|
||||
|
||||
// score multiplier (TODO: fade in color changes)
|
||||
float mult = GameMod.getScoreMultiplier();
|
||||
String multString = String.format("Score Multiplier: %.2fx", mult);
|
||||
Color multColor = (mult == 1f) ? Color.white : (mult > 1f) ? Color.green : Color.red;
|
||||
float multY = Utils.FONT_LARGE.getLineHeight() * 2 + height * 0.06f;
|
||||
Utils.FONT_LARGE.drawString(
|
||||
(width - Utils.FONT_LARGE.getWidth(multString)) / 2f,
|
||||
multY, multString, multColor);
|
||||
|
||||
// category text
|
||||
for (GameMod.Category category : GameMod.Category.values()) {
|
||||
Utils.FONT_LARGE.drawString(category.getX(),
|
||||
category.getY() - Utils.FONT_LARGE.getLineHeight() / 2f,
|
||||
category.getName(), category.getColor());
|
||||
}
|
||||
|
||||
// buttons (TODO: draw descriptions when hovering)
|
||||
for (GameMod mod : GameMod.values())
|
||||
mod.draw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(GameContainer container, int delta, int mouseX, int mouseY) {
|
||||
super.update(container, delta, mouseX, mouseY);
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
if (mod.isActive())
|
||||
mod.hoverUpdate(delta, mod.getButtonX(), mod.getButtonY());
|
||||
else
|
||||
mod.hoverUpdate(delta, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPress(GameContainer container, StateBasedGame game, int key, char c) {
|
||||
super.keyPress(container, game, key, c);
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
if (key == mod.getKey()) {
|
||||
mod.toggle(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(GameContainer container, StateBasedGame game, int cx, int cy) {
|
||||
super.click(container, game, cx, cy);
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
if (mod.contains(cx, cy)) {
|
||||
boolean prevState = mod.isActive();
|
||||
mod.toggle(true);
|
||||
if (mod.isActive() != prevState)
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** The buttons in the state. */
|
||||
@@ -153,23 +243,29 @@ public class ButtonMenu extends BasicGameState {
|
||||
*/
|
||||
public void init(GameContainer container, StateBasedGame game, Image button, Image buttonL, Image buttonR) {
|
||||
float center = container.getWidth() / 2f;
|
||||
float centerOffset = container.getWidth() * OFFSET_WIDTH_RATIO;
|
||||
float baseY = container.getHeight() * 0.2f;
|
||||
baseY += ((getTitle(container, game).length - 1) * Utils.FONT_LARGE.getLineHeight());
|
||||
float baseY = getBaseY(container, game);
|
||||
float offsetY = button.getHeight() * 1.25f;
|
||||
|
||||
menuButtons = new MenuButton[buttons.length];
|
||||
for (int i = 0; i < buttons.length; i++) {
|
||||
MenuButton b = new MenuButton(button, buttonL, buttonR,
|
||||
center + ((i % 2 == 0) ? centerOffset * -1 : centerOffset),
|
||||
baseY + (i * offsetY));
|
||||
b.setText(String.format("%d. %s", i + 1, buttons[i].getText()),
|
||||
Utils.FONT_XLARGE, Color.white);
|
||||
MenuButton b = new MenuButton(button, buttonL, buttonR, center, baseY + (i * offsetY));
|
||||
b.setText(String.format("%d. %s", i + 1, buttons[i].getText()), Utils.FONT_XLARGE, Color.white);
|
||||
b.setHoverFade();
|
||||
menuButtons[i] = b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base Y coordinate for the buttons.
|
||||
* @param container the game container
|
||||
* @param game the game
|
||||
*/
|
||||
protected float getBaseY(GameContainer container, StateBasedGame game) {
|
||||
float baseY = container.getHeight() * 0.2f;
|
||||
baseY += ((getTitle(container, game).length - 1) * Utils.FONT_LARGE.getLineHeight());
|
||||
return baseY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the title and buttons to the graphics context.
|
||||
* @param container the game container
|
||||
@@ -231,13 +327,14 @@ public class ButtonMenu extends BasicGameState {
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a key press action (numeric digits only).
|
||||
* Processes a key press action.
|
||||
* @param container the game container
|
||||
* @param game the game
|
||||
* @param digit the digit pressed
|
||||
* @param key the key code that was pressed (see {@link org.newdawn.slick.Input})
|
||||
* @param c the character of the key that was pressed
|
||||
*/
|
||||
public void keyPress(GameContainer container, StateBasedGame game, int digit) {
|
||||
int index = digit - 1;
|
||||
public void keyPress(GameContainer container, StateBasedGame game, int key, char c) {
|
||||
int index = Character.getNumericValue(c) - 1;
|
||||
if (index >= 0 && index < buttons.length)
|
||||
buttons[index].click(container, game);
|
||||
}
|
||||
@@ -384,6 +481,16 @@ public class ButtonMenu extends BasicGameState {
|
||||
public void click(GameContainer container, StateBasedGame game) {
|
||||
CANCEL.click(container, game);
|
||||
}
|
||||
},
|
||||
RESET_MODS ("Reset All Mods", Color.red) {
|
||||
@Override
|
||||
public void click(GameContainer container, StateBasedGame game) {
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
if (mod.isActive())
|
||||
mod.toggle(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** The text to show on the button. */
|
||||
@@ -500,7 +607,7 @@ public class ButtonMenu extends BasicGameState {
|
||||
break;
|
||||
default:
|
||||
if (menuState != null)
|
||||
menuState.keyPress(container, game, Character.getNumericValue(c));
|
||||
menuState.keyPress(container, game, key, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,6 +229,7 @@ public class DownloadsMenu extends BasicGameState {
|
||||
|
||||
// search
|
||||
g.setColor(Color.white);
|
||||
g.setLineWidth(2f);
|
||||
search.render(container, g);
|
||||
Utils.FONT_BOLD.drawString(
|
||||
search.getX() + search.getWidth() * 0.01f, search.getY() + search.getHeight() * 1.3f,
|
||||
|
||||
@@ -701,7 +701,7 @@ public class Game extends BasicGameState {
|
||||
resetGameData();
|
||||
|
||||
// needs to play before setting position to resume without lag later
|
||||
MusicController.play();
|
||||
MusicController.play(false);
|
||||
MusicController.setPosition(0);
|
||||
MusicController.pause();
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
package itdelatrisu.opsu.states;
|
||||
|
||||
import itdelatrisu.opsu.GameImage;
|
||||
import itdelatrisu.opsu.GameMod;
|
||||
import itdelatrisu.opsu.MenuButton;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.Options;
|
||||
@@ -171,10 +170,6 @@ public class OptionsMenu extends BasicGameState {
|
||||
int width = container.getWidth();
|
||||
int height = container.getHeight();
|
||||
|
||||
// game option coordinate modifiers
|
||||
textY = 20 + (Utils.FONT_XLARGE.getLineHeight() * 3 / 2);
|
||||
offsetY = (int) (((height * 0.8f) - textY) / maxOptionsScreen);
|
||||
|
||||
// option tabs
|
||||
Image tabImage = GameImage.MENU_TAB.getImage();
|
||||
int subtextWidth = Utils.FONT_DEFAULT.getWidth("Click or drag an option to change it.");
|
||||
@@ -184,6 +179,10 @@ public class OptionsMenu extends BasicGameState {
|
||||
(width/2) / 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());
|
||||
offsetY = (height - textY - GameImage.MENU_BACK.getImage().getHeight()) / maxOptionsScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,21 +231,6 @@ public class OptionsMenu extends BasicGameState {
|
||||
g.drawLine(0, lineY, width, lineY);
|
||||
g.resetLineWidth();
|
||||
|
||||
// game mods
|
||||
Utils.FONT_LARGE.drawString(width / 30, height * 0.8f, "Game Mods:", Color.white);
|
||||
boolean descDrawn = false;
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
mod.draw();
|
||||
if (!descDrawn && mod.contains(mouseX, mouseY)) {
|
||||
Utils.FONT_DEFAULT.drawString(
|
||||
(width - Utils.FONT_DEFAULT.getWidth(mod.getDescription())) / 2,
|
||||
height * 0.975f - Utils.FONT_DEFAULT.getLineHeight(),
|
||||
mod.getDescription(), Color.white
|
||||
);
|
||||
descDrawn = true;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.getBackButton().draw();
|
||||
|
||||
// key entry state
|
||||
@@ -272,8 +256,6 @@ public class OptionsMenu extends BasicGameState {
|
||||
Utils.updateVolumeDisplay(delta);
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
Utils.getBackButton().hoverUpdate(delta, mouseX, mouseY);
|
||||
for (GameMod mod : GameMod.values())
|
||||
mod.hoverUpdate(delta, mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -309,17 +291,6 @@ public class OptionsMenu extends BasicGameState {
|
||||
}
|
||||
}
|
||||
|
||||
// game mods
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
if (mod.contains(x, y)) {
|
||||
boolean prevState = mod.isActive();
|
||||
mod.toggle(true);
|
||||
if (mod.isActive() != prevState)
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// options (click only)
|
||||
GameOption option = getClickedOption(y);
|
||||
if (option != GameOption.NULL)
|
||||
@@ -400,15 +371,6 @@ public class OptionsMenu extends BasicGameState {
|
||||
currentTab = currentTab.next();
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
break;
|
||||
default:
|
||||
// check mod shortcut keys
|
||||
for (GameMod mod : GameMod.values()) {
|
||||
if (key == mod.getKey()) {
|
||||
mod.toggle(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,8 +379,6 @@ public class OptionsMenu extends BasicGameState {
|
||||
throws SlickException {
|
||||
currentTab = OptionTab.DISPLAY;
|
||||
Utils.getBackButton().resetHover();
|
||||
for (GameMod mod : GameMod.values())
|
||||
mod.resetHover();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,6 +83,12 @@ public class SongMenu extends BasicGameState {
|
||||
/** Maximum x offset of song buttons for mouse hover, in pixels. */
|
||||
private static final float MAX_HOVER_OFFSET = 30f;
|
||||
|
||||
/** Time, in milliseconds, for the search bar to fade in or out. */
|
||||
private static final int SEARCH_TRANSITION_TIME = 250;
|
||||
|
||||
/** Line width of the header/footer divider. */
|
||||
private static final int DIVIDER_LINE_WIDTH = 4;
|
||||
|
||||
/** Song node class representing an OsuGroupNode and file index. */
|
||||
private static class SongNode {
|
||||
/** Song node. */
|
||||
@@ -136,8 +142,8 @@ public class SongMenu extends BasicGameState {
|
||||
/** Current index of hovered song button. */
|
||||
private int hoverIndex = -1;
|
||||
|
||||
/** The options button (to enter the "Game Options" menu). */
|
||||
private MenuButton optionsButton;
|
||||
/** The selection buttons. */
|
||||
private MenuButton selectModsButton, selectRandomButton, selectMapOptionsButton, selectOptionsButton;
|
||||
|
||||
/** The search textfield. */
|
||||
private TextField search;
|
||||
@@ -146,10 +152,10 @@ public class SongMenu extends BasicGameState {
|
||||
* Delay timer, in milliseconds, before running another search.
|
||||
* This is overridden by character entry (reset) and 'esc' (immediate search).
|
||||
*/
|
||||
private int searchTimer;
|
||||
private int searchTimer = 0;
|
||||
|
||||
/** Information text to display based on the search query. */
|
||||
private String searchResultString;
|
||||
private String searchResultString = null;
|
||||
|
||||
/** Loader animation. */
|
||||
private Animation loader;
|
||||
@@ -184,6 +190,12 @@ public class SongMenu extends BasicGameState {
|
||||
/** Current start score (topmost score entry). */
|
||||
private int startScore = 0;
|
||||
|
||||
/** Header and footer end and start y coordinates, respectively. */
|
||||
private float headerY, footerY;
|
||||
|
||||
/** Time, in milliseconds, for fading the search bar. */
|
||||
private int searchTransitionTimer = SEARCH_TRANSITION_TIME;
|
||||
|
||||
// game-related variables
|
||||
private GameContainer container;
|
||||
private StateBasedGame game;
|
||||
@@ -204,26 +216,35 @@ public class SongMenu extends BasicGameState {
|
||||
int width = container.getWidth();
|
||||
int height = container.getHeight();
|
||||
|
||||
// header/footer coordinates
|
||||
headerY = height * 0.0075f + GameImage.MENU_MUSICNOTE.getImage().getHeight() +
|
||||
Utils.FONT_BOLD.getLineHeight() + Utils.FONT_DEFAULT.getLineHeight() +
|
||||
Utils.FONT_SMALL.getLineHeight();
|
||||
footerY = height - GameImage.SELECTION_MODS.getImage().getHeight();
|
||||
|
||||
// initialize sorts
|
||||
for (SongSort sort : SongSort.values())
|
||||
sort.init(width, headerY - SongMenu.DIVIDER_LINE_WIDTH / 2);
|
||||
|
||||
// initialize score data buttons
|
||||
ScoreData.init(width, headerY + height * 0.01f);
|
||||
|
||||
// song button background & graphics context
|
||||
Image menuBackground = GameImage.MENU_BUTTON_BG.getImage();
|
||||
|
||||
// song button coordinates
|
||||
buttonX = width * 0.6f;
|
||||
buttonY = height * 0.16f;
|
||||
buttonY = headerY;
|
||||
buttonWidth = menuBackground.getWidth();
|
||||
buttonHeight = menuBackground.getHeight();
|
||||
buttonOffset = (height * 0.8f) / MAX_SONG_BUTTONS;
|
||||
buttonOffset = (footerY - headerY - DIVIDER_LINE_WIDTH) / MAX_SONG_BUTTONS;
|
||||
|
||||
// search
|
||||
searchTimer = 0;
|
||||
searchResultString = "Type to search!";
|
||||
Image searchIcon = GameImage.MENU_SEARCH.getImage();
|
||||
Image tab = GameImage.MENU_TAB.getImage();
|
||||
int textFieldX = (int) (width * 0.7125f + Utils.FONT_BOLD.getWidth("Search: "));
|
||||
int textFieldY = (int) (headerY + Utils.FONT_BOLD.getLineHeight() / 2);
|
||||
search = new TextField(
|
||||
container, Utils.FONT_DEFAULT,
|
||||
(int) buttonX + (tab.getWidth() / 2) + searchIcon.getWidth(),
|
||||
(int) ((height * 0.15f) - (tab.getHeight() * 2.5f)),
|
||||
(int) (buttonWidth / 2), Utils.FONT_DEFAULT.getLineHeight()
|
||||
container, Utils.FONT_BOLD, textFieldX, textFieldY,
|
||||
(int) (width * 0.99f) - textFieldX, Utils.FONT_BOLD.getLineHeight()
|
||||
);
|
||||
search.setBackgroundColor(Color.transparent);
|
||||
search.setBorderColor(Color.transparent);
|
||||
@@ -231,10 +252,22 @@ public class SongMenu extends BasicGameState {
|
||||
search.setConsumeEvents(false);
|
||||
search.setMaxLength(60);
|
||||
|
||||
// options button
|
||||
Image optionsIcon = GameImage.MENU_OPTIONS.getImage();
|
||||
optionsButton = new MenuButton(optionsIcon, search.getX() - (optionsIcon.getWidth() * 1.5f), search.getY());
|
||||
optionsButton.setHoverExpand(1.75f);
|
||||
// selection buttons
|
||||
float selectX = GameImage.MENU_BACK.getImage().getWidth() * 1.75f;
|
||||
float selectY = height - GameImage.SELECTION_MODS.getImage().getHeight() / 2f;
|
||||
float selectOffset = GameImage.SELECTION_MODS.getImage().getWidth() * 1.05f;
|
||||
selectModsButton = new MenuButton(GameImage.SELECTION_MODS_OVERLAY.getImage(),
|
||||
selectX, selectY);
|
||||
selectRandomButton = new MenuButton(GameImage.SELECTION_RANDOM_OVERLAY.getImage(),
|
||||
selectX + selectOffset, selectY);
|
||||
selectMapOptionsButton = new MenuButton(GameImage.SELECTION_OPTIONS_OVERLAY.getImage(),
|
||||
selectX + selectOffset * 2f, selectY);
|
||||
selectOptionsButton = new MenuButton(GameImage.SELECTION_OTHER_OPTIONS_OVERLAY.getImage(),
|
||||
selectX + selectOffset * 3f, selectY);
|
||||
selectModsButton.setHoverFade(0f);
|
||||
selectRandomButton.setHoverFade(0f);
|
||||
selectMapOptionsButton.setHoverFade(0f);
|
||||
selectOptionsButton.setHoverFade(0f);
|
||||
|
||||
// loader
|
||||
int loaderDim = GameImage.MENU_MUSICNOTE.getImage().getWidth();
|
||||
@@ -258,19 +291,19 @@ public class SongMenu extends BasicGameState {
|
||||
GameImage.PLAYFIELD.getImage().draw();
|
||||
}
|
||||
|
||||
// header setup
|
||||
float lowerBound = height * 0.15f;
|
||||
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||
g.fillRect(0, 0, width, lowerBound);
|
||||
// top/bottom bars
|
||||
g.setColor(Color.black);
|
||||
g.fillRect(0, 0, width, headerY);
|
||||
g.fillRect(0, footerY, width, height - footerY);
|
||||
g.setColor(Utils.COLOR_BLUE_DIVIDER);
|
||||
g.setLineWidth(2f);
|
||||
g.drawLine(0, lowerBound, width, lowerBound);
|
||||
g.setLineWidth(DIVIDER_LINE_WIDTH);
|
||||
g.drawLine(0, headerY, width, headerY);
|
||||
g.drawLine(0, footerY - DIVIDER_LINE_WIDTH / 2, width, footerY - DIVIDER_LINE_WIDTH / 2);
|
||||
g.resetLineWidth();
|
||||
|
||||
// header
|
||||
if (focusNode != null) {
|
||||
float marginX = width * 0.005f, marginY = height * 0.005f;
|
||||
|
||||
Image musicNote = GameImage.MENU_MUSICNOTE.getImage();
|
||||
if (MusicController.isTrackLoading())
|
||||
loader.draw(marginX, marginY);
|
||||
@@ -282,14 +315,14 @@ public class SongMenu extends BasicGameState {
|
||||
if (songInfo == null)
|
||||
songInfo = focusNode.getInfo();
|
||||
marginX += 5;
|
||||
Utils.FONT_LARGE.drawString(marginX + iconWidth, marginY, songInfo[0], Color.white);
|
||||
Utils.FONT_DEFAULT.drawString(marginX + iconWidth, marginY + Utils.FONT_LARGE.getLineHeight() * 0.75f, songInfo[1], Color.white);
|
||||
float headerY = marginY + iconHeight;
|
||||
Utils.FONT_BOLD.drawString(marginX, headerY, songInfo[2], Color.white);
|
||||
headerY += Utils.FONT_BOLD.getLineHeight() - 6;
|
||||
Utils.FONT_DEFAULT.drawString(marginX, headerY, songInfo[3], Color.white);
|
||||
headerY += Utils.FONT_DEFAULT.getLineHeight() - 4;
|
||||
Utils.FONT_SMALL.drawString(marginX, headerY, songInfo[4], Color.white);
|
||||
Utils.FONT_LARGE.drawString(marginX + iconWidth * 1.05f, marginY, songInfo[0], Color.white);
|
||||
Utils.FONT_DEFAULT.drawString(marginX + iconWidth * 1.05f, marginY + Utils.FONT_LARGE.getLineHeight() * 0.75f, songInfo[1], Color.white);
|
||||
float headerTextY = marginY + iconHeight;
|
||||
Utils.FONT_BOLD.drawString(marginX, headerTextY, songInfo[2], Color.white);
|
||||
headerTextY += Utils.FONT_BOLD.getLineHeight() - 6;
|
||||
Utils.FONT_DEFAULT.drawString(marginX, headerTextY, songInfo[3], Color.white);
|
||||
headerTextY += Utils.FONT_DEFAULT.getLineHeight() - 4;
|
||||
Utils.FONT_SMALL.drawString(marginX, headerTextY, songInfo[4], Color.white);
|
||||
}
|
||||
|
||||
// song buttons
|
||||
@@ -300,6 +333,7 @@ public class SongMenu extends BasicGameState {
|
||||
ScoreData[] scores = getScoreDataForNode(node, false);
|
||||
node.draw(
|
||||
buttonX - offset, buttonY + (i*buttonOffset),
|
||||
headerY + DIVIDER_LINE_WIDTH / 2, footerY - DIVIDER_LINE_WIDTH,
|
||||
(scores == null) ? Grade.NULL : scores[0].getGrade(),
|
||||
(node == focusNode)
|
||||
);
|
||||
@@ -324,8 +358,15 @@ public class SongMenu extends BasicGameState {
|
||||
ScoreData.drawScrollbar(g, startScore, focusScores.length);
|
||||
}
|
||||
|
||||
// options button
|
||||
optionsButton.draw();
|
||||
// selection buttons
|
||||
GameImage.SELECTION_MODS.getImage().drawCentered(selectModsButton.getX(), selectModsButton.getY());
|
||||
selectModsButton.draw();
|
||||
GameImage.SELECTION_RANDOM.getImage().drawCentered(selectRandomButton.getX(), selectRandomButton.getY());
|
||||
selectRandomButton.draw();
|
||||
GameImage.SELECTION_OPTIONS.getImage().drawCentered(selectMapOptionsButton.getX(), selectMapOptionsButton.getY());
|
||||
selectMapOptionsButton.draw();
|
||||
GameImage.SELECTION_OTHER_OPTIONS.getImage().drawCentered(selectOptionsButton.getX(), selectOptionsButton.getY());
|
||||
selectOptionsButton.draw();
|
||||
|
||||
// sorting tabs
|
||||
SongSort currentSort = SongSort.getSort();
|
||||
@@ -343,15 +384,37 @@ public class SongMenu extends BasicGameState {
|
||||
currentSort.draw(true, false);
|
||||
|
||||
// search
|
||||
Image searchIcon = GameImage.MENU_SEARCH.getImage();
|
||||
Utils.FONT_BOLD.drawString(
|
||||
search.getX(), search.getY() - Utils.FONT_BOLD.getLineHeight(),
|
||||
searchResultString, Color.white
|
||||
);
|
||||
searchIcon.draw(search.getX() - searchIcon.getWidth(),
|
||||
search.getY() - Utils.FONT_DEFAULT.getLineHeight());
|
||||
g.setColor(Color.white);
|
||||
search.render(container, g);
|
||||
boolean searchEmpty = search.getText().isEmpty();
|
||||
int searchX = search.getX(), searchY = search.getY();
|
||||
float searchBaseX = width * 0.7f;
|
||||
float searchTextX = width * 0.7125f;
|
||||
float searchRectHeight = Utils.FONT_BOLD.getLineHeight() * 2;
|
||||
float searchExtraHeight = Utils.FONT_DEFAULT.getLineHeight() * 0.7f;
|
||||
float searchProgress = (searchTransitionTimer < SEARCH_TRANSITION_TIME) ?
|
||||
((float) searchTransitionTimer / SEARCH_TRANSITION_TIME) : 1f;
|
||||
float oldAlpha = Utils.COLOR_BLACK_ALPHA.a;
|
||||
if (searchEmpty) {
|
||||
searchRectHeight += (1f - searchProgress) * searchExtraHeight;
|
||||
Utils.COLOR_BLACK_ALPHA.a = 0.5f - searchProgress * 0.3f;
|
||||
} else {
|
||||
searchRectHeight += searchProgress * searchExtraHeight;
|
||||
Utils.COLOR_BLACK_ALPHA.a = 0.2f + searchProgress * 0.3f;
|
||||
}
|
||||
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||
g.fillRect(searchBaseX, headerY + DIVIDER_LINE_WIDTH / 2, width - searchBaseX, searchRectHeight);
|
||||
Utils.COLOR_BLACK_ALPHA.a = oldAlpha;
|
||||
Utils.FONT_BOLD.drawString(searchTextX, searchY, "Search:", Utils.COLOR_GREEN_SEARCH);
|
||||
if (searchEmpty)
|
||||
Utils.FONT_BOLD.drawString(searchX, searchY, "Type to search!", Color.white);
|
||||
else {
|
||||
g.setColor(Color.white);
|
||||
// TODO: why is this needed to correctly position the TextField?
|
||||
search.setLocation(searchX - 3, searchY - 1);
|
||||
search.render(container, g);
|
||||
search.setLocation(searchX, searchY);
|
||||
Utils.FONT_DEFAULT.drawString(searchTextX, searchY + Utils.FONT_BOLD.getLineHeight(),
|
||||
(searchResultString == null) ? "Searching..." : searchResultString, Color.white);
|
||||
}
|
||||
|
||||
// scroll bar
|
||||
if (focusNode != null) {
|
||||
@@ -364,7 +427,7 @@ public class SongMenu extends BasicGameState {
|
||||
else if (startNode.index == focusNode.index)
|
||||
startIndex += startNode.osuFileIndex;
|
||||
Utils.drawScrollbar(g, startIndex, totalNodes, MAX_SONG_BUTTONS,
|
||||
width, height * 0.16f, 0, buttonHeight, buttonOffset,
|
||||
width, headerY + DIVIDER_LINE_WIDTH / 2, 0, buttonOffset - DIVIDER_LINE_WIDTH * 1.5f, buttonOffset,
|
||||
Utils.COLOR_BLACK_ALPHA, Color.white, true);
|
||||
}
|
||||
}
|
||||
@@ -394,7 +457,10 @@ public class SongMenu extends BasicGameState {
|
||||
Utils.updateVolumeDisplay(delta);
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
Utils.getBackButton().hoverUpdate(delta, mouseX, mouseY);
|
||||
optionsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectModsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectRandomButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectMapOptionsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectOptionsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
|
||||
// beatmap menu timer
|
||||
if (beatmapMenuTimer > -1) {
|
||||
@@ -425,7 +491,7 @@ public class SongMenu extends BasicGameState {
|
||||
|
||||
// empty search
|
||||
if (search.getText().isEmpty())
|
||||
searchResultString = "Type to search!";
|
||||
searchResultString = null;
|
||||
|
||||
// search produced new list: re-initialize it
|
||||
startNode = focusNode = null;
|
||||
@@ -450,39 +516,45 @@ public class SongMenu extends BasicGameState {
|
||||
searchResultString = "No matches found. Hit 'esc' to reset.";
|
||||
}
|
||||
}
|
||||
if (searchTransitionTimer < SEARCH_TRANSITION_TIME) {
|
||||
searchTransitionTimer += delta;
|
||||
if (searchTransitionTimer > SEARCH_TRANSITION_TIME)
|
||||
searchTransitionTimer = SEARCH_TRANSITION_TIME;
|
||||
}
|
||||
|
||||
// slide buttons
|
||||
int height = container.getHeight();
|
||||
float targetY = height * 0.16f;
|
||||
if (buttonY > targetY) {
|
||||
if (buttonY > headerY) {
|
||||
buttonY -= height * delta / 20000f;
|
||||
if (buttonY < targetY)
|
||||
buttonY = targetY;
|
||||
} else if (buttonY < targetY) {
|
||||
if (buttonY < headerY)
|
||||
buttonY = headerY;
|
||||
} else if (buttonY < headerY) {
|
||||
buttonY += height * delta / 20000f;
|
||||
if (buttonY > targetY)
|
||||
buttonY = targetY;
|
||||
if (buttonY > headerY)
|
||||
buttonY = headerY;
|
||||
}
|
||||
|
||||
// mouse hover
|
||||
OsuGroupNode node = startNode;
|
||||
boolean isHover = false;
|
||||
for (int i = 0; i < MAX_SONG_BUTTONS && node != null; i++, node = node.next) {
|
||||
float cx = (node.index == OsuGroupList.get().getExpandedIndex()) ? buttonX * 0.9f : buttonX;
|
||||
if ((mouseX > cx && mouseX < cx + buttonWidth) &&
|
||||
(mouseY > buttonY + (i * buttonOffset) && mouseY < buttonY + (i * buttonOffset) + buttonHeight)) {
|
||||
if (i == hoverIndex) {
|
||||
if (hoverOffset < MAX_HOVER_OFFSET) {
|
||||
hoverOffset += delta / 3f;
|
||||
if (hoverOffset > MAX_HOVER_OFFSET)
|
||||
hoverOffset = MAX_HOVER_OFFSET;
|
||||
if (mouseY > headerY && mouseY < footerY) {
|
||||
OsuGroupNode node = startNode;
|
||||
for (int i = 0; i < MAX_SONG_BUTTONS && node != null; i++, node = node.next) {
|
||||
float cx = (node.index == OsuGroupList.get().getExpandedIndex()) ? buttonX * 0.9f : buttonX;
|
||||
if ((mouseX > cx && mouseX < cx + buttonWidth) &&
|
||||
(mouseY > buttonY + (i * buttonOffset) && mouseY < buttonY + (i * buttonOffset) + buttonHeight)) {
|
||||
if (i == hoverIndex) {
|
||||
if (hoverOffset < MAX_HOVER_OFFSET) {
|
||||
hoverOffset += delta / 3f;
|
||||
if (hoverOffset > MAX_HOVER_OFFSET)
|
||||
hoverOffset = MAX_HOVER_OFFSET;
|
||||
}
|
||||
} else {
|
||||
hoverIndex = i;
|
||||
hoverOffset = 0f;
|
||||
}
|
||||
} else {
|
||||
hoverIndex = i;
|
||||
hoverOffset = 0f;
|
||||
isHover = true;
|
||||
break;
|
||||
}
|
||||
isHover = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isHover) {
|
||||
@@ -512,8 +584,17 @@ public class SongMenu extends BasicGameState {
|
||||
return;
|
||||
}
|
||||
|
||||
// options
|
||||
if (optionsButton.contains(x, y)) {
|
||||
// selection buttons
|
||||
if (selectModsButton.contains(x, y)) {
|
||||
this.keyPressed(Input.KEY_F1, '\0');
|
||||
return;
|
||||
} else if (selectRandomButton.contains(x, y)) {
|
||||
this.keyPressed(Input.KEY_F2, '\0');
|
||||
return;
|
||||
} else if (selectMapOptionsButton.contains(x, y)) {
|
||||
this.keyPressed(Input.KEY_F3, '\0');
|
||||
return;
|
||||
} else if (selectOptionsButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
game.enterState(Opsu.STATE_OPTIONSMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||
return;
|
||||
@@ -539,46 +620,48 @@ public class SongMenu extends BasicGameState {
|
||||
}
|
||||
|
||||
// song buttons
|
||||
int expandedIndex = OsuGroupList.get().getExpandedIndex();
|
||||
OsuGroupNode node = startNode;
|
||||
for (int i = 0; i < MAX_SONG_BUTTONS && node != null; i++, node = node.next) {
|
||||
// is button at this index clicked?
|
||||
float cx = (node.index == expandedIndex) ? buttonX * 0.9f : buttonX;
|
||||
if ((x > cx && x < cx + buttonWidth) &&
|
||||
(y > buttonY + (i * buttonOffset) && y < buttonY + (i * buttonOffset) + buttonHeight)) {
|
||||
float oldHoverOffset = hoverOffset;
|
||||
int oldHoverIndex = hoverIndex;
|
||||
|
||||
// clicked node is already expanded
|
||||
if (node.index == expandedIndex) {
|
||||
if (node.osuFileIndex == focusNode.osuFileIndex) {
|
||||
// if already focused, load the beatmap
|
||||
if (button != Input.MOUSE_RIGHT_BUTTON)
|
||||
startGame();
|
||||
else
|
||||
if (y > headerY && y < footerY) {
|
||||
int expandedIndex = OsuGroupList.get().getExpandedIndex();
|
||||
OsuGroupNode node = startNode;
|
||||
for (int i = 0; i < MAX_SONG_BUTTONS && node != null; i++, node = node.next) {
|
||||
// is button at this index clicked?
|
||||
float cx = (node.index == expandedIndex) ? buttonX * 0.9f : buttonX;
|
||||
if ((x > cx && x < cx + buttonWidth) &&
|
||||
(y > buttonY + (i * buttonOffset) && y < buttonY + (i * buttonOffset) + buttonHeight)) {
|
||||
float oldHoverOffset = hoverOffset;
|
||||
int oldHoverIndex = hoverIndex;
|
||||
|
||||
// clicked node is already expanded
|
||||
if (node.index == expandedIndex) {
|
||||
if (node.osuFileIndex == focusNode.osuFileIndex) {
|
||||
// if already focused, load the beatmap
|
||||
if (button != Input.MOUSE_RIGHT_BUTTON)
|
||||
startGame();
|
||||
else
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
} else {
|
||||
// focus the node
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
} else {
|
||||
// focus the node
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
setFocus(node, 0, false);
|
||||
setFocus(node, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
// clicked node is a new group
|
||||
else {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
setFocus(node, -1, false);
|
||||
}
|
||||
|
||||
// restore hover data
|
||||
hoverOffset = oldHoverOffset;
|
||||
hoverIndex = oldHoverIndex;
|
||||
|
||||
// open beatmap menu
|
||||
if (button == Input.MOUSE_RIGHT_BUTTON)
|
||||
beatmapMenuTimer = (node.index == expandedIndex) ? BEATMAP_MENU_DELAY * 4 / 5 : 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// clicked node is a new group
|
||||
else {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
setFocus(node, -1, false);
|
||||
}
|
||||
|
||||
// restore hover data
|
||||
hoverOffset = oldHoverOffset;
|
||||
hoverIndex = oldHoverIndex;
|
||||
|
||||
// open beatmap menu
|
||||
if (button == Input.MOUSE_RIGHT_BUTTON)
|
||||
beatmapMenuTimer = (node.index == expandedIndex) ? BEATMAP_MENU_DELAY * 4 / 5 : 0;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,6 +704,7 @@ public class SongMenu extends BasicGameState {
|
||||
// clear search text
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
searchTransitionTimer = 0;
|
||||
} else {
|
||||
// return to main menu
|
||||
SoundController.playSound(SoundEffect.MENUBACK);
|
||||
@@ -630,11 +714,13 @@ public class SongMenu extends BasicGameState {
|
||||
break;
|
||||
case Input.KEY_F1:
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
game.enterState(Opsu.STATE_OPTIONSMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||
((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).setMenuState(MenuState.MODS);
|
||||
game.enterState(Opsu.STATE_BUTTONMENU);
|
||||
break;
|
||||
case Input.KEY_F2:
|
||||
if (focusNode == null)
|
||||
break;
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
if (input.isKeyDown(Input.KEY_RSHIFT) || input.isKeyDown(Input.KEY_LSHIFT)) {
|
||||
// shift key: previous random track
|
||||
SongNode prev;
|
||||
@@ -718,8 +804,16 @@ public class SongMenu extends BasicGameState {
|
||||
break;
|
||||
default:
|
||||
// wait for user to finish typing
|
||||
if (Character.isLetterOrDigit(c) || key == Input.KEY_BACK)
|
||||
// TODO: accept all characters (current conditions are from TextField class)
|
||||
if ((c > 31 && c < 127) || key == Input.KEY_BACK) {
|
||||
searchTimer = 0;
|
||||
int textLength = search.getText().length();
|
||||
if (key == Input.KEY_BACK) {
|
||||
if (textLength == 0)
|
||||
searchTransitionTimer = 0;
|
||||
} else if (textLength == 1)
|
||||
searchTransitionTimer = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -782,11 +876,15 @@ public class SongMenu extends BasicGameState {
|
||||
throws SlickException {
|
||||
Display.setTitle(game.getTitle());
|
||||
Utils.getBackButton().resetHover();
|
||||
optionsButton.resetHover();
|
||||
selectModsButton.resetHover();
|
||||
selectRandomButton.resetHover();
|
||||
selectMapOptionsButton.resetHover();
|
||||
selectOptionsButton.resetHover();
|
||||
hoverOffset = 0f;
|
||||
hoverIndex = -1;
|
||||
startScore = 0;
|
||||
beatmapMenuTimer = -1;
|
||||
searchTransitionTimer = SEARCH_TRANSITION_TIME;
|
||||
|
||||
// reset song stack
|
||||
randomStack = new Stack<SongNode>();
|
||||
@@ -920,7 +1018,8 @@ public class SongMenu extends BasicGameState {
|
||||
hoverIndex = -1;
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
searchResultString = "Type to search!";
|
||||
searchTransitionTimer = SEARCH_TRANSITION_TIME;
|
||||
searchResultString = null;
|
||||
|
||||
// reload songs in new thread
|
||||
reloadThread = new Thread() {
|
||||
@@ -977,16 +1076,16 @@ public class SongMenu extends BasicGameState {
|
||||
if (n < 0 && startNode.prev != null) {
|
||||
startNode = startNode.prev;
|
||||
buttonY += buttonOffset / 4;
|
||||
if (buttonY > height * 0.18f)
|
||||
buttonY = height * 0.18f;
|
||||
if (buttonY > headerY + height * 0.02f)
|
||||
buttonY = headerY + height * 0.02f;
|
||||
n++;
|
||||
shifted = true;
|
||||
} else if (n > 0 && startNode.next != null &&
|
||||
OsuGroupList.get().getNode(startNode, MAX_SONG_BUTTONS) != null) {
|
||||
startNode = startNode.next;
|
||||
buttonY -= buttonOffset / 4;
|
||||
if (buttonY < height * 0.14f)
|
||||
buttonY = height * 0.14f;
|
||||
if (buttonY < headerY - height * 0.02f)
|
||||
buttonY = headerY - height * 0.02f;
|
||||
n--;
|
||||
shifted = true;
|
||||
} else
|
||||
|
||||
Reference in New Issue
Block a user