diff --git a/.gitignore b/.gitignore index 5935a4ba..2ced573a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ -/.osu_tmp/ -/screenshot/ -/songs/ +/.opsu_tmp/ +/Screenshots/ +/Skins/ +/Songs/ /.opsu.log /.opsu.cfg diff --git a/src/itdelatrisu/opsu/Opsu.java b/src/itdelatrisu/opsu/Opsu.java index 89c8f2cd..c3b259f7 100644 --- a/src/itdelatrisu/opsu/Opsu.java +++ b/src/itdelatrisu/opsu/Opsu.java @@ -40,6 +40,7 @@ import org.newdawn.slick.SlickException; import org.newdawn.slick.state.StateBasedGame; import org.newdawn.slick.state.transition.FadeInTransition; import org.newdawn.slick.state.transition.FadeOutTransition; +import org.newdawn.slick.util.ClasspathLocation; import org.newdawn.slick.util.DefaultLogSystem; import org.newdawn.slick.util.FileSystemLocation; import org.newdawn.slick.util.Log; @@ -117,7 +118,11 @@ public class Opsu extends StateBasedGame { // set path for lwjgl natives - NOT NEEDED if using JarSplice // System.setProperty("org.lwjgl.librarypath", new File("native").getAbsolutePath()); - // set the resource path + // set the resource paths + ResourceLoader.removeAllResourceLocations(); + ResourceLoader.addResourceLocation(new FileSystemLocation(Options.getSkinDir())); + ResourceLoader.addResourceLocation(new ClasspathLocation()); + ResourceLoader.addResourceLocation(new FileSystemLocation(new File("."))); ResourceLoader.addResourceLocation(new FileSystemLocation(new File("./res/"))); // start the game diff --git a/src/itdelatrisu/opsu/Utils.java b/src/itdelatrisu/opsu/Utils.java index 4417187c..904ed69e 100644 --- a/src/itdelatrisu/opsu/Utils.java +++ b/src/itdelatrisu/opsu/Utils.java @@ -131,21 +131,30 @@ public class Utils { Log.error("Failed to set the cursor.", e); } - // load cursor images + // load cursor images (TODO: cleanup) + boolean skinCursor = new File(Options.getSkinDir(), "cursor.png").isFile(); if (Options.isNewCursorEnabled()) { // load new cursor type - try { + // if skin cursor exists but middle part does not, don't load default middle + if (skinCursor && !new File(Options.getSkinDir(), "cursormiddle.png").isFile()) + ; + else { cursorMiddle = new Image("cursormiddle.png"); cursor = new Image("cursor.png"); cursorTrail = new Image("cursortrail.png"); - } catch (Exception e) { - // optional } } if (cursorMiddle == null) { // load old cursor type - cursor = new Image("cursor2.png"); - cursorTrail = new Image("cursortrail2.png"); + // default is stored as *2.png, but load skin cursor if it exists + if (skinCursor) + cursor = new Image("cursor.png"); + else + cursor = new Image("cursor2.png"); + if (new File(Options.getSkinDir(), "cursortrail.png").isFile()) + cursorTrail = new Image("cursortrail.png"); + else + cursorTrail = new Image("cursortrail2.png"); } // create fonts diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index d3a4c766..b874f271 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -652,8 +652,8 @@ public class Game extends BasicGameState { if (osu == null || osu.objects == null) throw new RuntimeException("Running game with no OsuFile loaded."); - // grab the mouse - container.setMouseGrabbed(true); + // grab the mouse (not working for touchscreen) +// container.setMouseGrabbed(true); // restart the game if (restart != RESTART_FALSE) { @@ -728,11 +728,11 @@ public class Game extends BasicGameState { } } - @Override - public void leave(GameContainer container, StateBasedGame game) - throws SlickException { - container.setMouseGrabbed(false); - } +// @Override +// public void leave(GameContainer container, StateBasedGame game) +// throws SlickException { +// container.setMouseGrabbed(false); +// } /** * Skips the beginning of a track. diff --git a/src/itdelatrisu/opsu/states/Options.java b/src/itdelatrisu/opsu/states/Options.java index bcbcf89c..ab8fc6f9 100644 --- a/src/itdelatrisu/opsu/states/Options.java +++ b/src/itdelatrisu/opsu/states/Options.java @@ -51,25 +51,30 @@ public class Options extends BasicGameState { /** * Temporary folder for file conversions, auto-deleted upon successful exit. */ - public static final File TMP_DIR = new File(".osu_tmp/"); + public static final File TMP_DIR = new File(".opsu_tmp/"); /** * Directory for screenshots (created when needed). */ - public static final File SCREENSHOT_DIR = new File("screenshot/"); - + public static final File SCREENSHOT_DIR = new File("Screenshots/"); + /** * File for logging errors. */ public static final File LOG_FILE = new File(".opsu.log"); + /** + * File for storing user options. + */ + private static final File OPTIONS_FILE = new File(".opsu.cfg"); + /** * Beatmap directories (where to search for files). */ private static final String[] BEATMAP_DIRS = { "C:/Program Files (x86)/osu!/Songs/", "C:/Program Files/osu!/Songs/", - "songs/" + "Songs/" }; /** @@ -78,9 +83,9 @@ public class Options extends BasicGameState { private static File beatmapDir; /** - * File for storing user options. + * The current skin directory (for user skins). */ - private static final String OPTIONS_FILE = ".opsu.cfg"; + private static File skinDir; /** * Game mods. @@ -611,6 +616,7 @@ public class Options extends BasicGameState { * Returns the current beatmap directory. * If invalid, this will attempt to search for the directory, * and if nothing found, will create one. + * @return the beatmap directory */ public static File getBeatmapDir() { if (beatmapDir != null && beatmapDir.isDirectory()) @@ -626,19 +632,31 @@ public class Options extends BasicGameState { return beatmapDir; } + /** + * Returns the current skin directory. + * If invalid, this will create a "Skins" folder in the root directory. + * @return the skin directory + */ + public static File getSkinDir() { + if (skinDir != null && skinDir.isDirectory()) + return skinDir; + + skinDir = new File("Skins/"); + skinDir.mkdir(); + return skinDir; + } /** * Reads user options from the options file, if it exists. */ public static void parseOptions() { // if no config file, use default settings - File file = new File(OPTIONS_FILE); - if (!file.isFile()) { + if (!OPTIONS_FILE.isFile()) { saveOptions(); return; } - try (BufferedReader in = new BufferedReader(new FileReader(file))) { + try (BufferedReader in = new BufferedReader(new FileReader(OPTIONS_FILE))) { String line; String name, value; int i; @@ -655,6 +673,9 @@ public class Options extends BasicGameState { case "BeatmapDirectory": beatmapDir = new File(value); break; + case "Skin": + skinDir = new File(value); + break; case "ScreenResolution": i = Integer.parseInt(value); if (i >= 0 && i < resolutions.length) @@ -708,7 +729,7 @@ public class Options extends BasicGameState { } } } catch (IOException e) { - Log.error(String.format("Failed to read file '%s'.", OPTIONS_FILE), e); + Log.error(String.format("Failed to read file '%s'.", OPTIONS_FILE.getAbsolutePath()), e); } catch (NumberFormatException e) { Log.warn("Format error in options file.", e); return; @@ -732,10 +753,10 @@ public class Options extends BasicGameState { writer.newLine(); // options - if (beatmapDir != null) { - writer.write(String.format("BeatmapDirectory = %s", beatmapDir.getAbsolutePath())); - writer.newLine(); - } + writer.write(String.format("BeatmapDirectory = %s", getBeatmapDir().getAbsolutePath())); + writer.newLine(); + writer.write(String.format("Skin = %s", getSkinDir().getAbsolutePath())); + writer.newLine(); writer.write(String.format("ScreenResolution = %d", resolutionIndex)); writer.newLine(); // writer.write(String.format("Fullscreen = %b", fullscreen)); @@ -762,7 +783,7 @@ public class Options extends BasicGameState { writer.newLine(); writer.close(); } catch (IOException e) { - Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE), e); + Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE.getAbsolutePath()), e); } } }