Merge remote-tracking branch 'remotes/original/master' into upstream
# Conflicts: # src/itdelatrisu/opsu/Container.java # src/itdelatrisu/opsu/GameData.java # src/itdelatrisu/opsu/Options.java # src/itdelatrisu/opsu/audio/MusicController.java # src/itdelatrisu/opsu/objects/Circle.java # src/itdelatrisu/opsu/objects/Slider.java # src/itdelatrisu/opsu/render/CurveRenderState.java # src/itdelatrisu/opsu/states/Game.java # src/itdelatrisu/opsu/states/MainMenu.java # src/itdelatrisu/opsu/states/SongMenu.java # src/itdelatrisu/opsu/ui/Colors.java # src/itdelatrisu/opsu/ui/MenuButton.java
This commit is contained in:
@@ -46,8 +46,8 @@ 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 org.newdawn.slick.state.transition.FadeInTransition;
|
||||
|
||||
/**
|
||||
* Generic button menu state.
|
||||
@@ -69,8 +69,8 @@ public class ButtonMenu extends BasicGameState {
|
||||
Button.NO.click(container, game);
|
||||
}
|
||||
},
|
||||
/** The initial beatmap management screen. */
|
||||
BEATMAP (new Button[] { Button.CLEAR_SCORES, Button.DELETE, Button.CANCEL }) {
|
||||
/** The initial beatmap management screen (for a non-"favorite" beatmap). */
|
||||
BEATMAP (new Button[] { Button.CLEAR_SCORES, Button.FAVORITE_ADD, Button.DELETE, Button.CANCEL }) {
|
||||
@Override
|
||||
public String[] getTitle(GameContainer container, StateBasedGame game) {
|
||||
BeatmapSetNode node = ((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).getNode();
|
||||
@@ -90,6 +90,23 @@ public class ButtonMenu extends BasicGameState {
|
||||
super.scroll(container, game, newValue);
|
||||
}
|
||||
},
|
||||
/** The initial beatmap management screen (for a "favorite" beatmap). */
|
||||
BEATMAP_FAVORITE (new Button[] { Button.CLEAR_SCORES, Button.FAVORITE_REMOVE, Button.DELETE, Button.CANCEL }) {
|
||||
@Override
|
||||
public String[] getTitle(GameContainer container, StateBasedGame game) {
|
||||
return BEATMAP.getTitle(container, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leave(GameContainer container, StateBasedGame game) {
|
||||
BEATMAP.leave(container, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scroll(GameContainer container, StateBasedGame game, int newValue) {
|
||||
BEATMAP.scroll(container, game, newValue);
|
||||
}
|
||||
},
|
||||
/** The beatmap deletion screen for a beatmap set with multiple beatmaps. */
|
||||
BEATMAP_DELETE_SELECT (new Button[] { Button.DELETE_GROUP, Button.DELETE_SONG, Button.CANCEL_DELETE }) {
|
||||
@Override
|
||||
@@ -468,6 +485,25 @@ public class ButtonMenu extends BasicGameState {
|
||||
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
|
||||
}
|
||||
},
|
||||
FAVORITE_ADD ("Add to Favorites", Color.blue) {
|
||||
@Override
|
||||
public void click(GameContainer container, StateBasedGame game) {
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
BeatmapSetNode node = ((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).getNode();
|
||||
node.getBeatmapSet().setFavorite(true);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
|
||||
}
|
||||
},
|
||||
FAVORITE_REMOVE ("Remove from Favorites", Color.blue) {
|
||||
@Override
|
||||
public void click(GameContainer container, StateBasedGame game) {
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
BeatmapSetNode node = ((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).getNode();
|
||||
node.getBeatmapSet().setFavorite(false);
|
||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).doStateActionOnLoad(MenuState.BEATMAP_FAVORITE);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition());
|
||||
}
|
||||
},
|
||||
DELETE ("Delete...", Color.red) {
|
||||
@Override
|
||||
public void click(GameContainer container, StateBasedGame game) {
|
||||
|
||||
@@ -49,6 +49,7 @@ import itdelatrisu.opsu.replay.PlaybackSpeed;
|
||||
import itdelatrisu.opsu.replay.Replay;
|
||||
import itdelatrisu.opsu.replay.ReplayFrame;
|
||||
import itdelatrisu.opsu.ui.*;
|
||||
import itdelatrisu.opsu.ui.animations.AnimatedValue;
|
||||
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||
|
||||
import java.io.File;
|
||||
@@ -98,6 +99,9 @@ public class Game extends BasicGameState {
|
||||
/** Screen fade-out time, in milliseconds, when health hits zero. */
|
||||
private static final int LOSE_FADEOUT_TIME = 500;
|
||||
|
||||
/** Game element fade-out time, in milliseconds, when the game ends. */
|
||||
private static final int FINISHED_FADEOUT_TIME = 400;
|
||||
|
||||
/** Maximum rotation, in degrees, over fade out upon death. */
|
||||
private static final float MAX_ROTATION = 90f;
|
||||
|
||||
@@ -287,6 +291,15 @@ public class Game extends BasicGameState {
|
||||
/** The current alpha of the scoreboard. */
|
||||
private float currentScoreboardAlpha;
|
||||
|
||||
/** The star stream shown when passing another score. */
|
||||
private StarStream scoreboardStarStream;
|
||||
|
||||
/** Whether the game is finished (last hit object passed). */
|
||||
private boolean gameFinished = false;
|
||||
|
||||
/** Timer after game has finished, before changing states. */
|
||||
private AnimatedValue gameFinishedTimer = new AnimatedValue(2500, 0, 1, AnimationEquation.LINEAR);
|
||||
|
||||
/** Music position bar background colors. */
|
||||
private static final Color
|
||||
MUSICBAR_NORMAL = new Color(12, 9, 10, 0.25f),
|
||||
@@ -369,6 +382,12 @@ public class Game extends BasicGameState {
|
||||
musicBarWidth = Math.max(width * 0.005f, 7);
|
||||
musicBarHeight = height * 0.9f;
|
||||
|
||||
// initialize scoreboard star stream
|
||||
scoreboardStarStream = new StarStream(0, height * 2f / 3f, width / 4, 0, 0);
|
||||
scoreboardStarStream.setPositionSpread(height / 20f);
|
||||
scoreboardStarStream.setDirectionSpread(10f);
|
||||
scoreboardStarStream.setDurationSpread(700, 100);
|
||||
|
||||
// create the associated GameData object
|
||||
data = new GameData(width, height);
|
||||
}
|
||||
@@ -513,7 +532,7 @@ public class Game extends BasicGameState {
|
||||
}
|
||||
|
||||
if (!Options.isHideUI() || !GameMod.AUTO.isActive()) {
|
||||
data.drawGameElements(g, true, objectIndex == 0);
|
||||
data.drawGameElements(g, true, objectIndex == 0, 1f);
|
||||
}
|
||||
|
||||
if (breakLength >= 8000 &&
|
||||
@@ -552,7 +571,13 @@ public class Game extends BasicGameState {
|
||||
else {
|
||||
if (!GameMod.AUTO.isActive() || !Options.isHideUI()) {
|
||||
// game elements
|
||||
data.drawGameElements(g, false, objectIndex == 0);
|
||||
float gameElementAlpha = 1f;
|
||||
if (gameFinished) {
|
||||
// game finished: fade everything out
|
||||
float t = 1f - Math.min(gameFinishedTimer.getTime() / (float) FINISHED_FADEOUT_TIME, 1f);
|
||||
gameElementAlpha = AnimationEquation.OUT_CUBIC.calc(t);
|
||||
}
|
||||
data.drawGameElements(g, false, objectIndex == 0, gameElementAlpha);
|
||||
|
||||
// skip beginning
|
||||
if (objectIndex == 0 &&
|
||||
@@ -639,6 +664,7 @@ public class Game extends BasicGameState {
|
||||
ScoreData currentScore = data.getCurrentScoreData(beatmap, true);
|
||||
while (currentRank > 0 && previousScores[currentRank - 1].score < currentScore.score) {
|
||||
currentRank--;
|
||||
scoreboardStarStream.burst(20);
|
||||
lastRankUpdateTime = trackPosition;
|
||||
}
|
||||
|
||||
@@ -647,6 +673,9 @@ public class Game extends BasicGameState {
|
||||
);
|
||||
int scoreboardPosition = 2 * container.getHeight() / 3;
|
||||
|
||||
// draw star stream behind the scores
|
||||
scoreboardStarStream.draw();
|
||||
|
||||
if (currentRank < 4) {
|
||||
// draw the (new) top 5 ranks
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -749,6 +778,7 @@ public class Game extends BasicGameState {
|
||||
playbackSpeed.getButton().hoverUpdate(delta, mouseX, mouseY);
|
||||
int trackPosition = MusicController.getPosition();
|
||||
int firstObjectTime = beatmap.objects[0].getTime();
|
||||
scoreboardStarStream.update(delta);
|
||||
|
||||
// returning from pause screen: must click previous mouse position
|
||||
if (pauseTime > -1) {
|
||||
@@ -803,11 +833,11 @@ public class Game extends BasicGameState {
|
||||
}
|
||||
|
||||
// normal game update
|
||||
if (!isReplay)
|
||||
if (!isReplay && !gameFinished)
|
||||
addReplayFrameAndRun(mouseX, mouseY, lastKeysPressed, trackPosition);
|
||||
|
||||
// watching replay
|
||||
else {
|
||||
else if (!gameFinished) {
|
||||
// out of frames, use previous data
|
||||
if (replayIndex >= replay.frames.length)
|
||||
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
|
||||
@@ -857,7 +887,8 @@ public class Game extends BasicGameState {
|
||||
// update in-game scoreboard
|
||||
if (!Options.isHideUI() && previousScores != null && trackPosition > firstObjectTime) {
|
||||
// show scoreboard if selected, and always in break
|
||||
if (scoreboardVisible || breakTime > 0) {
|
||||
// hide when game ends
|
||||
if ((scoreboardVisible || breakTime > 0) && !gameFinished) {
|
||||
currentScoreboardAlpha += 1f / SCOREBOARD_FADE_IN_TIME * delta;
|
||||
if (currentScoreboardAlpha > 1f)
|
||||
currentScoreboardAlpha = 1f;
|
||||
@@ -869,6 +900,14 @@ public class Game extends BasicGameState {
|
||||
}
|
||||
|
||||
data.updateDisplays(delta);
|
||||
|
||||
// game finished: change state after timer expires
|
||||
if (gameFinished && !gameFinishedTimer.update(delta)) {
|
||||
if (checkpointLoaded) // if checkpoint used, skip ranking screen
|
||||
game.closeRequested();
|
||||
else // go to ranking screen
|
||||
game.enterState(Opsu.STATE_GAMERANKING, new EasedFadeOutTransition(), new FadeInTransition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -892,12 +931,8 @@ public class Game extends BasicGameState {
|
||||
if (MusicController.trackEnded() && objectIndex < gameObjects.length)
|
||||
gameObjects[objectIndex].update(true, delta, mouseX, mouseY, false, trackPosition);
|
||||
|
||||
// if checkpoint used, skip ranking screen
|
||||
if (checkpointLoaded)
|
||||
game.closeRequested();
|
||||
|
||||
// go to ranking screen
|
||||
else {
|
||||
// save score and replay
|
||||
if (!checkpointLoaded) {
|
||||
boolean unranked = (GameMod.AUTO.isActive() || GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive());
|
||||
((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameData(data);
|
||||
if (isReplay)
|
||||
@@ -918,9 +953,12 @@ public class Game extends BasicGameState {
|
||||
// add score to database
|
||||
if (!unranked && !isReplay)
|
||||
ScoreDB.addScore(score);
|
||||
|
||||
game.enterState(Opsu.STATE_GAMERANKING, new EasedFadeOutTransition(), new FadeInTransition());
|
||||
}
|
||||
|
||||
// start timer
|
||||
gameFinished = true;
|
||||
gameFinishedTimer.setTime(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1050,6 +1088,8 @@ public class Game extends BasicGameState {
|
||||
|
||||
@Override
|
||||
public void keyPressed(int key, char c) {
|
||||
if (gameFinished)
|
||||
return;
|
||||
|
||||
if (sbOverlay.keyPressed(key, c)) {
|
||||
return;
|
||||
@@ -1199,9 +1239,13 @@ public class Game extends BasicGameState {
|
||||
|
||||
@Override
|
||||
public void mousePressed(int button, int x, int y) {
|
||||
if (gameFinished)
|
||||
return;
|
||||
|
||||
if (sbOverlay.mousePressed(button, x, y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// watching replay
|
||||
if (isReplay || GameMod.AUTO.isActive()) {
|
||||
if (button == Input.MOUSE_MIDDLE_BUTTON)
|
||||
@@ -1294,6 +1338,9 @@ public class Game extends BasicGameState {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int button, int x, int y) {
|
||||
if (gameFinished)
|
||||
return;
|
||||
|
||||
if (sbOverlay.mouseReleased(button, x, y)) {
|
||||
return;
|
||||
}
|
||||
@@ -1315,6 +1362,9 @@ public class Game extends BasicGameState {
|
||||
|
||||
@Override
|
||||
public void keyReleased(int key, char c) {
|
||||
if (gameFinished)
|
||||
return;
|
||||
|
||||
int keys = ReplayFrame.KEY_NONE;
|
||||
if (key == Options.getGameKeyLeft())
|
||||
keys = ReplayFrame.KEY_K1;
|
||||
@@ -1343,7 +1393,7 @@ public class Game extends BasicGameState {
|
||||
if (sbOverlay.mouseWheelMoved(newValue)) {
|
||||
return;
|
||||
}
|
||||
if (Options.isMouseWheelDisabled() || Options.isMouseDisabled())
|
||||
if (Options.isMouseWheelDisabled())
|
||||
return;
|
||||
|
||||
UI.changeVolume((newValue < 0) ? -1 : 1);
|
||||
@@ -1375,6 +1425,11 @@ public class Game extends BasicGameState {
|
||||
|
||||
// restart the game
|
||||
if (restart != Restart.FALSE) {
|
||||
// update play stats
|
||||
if (restart == Restart.NEW) {
|
||||
beatmap.incrementPlayCounter();
|
||||
BeatmapDB.updatePlayStatistics(beatmap);
|
||||
}
|
||||
|
||||
// load epilepsy warning img
|
||||
epiImgTime = Options.getEpilepsyWarningLength();
|
||||
@@ -1400,11 +1455,13 @@ public class Game extends BasicGameState {
|
||||
loadImages();
|
||||
setMapModifiers();
|
||||
retries = 0;
|
||||
} else if (restart == Restart.MANUAL) {
|
||||
} else if (restart == Restart.MANUAL && !GameMod.AUTO.isActive()) {
|
||||
// retry
|
||||
retries++;
|
||||
} else if (restart == Restart.REPLAY)
|
||||
} else if (restart == Restart.REPLAY || GameMod.AUTO.isActive()) {
|
||||
// replay
|
||||
retries = 0;
|
||||
}
|
||||
|
||||
gameObjects = new GameObject[beatmap.objects.length];
|
||||
playbackSpeed = PlaybackSpeed.NORMAL;
|
||||
@@ -1613,6 +1670,11 @@ public class Game extends BasicGameState {
|
||||
* @param trackPosition the track position
|
||||
*/
|
||||
private void drawHitObjects(Graphics g, int trackPosition) {
|
||||
// draw result objects
|
||||
if (!Options.isHideObjects()) {
|
||||
data.drawHitResults(trackPosition);
|
||||
}
|
||||
|
||||
if (Options.isMergingSliders() && knorkesliders != null) {
|
||||
knorkesliders.draw(Color.white, this.slidercurveFrom, this.slidercurveTo);
|
||||
if (Options.isMirror()) {
|
||||
@@ -1622,6 +1684,7 @@ public class Game extends BasicGameState {
|
||||
g.popTransform();
|
||||
}
|
||||
}
|
||||
|
||||
// include previous object in follow points
|
||||
int lastObjectIndex = -1;
|
||||
if (objectIndex > 0 && objectIndex < beatmap.objects.length &&
|
||||
@@ -1736,18 +1799,13 @@ public class Game extends BasicGameState {
|
||||
|
||||
// translate and rotate the object
|
||||
g.translate(0, dt * dt * container.getHeight());
|
||||
Vec2f rotationCenter = gameObj.getPointAt(beatmap.objects[idx].getTime());
|
||||
Vec2f rotationCenter = gameObj.getPointAt((beatmap.objects[idx].getTime() + beatmap.objects[idx].getEndTime()) / 2);
|
||||
g.rotate(rotationCenter.x, rotationCenter.y, rotSpeed * dt);
|
||||
gameObj.draw(g, trackPosition, false);
|
||||
|
||||
g.popTransform();
|
||||
}
|
||||
}
|
||||
|
||||
// draw result objects
|
||||
if (!Options.isHideObjects()) {
|
||||
data.drawHitResults(trackPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1760,7 +1818,7 @@ public class Game extends BasicGameState {
|
||||
}
|
||||
this.beatmap = beatmap;
|
||||
Display.setTitle(String.format("%s - %s", game.getTitle(), beatmap.toString()));
|
||||
if (beatmap.timingPoints == null)
|
||||
if (beatmap.breaks == null)
|
||||
BeatmapDB.load(beatmap, BeatmapDB.LOAD_ARRAY);
|
||||
BeatmapParser.parseHitObjects(beatmap);
|
||||
HitSound.setDefaultSampleSet(beatmap.sampleSet);
|
||||
@@ -1792,6 +1850,9 @@ public class Game extends BasicGameState {
|
||||
autoMousePosition = new Vec2f();
|
||||
autoMousePressed = false;
|
||||
flashlightRadius = container.getHeight() * 2 / 3;
|
||||
scoreboardStarStream.clear();
|
||||
gameFinished = false;
|
||||
gameFinishedTimer.setTime(0);
|
||||
|
||||
System.gc();
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ public class GamePauseMenu extends BasicGameState {
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(int newValue) {
|
||||
if (Options.isMouseWheelDisabled() || Options.isMouseDisabled())
|
||||
if (Options.isMouseWheelDisabled())
|
||||
return;
|
||||
|
||||
UI.changeVolume((newValue < 0) ? -1 : 1);
|
||||
|
||||
@@ -32,8 +32,12 @@ import itdelatrisu.opsu.beatmap.BeatmapSetNode;
|
||||
import itdelatrisu.opsu.beatmap.TimingPoint;
|
||||
import itdelatrisu.opsu.downloads.Updater;
|
||||
import itdelatrisu.opsu.states.ButtonMenu.MenuState;
|
||||
import itdelatrisu.opsu.ui.*;
|
||||
import itdelatrisu.opsu.ui.Colors;
|
||||
import itdelatrisu.opsu.ui.Fonts;
|
||||
import itdelatrisu.opsu.ui.MenuButton;
|
||||
import itdelatrisu.opsu.ui.MenuButton.Expand;
|
||||
import itdelatrisu.opsu.ui.StarFountain;
|
||||
import itdelatrisu.opsu.ui.UI;
|
||||
import itdelatrisu.opsu.ui.animations.AnimatedValue;
|
||||
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||
|
||||
@@ -51,8 +55,8 @@ 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.EasedFadeOutTransition;
|
||||
import org.newdawn.slick.state.transition.FadeInTransition;
|
||||
|
||||
/**
|
||||
* "Main Menu" state.
|
||||
@@ -117,15 +121,18 @@ public class MainMenu extends BasicGameState {
|
||||
/** Music position bar coordinates and dimensions. */
|
||||
private float musicBarX, musicBarY, musicBarWidth, musicBarHeight;
|
||||
|
||||
/** Last measure progress value. */
|
||||
private float lastMeasureProgress = 0f;
|
||||
|
||||
/** The star fountain. */
|
||||
private StarFountain starFountain;
|
||||
|
||||
// game-related variables
|
||||
private GameContainer container;
|
||||
private StateBasedGame game;
|
||||
private Input input;
|
||||
private final int state;
|
||||
|
||||
private float hue = 0;
|
||||
private boolean huedone = false;
|
||||
|
||||
public MainMenu(int state) {
|
||||
this.state = state;
|
||||
}
|
||||
@@ -203,9 +210,6 @@ public class MainMenu extends BasicGameState {
|
||||
repoButton.setHoverAnimationDuration(350);
|
||||
repoButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
|
||||
repoButton.setHoverExpand();
|
||||
}
|
||||
|
||||
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { // only if a webpage can be opened
|
||||
Image repoImg = GameImage.REPOSITORY.getImage();
|
||||
danceRepoButton = new MenuButton(repoImg,
|
||||
startX - repoImg.getWidth(), startY - repoImg.getHeight()
|
||||
@@ -228,6 +232,9 @@ public class MainMenu extends BasicGameState {
|
||||
restartButton.setHoverAnimationEquation(AnimationEquation.LINEAR);
|
||||
restartButton.setHoverRotate(360);
|
||||
|
||||
// initialize star fountain
|
||||
starFountain = new StarFountain(width, height);
|
||||
|
||||
// logo animations
|
||||
float centerOffsetX = width / 6.5f;
|
||||
logoOpen = new AnimatedValue(100, 0, centerOffsetX, AnimationEquation.OUT_QUAD);
|
||||
@@ -262,6 +269,9 @@ public class MainMenu extends BasicGameState {
|
||||
g.fillRect(0, height * 8 / 9f, width, height / 9f);
|
||||
Colors.BLACK_ALPHA.a = oldAlpha;
|
||||
|
||||
// draw star fountain
|
||||
starFountain.draw();
|
||||
|
||||
// draw downloads button
|
||||
downloadsButton.draw();
|
||||
|
||||
@@ -271,26 +281,15 @@ public class MainMenu extends BasicGameState {
|
||||
exitButton.draw();
|
||||
}
|
||||
|
||||
// logo
|
||||
Double position = MusicController.getBeatProgress();
|
||||
Color color = Options.isColorMainMenuLogo() ? Cursor.lastCursorColor : Color.white;
|
||||
boolean renderPiece = position != null;
|
||||
if (position == null) {
|
||||
position = System.currentTimeMillis() % 1000 / 1000d;
|
||||
}
|
||||
double scale = 1 - (0 - position) * 0.05;
|
||||
logo.draw(color, (float) scale);
|
||||
if (renderPiece) {
|
||||
Image piece = GameImage.MENU_LOGO_PIECE.getImage().getScaledCopy(logo.getCurrentScale());
|
||||
float scaleposmodx = piece.getWidth() / 2;
|
||||
float scaleposmody = piece.getHeight() / 2;
|
||||
piece.rotate((float) (position * 360));
|
||||
piece.draw(logo.getX() - scaleposmodx, logo.getY() - scaleposmody, color);
|
||||
}
|
||||
Image logoCopy = GameImage.MENU_LOGO.getImage().getScaledCopy(logo.getCurrentScale() / (float) scale * 1.05f);
|
||||
float scaleposmodx = logoCopy.getWidth() / 2;
|
||||
float scaleposmody = logoCopy.getHeight() / 2;
|
||||
logoCopy.draw(logo.getX() - scaleposmodx, logo.getY() - scaleposmody, Colors.GHOST_LOGO);
|
||||
// draw logo (pulsing)
|
||||
Float position = MusicController.getBeatProgress();
|
||||
if (position == null) // default to 60bpm
|
||||
position = System.currentTimeMillis() % 1000 / 1000f;
|
||||
float scale = 1f + position * 0.05f;
|
||||
logo.draw(Color.white, scale);
|
||||
float ghostScale = logo.getLastScale() / scale * 1.05f;
|
||||
Image ghostLogo = GameImage.MENU_LOGO.getImage().getScaledCopy(ghostScale);
|
||||
ghostLogo.drawCentered(logo.getX(), logo.getY(), Colors.GHOST_LOGO);
|
||||
|
||||
// draw music buttons
|
||||
if (MusicController.isPlaying())
|
||||
@@ -310,16 +309,13 @@ public class MainMenu extends BasicGameState {
|
||||
g.fillRoundRect(musicBarX, musicBarY, musicBarWidth * musicBarPosition, musicBarHeight, 4);
|
||||
}
|
||||
|
||||
// draw repository button
|
||||
// draw repository buttons
|
||||
if (repoButton != null) {
|
||||
repoButton.draw();
|
||||
String text = "opsu!";
|
||||
int fheight = Fonts.SMALL.getLineHeight();
|
||||
int fwidth = Fonts.SMALL.getWidth(text);
|
||||
Fonts.SMALL.drawString(repoButton.getX() - fwidth / 2, repoButton.getY() - repoButton.getImage().getHeight() / 2 - fheight, text, Color.white);
|
||||
}
|
||||
|
||||
if (danceRepoButton != null) {
|
||||
danceRepoButton.draw();
|
||||
String text = "opsu!dance";
|
||||
int fheight = Fonts.SMALL.getLineHeight();
|
||||
@@ -367,15 +363,15 @@ public class MainMenu extends BasicGameState {
|
||||
throws SlickException {
|
||||
UI.update(delta);
|
||||
if (MusicController.trackEnded())
|
||||
nextTrack(); // end of track: go to next track
|
||||
nextTrack(false); // end of track: go to next track
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
logo.hoverUpdate(delta, mouseX, mouseY, 0.25f);
|
||||
playButton.hoverUpdate(delta, mouseX, mouseY, 0.25f);
|
||||
exitButton.hoverUpdate(delta, mouseX, mouseY, 0.25f);
|
||||
if (repoButton != null)
|
||||
if (repoButton != null) {
|
||||
repoButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
if (danceRepoButton != null)
|
||||
danceRepoButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
}
|
||||
if (Updater.get().showButton()) {
|
||||
updateButton.autoHoverUpdate(delta, true);
|
||||
restartButton.autoHoverUpdate(delta, false);
|
||||
@@ -389,6 +385,7 @@ public class MainMenu extends BasicGameState {
|
||||
noHoverUpdate |= contains;
|
||||
musicNext.hoverUpdate(delta, !noHoverUpdate && musicNext.contains(mouseX, mouseY));
|
||||
musicPrevious.hoverUpdate(delta, !noHoverUpdate && musicPrevious.contains(mouseX, mouseY));
|
||||
starFountain.update(delta);
|
||||
|
||||
// window focus change: increase/decrease theme song volume
|
||||
if (MusicController.isThemePlaying() &&
|
||||
@@ -400,6 +397,14 @@ public class MainMenu extends BasicGameState {
|
||||
if (!(Options.isDynamicBackgroundEnabled() && beatmap != null && beatmap.isBackgroundLoading()))
|
||||
bgAlpha.update(delta);
|
||||
|
||||
// check measure progress
|
||||
Float measureProgress = MusicController.getMeasureProgress(2);
|
||||
if (measureProgress != null) {
|
||||
if (measureProgress < lastMeasureProgress)
|
||||
starFountain.burst(true);
|
||||
lastMeasureProgress = measureProgress;
|
||||
}
|
||||
|
||||
// buttons
|
||||
int centerX = container.getWidth() / 2;
|
||||
float currentLogoButtonAlpha;
|
||||
@@ -472,6 +477,10 @@ public class MainMenu extends BasicGameState {
|
||||
}
|
||||
}
|
||||
|
||||
// reset measure info
|
||||
lastMeasureProgress = 0f;
|
||||
starFountain.clear();
|
||||
|
||||
// reset button hover states if mouse is not currently hovering over the button
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
if (!logo.contains(mouseX, mouseY, 0.25f))
|
||||
@@ -514,6 +523,7 @@ public class MainMenu extends BasicGameState {
|
||||
// music position bar
|
||||
if (MusicController.isPlaying()) {
|
||||
if (musicPositionBarContains(x, y)) {
|
||||
lastMeasureProgress = 0f;
|
||||
float pos = (x - musicBarX) / musicBarWidth;
|
||||
MusicController.setPosition((int) (pos * MusicController.getDuration()));
|
||||
return;
|
||||
@@ -531,10 +541,11 @@ public class MainMenu extends BasicGameState {
|
||||
}
|
||||
return;
|
||||
} else if (musicNext.contains(x, y)) {
|
||||
nextTrack();
|
||||
nextTrack(true);
|
||||
UI.sendBarNotification(">> Next");
|
||||
return;
|
||||
} else if (musicPrevious.contains(x, y)) {
|
||||
lastMeasureProgress = 0f;
|
||||
if (!previous.isEmpty()) {
|
||||
SongMenu menu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
|
||||
menu.setFocus(BeatmapSetList.get().getBaseNode(previous.pop()), -1, true, false);
|
||||
@@ -657,7 +668,7 @@ public class MainMenu extends BasicGameState {
|
||||
game.enterState(Opsu.STATE_DOWNLOADSMENU, new EasedFadeOutTransition(), new FadeInTransition());
|
||||
break;
|
||||
case Input.KEY_R:
|
||||
nextTrack();
|
||||
nextTrack(true);
|
||||
break;
|
||||
case Input.KEY_UP:
|
||||
UI.changeVolume(1);
|
||||
@@ -717,9 +728,17 @@ public class MainMenu extends BasicGameState {
|
||||
|
||||
/**
|
||||
* Plays the next track, and adds the previous one to the stack.
|
||||
* @param user {@code true} if this was user-initiated, false otherwise (track end)
|
||||
*/
|
||||
private void nextTrack() {
|
||||
private void nextTrack(boolean user) {
|
||||
lastMeasureProgress = 0f;
|
||||
boolean isTheme = MusicController.isThemePlaying();
|
||||
if (isTheme && !user) {
|
||||
// theme was playing, restart
|
||||
// NOTE: not looping due to inaccurate track positions after loop
|
||||
MusicController.playAt(0, false);
|
||||
return;
|
||||
}
|
||||
SongMenu menu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
|
||||
BeatmapSetNode node = menu.setFocus(BeatmapSetList.get().getRandomNode(), -1, true, false);
|
||||
boolean sameAudio = false;
|
||||
|
||||
@@ -32,6 +32,7 @@ import itdelatrisu.opsu.audio.SoundController;
|
||||
import itdelatrisu.opsu.audio.SoundEffect;
|
||||
import itdelatrisu.opsu.beatmap.Beatmap;
|
||||
import itdelatrisu.opsu.beatmap.BeatmapDifficultyCalculator;
|
||||
import itdelatrisu.opsu.beatmap.BeatmapGroup;
|
||||
import itdelatrisu.opsu.beatmap.BeatmapParser;
|
||||
import itdelatrisu.opsu.beatmap.BeatmapSet;
|
||||
import itdelatrisu.opsu.beatmap.BeatmapSetList;
|
||||
@@ -45,6 +46,7 @@ import itdelatrisu.opsu.db.BeatmapDB;
|
||||
import itdelatrisu.opsu.db.ScoreDB;
|
||||
import itdelatrisu.opsu.states.ButtonMenu.MenuState;
|
||||
import itdelatrisu.opsu.ui.Colors;
|
||||
import itdelatrisu.opsu.ui.DropdownMenu;
|
||||
import itdelatrisu.opsu.ui.Fonts;
|
||||
import itdelatrisu.opsu.ui.KineticScrolling;
|
||||
import itdelatrisu.opsu.ui.MenuButton;
|
||||
@@ -259,8 +261,11 @@ public class SongMenu extends BasicGameState {
|
||||
/** Header and footer end and start y coordinates, respectively. */
|
||||
private float headerY, footerY;
|
||||
|
||||
/** Height of the footer */
|
||||
private float footerHeight;
|
||||
/** Footer pulsing logo button. */
|
||||
private MenuButton footerLogoButton;
|
||||
|
||||
/** Size of the pulsing logo in the footer. */
|
||||
private float footerLogoSize;
|
||||
|
||||
/** Time, in milliseconds, for fading the search bar. */
|
||||
private int searchTransitionTimer = SEARCH_TRANSITION_TIME;
|
||||
@@ -309,9 +314,15 @@ public class SongMenu extends BasicGameState {
|
||||
/** The star stream. */
|
||||
private StarStream starStream;
|
||||
|
||||
/** The maximum number of stars in the star stream. */
|
||||
private static final int MAX_STREAM_STARS = 20;
|
||||
|
||||
/** Whether the menu is currently scrolling to the focus node (blocks other actions). */
|
||||
private boolean isScrollingToFocusNode = false;
|
||||
|
||||
/** Sort order dropdown menu. */
|
||||
private DropdownMenu<BeatmapSortOrder> sortMenu;
|
||||
|
||||
// game-related variables
|
||||
private GameContainer container;
|
||||
private StateBasedGame game;
|
||||
@@ -337,11 +348,48 @@ public class SongMenu extends BasicGameState {
|
||||
Fonts.BOLD.getLineHeight() + Fonts.DEFAULT.getLineHeight() +
|
||||
Fonts.SMALL.getLineHeight();
|
||||
footerY = height - GameImage.SELECTION_MODS.getImage().getHeight();
|
||||
footerHeight = height - footerY;
|
||||
|
||||
// footer logo coordinates
|
||||
float footerHeight = height - footerY;
|
||||
footerLogoSize = footerHeight * 3.25f;
|
||||
Image logo = GameImage.MENU_LOGO.getImage();
|
||||
logo = logo.getScaledCopy(footerLogoSize / logo.getWidth());
|
||||
footerLogoButton = new MenuButton(logo, width - footerHeight * 0.8f, height - footerHeight * 0.65f);
|
||||
footerLogoButton.setHoverAnimationDuration(1);
|
||||
footerLogoButton.setHoverExpand(1.2f);
|
||||
|
||||
// initialize sorts
|
||||
for (BeatmapSortOrder sort : BeatmapSortOrder.values())
|
||||
sort.init(width, headerY - SongMenu.DIVIDER_LINE_WIDTH / 2);
|
||||
int sortWidth = (int) (width * 0.12f);
|
||||
sortMenu = new DropdownMenu<BeatmapSortOrder>(container, BeatmapSortOrder.values(),
|
||||
width * 0.87f, headerY - GameImage.MENU_TAB.getImage().getHeight() * 2.25f, sortWidth) {
|
||||
@Override
|
||||
public void itemSelected(int index, BeatmapSortOrder item) {
|
||||
BeatmapSortOrder.set(item);
|
||||
if (focusNode == null)
|
||||
return;
|
||||
BeatmapSetNode oldFocusBase = BeatmapSetList.get().getBaseNode(focusNode.index);
|
||||
int oldFocusFileIndex = focusNode.beatmapIndex;
|
||||
focusNode = null;
|
||||
BeatmapSetList.get().init();
|
||||
SongMenu.this.setFocus(oldFocusBase, oldFocusFileIndex, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean menuClicked(int index) {
|
||||
if (isInputBlocked())
|
||||
return false;
|
||||
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
sortMenu.setBackgroundColor(Colors.BLACK_BG_HOVER);
|
||||
sortMenu.setBorderColor(Colors.BLUE_DIVIDER);
|
||||
sortMenu.setChevronRightColor(Color.white);
|
||||
|
||||
// initialize group tabs
|
||||
for (BeatmapGroup group : BeatmapGroup.values())
|
||||
group.init(width, headerY - DIVIDER_LINE_WIDTH / 2);
|
||||
|
||||
// initialize score data buttons
|
||||
ScoreData.init(width, headerY + height * 0.01f);
|
||||
@@ -414,7 +462,9 @@ public class SongMenu extends BasicGameState {
|
||||
});
|
||||
|
||||
// star stream
|
||||
starStream = new StarStream(width, height);
|
||||
starStream = new StarStream(width, (height - GameImage.STAR.getImage().getHeight()) / 2, -width, 0, MAX_STREAM_STARS);
|
||||
starStream.setPositionSpread(height / 20f);
|
||||
starStream.setDirectionSpread(10f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -425,6 +475,7 @@ public class SongMenu extends BasicGameState {
|
||||
int width = container.getWidth();
|
||||
int height = container.getHeight();
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
boolean inDropdownMenu = sortMenu.contains(mouseX, mouseY);
|
||||
|
||||
// background
|
||||
if (focusNode != null) {
|
||||
@@ -496,7 +547,7 @@ public class SongMenu extends BasicGameState {
|
||||
g.clearClip();
|
||||
|
||||
// scroll bar
|
||||
if (focusScores.length > MAX_SCORE_BUTTONS && ScoreData.areaContains(mouseX, mouseY))
|
||||
if (focusScores.length > MAX_SCORE_BUTTONS && ScoreData.areaContains(mouseX, mouseY) && !inDropdownMenu)
|
||||
ScoreData.drawScrollbar(g, startScorePos.getPosition(), focusScores.length * ScoreData.getButtonOffset());
|
||||
}
|
||||
|
||||
@@ -510,25 +561,22 @@ public class SongMenu extends BasicGameState {
|
||||
g.drawLine(0, footerY, width, footerY);
|
||||
g.resetLineWidth();
|
||||
|
||||
// opsu logo in bottom bar
|
||||
Image logo = GameImage.MENU_LOGO.getImage();
|
||||
float logoSize = footerHeight * 2f;
|
||||
logo = logo.getScaledCopy(logoSize / logo.getWidth());
|
||||
Double position = MusicController.getBeatProgress();
|
||||
float x = width - footerHeight * 0.61f;
|
||||
float y = height - footerHeight * 0.40f;
|
||||
if (position != null) {
|
||||
Image ghostLogo = logo.getScaledCopy((float) (1 - (0 - position) * 0.15));
|
||||
logo = logo.getScaledCopy((float) (1 - (position) * 0.15));
|
||||
logoSize = logo.getWidth();
|
||||
logo.draw(x - logoSize / 2, y - logoSize / 2);
|
||||
logoSize = ghostLogo.getWidth();
|
||||
float a = Colors.GHOST_LOGO.a;
|
||||
Colors.GHOST_LOGO.a *= (1d - position);
|
||||
ghostLogo.draw(x - logoSize / 2, y - logoSize / 2, Colors.GHOST_LOGO);
|
||||
Colors.GHOST_LOGO.a = a;
|
||||
// footer logo (pulsing)
|
||||
Float position = MusicController.getBeatProgress();
|
||||
if (position == null) // default to 60bpm
|
||||
position = System.currentTimeMillis() % 1000 / 1000f;
|
||||
if (footerLogoButton.contains(mouseX, mouseY, 0.25f) && !inDropdownMenu) {
|
||||
// hovering over logo: stop pulsing
|
||||
footerLogoButton.draw();
|
||||
} else {
|
||||
logo.draw(x - logoSize / 2, y - logoSize / 2);
|
||||
float expand = position * 0.15f;
|
||||
footerLogoButton.draw(Color.white, 1f - expand);
|
||||
Image ghostLogo = GameImage.MENU_LOGO.getImage();
|
||||
ghostLogo = ghostLogo.getScaledCopy((1f + expand) * footerLogoSize / ghostLogo.getWidth());
|
||||
float oldGhostAlpha = Colors.GHOST_LOGO.a;
|
||||
Colors.GHOST_LOGO.a *= (1f - position);
|
||||
ghostLogo.drawCentered(footerLogoButton.getX(), footerLogoButton.getY(), Colors.GHOST_LOGO);
|
||||
Colors.GHOST_LOGO.a = oldGhostAlpha;
|
||||
}
|
||||
|
||||
// header
|
||||
@@ -607,20 +655,22 @@ public class SongMenu extends BasicGameState {
|
||||
GameImage.SELECTION_OTHER_OPTIONS.getImage().drawCentered(selectOptionsButton.getX(), selectOptionsButton.getY());
|
||||
selectOptionsButton.draw();
|
||||
|
||||
// sorting tabs
|
||||
BeatmapSortOrder currentSort = BeatmapSortOrder.getSort();
|
||||
BeatmapSortOrder hoverSort = null;
|
||||
for (BeatmapSortOrder sort : BeatmapSortOrder.values()) {
|
||||
if (sort.contains(mouseX, mouseY)) {
|
||||
hoverSort = sort;
|
||||
break;
|
||||
// group tabs
|
||||
BeatmapGroup currentGroup = BeatmapGroup.current();
|
||||
BeatmapGroup hoverGroup = null;
|
||||
if (!inDropdownMenu) {
|
||||
for (BeatmapGroup group : BeatmapGroup.values()) {
|
||||
if (group.contains(mouseX, mouseY)) {
|
||||
hoverGroup = group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (BeatmapSortOrder sort : BeatmapSortOrder.VALUES_REVERSED) {
|
||||
if (sort != currentSort)
|
||||
sort.draw(false, sort == hoverSort);
|
||||
for (BeatmapGroup group : BeatmapGroup.VALUES_REVERSED) {
|
||||
if (group != currentGroup)
|
||||
group.draw(false, group == hoverGroup);
|
||||
}
|
||||
currentSort.draw(true, false);
|
||||
currentGroup.draw(true, false);
|
||||
|
||||
// search
|
||||
boolean searchEmpty = search.getText().isEmpty();
|
||||
@@ -655,6 +705,9 @@ public class SongMenu extends BasicGameState {
|
||||
(searchResultString == null) ? "Searching..." : searchResultString, Color.white);
|
||||
}
|
||||
|
||||
// sorting options
|
||||
sortMenu.render(container, g);
|
||||
|
||||
// reloading beatmaps
|
||||
if (reloadThread != null) {
|
||||
// darken the screen
|
||||
@@ -678,20 +731,25 @@ public class SongMenu extends BasicGameState {
|
||||
if (reloadThread == null)
|
||||
MusicController.loopTrackIfEnded(true);
|
||||
else if (reloadThread.isFinished()) {
|
||||
BeatmapGroup.set(BeatmapGroup.ALL);
|
||||
BeatmapSortOrder.set(BeatmapSortOrder.TITLE);
|
||||
BeatmapSetList.get().reset();
|
||||
BeatmapSetList.get().init();
|
||||
if (BeatmapSetList.get().size() > 0) {
|
||||
// initialize song list
|
||||
BeatmapSetList.get().init();
|
||||
setFocus(BeatmapSetList.get().getRandomNode(), -1, true, true);
|
||||
} else
|
||||
MusicController.playThemeSong();
|
||||
reloadThread = null;
|
||||
}
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
boolean inDropdownMenu = sortMenu.contains(mouseX, mouseY);
|
||||
UI.getBackButton().hoverUpdate(delta, mouseX, mouseY);
|
||||
selectModsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectRandomButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectMapOptionsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
selectOptionsButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
footerLogoButton.hoverUpdate(delta, mouseX, mouseY, 0.25f);
|
||||
|
||||
// beatmap menu timer
|
||||
if (beatmapMenuTimer > -1) {
|
||||
@@ -699,7 +757,9 @@ public class SongMenu extends BasicGameState {
|
||||
if (beatmapMenuTimer >= BEATMAP_MENU_DELAY) {
|
||||
beatmapMenuTimer = -1;
|
||||
if (focusNode != null) {
|
||||
((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).setMenuState(MenuState.BEATMAP, focusNode);
|
||||
MenuState state = focusNode.getBeatmapSet().isFavorite() ?
|
||||
MenuState.BEATMAP_FAVORITE : MenuState.BEATMAP;
|
||||
((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).setMenuState(state, focusNode);
|
||||
game.enterState(Opsu.STATE_BUTTONMENU);
|
||||
}
|
||||
return;
|
||||
@@ -788,7 +848,7 @@ public class SongMenu extends BasicGameState {
|
||||
|
||||
// mouse hover
|
||||
BeatmapSetNode node = getNodeAtPosition(mouseX, mouseY);
|
||||
if (node != null) {
|
||||
if (node != null && !inDropdownMenu) {
|
||||
if (node == hoverIndex)
|
||||
hoverOffset.update(delta);
|
||||
else {
|
||||
@@ -802,7 +862,9 @@ public class SongMenu extends BasicGameState {
|
||||
}
|
||||
|
||||
// tooltips
|
||||
if (focusScores != null && ScoreData.areaContains(mouseX, mouseY)) {
|
||||
if (sortMenu.baseContains(mouseX, mouseY))
|
||||
UI.updateTooltip(delta, "Sort by...", false);
|
||||
else if (focusScores != null && ScoreData.areaContains(mouseX, mouseY)) {
|
||||
int startScore = (int) (startScorePos.getPosition() / ScoreData.getButtonOffset());
|
||||
int offset = (int) (-startScorePos.getPosition() + startScore * ScoreData.getButtonOffset());
|
||||
int scoreButtons = Math.min(focusScores.length - startScore, MAX_SCORE_BUTTONS);
|
||||
@@ -880,25 +942,42 @@ public class SongMenu extends BasicGameState {
|
||||
return;
|
||||
}
|
||||
|
||||
if (focusNode == null)
|
||||
return;
|
||||
|
||||
// sorting buttons
|
||||
for (BeatmapSortOrder sort : BeatmapSortOrder.values()) {
|
||||
if (sort.contains(x, y)) {
|
||||
if (sort != BeatmapSortOrder.getSort()) {
|
||||
BeatmapSortOrder.setSort(sort);
|
||||
// group tabs
|
||||
for (BeatmapGroup group : BeatmapGroup.values()) {
|
||||
if (group.contains(x, y)) {
|
||||
if (group != BeatmapGroup.current()) {
|
||||
BeatmapGroup.set(group);
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
BeatmapSetNode oldFocusBase = BeatmapSetList.get().getBaseNode(focusNode.index);
|
||||
int oldFocusFileIndex = focusNode.beatmapIndex;
|
||||
focusNode = null;
|
||||
startNode = focusNode = null;
|
||||
oldFocusNode = null;
|
||||
randomStack = new Stack<SongNode>();
|
||||
songInfo = null;
|
||||
scoreMap = null;
|
||||
focusScores = null;
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
searchTransitionTimer = SEARCH_TRANSITION_TIME;
|
||||
searchResultString = null;
|
||||
BeatmapSetList.get().reset();
|
||||
BeatmapSetList.get().init();
|
||||
setFocus(oldFocusBase, oldFocusFileIndex, true, true);
|
||||
setFocus(BeatmapSetList.get().getRandomNode(), -1, true, true);
|
||||
|
||||
if (BeatmapSetList.get().size() < 1 && group.getEmptyMessage() != null)
|
||||
UI.sendBarNotification(group.getEmptyMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (focusNode == null)
|
||||
return;
|
||||
|
||||
// logo: start game
|
||||
if (footerLogoButton.contains(x, y, 0.25f)) {
|
||||
startGame();
|
||||
return;
|
||||
}
|
||||
|
||||
// song buttons
|
||||
BeatmapSetNode node = getNodeAtPosition(x, y);
|
||||
if (node != null) {
|
||||
@@ -978,6 +1057,7 @@ public class SongMenu extends BasicGameState {
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
searchTransitionTimer = 0;
|
||||
searchResultString = null;
|
||||
} else {
|
||||
// return to main menu
|
||||
SoundController.playSound(SoundEffect.MENUBACK);
|
||||
@@ -999,7 +1079,11 @@ public class SongMenu extends BasicGameState {
|
||||
SongNode prev;
|
||||
if (randomStack.isEmpty() || (prev = randomStack.pop()) == null)
|
||||
break;
|
||||
setFocus(prev.getNode(), prev.getIndex(), true, true);
|
||||
BeatmapSetNode node = prev.getNode();
|
||||
int expandedIndex = BeatmapSetList.get().getExpandedIndex();
|
||||
if (node.index == expandedIndex)
|
||||
node = node.next; // move past base node
|
||||
setFocus(node, prev.getIndex(), true, true);
|
||||
} else {
|
||||
// random track, add previous to stack
|
||||
randomStack.push(new SongNode(BeatmapSetList.get().getBaseNode(focusNode.index), focusNode.beatmapIndex));
|
||||
@@ -1010,7 +1094,9 @@ public class SongMenu extends BasicGameState {
|
||||
if (focusNode == null)
|
||||
break;
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).setMenuState(MenuState.BEATMAP, focusNode);
|
||||
MenuState state = focusNode.getBeatmapSet().isFavorite() ?
|
||||
MenuState.BEATMAP_FAVORITE : MenuState.BEATMAP;
|
||||
((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).setMenuState(state, focusNode);
|
||||
game.enterState(Opsu.STATE_BUTTONMENU);
|
||||
break;
|
||||
case Input.KEY_F5:
|
||||
@@ -1045,11 +1131,6 @@ public class SongMenu extends BasicGameState {
|
||||
case Input.KEY_ENTER:
|
||||
if (focusNode == null)
|
||||
break;
|
||||
if (input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) {
|
||||
// turn on "auto" mod
|
||||
if (!GameMod.AUTO.isActive())
|
||||
GameMod.AUTO.toggle(true);
|
||||
}
|
||||
startGame();
|
||||
break;
|
||||
case Input.KEY_DOWN:
|
||||
@@ -1194,6 +1275,8 @@ public class SongMenu extends BasicGameState {
|
||||
songChangeTimer.setTime(songChangeTimer.getDuration());
|
||||
musicIconBounceTimer.setTime(musicIconBounceTimer.getDuration());
|
||||
starStream.clear();
|
||||
sortMenu.activate();
|
||||
sortMenu.reset();
|
||||
|
||||
// reset song stack
|
||||
randomStack = new Stack<SongNode>();
|
||||
@@ -1241,6 +1324,15 @@ public class SongMenu extends BasicGameState {
|
||||
focusScores = getScoreDataForNode(focusNode, true);
|
||||
}
|
||||
|
||||
// re-sort (in case play count updated)
|
||||
if (BeatmapSortOrder.current() == BeatmapSortOrder.PLAYS) {
|
||||
BeatmapSetNode oldFocusBase = BeatmapSetList.get().getBaseNode(focusNode.index);
|
||||
int oldFocusFileIndex = focusNode.beatmapIndex;
|
||||
focusNode = null;
|
||||
BeatmapSetList.get().init();
|
||||
setFocus(oldFocusBase, oldFocusFileIndex, true, true);
|
||||
}
|
||||
|
||||
resetGame = false;
|
||||
}
|
||||
|
||||
@@ -1325,6 +1417,19 @@ public class SongMenu extends BasicGameState {
|
||||
case RELOAD: // reload beatmaps
|
||||
reloadBeatmaps(true);
|
||||
break;
|
||||
case BEATMAP_FAVORITE: // removed favorite, reset beatmap list
|
||||
if (BeatmapGroup.current() == BeatmapGroup.FAVORITE) {
|
||||
startNode = focusNode = null;
|
||||
oldFocusNode = null;
|
||||
randomStack = new Stack<SongNode>();
|
||||
songInfo = null;
|
||||
scoreMap = null;
|
||||
focusScores = null;
|
||||
BeatmapSetList.get().reset();
|
||||
BeatmapSetList.get().init();
|
||||
setFocus(BeatmapSetList.get().getRandomNode(), -1, true, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1338,6 +1443,7 @@ public class SongMenu extends BasicGameState {
|
||||
public void leave(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
search.setFocus(false);
|
||||
sortMenu.deactivate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1430,7 +1536,8 @@ public class SongMenu extends BasicGameState {
|
||||
focusNode = BeatmapSetList.get().getNode(node, beatmapIndex);
|
||||
Beatmap beatmap = focusNode.getSelectedBeatmap();
|
||||
if (beatmap.timingPoints == null) {
|
||||
BeatmapParser.parseOnlyTimingPoints(beatmap);
|
||||
// parse timing points so we can pulse the logo
|
||||
BeatmapParser.parseTimingPoints(beatmap);
|
||||
}
|
||||
MusicController.play(beatmap, false, preview);
|
||||
|
||||
@@ -1670,12 +1777,19 @@ public class SongMenu extends BasicGameState {
|
||||
if (MusicController.isTrackLoading())
|
||||
return;
|
||||
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
Beatmap beatmap = MusicController.getBeatmap();
|
||||
if (focusNode == null || beatmap != focusNode.getSelectedBeatmap()) {
|
||||
UI.sendBarNotification("Unable to load the beatmap audio.");
|
||||
return;
|
||||
}
|
||||
|
||||
// turn on "auto" mod if holding "ctrl" key
|
||||
if (input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) {
|
||||
if (!GameMod.AUTO.isActive())
|
||||
GameMod.AUTO.toggle(true);
|
||||
}
|
||||
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
MultiClip.destroyExtraClips();
|
||||
Game gameState = (Game) game.getState(Opsu.STATE_GAME);
|
||||
gameState.loadBeatmap(beatmap);
|
||||
|
||||
Reference in New Issue
Block a user