/* * opsu! - an open-source osu! client * Copyright (C) 2014-2017 Jeffrey Han * * opsu! is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * opsu! is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with opsu!. If not, see <http://www.gnu.org/licenses/>. */ package itdelatrisu.opsu.user; import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.ui.Colors; import itdelatrisu.opsu.ui.Fonts; import itdelatrisu.opsu.ui.animations.AnimatedValue; import itdelatrisu.opsu.ui.animations.AnimationEquation; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; /** * User button. */ public class UserButton { /** Button dimensions. */ private static int buttonWidth, buttonHeight; /** User icon size. */ private static int iconSize; /** Button coordinates. */ private int x, y; /** Background color. */ private Color bgColor; /** Background alpha level. */ private AnimatedValue bgAlpha = new AnimatedValue(200, 0f, 1f, AnimationEquation.OUT_QUAD); /** Bar colors. */ private Color barBgColor = new Color(Color.darkGray), barBorderColor = new Color(Color.lightGray), barFillColor = new Color(Colors.YELLOW_FILL); /** Flash color. */ private Color flashColor = new Color(218, 28, 63); /** Whether the button is currently flashing. */ private boolean flashing = false; /** The user. */ private User user; /** Placeholder text to display if {@link #user} is null. */ private String placeholderText; /** * Initializes the user buttons. * @param width the container width * @param height the container height */ public static void init(int width, int height) { buttonWidth = width * 5 / 18; buttonHeight = height / 9; iconSize = buttonHeight - 4 * 4; } /** Returns the button width. */ public static int getWidth() { return buttonWidth; } /** Returns the button height. */ public static int getHeight() { return buttonHeight; } /** * Returns the user icon image with the given identifier, * or the default image if invalid. */ public static Image getIconImage(int id) { int i = (id < 0 || id >= getIconCount()) ? 0 : id; return GameImage.USER.getImages()[i].getScaledCopy(iconSize, iconSize); } /** Returns the total number of user icons. */ public static int getIconCount() { return GameImage.USER.getImages().length; } /** Returns the size of an icon. */ public static int getIconSize() { return iconSize; } /** * Creates a user button. * @param x the top-left x coordinate * @param y the top-left y coordinate * @param color the background color (when focused) */ public UserButton(int x, int y, Color color) { setPosition(x, y); this.bgColor = new Color(color); } /** * Sets the button position. * @param x the top-left x coordinate * @param y the top-left y coordinate */ public void setPosition(int x, int y) { this.x = x; this.y = y; } /** Sets the user. */ public void setUser(User user) { this.user = user; Fonts.loadGlyphs(Fonts.MEDIUM, user.getName()); } /** Returns the user. */ public User getUser() { return user; } /** Sets the text to display if no user is set. */ public void setPlaceholderText(String placeholderText) { this.placeholderText = placeholderText; } /** Returns the placeholder text. */ public String getPlaceholderText() { return placeholderText; } /** * Returns true if the coordinates are within the button bounds. * @param cx the x coordinate * @param cy the y coordinate */ public boolean contains(int cx, int cy) { return ((cx > x && cx < x + buttonWidth) && (cy > y && cy < y + buttonHeight)); } /** * Draws a user button. * @param g the graphics context */ public void draw(Graphics g) { draw(g, 1f); } /** * Draws a user button. * @param g the graphics context * @param alpha the alpha multiplier */ public void draw(Graphics g, float alpha) { int padding = 4; int cx = x + padding, cy = y + padding; float t = bgAlpha.getValue(); float oldWhiteAlpha = Colors.WHITE_FADE.a; Colors.WHITE_FADE.a = alpha; // rectangle Color bg; if (flashing) { bg = flashColor; bg.a = t * alpha; } else { bg = bgColor; bg.a = (0.5f * t) * alpha; } g.setColor(bg); g.fillRoundRect(cx, cy, buttonWidth - padding * 2, buttonHeight - padding * 2, 4); // no user? if (user == null && placeholderText != null) { Fonts.LARGE.drawString( x + (buttonWidth - Fonts.LARGE.getWidth(placeholderText)) / 2, y + (buttonHeight - Fonts.LARGE.getLineHeight()) / 2, placeholderText, Colors.WHITE_FADE ); Colors.WHITE_FADE.a = oldWhiteAlpha; return; } // icon int iconSize = buttonHeight - padding * 4; Image img = getIconImage(user.getIconId()); img.setAlpha(alpha); img.draw(cx + padding, cy + padding); // text int textX = cx + iconSize + padding * 3; int textY = cy + padding / 2; Fonts.MEDIUM.drawString(textX, textY, user.getName(), Colors.WHITE_FADE); textY += Fonts.MEDIUM.getLineHeight() - 3; Fonts.SMALL.drawString(textX, textY, String.format("Score: %,d", user.getScore()), Colors.WHITE_FADE); textY += Fonts.SMALL.getLineHeight() - 2; Fonts.SMALL.drawString(textX, textY, String.format("Accuracy: %.2f%%", user.getAccuracy()), Colors.WHITE_FADE); textY += Fonts.SMALL.getLineHeight() - 2; Fonts.SMALL.drawString(textX, textY, String.format("Lv%d", user.getLevel()), Colors.WHITE_FADE); // progress bar int barX = textX + Fonts.SMALL.getWidth("Lv#####"); int barWidth = x + buttonWidth - padding - barX - 1; int barHeight = buttonHeight / 7; int barY = y + buttonHeight - padding - barHeight - 1; int barRadius = 8; float barAlpha = (0.75f + 0.25f * t) * alpha; barBgColor.a = barBorderColor.a = barFillColor.a = barAlpha; g.setColor(barBgColor); g.fillRoundRect(barX, barY, barWidth, barHeight, barRadius); g.setClip(barX, barY, (int) (barWidth * user.getNextLevelProgress()), barHeight); g.setColor(barFillColor); g.fillRoundRect(barX, barY, barWidth, barHeight, barRadius); g.clearClip(); g.setAntiAlias(true); g.setColor(barBorderColor); g.setLineWidth(2f); g.drawRoundRect(barX, barY, barWidth, barHeight, barRadius); g.resetLineWidth(); g.setAntiAlias(false); Colors.WHITE_FADE.a = oldWhiteAlpha; } /** * Processes a hover action depending on whether or not the cursor * is hovering over the button. * @param delta the delta interval * @param isHover true if the cursor is currently hovering over the button */ public void hoverUpdate(int delta, boolean isHover) { if (flashing) { if (!bgAlpha.update(-delta / 2)) flashing = false; } else { int d = delta * (isHover ? 1 : -1); bgAlpha.update(d); } } /** * Sets the hover animation duration. * @param duration the duration, in milliseconds */ public void setHoverAnimationDuration(int duration) { bgAlpha.setDuration(duration); } /** * Sets the hover animation equation. * @param eqn the equation to use */ public void setHoverAnimationEquation(AnimationEquation eqn) { bgAlpha.setEquation(eqn); } /** * Sets the hover animation base value. * @param base the base value */ public void setHoverAnimationBase(float base) { AnimatedValue value = new AnimatedValue(bgAlpha.getDuration(), base, 1f, bgAlpha.getEquation()); value.setTime(bgAlpha.getTime()); bgAlpha = value; } /** Resets the hover fields for the button. */ public void resetHover() { bgAlpha.setTime(0); flashing = false; } /** Flashes the button. */ public void flash() { bgAlpha.setTime(bgAlpha.getDuration()); flashing = true; } }