default back button
This commit is contained in:
parent
61340eb9ee
commit
62b5d574da
BIN
res/menu-back-chevron.png
Normal file
BIN
res/menu-back-chevron.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
res/menu-back-slope.png
Normal file
BIN
res/menu-back-slope.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 972 B |
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 162 B |
|
@ -253,6 +253,8 @@ public enum GameImage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MENU_BACK ("menu-back", "menu-back-%d", "png"),
|
MENU_BACK ("menu-back", "menu-back-%d", "png"),
|
||||||
|
MENU_BACK_CHEVRON ("menu-back-chevron", "png"),
|
||||||
|
MENU_BACK_SLOPE("menu-back-slope", "png"),
|
||||||
MENU_BUTTON_BG ("menu-button-background", "png", false, false),
|
MENU_BUTTON_BG ("menu-button-background", "png", false, false),
|
||||||
MENU_TAB ("selection-tab", "png", false, false) {
|
MENU_TAB ("selection-tab", "png", false, false) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -519,7 +519,7 @@ public class DownloadsMenu extends ComplexOpsuState {
|
||||||
|
|
||||||
// back button
|
// back button
|
||||||
else
|
else
|
||||||
UI.getBackButton().draw();
|
UI.getBackButton().draw(g);
|
||||||
|
|
||||||
UI.draw(g);
|
UI.draw(g);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class GameRanking extends BaseOpsuState {
|
||||||
replayButton.draw();
|
replayButton.draw();
|
||||||
if (data.isGameplay() && !GameMod.AUTO.isActive())
|
if (data.isGameplay() && !GameMod.AUTO.isActive())
|
||||||
retryButton.draw();
|
retryButton.draw();
|
||||||
UI.getBackButton().draw();
|
UI.getBackButton().draw(g);
|
||||||
|
|
||||||
UI.draw(g);
|
UI.draw(g);
|
||||||
|
|
||||||
|
|
|
@ -715,7 +715,7 @@ public class SongMenu extends ComplexOpsuState {
|
||||||
|
|
||||||
// back button
|
// back button
|
||||||
else
|
else
|
||||||
UI.getBackButton().draw();
|
UI.getBackButton().draw(g);
|
||||||
|
|
||||||
UI.draw(g);
|
UI.draw(g);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.Graphics;
|
import org.newdawn.slick.Graphics;
|
||||||
import org.newdawn.slick.Image;
|
import org.newdawn.slick.Image;
|
||||||
import yugecin.opsudance.core.DisplayContainer;
|
import yugecin.opsudance.core.DisplayContainer;
|
||||||
|
import yugecin.opsudance.events.ResolutionOrSkinChangedEvent;
|
||||||
|
import yugecin.opsudance.ui.BackButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws common UI components.
|
* Draws common UI components.
|
||||||
|
@ -40,7 +42,7 @@ import yugecin.opsudance.core.DisplayContainer;
|
||||||
public class UI {
|
public class UI {
|
||||||
|
|
||||||
/** Back button. */
|
/** Back button. */
|
||||||
private static MenuButton backButton;
|
private static BackButton backButton;
|
||||||
|
|
||||||
/** Time to show volume image, in milliseconds. */
|
/** Time to show volume image, in milliseconds. */
|
||||||
private static final int VOLUME_DISPLAY_TIME = 1500;
|
private static final int VOLUME_DISPLAY_TIME = 1500;
|
||||||
|
@ -68,18 +70,10 @@ public class UI {
|
||||||
*/
|
*/
|
||||||
public static void init(DisplayContainer displayContainer) {
|
public static void init(DisplayContainer displayContainer) {
|
||||||
UI.displayContainer = displayContainer;
|
UI.displayContainer = displayContainer;
|
||||||
|
|
||||||
// back button
|
|
||||||
if (GameImage.MENU_BACK.getImages() != null) {
|
|
||||||
Animation back = GameImage.MENU_BACK.getAnimation(120);
|
|
||||||
backButton = new MenuButton(back, back.getWidth() / 2f, displayContainer.height - (back.getHeight() / 2f));
|
|
||||||
} else {
|
|
||||||
Image back = GameImage.MENU_BACK.getImage();
|
|
||||||
backButton = new MenuButton(back, back.getWidth() / 2f, displayContainer.height - (back.getHeight() / 2f));
|
|
||||||
}
|
}
|
||||||
backButton.setHoverAnimationDuration(350);
|
|
||||||
backButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
|
public static void revalidate() {
|
||||||
backButton.setHoverExpand(MenuButton.Expand.UP_RIGHT);
|
backButton = new BackButton(displayContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,7 +104,7 @@ public class UI {
|
||||||
/**
|
/**
|
||||||
* Returns the 'menu-back' MenuButton.
|
* Returns the 'menu-back' MenuButton.
|
||||||
*/
|
*/
|
||||||
public static MenuButton getBackButton() { return backButton; }
|
public static BackButton getBackButton() { return backButton; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a tab image and text centered at a location.
|
* Draws a tab image and text centered at a location.
|
||||||
|
|
|
@ -350,6 +350,7 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
|
||||||
Fonts.init();
|
Fonts.init();
|
||||||
|
|
||||||
eventBus.post(new ResolutionOrSkinChangedEvent());
|
eventBus.post(new ResolutionOrSkinChangedEvent());
|
||||||
|
UI.revalidate(); // TODO this shouldn't be here
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetCursor() {
|
public void resetCursor() {
|
||||||
|
|
225
src/yugecin/opsudance/ui/BackButton.java
Normal file
225
src/yugecin/opsudance/ui/BackButton.java
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* opsu!dance - fork of opsu! with cursordance auto
|
||||||
|
* Copyright (C) 2017 yugecin
|
||||||
|
*
|
||||||
|
* opsu!dance 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!dance 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!dance. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package yugecin.opsudance.ui;
|
||||||
|
|
||||||
|
import itdelatrisu.opsu.GameImage;
|
||||||
|
import itdelatrisu.opsu.audio.MusicController;
|
||||||
|
import itdelatrisu.opsu.ui.Fonts;
|
||||||
|
import itdelatrisu.opsu.ui.MenuButton;
|
||||||
|
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||||
|
import org.newdawn.slick.*;
|
||||||
|
import yugecin.opsudance.core.DisplayContainer;
|
||||||
|
|
||||||
|
public class BackButton {
|
||||||
|
|
||||||
|
/** Skinned back button. */
|
||||||
|
private MenuButton backButton;
|
||||||
|
|
||||||
|
/** Colors. */
|
||||||
|
private static final Color
|
||||||
|
COLOR_PINK = new Color(238, 51, 153),
|
||||||
|
COLOR_DARKPINK = new Color(186, 19, 121);
|
||||||
|
|
||||||
|
/** Target duration, in ms, of the button animations. */
|
||||||
|
private static final int ANIMATION_TIME = 500;
|
||||||
|
|
||||||
|
/** How much time passed for the animations. */
|
||||||
|
private int animationTime;
|
||||||
|
|
||||||
|
/** The size of the slope image (square shape). */
|
||||||
|
private int slopeImageSize;
|
||||||
|
|
||||||
|
/** The width of the slope part in the slope image. */
|
||||||
|
private int slopeImageSlopeWidth;
|
||||||
|
|
||||||
|
/** The width of the first part of the button. */
|
||||||
|
private int firstButtonWidth;
|
||||||
|
|
||||||
|
/** The width of the second part of the button. */
|
||||||
|
private int secondButtonSize;
|
||||||
|
|
||||||
|
/** Variable to hold the hovered state, to not recalculate it twice per frame. */
|
||||||
|
private boolean isHovered;
|
||||||
|
|
||||||
|
/** The width of the "back" text to draw. */
|
||||||
|
private int textWidth;
|
||||||
|
|
||||||
|
/** Y padding for the text and general positioning. */
|
||||||
|
private float paddingY;
|
||||||
|
|
||||||
|
/** X padding for the text. */
|
||||||
|
private float paddingX;
|
||||||
|
|
||||||
|
/** Y text offset because getHeight is not so accurate. */
|
||||||
|
private float textOffset;
|
||||||
|
|
||||||
|
/** The base size of the chevron. */
|
||||||
|
private float chevronBaseSize;
|
||||||
|
|
||||||
|
/** The Y position of where the button starts. */
|
||||||
|
private int buttonYpos;
|
||||||
|
|
||||||
|
/** Variable holding the slope image. */
|
||||||
|
private Image slopeImage;
|
||||||
|
|
||||||
|
/** The real button with, determined by the size and animations. */
|
||||||
|
private int realButtonWidth;
|
||||||
|
|
||||||
|
public BackButton(DisplayContainer container) {
|
||||||
|
//if (!GameImage.MENU_BACK.hasGameSkinImage()) {
|
||||||
|
if (GameImage.MENU_BACK.getImage() != null && GameImage.MENU_BACK.getImage().getWidth() < 2) {
|
||||||
|
backButton = null;
|
||||||
|
textWidth = Fonts.MEDIUM.getWidth("back");
|
||||||
|
paddingY = Fonts.MEDIUM.getHeight("back");
|
||||||
|
// getHeight doesn't seem to be so accurate
|
||||||
|
textOffset = paddingY * 0.264f;
|
||||||
|
paddingY *= 0.736f;
|
||||||
|
paddingX = paddingY / 2f;
|
||||||
|
chevronBaseSize = paddingY * 3f / 2f;
|
||||||
|
buttonYpos = (int) (container.height - paddingY * 4f);
|
||||||
|
slopeImageSize = (int) (paddingY * 3f);
|
||||||
|
slopeImageSlopeWidth = (int) (slopeImageSize * 0.295f);
|
||||||
|
firstButtonWidth = slopeImageSize;
|
||||||
|
secondButtonSize = (int) (slopeImageSlopeWidth + paddingX * 2 + textWidth);
|
||||||
|
slopeImage = GameImage.MENU_BACK_SLOPE.getImage().getScaledCopy(slopeImageSize, slopeImageSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameImage.MENU_BACK.getImages() != null) {
|
||||||
|
Animation back = GameImage.MENU_BACK.getAnimation(120);
|
||||||
|
backButton = new MenuButton(back, back.getWidth() / 2f, container.height - (back.getHeight() / 2f));
|
||||||
|
} else {
|
||||||
|
Image back = GameImage.MENU_BACK.getImage();
|
||||||
|
backButton = new MenuButton(back, back.getWidth() / 2f, container.height - (back.getHeight() / 2f));
|
||||||
|
}
|
||||||
|
backButton.setHoverAnimationDuration(350);
|
||||||
|
backButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
|
||||||
|
backButton.setHoverExpand(MenuButton.Expand.UP_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the backbutton.
|
||||||
|
*/
|
||||||
|
public void draw(Graphics g) {
|
||||||
|
// draw image if it's skinned
|
||||||
|
if (backButton != null) {
|
||||||
|
backButton.draw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc chevron size
|
||||||
|
Float beatProgress = MusicController.getBeatProgress();
|
||||||
|
if (beatProgress == null) {
|
||||||
|
beatProgress = 0f;
|
||||||
|
}
|
||||||
|
int chevronSize = (int) (chevronBaseSize - (isHovered ? 6f : 3f) * beatProgress);
|
||||||
|
|
||||||
|
// calc button sizes
|
||||||
|
AnimationEquation anim;
|
||||||
|
if (isHovered) {
|
||||||
|
anim = AnimationEquation.OUT_ELASTIC;
|
||||||
|
} else {
|
||||||
|
anim = AnimationEquation.IN_ELASTIC;
|
||||||
|
}
|
||||||
|
float progress = anim.calc((float) animationTime / ANIMATION_TIME);
|
||||||
|
float firstSize = firstButtonWidth + (firstButtonWidth - slopeImageSlopeWidth * 2) * progress;
|
||||||
|
float secondSize = secondButtonSize + secondButtonSize * 0.25f * progress;
|
||||||
|
realButtonWidth = (int) (firstSize + secondSize);
|
||||||
|
|
||||||
|
// right part
|
||||||
|
g.setColor(COLOR_PINK);
|
||||||
|
g.fillRect(0, buttonYpos, firstSize + secondSize - slopeImageSlopeWidth, slopeImageSize);
|
||||||
|
slopeImage.draw(firstSize + secondSize - slopeImageSize, buttonYpos, COLOR_PINK);
|
||||||
|
|
||||||
|
// left part
|
||||||
|
Color hoverColor = new Color(0f, 0f, 0f);
|
||||||
|
hoverColor.r = COLOR_PINK.r + (COLOR_DARKPINK.r - COLOR_PINK.r) * progress;
|
||||||
|
hoverColor.g = COLOR_PINK.g + (COLOR_DARKPINK.g - COLOR_PINK.g) * progress;
|
||||||
|
hoverColor.b = COLOR_PINK.b + (COLOR_DARKPINK.b - COLOR_PINK.b) * progress;
|
||||||
|
g.setColor(hoverColor);
|
||||||
|
g.fillRect(0, buttonYpos, firstSize - slopeImageSlopeWidth, slopeImageSize);
|
||||||
|
slopeImage.draw(firstSize - slopeImageSize, buttonYpos, hoverColor);
|
||||||
|
|
||||||
|
// chevron
|
||||||
|
GameImage.MENU_BACK_CHEVRON.getImage().getScaledCopy(chevronSize, chevronSize).drawCentered((firstSize - slopeImageSlopeWidth / 2) / 2, buttonYpos + paddingY * 1.5f);
|
||||||
|
|
||||||
|
// text
|
||||||
|
float textY = buttonYpos + paddingY - textOffset;
|
||||||
|
float textX = firstSize + (secondSize - paddingX * 2 - textWidth) / 2;
|
||||||
|
Fonts.MEDIUM.drawString(textX, textY + 1, "back", Color.black);
|
||||||
|
Fonts.MEDIUM.drawString(textX, textY, "back", Color.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, int cx, int cy) {
|
||||||
|
if (backButton != null) {
|
||||||
|
backButton.hoverUpdate(delta, cx, cy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean wasHovered = isHovered;
|
||||||
|
isHovered = buttonYpos - paddingY < cy && cx < realButtonWidth;
|
||||||
|
if (isHovered) {
|
||||||
|
if (!wasHovered) {
|
||||||
|
animationTime = 0;
|
||||||
|
}
|
||||||
|
animationTime += delta;
|
||||||
|
if (animationTime > ANIMATION_TIME) {
|
||||||
|
animationTime = ANIMATION_TIME;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (wasHovered) {
|
||||||
|
animationTime = ANIMATION_TIME;
|
||||||
|
}
|
||||||
|
animationTime -= delta;
|
||||||
|
if (animationTime < 0) {
|
||||||
|
animationTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the coordinates are within the button bounds.
|
||||||
|
* @param cx the x coordinate
|
||||||
|
* @param cy the y coordinate
|
||||||
|
*/
|
||||||
|
public boolean contains(float cx, float cy) {
|
||||||
|
if (backButton != null) {
|
||||||
|
return backButton.contains(cx, cy);
|
||||||
|
}
|
||||||
|
return buttonYpos - paddingY < cy && cx < realButtonWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the hover fields for the button.
|
||||||
|
*/
|
||||||
|
public void resetHover() {
|
||||||
|
if (backButton != null) {
|
||||||
|
backButton.resetHover();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isHovered = false;
|
||||||
|
animationTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -259,7 +259,7 @@ public class OptionsOverlay extends OverlayOpsuState {
|
||||||
g.clearClip();
|
g.clearClip();
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
UI.getBackButton().draw();
|
UI.getBackButton().draw(g);
|
||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
renderTooltip(g);
|
renderTooltip(g);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user