Beatmap downloader improvements and fixes.
Updates: - Added some buttons to downloads menu: clear inactive downloads, import beatmaps, reset search, and show/hide unranked maps. - Small changes to OsuParser, OszUnpacker, and OsuGroupList (mostly adding return values) to allow parsing only newly unpacked beatmaps. - Added alpha fade hover effect to MenuButton, as an alternative to expanding (used for 3-part menu buttons). - Added text rendering fields to MenuButton (also for the 3-part menu buttons). - Added sound effects to downloads menu. Fixes: - Check downloads for illegal filename characters, and remove them if necessary. - The number of results and downloads shown now supports all resolutions. - Confirmation dialog no longer appears when restarting the application (since downloads are static). - Do not set a focus node immediately if the theme song will be played. - Always play the theme song if no songs are loaded (even if disabled in settings). Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
cfc0449ab2
commit
ec90d6fd03
|
@ -115,7 +115,7 @@ public class Container extends AppGameContainer {
|
|||
@Override
|
||||
public void exit() {
|
||||
// show confirmation dialog if any downloads are active
|
||||
if (DownloadList.get().hasActiveDownloads() && DownloadList.showExitConfirmation())
|
||||
if (forceExit && DownloadList.get().hasActiveDownloads() && DownloadList.showExitConfirmation())
|
||||
return;
|
||||
|
||||
super.exit();
|
||||
|
|
|
@ -441,12 +441,7 @@ public enum GameImage {
|
|||
return img.getScaledCopy(MENU_LOGO.getImage().getWidth() * 0.66f / img.getWidth());
|
||||
}
|
||||
},
|
||||
MENU_BUTTON_MID ("button-middle", "png", false, false) {
|
||||
@Override
|
||||
protected Image process_sub(Image img, int w, int h) {
|
||||
return img.getScaledCopy(w / 2, img.getHeight());
|
||||
}
|
||||
},
|
||||
MENU_BUTTON_MID ("button-middle", "png", false, false),
|
||||
MENU_BUTTON_LEFT ("button-left", "png", false, false),
|
||||
MENU_BUTTON_RIGHT ("button-right", "png", false, false),
|
||||
MUSIC_PLAY ("music-play", "png", false, false),
|
||||
|
|
|
@ -143,7 +143,7 @@ public enum GameMod {
|
|||
|
||||
// create button
|
||||
this.button = new MenuButton(img, x + (offsetX * id), y);
|
||||
this.button.setHoverScale(1.15f);
|
||||
this.button.setHoverExpand(1.15f);
|
||||
|
||||
// reset state
|
||||
this.active = false;
|
||||
|
@ -245,10 +245,9 @@ public enum GameMod {
|
|||
public boolean contains(float x, float y) { return button.contains(x, y); }
|
||||
|
||||
/**
|
||||
* Sets the current button scale (for hovering).
|
||||
* @param scale the new scale (default 1.0f)
|
||||
* Resets the hover fields for the button.
|
||||
*/
|
||||
public void setScale(float scale) { button.setScale(scale); }
|
||||
public void resetHover() { button.resetHover(); }
|
||||
|
||||
/**
|
||||
* Updates the scale of the button depending on whether or not the cursor
|
||||
|
|
|
@ -20,6 +20,7 @@ package itdelatrisu.opsu;
|
|||
|
||||
import org.newdawn.slick.Animation;
|
||||
import org.newdawn.slick.Color;
|
||||
import org.newdawn.slick.Font;
|
||||
import org.newdawn.slick.Image;
|
||||
|
||||
/**
|
||||
|
@ -43,8 +44,26 @@ public class MenuButton {
|
|||
/** The x and y radius of the button (scaled). */
|
||||
private float xRadius, yRadius;
|
||||
|
||||
/** The text to draw on the button. */
|
||||
private String text;
|
||||
|
||||
/** The font to draw the text with. */
|
||||
private Font font;
|
||||
|
||||
/** The color to draw the text with. */
|
||||
private Color color;
|
||||
|
||||
/** Hover action types. */
|
||||
private enum HoverAction { NONE, EXPAND, FADE };
|
||||
|
||||
/** The hover action for this button. */
|
||||
private HoverAction hoverAction = HoverAction.NONE;
|
||||
|
||||
/** The current and max scale of the button (for hovering). */
|
||||
private float scale, hoverScale = 1.25f;
|
||||
private float scale = 1f, hoverScale = 1.25f;
|
||||
|
||||
/** The current and base alpha level of the button (for hovering). */
|
||||
private float alpha = 1f, baseAlpha = 0.75f;
|
||||
|
||||
/** The scaled expansion direction for the button (for hovering). */
|
||||
private Expand dir = Expand.CENTER;
|
||||
|
@ -64,7 +83,6 @@ public class MenuButton {
|
|||
this.y = y;
|
||||
this.xRadius = img.getWidth() / 2f;
|
||||
this.yRadius = img.getHeight() / 2f;
|
||||
this.scale = 1f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +101,6 @@ public class MenuButton {
|
|||
this.y = y;
|
||||
this.xRadius = (img.getWidth() + imgL.getWidth() + imgR.getWidth()) / 2f;
|
||||
this.yRadius = img.getHeight() / 2f;
|
||||
this.scale = 1f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,7 +115,6 @@ public class MenuButton {
|
|||
this.y = y;
|
||||
this.xRadius = anim.getWidth() / 2f;
|
||||
this.yRadius = anim.getHeight() / 2f;
|
||||
this.scale = 1f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,6 +137,18 @@ public class MenuButton {
|
|||
*/
|
||||
public float getY() { return y; }
|
||||
|
||||
/**
|
||||
* Sets text to draw in the middle of the button.
|
||||
* @param text the text to draw
|
||||
* @param font the font to use when drawing
|
||||
* @color the color to draw the text
|
||||
*/
|
||||
public void setText(String text, Font font, Color color) {
|
||||
this.text = text;
|
||||
this.font = font;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated image.
|
||||
*/
|
||||
|
@ -137,16 +165,39 @@ public class MenuButton {
|
|||
public void draw() {
|
||||
if (img != null) {
|
||||
if (imgL == null) {
|
||||
Image imgScaled = (scale == 1f) ? img : img.getScaledCopy(scale);
|
||||
imgScaled.setAlpha(img.getAlpha());
|
||||
imgScaled.draw(x - xRadius, y - yRadius);
|
||||
if (hoverAction == HoverAction.EXPAND) {
|
||||
Image imgScaled = (scale == 1f) ? img : img.getScaledCopy(scale);
|
||||
imgScaled.setAlpha(img.getAlpha());
|
||||
imgScaled.draw(x - xRadius, y - yRadius);
|
||||
} else if (hoverAction == HoverAction.FADE) {
|
||||
float a = img.getAlpha();
|
||||
img.setAlpha(alpha);
|
||||
img.draw(x - xRadius, y - yRadius);
|
||||
img.setAlpha(a);
|
||||
} else
|
||||
img.draw(x - xRadius, y - yRadius);
|
||||
} else {
|
||||
img.draw(x - xRadius + imgL.getWidth(), y - yRadius);
|
||||
imgL.draw(x - xRadius, y - yRadius);
|
||||
imgR.draw(x + xRadius - imgR.getWidth(), y - yRadius);
|
||||
if (hoverAction == HoverAction.FADE) {
|
||||
float a = img.getAlpha(), aL = imgL.getAlpha(), aR = imgR.getAlpha();
|
||||
img.setAlpha(alpha);
|
||||
imgL.setAlpha(alpha);
|
||||
imgR.setAlpha(alpha);
|
||||
img.draw(x - xRadius + imgL.getWidth(), y - yRadius);
|
||||
imgL.draw(x - xRadius, y - yRadius);
|
||||
imgR.draw(x + xRadius - imgR.getWidth(), y - yRadius);
|
||||
img.setAlpha(a);
|
||||
imgL.setAlpha(aL);
|
||||
imgR.setAlpha(aR);
|
||||
} else {
|
||||
img.draw(x - xRadius + imgL.getWidth(), y - yRadius);
|
||||
imgL.draw(x - xRadius, y - yRadius);
|
||||
imgR.draw(x + xRadius - imgR.getWidth(), y - yRadius);
|
||||
}
|
||||
}
|
||||
} else
|
||||
anim.draw(x - xRadius, y - yRadius);
|
||||
if (text != null)
|
||||
font.drawString(x - font.getWidth(text) / 2f, y - font.getLineHeight() / 2f, text, color);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,15 +206,40 @@ public class MenuButton {
|
|||
*/
|
||||
public void draw(Color filter) {
|
||||
if (img != null) {
|
||||
if (imgL == null)
|
||||
img.getScaledCopy(scale).draw(x - xRadius, y - yRadius, filter);
|
||||
else {
|
||||
img.draw(x - xRadius + imgL.getWidth(), y - yRadius, filter);
|
||||
imgL.draw(x - xRadius, y - yRadius, filter);
|
||||
imgR.draw(x + xRadius - imgR.getWidth(), y - yRadius, filter);
|
||||
if (imgL == null) {
|
||||
if (hoverAction == HoverAction.EXPAND) {
|
||||
Image imgScaled = (scale == 1f) ? img : img.getScaledCopy(scale);
|
||||
imgScaled.setAlpha(img.getAlpha());
|
||||
imgScaled.draw(x - xRadius, y - yRadius, filter);
|
||||
} else if (hoverAction == HoverAction.FADE) {
|
||||
float a = img.getAlpha();
|
||||
img.setAlpha(alpha);
|
||||
img.draw(x - xRadius, y - yRadius, filter);
|
||||
img.setAlpha(a);
|
||||
} else
|
||||
img.draw(x - xRadius, y - yRadius, filter);
|
||||
} else {
|
||||
if (hoverAction == HoverAction.FADE) {
|
||||
float a = img.getAlpha(), aL = imgL.getAlpha(), aR = imgR.getAlpha();
|
||||
img.setAlpha(alpha);
|
||||
imgL.setAlpha(alpha);
|
||||
imgR.setAlpha(alpha);
|
||||
img.draw(x - xRadius + imgL.getWidth(), y - yRadius, filter);
|
||||
imgL.draw(x - xRadius, y - yRadius, filter);
|
||||
imgR.draw(x + xRadius - imgR.getWidth(), y - yRadius, filter);
|
||||
img.setAlpha(a);
|
||||
imgL.setAlpha(aL);
|
||||
imgR.setAlpha(aR);
|
||||
} else {
|
||||
img.draw(x - xRadius + imgL.getWidth(), y - yRadius, filter);
|
||||
imgL.draw(x - xRadius, y - yRadius, filter);
|
||||
imgR.draw(x + xRadius - imgR.getWidth(), y - yRadius, filter);
|
||||
}
|
||||
}
|
||||
} else
|
||||
anim.draw(x - xRadius, y - yRadius, filter);
|
||||
if (text != null)
|
||||
font.drawString(x - font.getWidth(text) / 2f, y - font.getLineHeight() / 2f, text, color);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,45 +253,91 @@ public class MenuButton {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the current button scale (for hovering).
|
||||
* @param scale the new scale (default 1.0f)
|
||||
* Resets the hover fields for the button.
|
||||
*/
|
||||
public void setScale(float scale) {
|
||||
this.scale = scale;
|
||||
setHoverRadius();
|
||||
public void resetHover() {
|
||||
if (hoverAction == HoverAction.EXPAND) {
|
||||
this.scale = 1f;
|
||||
setHoverRadius();
|
||||
} else if (hoverAction == HoverAction.FADE)
|
||||
this.alpha = baseAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum scale factor for the button (for hovering).
|
||||
* Sets the hover action to "expand".
|
||||
*/
|
||||
public void setHoverExpand() { this.hoverAction = HoverAction.EXPAND; }
|
||||
|
||||
/**
|
||||
* Sets the hover action to "expand".
|
||||
* @param scale the maximum scale factor (default 1.25f)
|
||||
*/
|
||||
public void setHoverScale(float scale) { this.hoverScale = scale; }
|
||||
public void setHoverExpand(float scale) { setHoverExpand(scale, this.dir); }
|
||||
|
||||
/**
|
||||
* Sets the expansion direction when hovering over the button.
|
||||
* @param dir the direction
|
||||
* Sets the hover action to "expand".
|
||||
* @param dir the expansion direction
|
||||
*/
|
||||
public void setHoverDir(Expand dir) { this.dir = dir; }
|
||||
public void setHoverExpand(Expand dir) { setHoverExpand(this.hoverScale, dir); }
|
||||
|
||||
/**
|
||||
* Updates the scale of the button depending on whether or not the cursor
|
||||
* Sets the hover action to "expand".
|
||||
* @param scale the maximum scale factor (default 1.25f)
|
||||
* @param dir the expansion direction
|
||||
*/
|
||||
public void setHoverExpand(float scale, Expand dir) {
|
||||
this.hoverAction = HoverAction.EXPAND;
|
||||
this.hoverScale = scale;
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hover action to "fade".
|
||||
*/
|
||||
public void setHoverFade() { this.hoverAction = HoverAction.FADE; }
|
||||
|
||||
/**
|
||||
* Sets the hover action to "fade".
|
||||
* @param baseAlpha the base alpha level to fade in from (default 0.7f)
|
||||
*/
|
||||
public void setHoverFade(float baseAlpha) {
|
||||
this.hoverAction = HoverAction.FADE;
|
||||
this.baseAlpha = baseAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a hover action depending on whether or not the cursor
|
||||
* is hovering over the button.
|
||||
* @param delta the delta interval
|
||||
* @param cx the x coordinate
|
||||
* @param cy the y coordinate
|
||||
*/
|
||||
public void hoverUpdate(int delta, float cx, float cy) {
|
||||
if (hoverAction == HoverAction.NONE)
|
||||
return;
|
||||
|
||||
boolean isHover = contains(cx, cy);
|
||||
if (isHover && scale < hoverScale) {
|
||||
scale += (hoverScale - 1f) * delta / 100f;
|
||||
if (scale > hoverScale)
|
||||
scale = hoverScale;
|
||||
setHoverRadius();
|
||||
} else if (!isHover && scale > 1f) {
|
||||
scale -= (hoverScale - 1f) * delta / 100f;
|
||||
if (scale < 1f)
|
||||
scale = 1f;
|
||||
if (hoverAction == HoverAction.EXPAND) {
|
||||
// scale the button
|
||||
int sign;
|
||||
if (isHover && scale < hoverScale)
|
||||
sign = 1;
|
||||
else if (!isHover && scale > 1f)
|
||||
sign = -1;
|
||||
else
|
||||
return;
|
||||
scale = Utils.getBoundedValue(scale, sign * (hoverScale - 1f) * delta / 100f, 1, hoverScale);
|
||||
setHoverRadius();
|
||||
} else {
|
||||
// fade the button
|
||||
int sign;
|
||||
if (isHover && alpha < 1f)
|
||||
sign = 1;
|
||||
else if (!isHover && alpha > baseAlpha)
|
||||
sign = -1;
|
||||
else
|
||||
return;
|
||||
alpha = Utils.getBoundedValue(alpha, sign * (1f - baseAlpha) * delta / 200f, baseAlpha, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,10 +89,13 @@ public class OsuGroupList {
|
|||
/**
|
||||
* Adds a song group.
|
||||
* @param osuFiles the list of OsuFile objects in the group
|
||||
* @return the new OsuGroupNode
|
||||
*/
|
||||
public void addSongGroup(ArrayList<OsuFile> osuFiles) {
|
||||
parsedNodes.add(new OsuGroupNode(osuFiles));
|
||||
public OsuGroupNode addSongGroup(ArrayList<OsuFile> osuFiles) {
|
||||
OsuGroupNode node = new OsuGroupNode(osuFiles);
|
||||
parsedNodes.add(node);
|
||||
mapCount += osuFiles.size();
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,23 +53,38 @@ public class OsuParser {
|
|||
private OsuParser() {}
|
||||
|
||||
/**
|
||||
* Invokes parser for each OSU file in a root directory.
|
||||
* Invokes parser for each OSU file in a root directory and
|
||||
* adds the OsuFiles to a new OsuGroupList.
|
||||
* @param root the root directory (search has depth 1)
|
||||
*/
|
||||
public static void parseAllFiles(File root) {
|
||||
// create a new OsuGroupList
|
||||
OsuGroupList.create();
|
||||
|
||||
// progress tracking
|
||||
File[] folders = root.listFiles();
|
||||
currentDirectoryIndex = 0;
|
||||
totalDirectories = folders.length;
|
||||
// parse all directories
|
||||
parseDirectories(root.listFiles());
|
||||
}
|
||||
|
||||
for (File folder : folders) {
|
||||
/**
|
||||
* Invokes parser for each directory in the given array and
|
||||
* adds the OsuFiles to the existing OsuGroupList.
|
||||
* @param dirs the array of directories to parse
|
||||
* @return the last OsuGroupNode parsed
|
||||
*/
|
||||
public static OsuGroupNode parseDirectories(File[] dirs) {
|
||||
// progress tracking
|
||||
currentDirectoryIndex = 0;
|
||||
totalDirectories = dirs.length;
|
||||
|
||||
// parse directories
|
||||
OsuGroupNode lastNode = null;
|
||||
for (File dir : dirs) {
|
||||
currentDirectoryIndex++;
|
||||
if (!folder.isDirectory())
|
||||
if (!dir.isDirectory())
|
||||
continue;
|
||||
File[] files = folder.listFiles(new FilenameFilter() {
|
||||
|
||||
// find all OSU files
|
||||
File[] files = dir.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().endsWith(".osu");
|
||||
|
@ -90,10 +105,10 @@ public class OsuParser {
|
|||
if (!osuFiles.isEmpty()) { // add entry if non-empty
|
||||
osuFiles.trimToSize();
|
||||
Collections.sort(osuFiles);
|
||||
OsuGroupList.get().addSongGroup(osuFiles);
|
||||
lastNode = OsuGroupList.get().addSongGroup(osuFiles);
|
||||
}
|
||||
|
||||
// stop parsing files (interrupt sent by Splash)
|
||||
// stop parsing files (interrupted)
|
||||
if (Thread.interrupted())
|
||||
break;
|
||||
}
|
||||
|
@ -104,6 +119,7 @@ public class OsuParser {
|
|||
currentFile = null;
|
||||
currentDirectoryIndex = -1;
|
||||
totalDirectories = -1;
|
||||
return lastNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,8 @@ package itdelatrisu.opsu;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lingala.zip4j.core.ZipFile;
|
||||
import net.lingala.zip4j.exception.ZipException;
|
||||
|
@ -41,8 +43,13 @@ public class OszUnpacker {
|
|||
* Invokes the unpacker for each OSZ archive in a root directory.
|
||||
* @param root the root directory
|
||||
* @param dest the destination directory
|
||||
* @return an array containing the new (unpacked) directories, or null
|
||||
* if no OSZs found
|
||||
*/
|
||||
public static void unpackAllFiles(File root, File dest) {
|
||||
public static File[] unpackAllFiles(File root, File dest) {
|
||||
List<File> dirs = new ArrayList<File>();
|
||||
|
||||
// find all OSZ files
|
||||
files = root.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
|
@ -51,9 +58,10 @@ public class OszUnpacker {
|
|||
});
|
||||
if (files.length < 1) {
|
||||
files = null;
|
||||
return;
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
// unpack OSZs
|
||||
for (File file : files) {
|
||||
fileIndex++;
|
||||
String dirName = file.getName().substring(0, file.getName().lastIndexOf('.'));
|
||||
|
@ -62,11 +70,13 @@ public class OszUnpacker {
|
|||
songDir.mkdir();
|
||||
unzip(file, songDir);
|
||||
file.delete(); // delete the OSZ when finished
|
||||
dirs.add(songDir);
|
||||
}
|
||||
}
|
||||
|
||||
fileIndex = -1;
|
||||
files = null;
|
||||
return dirs.toArray(new File[dirs.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.io.File;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -109,6 +110,19 @@ public class Utils {
|
|||
/** Set of all Unicode strings already loaded. */
|
||||
private static HashSet<String> loadedGlyphs = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* List of illegal filename characters.
|
||||
* @see #cleanFileName(String, char)
|
||||
*/
|
||||
private final static int[] illegalChars = {
|
||||
34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47
|
||||
};
|
||||
static {
|
||||
Arrays.sort(illegalChars);
|
||||
}
|
||||
|
||||
// game-related variables
|
||||
private static GameContainer container;
|
||||
private static StateBasedGame game;
|
||||
|
@ -211,7 +225,7 @@ public class Utils {
|
|||
backButton = new MenuButton(back,
|
||||
back.getWidth() / 2f,
|
||||
height - (back.getHeight() / 2f));
|
||||
backButton.setHoverDir(MenuButton.Expand.UP_RIGHT);
|
||||
backButton.setHoverExpand(MenuButton.Expand.UP_RIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -704,4 +718,24 @@ public class Utils {
|
|||
char pre = "KMGTPE".charAt(exp - 1);
|
||||
return String.format("%.1f %cB", bytes / Math.pow(1024, exp), pre);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans a file name.
|
||||
* @param badFileName the original name string
|
||||
* @param replace the character to replace illegal characters with (or 0 if none)
|
||||
* @return the cleaned file name
|
||||
* @author Sarel Botha (http://stackoverflow.com/a/5626340)
|
||||
*/
|
||||
public static String cleanFileName(String badFileName, char replace) {
|
||||
boolean doReplace = (replace > 0 && Arrays.binarySearch(illegalChars, replace) < 0);
|
||||
StringBuilder cleanName = new StringBuilder();
|
||||
for (int i = 0, n = badFileName.length(); i < n; i++) {
|
||||
int c = badFileName.charAt(i);
|
||||
if (Arrays.binarySearch(illegalChars, c) < 0)
|
||||
cleanName.append((char) c);
|
||||
else if (doReplace)
|
||||
cleanName.append(replace);
|
||||
}
|
||||
return cleanName.toString();
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
package itdelatrisu.opsu.downloads;
|
||||
|
||||
import itdelatrisu.opsu.ErrorHandler;
|
||||
import itdelatrisu.opsu.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -155,8 +156,9 @@ public class Download {
|
|||
rbc.close();
|
||||
fos.close();
|
||||
if (rename != null) {
|
||||
String cleanedName = Utils.cleanFileName(rename, '-');
|
||||
Path source = new File(localPath).toPath();
|
||||
Files.move(source, source.resolveSibling(rename), StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.move(source, source.resolveSibling(cleanedName), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import itdelatrisu.opsu.ErrorHandler;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -126,6 +127,21 @@ public class DownloadList {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all inactive downloads from the list.
|
||||
*/
|
||||
public void clearInactiveDownloads() {
|
||||
Iterator<DownloadNode> iter = nodes.iterator();
|
||||
while (iter.hasNext()) {
|
||||
DownloadNode node = iter.next();
|
||||
Download dl = node.getDownload();
|
||||
if (dl != null && !dl.isActive()) {
|
||||
iter.remove();
|
||||
map.remove(node.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a confirmation dialog (used before exiting the game).
|
||||
* @return true if user selects "yes", false otherwise
|
||||
|
|
|
@ -23,7 +23,6 @@ import itdelatrisu.opsu.GameImage;
|
|||
import itdelatrisu.opsu.Options;
|
||||
import itdelatrisu.opsu.Utils;
|
||||
import itdelatrisu.opsu.downloads.Download.Status;
|
||||
import itdelatrisu.opsu.states.DownloadsMenu;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
@ -59,6 +58,9 @@ public class DownloadNode {
|
|||
/** Information drawing values. */
|
||||
private static float infoBaseX, infoBaseY, infoWidth, infoHeight;
|
||||
|
||||
/** Maximum number of results and downloads to display on one screen. */
|
||||
private static int maxResultsShown, maxDownloadsShown;
|
||||
|
||||
/** Container dimensions. */
|
||||
private static int containerWidth, containerHeight;
|
||||
|
||||
|
@ -89,8 +91,23 @@ public class DownloadNode {
|
|||
infoBaseY = height * 0.07f + Utils.FONT_LARGE.getLineHeight() * 2f;
|
||||
infoWidth = width * 0.25f;
|
||||
infoHeight = Utils.FONT_DEFAULT.getLineHeight() * 2.4f;
|
||||
|
||||
float searchY = (height * 0.05f) + Utils.FONT_LARGE.getLineHeight();
|
||||
float buttonHeight = height * 0.038f;
|
||||
maxResultsShown = (int) ((height - buttonBaseY - searchY) / buttonOffset);
|
||||
maxDownloadsShown = (int) ((height - infoBaseY - searchY - buttonHeight) / infoHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max number of search result buttons to be shown at a time.
|
||||
*/
|
||||
public static int maxResultsShown() { return maxResultsShown; }
|
||||
|
||||
/**
|
||||
* Returns the max number of downloads to be shown at a time.
|
||||
*/
|
||||
public static int maxDownloadsShown() { return maxDownloadsShown; }
|
||||
|
||||
/**
|
||||
* Returns true if the coordinates are within the bounds of the
|
||||
* download result button at the given index.
|
||||
|
@ -112,7 +129,7 @@ public class DownloadNode {
|
|||
*/
|
||||
public static boolean resultAreaContains(float cx, float cy) {
|
||||
return ((cx > buttonBaseX && cx < buttonBaseX + buttonWidth) &&
|
||||
(cy > buttonBaseY && cy < buttonBaseY + buttonOffset * DownloadsMenu.MAX_RESULT_BUTTONS));
|
||||
(cy > buttonBaseY && cy < buttonBaseY + buttonOffset * maxResultsShown));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,7 +169,7 @@ public class DownloadNode {
|
|||
*/
|
||||
public static boolean downloadAreaContains(float cx, float cy) {
|
||||
return ((cx > infoBaseX && cx <= containerWidth) &&
|
||||
(cy > infoBaseY && cy < infoBaseY + infoHeight * DownloadsMenu.MAX_DOWNLOADS_SHOWN));
|
||||
(cy > infoBaseY && cy < infoBaseY + infoHeight * maxDownloadsShown));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,10 +182,10 @@ public class DownloadNode {
|
|||
float scrollbarWidth = containerWidth * 0.00347f;
|
||||
float heightRatio = 0.0016f * (total * total) - 0.0705f * total + 0.9965f;
|
||||
float scrollbarHeight = containerHeight * heightRatio;
|
||||
float heightDiff = buttonHeight + buttonOffset * (DownloadsMenu.MAX_RESULT_BUTTONS - 1) - scrollbarHeight;
|
||||
float offsetY = heightDiff * ((float) index / (total - DownloadsMenu.MAX_RESULT_BUTTONS));
|
||||
float heightDiff = buttonHeight + buttonOffset * (maxResultsShown - 1) - scrollbarHeight;
|
||||
float offsetY = heightDiff * ((float) index / (total - maxResultsShown));
|
||||
g.setColor(BG_NORMAL);
|
||||
g.fillRect(buttonBaseX + buttonWidth * 1.005f, buttonBaseY, scrollbarWidth, buttonOffset * DownloadsMenu.MAX_RESULT_BUTTONS);
|
||||
g.fillRect(buttonBaseX + buttonWidth * 1.005f, buttonBaseY, scrollbarWidth, buttonOffset * maxResultsShown);
|
||||
g.setColor(Color.white);
|
||||
g.fillRect(buttonBaseX + buttonWidth * 1.005f, buttonBaseY + offsetY, scrollbarWidth, scrollbarHeight);
|
||||
}
|
||||
|
@ -183,10 +200,10 @@ public class DownloadNode {
|
|||
float scrollbarWidth = containerWidth * 0.00347f;
|
||||
float heightRatio = 0.0016f * (total * total) - 0.0705f * total + 0.9965f;
|
||||
float scrollbarHeight = containerHeight * heightRatio;
|
||||
float heightDiff = infoHeight + infoHeight * (DownloadsMenu.MAX_DOWNLOADS_SHOWN - 1) - scrollbarHeight;
|
||||
float offsetY = heightDiff * ((float) index / (total - DownloadsMenu.MAX_DOWNLOADS_SHOWN));
|
||||
float heightDiff = infoHeight + infoHeight * (maxDownloadsShown - 1) - scrollbarHeight;
|
||||
float offsetY = heightDiff * ((float) index / (total - maxDownloadsShown));
|
||||
g.setColor(BG_NORMAL);
|
||||
g.fillRect(infoBaseX + infoWidth - scrollbarWidth, infoBaseY, scrollbarWidth, infoHeight * DownloadsMenu.MAX_DOWNLOADS_SHOWN);
|
||||
g.fillRect(infoBaseX + infoWidth - scrollbarWidth, infoBaseY, scrollbarWidth, infoHeight * maxDownloadsShown);
|
||||
g.setColor(Color.white);
|
||||
g.fillRect(infoBaseX + infoWidth - scrollbarWidth, infoBaseY + offsetY, scrollbarWidth, scrollbarHeight);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ package itdelatrisu.opsu.states;
|
|||
import itdelatrisu.opsu.GameImage;
|
||||
import itdelatrisu.opsu.MenuButton;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.Options;
|
||||
import itdelatrisu.opsu.OsuGroupList;
|
||||
import itdelatrisu.opsu.OsuGroupNode;
|
||||
import itdelatrisu.opsu.OsuParser;
|
||||
import itdelatrisu.opsu.OszUnpacker;
|
||||
import itdelatrisu.opsu.Utils;
|
||||
import itdelatrisu.opsu.audio.SoundController;
|
||||
import itdelatrisu.opsu.audio.SoundEffect;
|
||||
|
@ -30,6 +35,7 @@ import itdelatrisu.opsu.downloads.DownloadList;
|
|||
import itdelatrisu.opsu.downloads.DownloadNode;
|
||||
import itdelatrisu.opsu.downloads.DownloadServer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
|
@ -48,12 +54,6 @@ import org.newdawn.slick.state.transition.FadeOutTransition;
|
|||
* Downloads menu.
|
||||
*/
|
||||
public class DownloadsMenu extends BasicGameState {
|
||||
/** The max number of search result buttons to be shown at a time. */
|
||||
public static final int MAX_RESULT_BUTTONS = 10;
|
||||
|
||||
/** The max number of downloads to be shown at a time. */
|
||||
public static final int MAX_DOWNLOADS_SHOWN = 11;
|
||||
|
||||
/** Delay time, in milliseconds, between each search. */
|
||||
private static final int SEARCH_DELAY = 700;
|
||||
|
||||
|
@ -129,8 +129,11 @@ public class DownloadsMenu extends BasicGameState {
|
|||
/** Previous and next page buttons. */
|
||||
private MenuButton prevPage, nextPage;
|
||||
|
||||
/** "Ranked only?" checkbox coordinates. */
|
||||
private float rankedBoxX, rankedBoxY, rankedBoxLength;
|
||||
/** Buttons. */
|
||||
private MenuButton clearButton, importButton, resetButton, rankedButton;
|
||||
|
||||
/** Beatmap importing thread. */
|
||||
private Thread importThread;
|
||||
|
||||
// game-related variables
|
||||
private StateBasedGame game;
|
||||
|
@ -150,14 +153,15 @@ public class DownloadsMenu extends BasicGameState {
|
|||
int width = container.getWidth();
|
||||
int height = container.getHeight();
|
||||
float baseX = width * 0.024f;
|
||||
float searchY = (height * 0.05f) + Utils.FONT_LARGE.getLineHeight();
|
||||
float searchWidth = width * 0.35f;
|
||||
|
||||
// search
|
||||
searchTimer = SEARCH_DELAY;
|
||||
searchResultString = "Type to search!";
|
||||
search = new TextField(
|
||||
container, Utils.FONT_DEFAULT,
|
||||
(int) baseX, (int) (height * 0.05f) + Utils.FONT_LARGE.getLineHeight(),
|
||||
(int) (width * 0.35f), Utils.FONT_MEDIUM.getLineHeight()
|
||||
container, Utils.FONT_DEFAULT, (int) baseX, (int) searchY,
|
||||
(int) searchWidth, Utils.FONT_MEDIUM.getLineHeight()
|
||||
);
|
||||
search.setBackgroundColor(DownloadNode.BG_NORMAL);
|
||||
search.setBorderColor(Color.white);
|
||||
|
@ -165,22 +169,46 @@ public class DownloadsMenu extends BasicGameState {
|
|||
search.setConsumeEvents(false);
|
||||
search.setMaxLength(255);
|
||||
|
||||
// ranked only?
|
||||
rankedBoxX = search.getX() + search.getWidth() * 1.2f;
|
||||
rankedBoxY = search.getY();
|
||||
rankedBoxLength = search.getHeight();
|
||||
|
||||
// page buttons
|
||||
float buttonY = height * 0.2f;
|
||||
float buttonWidth = width * 0.7f;
|
||||
float pageButtonY = height * 0.2f;
|
||||
float pageButtonWidth = width * 0.7f;
|
||||
Image prevImg = GameImage.MUSIC_PREVIOUS.getImage();
|
||||
Image nextImg = GameImage.MUSIC_NEXT.getImage();
|
||||
prevPage = new MenuButton(prevImg, baseX + prevImg.getWidth() / 2f,
|
||||
buttonY - prevImg.getHeight() / 2f);
|
||||
nextPage = new MenuButton(nextImg, baseX + buttonWidth - nextImg.getWidth() / 2f,
|
||||
buttonY - nextImg.getHeight() / 2f);
|
||||
prevPage.setHoverScale(1.5f);
|
||||
nextPage.setHoverScale(1.5f);
|
||||
pageButtonY - prevImg.getHeight() / 2f);
|
||||
nextPage = new MenuButton(nextImg, baseX + pageButtonWidth - nextImg.getWidth() / 2f,
|
||||
pageButtonY - nextImg.getHeight() / 2f);
|
||||
prevPage.setHoverExpand(1.5f);
|
||||
nextPage.setHoverExpand(1.5f);
|
||||
|
||||
// buttons
|
||||
float buttonWidth = width * 0.12f;
|
||||
float buttonMarginX = width * 0.004f;
|
||||
float buttonHeight = height * 0.038f;
|
||||
float topButtonY = searchY + Utils.FONT_MEDIUM.getLineHeight() / 2f;
|
||||
float lowerButtonY = height * 0.995f - searchY - buttonHeight / 2f;
|
||||
Image button = GameImage.MENU_BUTTON_MID.getImage();
|
||||
Image buttonL = GameImage.MENU_BUTTON_LEFT.getImage();
|
||||
Image buttonR = GameImage.MENU_BUTTON_RIGHT.getImage();
|
||||
buttonL = buttonL.getScaledCopy(buttonHeight / buttonL.getHeight());
|
||||
buttonR = buttonR.getScaledCopy(buttonHeight / buttonR.getHeight());
|
||||
button = button.getScaledCopy((int) buttonWidth - buttonL.getWidth() - buttonR.getWidth(), (int) buttonHeight);
|
||||
float fullButtonWidth = button.getWidth() + buttonL.getWidth() + buttonR.getWidth();
|
||||
clearButton = new MenuButton(button, buttonL, buttonR,
|
||||
width * 0.75f + buttonMarginX + fullButtonWidth / 2f, lowerButtonY);
|
||||
importButton = new MenuButton(button, buttonL, buttonR,
|
||||
width - buttonMarginX - fullButtonWidth / 2f, lowerButtonY);
|
||||
resetButton = new MenuButton(button, buttonL, buttonR,
|
||||
baseX + searchWidth + buttonMarginX + fullButtonWidth / 2f, topButtonY);
|
||||
rankedButton = new MenuButton(button, buttonL, buttonR,
|
||||
baseX + searchWidth + buttonMarginX * 2f + fullButtonWidth * 3 / 2f, topButtonY);
|
||||
clearButton.setText("Clear", Utils.FONT_MEDIUM, Color.white);
|
||||
importButton.setText("Import All", Utils.FONT_MEDIUM, Color.white);
|
||||
resetButton.setText("Reset Search", Utils.FONT_MEDIUM, Color.white);
|
||||
clearButton.setHoverFade();
|
||||
importButton.setHoverFade();
|
||||
resetButton.setHoverFade();
|
||||
rankedButton.setHoverFade();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -204,17 +232,11 @@ public class DownloadsMenu extends BasicGameState {
|
|||
searchResultString, Color.white
|
||||
);
|
||||
|
||||
// ranked only?
|
||||
if (rankedOnly)
|
||||
g.fillRect(rankedBoxX, rankedBoxY, rankedBoxLength, rankedBoxLength);
|
||||
else
|
||||
g.drawRect(rankedBoxX, rankedBoxY, rankedBoxLength, rankedBoxLength);
|
||||
Utils.FONT_MEDIUM.drawString(rankedBoxX + rankedBoxLength * 1.5f, rankedBoxY, "Show ranked maps only?", Color.white);
|
||||
|
||||
// search results
|
||||
DownloadNode[] nodes = resultList;
|
||||
if (nodes != null) {
|
||||
for (int i = 0; i < MAX_RESULT_BUTTONS; i++) {
|
||||
int maxResultsShown = DownloadNode.maxResultsShown();
|
||||
for (int i = 0; i < maxResultsShown; i++) {
|
||||
int index = startResult + i;
|
||||
if (index >= nodes.length)
|
||||
break;
|
||||
|
@ -222,7 +244,7 @@ public class DownloadsMenu extends BasicGameState {
|
|||
}
|
||||
|
||||
// scroll bar
|
||||
if (nodes.length > MAX_RESULT_BUTTONS)
|
||||
if (nodes.length > maxResultsShown)
|
||||
DownloadNode.drawResultScrollbar(g, startResult, nodes.length);
|
||||
|
||||
// pages
|
||||
|
@ -250,7 +272,8 @@ public class DownloadsMenu extends BasicGameState {
|
|||
Utils.FONT_LARGE.drawString(downloadsX + width * 0.015f, downloadsY + height * 0.015f, "Downloads", Color.white);
|
||||
int downloadsSize = DownloadList.get().size();
|
||||
if (downloadsSize > 0) {
|
||||
for (int i = 0; i < MAX_DOWNLOADS_SHOWN; i++) {
|
||||
int maxDownloadsShown = DownloadNode.maxDownloadsShown();
|
||||
for (int i = 0; i < maxDownloadsShown; i++) {
|
||||
int index = startDownloadIndex + i;
|
||||
if (index >= downloadsSize)
|
||||
break;
|
||||
|
@ -258,11 +281,30 @@ public class DownloadsMenu extends BasicGameState {
|
|||
}
|
||||
|
||||
// scroll bar
|
||||
if (downloadsSize > MAX_DOWNLOADS_SHOWN)
|
||||
if (downloadsSize > maxDownloadsShown)
|
||||
DownloadNode.drawDownloadScrollbar(g, startDownloadIndex, downloadsSize);
|
||||
}
|
||||
|
||||
Utils.getBackButton().draw();
|
||||
// buttons
|
||||
clearButton.draw(Color.gray);
|
||||
importButton.draw(Color.orange);
|
||||
resetButton.draw(Color.red);
|
||||
rankedButton.setText((rankedOnly) ? "Show Unranked" : "Hide Unranked", Utils.FONT_MEDIUM, Color.white);
|
||||
rankedButton.draw(Color.magenta);
|
||||
|
||||
// importing beatmaps
|
||||
if (importThread != null) {
|
||||
// darken the screen
|
||||
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
Utils.drawLoadingProgress(g);
|
||||
}
|
||||
|
||||
// back button
|
||||
else
|
||||
Utils.getBackButton().draw();
|
||||
|
||||
Utils.drawVolume(g);
|
||||
Utils.drawFPS();
|
||||
Utils.drawCursor();
|
||||
|
@ -277,6 +319,10 @@ public class DownloadsMenu extends BasicGameState {
|
|||
Utils.getBackButton().hoverUpdate(delta, mouseX, mouseY);
|
||||
prevPage.hoverUpdate(delta, mouseX, mouseY);
|
||||
nextPage.hoverUpdate(delta, mouseX, mouseY);
|
||||
clearButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
importButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
resetButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
rankedButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
|
||||
// focus timer
|
||||
if (focusResult != -1 && focusTimer < FOCUS_DELAY)
|
||||
|
@ -285,7 +331,7 @@ public class DownloadsMenu extends BasicGameState {
|
|||
// search
|
||||
search.setFocus(true);
|
||||
searchTimer += delta;
|
||||
if (searchTimer >= SEARCH_DELAY) {
|
||||
if (searchTimer >= SEARCH_DELAY && importThread == null) {
|
||||
searchTimer = 0;
|
||||
searchTimerReset = false;
|
||||
|
||||
|
@ -367,6 +413,10 @@ public class DownloadsMenu extends BasicGameState {
|
|||
if (button != Input.MOUSE_LEFT_BUTTON)
|
||||
return;
|
||||
|
||||
// block input during beatmap importing
|
||||
if (importThread != null)
|
||||
return;
|
||||
|
||||
// back
|
||||
if (Utils.getBackButton().contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUBACK);
|
||||
|
@ -375,25 +425,17 @@ public class DownloadsMenu extends BasicGameState {
|
|||
return;
|
||||
}
|
||||
|
||||
// ranked only?
|
||||
if ((x > rankedBoxX && x < rankedBoxX + rankedBoxLength) &&
|
||||
(y > rankedBoxY && y < rankedBoxY + rankedBoxLength)) {
|
||||
rankedOnly = !rankedOnly;
|
||||
lastQuery = null;
|
||||
pageDir = Page.CURRENT;
|
||||
resetSearchTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// search results
|
||||
DownloadNode[] nodes = resultList;
|
||||
if (nodes != null) {
|
||||
if (DownloadNode.resultAreaContains(x, y)) {
|
||||
for (int i = 0; i < MAX_RESULT_BUTTONS; i++) {
|
||||
int maxResultsShown = DownloadNode.maxResultsShown();
|
||||
for (int i = 0; i < maxResultsShown; i++) {
|
||||
int index = startResult + i;
|
||||
if (index >= nodes.length)
|
||||
break;
|
||||
if (DownloadNode.resultContains(x, y, i)) {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
if (index == focusResult) {
|
||||
if (focusTimer >= FOCUS_DELAY) {
|
||||
// too slow for double-click
|
||||
|
@ -424,6 +466,7 @@ public class DownloadsMenu extends BasicGameState {
|
|||
if (lastQueryDir == Page.PREVIOUS && queryThread != null && queryThread.isAlive())
|
||||
; // don't send consecutive requests
|
||||
else {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
pageDir = Page.PREVIOUS;
|
||||
lastQuery = null;
|
||||
resetSearchTimer();
|
||||
|
@ -434,6 +477,7 @@ public class DownloadsMenu extends BasicGameState {
|
|||
if (lastQueryDir == Page.NEXT && queryThread != null && queryThread.isAlive())
|
||||
; // don't send consecutive requests
|
||||
else {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
pageDir = Page.NEXT;
|
||||
lastQuery = null;
|
||||
resetSearchTimer();
|
||||
|
@ -443,9 +487,58 @@ public class DownloadsMenu extends BasicGameState {
|
|||
}
|
||||
}
|
||||
|
||||
// buttons
|
||||
if (clearButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
DownloadList.get().clearInactiveDownloads();
|
||||
return;
|
||||
}
|
||||
if (importButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
|
||||
// import songs in new thread
|
||||
importThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// invoke unpacker and parser
|
||||
File[] dirs = OszUnpacker.unpackAllFiles(Options.getOSZDir(), Options.getBeatmapDir());
|
||||
if (dirs != null && dirs.length > 0) {
|
||||
OsuGroupNode node = OsuParser.parseDirectories(dirs);
|
||||
if (node != null) {
|
||||
// initialize song list
|
||||
OsuGroupList.get().reset();
|
||||
OsuGroupList.get().init();
|
||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).setFocus(node, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
importThread = null;
|
||||
}
|
||||
};
|
||||
importThread.start();
|
||||
return;
|
||||
}
|
||||
if (resetButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
search.setText("");
|
||||
lastQuery = null;
|
||||
pageDir = Page.RESET;
|
||||
resetSearchTimer();
|
||||
return;
|
||||
}
|
||||
if (rankedButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
rankedOnly = !rankedOnly;
|
||||
lastQuery = null;
|
||||
pageDir = Page.CURRENT;
|
||||
resetSearchTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// downloads
|
||||
if (!DownloadList.get().isEmpty() && DownloadNode.downloadAreaContains(x, y)) {
|
||||
for (int i = 0, n = DownloadList.get().size(); i < MAX_DOWNLOADS_SHOWN; i++) {
|
||||
int maxDownloadsShown = DownloadNode.maxDownloadsShown();
|
||||
for (int i = 0, n = DownloadList.get().size(); i < maxDownloadsShown; i++) {
|
||||
int index = startDownloadIndex + i;
|
||||
if (index >= n)
|
||||
break;
|
||||
|
@ -472,6 +565,10 @@ public class DownloadsMenu extends BasicGameState {
|
|||
|
||||
@Override
|
||||
public void mouseWheelMoved(int newValue) {
|
||||
// block input during beatmap importing
|
||||
if (importThread != null)
|
||||
return;
|
||||
|
||||
int shift = (newValue < 0) ? 1 : -1;
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
scrollLists(mouseX, mouseY, shift);
|
||||
|
@ -479,6 +576,10 @@ public class DownloadsMenu extends BasicGameState {
|
|||
|
||||
@Override
|
||||
public void mouseDragged(int oldx, int oldy, int newx, int newy) {
|
||||
// block input during beatmap importing
|
||||
if (importThread != null)
|
||||
return;
|
||||
|
||||
// check mouse button
|
||||
if (!input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON) &&
|
||||
!input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON))
|
||||
|
@ -493,9 +594,16 @@ public class DownloadsMenu extends BasicGameState {
|
|||
|
||||
@Override
|
||||
public void keyPressed(int key, char c) {
|
||||
// block input during beatmap importing
|
||||
if (importThread != null && !(key == Input.KEY_ESCAPE || key == Input.KEY_F12))
|
||||
return;
|
||||
|
||||
switch (key) {
|
||||
case Input.KEY_ESCAPE:
|
||||
if (!search.getText().isEmpty()) {
|
||||
if (importThread != null) {
|
||||
// beatmap importing: stop parsing OsuFiles by sending interrupt to OsuParser
|
||||
importThread.interrupt();
|
||||
} else if (!search.getText().isEmpty()) {
|
||||
// clear search text
|
||||
search.setText("");
|
||||
pageDir = Page.RESET;
|
||||
|
@ -514,6 +622,7 @@ public class DownloadsMenu extends BasicGameState {
|
|||
}
|
||||
break;
|
||||
case Input.KEY_F5:
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
lastQuery = null;
|
||||
pageDir = Page.CURRENT;
|
||||
resetSearchTimer();
|
||||
|
@ -534,9 +643,13 @@ public class DownloadsMenu extends BasicGameState {
|
|||
@Override
|
||||
public void enter(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
Utils.getBackButton().setScale(1f);
|
||||
prevPage.setScale(1f);
|
||||
nextPage.setScale(1f);
|
||||
Utils.getBackButton().resetHover();
|
||||
prevPage.resetHover();
|
||||
nextPage.resetHover();
|
||||
clearButton.resetHover();
|
||||
importButton.resetHover();
|
||||
resetButton.resetHover();
|
||||
rankedButton.resetHover();
|
||||
focusResult = -1;
|
||||
startResult = 0;
|
||||
startDownloadIndex = 0;
|
||||
|
@ -567,18 +680,18 @@ public class DownloadsMenu extends BasicGameState {
|
|||
// search results
|
||||
if (DownloadNode.resultAreaContains(cx, cy)) {
|
||||
DownloadNode[] nodes = resultList;
|
||||
if (nodes != null && nodes.length >= MAX_RESULT_BUTTONS) {
|
||||
if (nodes != null && nodes.length >= DownloadNode.maxResultsShown()) {
|
||||
int newStartResult = startResult + shift;
|
||||
if (newStartResult >= 0 && newStartResult + MAX_RESULT_BUTTONS <= nodes.length)
|
||||
if (newStartResult >= 0 && newStartResult + DownloadNode.maxResultsShown() <= nodes.length)
|
||||
startResult = newStartResult;
|
||||
}
|
||||
}
|
||||
|
||||
// downloads
|
||||
else if (DownloadNode.downloadAreaContains(cx, cy)) {
|
||||
if (DownloadList.get().size() >= MAX_DOWNLOADS_SHOWN) {
|
||||
if (DownloadList.get().size() >= DownloadNode.maxDownloadsShown()) {
|
||||
int newStartDownloadIndex = startDownloadIndex + shift;
|
||||
if (newStartDownloadIndex >= 0 && newStartDownloadIndex + MAX_DOWNLOADS_SHOWN <= DownloadList.get().size())
|
||||
if (newStartDownloadIndex >= 0 && newStartDownloadIndex + DownloadNode.maxDownloadsShown() <= DownloadList.get().size())
|
||||
startDownloadIndex = newStartDownloadIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -730,7 +730,7 @@ public class Game extends BasicGameState {
|
|||
restart = Restart.FALSE;
|
||||
}
|
||||
|
||||
skipButton.setScale(1f);
|
||||
skipButton.resetHover();
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
@ -806,7 +806,7 @@ public class Game extends BasicGameState {
|
|||
skipButton = new MenuButton(skip,
|
||||
width - (skip.getWidth() / 2f),
|
||||
height - (skip.getHeight() / 2f));
|
||||
skipButton.setHoverDir(MenuButton.Expand.UP_LEFT);
|
||||
skipButton.setHoverExpand(MenuButton.Expand.UP_LEFT);
|
||||
|
||||
// load other images...
|
||||
((GamePauseMenu) game.getState(Opsu.STATE_GAMEPAUSEMENU)).loadImages();
|
||||
|
|
|
@ -196,9 +196,9 @@ public class GamePauseMenu extends BasicGameState {
|
|||
SoundController.playSound(SoundEffect.FAIL);
|
||||
} else
|
||||
MusicController.pause();
|
||||
continueButton.setScale(1f);
|
||||
retryButton.setScale(1f);
|
||||
backButton.setScale(1f);
|
||||
continueButton.resetHover();
|
||||
retryButton.resetHover();
|
||||
backButton.resetHover();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,5 +212,8 @@ public class GamePauseMenu extends BasicGameState {
|
|||
continueButton = new MenuButton(GameImage.PAUSE_CONTINUE.getImage(), width / 2f, height * 0.25f);
|
||||
retryButton = new MenuButton(GameImage.PAUSE_RETRY.getImage(), width / 2f, height * 0.5f);
|
||||
backButton = new MenuButton(GameImage.PAUSE_BACK.getImage(), width / 2f, height * 0.75f);
|
||||
continueButton.setHoverExpand();
|
||||
retryButton.setHoverExpand();
|
||||
backButton.setHoverExpand();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ public class GameRanking extends BasicGameState {
|
|||
public void enter(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
Display.setTitle(game.getTitle());
|
||||
Utils.getBackButton().setScale(1f);
|
||||
Utils.getBackButton().resetHover();
|
||||
if (!data.isGameplay()) {
|
||||
if (!MusicController.isTrackDimmed())
|
||||
MusicController.toggleTrackDimmed(0.5f);
|
||||
|
|
|
@ -126,9 +126,9 @@ public class MainMenu extends BasicGameState {
|
|||
exitButton = new MenuButton(exitImg,
|
||||
width * 0.75f - exitOffset, (height / 2) + (exitImg.getHeight() / 2f)
|
||||
);
|
||||
logo.setHoverScale(1.05f);
|
||||
playButton.setHoverScale(1.05f);
|
||||
exitButton.setHoverScale(1.05f);
|
||||
logo.setHoverExpand(1.05f);
|
||||
playButton.setHoverExpand(1.05f);
|
||||
exitButton.setHoverExpand(1.05f);
|
||||
|
||||
// initialize music buttons
|
||||
int musicWidth = 48;
|
||||
|
@ -137,16 +137,15 @@ public class MainMenu extends BasicGameState {
|
|||
musicPause = new MenuButton(GameImage.MUSIC_PAUSE.getImage(), width - (2 * musicWidth), musicHeight);
|
||||
musicNext = new MenuButton(GameImage.MUSIC_NEXT.getImage(), width - musicWidth, musicHeight);
|
||||
musicPrevious = new MenuButton(GameImage.MUSIC_PREVIOUS.getImage(), width - (3 * musicWidth), musicHeight);
|
||||
musicPlay.setHoverScale(1.5f);
|
||||
musicPause.setHoverScale(1.5f);
|
||||
musicNext.setHoverScale(1.5f);
|
||||
musicPrevious.setHoverScale(1.5f);
|
||||
musicPlay.setHoverExpand(1.5f);
|
||||
musicPause.setHoverExpand(1.5f);
|
||||
musicNext.setHoverExpand(1.5f);
|
||||
musicPrevious.setHoverExpand(1.5f);
|
||||
|
||||
// initialize downloads button
|
||||
Image dlImg = GameImage.DOWNLOADS.getImage();
|
||||
downloadsButton = new MenuButton(dlImg, width - dlImg.getWidth() / 2f, height / 2f);
|
||||
downloadsButton.setHoverDir(Expand.LEFT);
|
||||
downloadsButton.setHoverScale(1.05f);
|
||||
downloadsButton.setHoverExpand(1.03f, Expand.LEFT);
|
||||
|
||||
// initialize repository button
|
||||
if (Desktop.isDesktopSupported()) { // only if a webpage can be opened
|
||||
|
@ -154,6 +153,7 @@ public class MainMenu extends BasicGameState {
|
|||
repoButton = new MenuButton(repoImg,
|
||||
(width * 0.997f) - repoImg.getWidth(), (height * 0.997f) - repoImg.getHeight()
|
||||
);
|
||||
repoButton.setHoverExpand();
|
||||
}
|
||||
|
||||
reset();
|
||||
|
@ -318,23 +318,23 @@ public class MainMenu extends BasicGameState {
|
|||
// 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))
|
||||
logo.setScale(1f);
|
||||
logo.resetHover();
|
||||
if (!playButton.contains(mouseX, mouseY))
|
||||
playButton.setScale(1f);
|
||||
playButton.resetHover();
|
||||
if (!exitButton.contains(mouseX, mouseY))
|
||||
exitButton.setScale(1f);
|
||||
exitButton.resetHover();
|
||||
if (!musicPlay.contains(mouseX, mouseY))
|
||||
musicPlay.setScale(1f);
|
||||
musicPlay.resetHover();
|
||||
if (!musicPause.contains(mouseX, mouseY))
|
||||
musicPause.setScale(1f);
|
||||
musicPause.resetHover();
|
||||
if (!musicNext.contains(mouseX, mouseY))
|
||||
musicNext.setScale(1f);
|
||||
musicNext.resetHover();
|
||||
if (!musicPrevious.contains(mouseX, mouseY))
|
||||
musicPrevious.setScale(1f);
|
||||
musicPrevious.resetHover();
|
||||
if (repoButton != null && !repoButton.contains(mouseX, mouseY))
|
||||
repoButton.setScale(1f);
|
||||
repoButton.resetHover();
|
||||
if (!downloadsButton.contains(mouseX, mouseY))
|
||||
downloadsButton.setScale(1f);
|
||||
downloadsButton.resetHover();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -452,13 +452,13 @@ public class MainMenu extends BasicGameState {
|
|||
logoClicked = false;
|
||||
logoTimer = 0;
|
||||
|
||||
logo.setScale(1f);
|
||||
playButton.setScale(1f);
|
||||
exitButton.setScale(1f);
|
||||
musicPlay.setScale(1f);
|
||||
musicPause.setScale(1f);
|
||||
musicNext.setScale(1f);
|
||||
musicPrevious.setScale(1f);
|
||||
downloadsButton.setScale(1f);
|
||||
logo.resetHover();
|
||||
playButton.resetHover();
|
||||
exitButton.resetHover();
|
||||
musicPlay.resetHover();
|
||||
musicPause.resetHover();
|
||||
musicNext.resetHover();
|
||||
musicPrevious.resetHover();
|
||||
downloadsButton.resetHover();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public class MainMenuExit extends BasicGameState {
|
|||
// game-related variables
|
||||
private GameContainer container;
|
||||
private StateBasedGame game;
|
||||
private Input input;
|
||||
private int state;
|
||||
|
||||
public MainMenuExit(int state) {
|
||||
|
@ -62,6 +63,7 @@ public class MainMenuExit extends BasicGameState {
|
|||
throws SlickException {
|
||||
this.container = container;
|
||||
this.game = game;
|
||||
this.input = container.getInput();
|
||||
|
||||
int width = container.getWidth();
|
||||
int height = container.getHeight();
|
||||
|
@ -70,14 +72,19 @@ public class MainMenuExit extends BasicGameState {
|
|||
|
||||
// initialize buttons
|
||||
Image button = GameImage.MENU_BUTTON_MID.getImage();
|
||||
button = button.getScaledCopy(width / 2, button.getHeight());
|
||||
Image buttonL = GameImage.MENU_BUTTON_LEFT.getImage();
|
||||
Image buttonR = GameImage.MENU_BUTTON_RIGHT.getImage();
|
||||
yesButton = new MenuButton(button, buttonL, buttonR,
|
||||
width / 2f + centerOffset, height * 0.2f
|
||||
);
|
||||
yesButton.setText("1. Yes", Utils.FONT_XLARGE, Color.white);
|
||||
noButton = new MenuButton(button, buttonL, buttonR,
|
||||
width / 2f - centerOffset, height * 0.2f + (button.getHeight() * 1.25f)
|
||||
);
|
||||
noButton.setText("2. No", Utils.FONT_XLARGE, Color.white);
|
||||
yesButton.setHoverFade();
|
||||
noButton.setHoverFade();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,16 +99,6 @@ public class MainMenuExit extends BasicGameState {
|
|||
// draw buttons
|
||||
yesButton.draw(Color.green);
|
||||
noButton.draw(Color.red);
|
||||
Utils.FONT_XLARGE.drawString(
|
||||
yesButton.getX() - (Utils.FONT_XLARGE.getWidth("1. Yes") / 2f),
|
||||
yesButton.getY() - (Utils.FONT_XLARGE.getLineHeight() / 2f),
|
||||
"1. Yes", Color.white
|
||||
);
|
||||
Utils.FONT_XLARGE.drawString(
|
||||
noButton.getX() - (Utils.FONT_XLARGE.getWidth("2. No") / 2f),
|
||||
noButton.getY() - (Utils.FONT_XLARGE.getLineHeight() / 2f),
|
||||
"2. No", Color.white
|
||||
);
|
||||
|
||||
Utils.drawVolume(g);
|
||||
Utils.drawFPS();
|
||||
|
@ -113,6 +110,9 @@ public class MainMenuExit extends BasicGameState {
|
|||
throws SlickException {
|
||||
Utils.updateCursor(delta);
|
||||
Utils.updateVolumeDisplay(delta);
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
yesButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
noButton.hoverUpdate(delta, mouseX, mouseY);
|
||||
|
||||
// move buttons to center
|
||||
float yesX = yesButton.getX(), noX = noButton.getX();
|
||||
|
@ -160,5 +160,7 @@ public class MainMenuExit extends BasicGameState {
|
|||
float center = container.getWidth() / 2f;
|
||||
yesButton.setX(center - centerOffset);
|
||||
noButton.setX(center + centerOffset);
|
||||
yesButton.resetHover();
|
||||
noButton.resetHover();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -415,9 +415,9 @@ public class OptionsMenu extends BasicGameState {
|
|||
public void enter(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
currentTab = OptionTab.DISPLAY;
|
||||
Utils.getBackButton().setScale(1f);
|
||||
Utils.getBackButton().resetHover();
|
||||
for (GameMod mod : GameMod.values())
|
||||
mod.setScale(1f);
|
||||
mod.resetHover();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -220,7 +220,7 @@ public class SongMenu extends BasicGameState {
|
|||
// options button
|
||||
Image optionsIcon = GameImage.MENU_OPTIONS.getImage();
|
||||
optionsButton = new MenuButton(optionsIcon, search.getX() - (optionsIcon.getWidth() * 1.5f), search.getY());
|
||||
optionsButton.setHoverScale(1.75f);
|
||||
optionsButton.setHoverExpand(1.75f);
|
||||
|
||||
// loader
|
||||
int loaderDim = GameImage.MENU_MUSICNOTE.getImage().getWidth();
|
||||
|
@ -565,8 +565,7 @@ public class SongMenu extends BasicGameState {
|
|||
case Input.KEY_ESCAPE:
|
||||
if (reloadThread != null) {
|
||||
// beatmap reloading: stop parsing OsuFiles by sending interrupt to OsuParser
|
||||
if (reloadThread != null)
|
||||
reloadThread.interrupt();
|
||||
reloadThread.interrupt();
|
||||
} else if (!search.getText().isEmpty()) {
|
||||
// clear search text
|
||||
search.setText("");
|
||||
|
@ -626,7 +625,7 @@ public class SongMenu extends BasicGameState {
|
|||
if (OsuGroupList.get().size() > 0) {
|
||||
OsuGroupList.get().init();
|
||||
setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
} else if (Options.isThemSongEnabled())
|
||||
} else
|
||||
MusicController.playThemeSong();
|
||||
|
||||
reloadThread = null;
|
||||
|
@ -756,15 +755,15 @@ public class SongMenu extends BasicGameState {
|
|||
public void enter(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
Display.setTitle(game.getTitle());
|
||||
Utils.getBackButton().setScale(1f);
|
||||
optionsButton.setScale(1f);
|
||||
Utils.getBackButton().resetHover();
|
||||
optionsButton.resetHover();
|
||||
hoverOffset = 0f;
|
||||
hoverIndex = -1;
|
||||
startScore = 0;
|
||||
|
||||
// stop playing the theme song
|
||||
if (MusicController.isThemePlaying() && focusNode != null)
|
||||
MusicController.play(focusNode.osuFiles.get(focusNode.osuFileIndex), true);
|
||||
// set focus node if not set (e.g. theme song playing)
|
||||
if (focusNode == null && OsuGroupList.get().size() > 0)
|
||||
setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
|
||||
// reset music track
|
||||
else if (resetTrack) {
|
||||
|
|
|
@ -126,11 +126,14 @@ public class Splash extends BasicGameState {
|
|||
// initialize song list
|
||||
if (OsuGroupList.get().size() > 0) {
|
||||
OsuGroupList.get().init();
|
||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
if (Options.isThemSongEnabled())
|
||||
MusicController.playThemeSong();
|
||||
else
|
||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
}
|
||||
|
||||
// play the theme song
|
||||
if (Options.isThemSongEnabled())
|
||||
else
|
||||
MusicController.playThemeSong();
|
||||
|
||||
game.enterState(Opsu.STATE_MAINMENU);
|
||||
|
|
Loading…
Reference in New Issue
Block a user