diff --git a/src/itdelatrisu/opsu/states/DownloadsMenu.java b/src/itdelatrisu/opsu/states/DownloadsMenu.java index d25f56a6..15ed264a 100644 --- a/src/itdelatrisu/opsu/states/DownloadsMenu.java +++ b/src/itdelatrisu/opsu/states/DownloadsMenu.java @@ -56,6 +56,7 @@ import org.newdawn.slick.Image; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; +import org.newdawn.slick.UnicodeFont; import org.newdawn.slick.gui.TextField; import org.newdawn.slick.state.BasicGameState; import org.newdawn.slick.state.StateBasedGame; @@ -125,6 +126,9 @@ private enum Page { RESET, CURRENT, PREVIOUS, NEXT }; /** The search textfield. */ private TextField search; + + /** The search font. */ + private UnicodeFont searchFont; /** * Delay timer, in milliseconds, before running another search. @@ -314,8 +318,9 @@ public void init(GameContainer container, StateBasedGame game) // search searchTimer = SEARCH_DELAY; searchResultString = "Loading data from server..."; + searchFont = Fonts.DEFAULT; search = new TextField( - container, Fonts.DEFAULT, (int) baseX, (int) searchY, + container, searchFont, (int) baseX, (int) searchY, (int) searchWidth, Fonts.MEDIUM.getLineHeight() ); search.setBackgroundColor(Colors.BLACK_BG_NORMAL); @@ -929,6 +934,11 @@ public void keyPressed(int key, char c) { default: // wait for user to finish typing if (Character.isLetterOrDigit(c) || key == Input.KEY_BACK) { + // load glyphs + if (c > 255) + Fonts.loadGlyphs(searchFont, c); + + // reset search timer searchTimer = 0; pageDir = Page.RESET; } diff --git a/src/itdelatrisu/opsu/states/SongMenu.java b/src/itdelatrisu/opsu/states/SongMenu.java index 8298b6b6..7621db26 100644 --- a/src/itdelatrisu/opsu/states/SongMenu.java +++ b/src/itdelatrisu/opsu/states/SongMenu.java @@ -73,6 +73,7 @@ import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; import org.newdawn.slick.SpriteSheet; +import org.newdawn.slick.UnicodeFont; import org.newdawn.slick.gui.TextField; import org.newdawn.slick.state.BasicGameState; import org.newdawn.slick.state.StateBasedGame; @@ -172,6 +173,9 @@ public SongNode(BeatmapSetNode node, int index) { /** The search textfield. */ private TextField search; + /** The search font. */ + private UnicodeFont searchFont; + /** * Delay timer, in milliseconds, before running another search. * This is overridden by character entry (reset) and 'esc' (immediate search). @@ -272,7 +276,7 @@ private void reloadBeatmaps() { private int searchTransitionTimer = SEARCH_TRANSITION_TIME; /** The text length of the last string in the search TextField. */ - private int lastSearchTextLength = -1; + private int lastSearchTextLength = 0; /** Whether the song folder changed (notified via the watch service). */ private boolean songFolderChanged = false; @@ -419,8 +423,9 @@ public boolean menuClicked(int index) { // search int textFieldX = (int) (width * 0.7125f + Fonts.BOLD.getWidth("Search: ")); int textFieldY = (int) (headerY + Fonts.BOLD.getLineHeight() / 2); + searchFont = Fonts.BOLD; search = new TextField( - container, Fonts.BOLD, textFieldX, textFieldY, + container, searchFont, textFieldX, textFieldY, (int) (width * 0.99f) - textFieldX, Fonts.BOLD.getLineHeight() ); search.setBackgroundColor(Color.transparent); @@ -854,9 +859,11 @@ else if (reloadThread.isFinished()) { BeatmapSetList.get().init(); if (search.getText().isEmpty()) { // cleared search // use previous start/focus if possible - if (oldFocusNode != null) + if (oldFocusNode != null) { setFocus(oldFocusNode.getNode(), oldFocusNode.getIndex(), true, true); - else + songChangeTimer.setTime(songChangeTimer.getDuration()); + musicIconBounceTimer.setTime(musicIconBounceTimer.getDuration()); + } else setFocus(BeatmapSetList.get().getRandomNode(), -1, true, true); } else { int size = BeatmapSetList.get().size(); @@ -1117,6 +1124,7 @@ public void keyPressed(int key, char c) { searchTimer = SEARCH_DELAY; searchTransitionTimer = 0; searchResultString = null; + lastSearchTextLength = 0; } else { // return to main menu SoundController.playSound(SoundEffect.MENUBACK); @@ -1238,8 +1246,12 @@ public void keyPressed(int key, char c) { break; default: // wait for user to finish typing - // TODO: accept all characters (current conditions are from TextField class) - if ((c > 31 && c < 127) || key == Input.KEY_BACK) { + if (Character.isLetterOrDigit(c) || key == Input.KEY_BACK) { + // load glyphs + if (c > 255) + Fonts.loadGlyphs(searchFont, c); + + // reset search timer searchTimer = 0; int textLength = search.getText().length(); if (lastSearchTextLength != textLength) { @@ -1772,6 +1784,7 @@ private void reloadBeatmaps(final boolean fullReload) { searchTransitionTimer = SEARCH_TRANSITION_TIME; searchResultString = null; lastBackgroundImage = null; + lastSearchTextLength = 0; // reload songs in new thread reloadThread = new BeatmapReloadThread(fullReload); diff --git a/src/itdelatrisu/opsu/ui/Fonts.java b/src/itdelatrisu/opsu/ui/Fonts.java index feafbeec..fc0636a3 100644 --- a/src/itdelatrisu/opsu/ui/Fonts.java +++ b/src/itdelatrisu/opsu/ui/Fonts.java @@ -115,6 +115,20 @@ public static void loadGlyphs(UnicodeFont font, String s) { } } + /** + * Adds and loads glyphs for a font. + * @param font the font to add the glyphs to + * @param c the character to load + */ + public static void loadGlyphs(UnicodeFont font, char c) { + font.addGlyphs(c, c); + try { + font.loadGlyphs(); + } catch (SlickException e) { + Log.warn(String.format("Failed to load glyphs for codepoint '%d'.", (int) c), e); + } + } + /** * Wraps the given string into a list of split lines based on the width. * @param font the font used to draw the string diff --git a/src/org/newdawn/slick/Input.java b/src/org/newdawn/slick/Input.java index 3dd677c7..533dd90a 100644 --- a/src/org/newdawn/slick/Input.java +++ b/src/org/newdawn/slick/Input.java @@ -1200,9 +1200,10 @@ public void poll(int width, int height) { while (Keyboard.next()) { if (Keyboard.getEventKeyState()) { - int eventKey = resolveEventKey(Keyboard.getEventKey(), Keyboard.getEventCharacter()); + char eventCh = Keyboard.getEventCharacter(); + int eventKey = resolveEventKey(Keyboard.getEventKey(), eventCh); - keys[eventKey] = Keyboard.getEventCharacter(); + keys[eventKey] = eventCh; pressed[eventKey] = true; nextRepeat[eventKey] = System.currentTimeMillis() + keyRepeatInitial; @@ -1211,14 +1212,15 @@ public void poll(int width, int height) { KeyListener listener = (KeyListener) keyListeners.get(i); if (listener.isAcceptingInput()) { - listener.keyPressed(eventKey, Keyboard.getEventCharacter()); + listener.keyPressed(eventKey, eventCh); if (consumed) { break; } } } } else { - int eventKey = resolveEventKey(Keyboard.getEventKey(), Keyboard.getEventCharacter()); + char eventCh = Keyboard.getEventCharacter(); + int eventKey = resolveEventKey(Keyboard.getEventKey(), eventCh); nextRepeat[eventKey] = 0; consumed = false; @@ -1226,6 +1228,12 @@ public void poll(int width, int height) { KeyListener listener = (KeyListener) keyListeners.get(i); if (listener.isAcceptingInput()) { listener.keyReleased(eventKey, keys[eventKey]); + // Fix Unicode input in some keyboards (Chinese, Japanese, etc.) + // not firing keypress events: fire them here. + if (eventCh != Keyboard.CHAR_NONE && keys[eventKey] != eventCh) { + listener.keyPressed(eventKey, eventCh); + listener.keyReleased(eventKey, eventCh); + } if (consumed) { break; } diff --git a/src/org/newdawn/slick/gui/TextField.java b/src/org/newdawn/slick/gui/TextField.java index 73505127..d1bee53f 100644 --- a/src/org/newdawn/slick/gui/TextField.java +++ b/src/org/newdawn/slick/gui/TextField.java @@ -509,7 +509,7 @@ public void keyPressed(int key, char c) { if (consume) { container.getInput().consumeEvent(); } - } else if (c != Keyboard.CHAR_NONE && key != Input.KEY_TAB && value.length() < maxCharacter) { + } else if (c > 31 && value.length() < maxCharacter) { if (cursorPos < value.length()) { value = value.substring(0, cursorPos) + c + value.substring(cursorPos);