2014-06-30 04:17:04 +02:00
|
|
|
/*
|
|
|
|
* opsu! - an open-source osu! client
|
2015-01-16 18:05:44 +01:00
|
|
|
* Copyright (C) 2014, 2015 Jeffrey Han
|
2014-06-30 04:17:04 +02:00
|
|
|
*
|
|
|
|
* 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;
|
|
|
|
|
2015-01-28 09:47:24 +01:00
|
|
|
import itdelatrisu.opsu.GameData.Grade;
|
|
|
|
|
2014-06-30 04:17:04 +02:00
|
|
|
import java.util.ArrayList;
|
2014-07-18 03:16:15 +02:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2014-06-30 04:17:04 +02:00
|
|
|
|
|
|
|
import org.newdawn.slick.Color;
|
|
|
|
import org.newdawn.slick.Image;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Node in an OsuGroupList representing a group of OsuFile objects.
|
|
|
|
*/
|
2014-07-19 02:33:41 +02:00
|
|
|
public class OsuGroupNode {
|
2015-01-22 06:44:45 +01:00
|
|
|
/** List of associated OsuFile objects. */
|
2014-06-30 04:17:04 +02:00
|
|
|
public ArrayList<OsuFile> osuFiles;
|
|
|
|
|
2015-01-22 06:44:45 +01:00
|
|
|
/** Index of this OsuGroupNode. */
|
2014-06-30 04:17:04 +02:00
|
|
|
public int index = 0;
|
|
|
|
|
2015-01-22 06:44:45 +01:00
|
|
|
/** Index of selected osuFile (-1 if not focused). */
|
2014-06-30 04:17:04 +02:00
|
|
|
public int osuFileIndex = -1;
|
|
|
|
|
2015-01-22 06:44:45 +01:00
|
|
|
/** Links to other OsuGroupNode objects. */
|
2014-06-30 04:17:04 +02:00
|
|
|
public OsuGroupNode prev, next;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* @param osuFiles the OsuFile objects in this group
|
|
|
|
*/
|
|
|
|
public OsuGroupNode(ArrayList<OsuFile> osuFiles) {
|
|
|
|
this.osuFiles = osuFiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Draws the button.
|
|
|
|
* @param x the x coordinate
|
|
|
|
* @param y the y coordinate
|
2015-02-16 03:38:54 +01:00
|
|
|
* @param headerY the header end y coordinate (for cropping)
|
|
|
|
* @param footerY the footer start y coordinate (for cropping)
|
2015-01-28 09:47:24 +01:00
|
|
|
* @param grade the highest grade, if any
|
2014-06-30 04:17:04 +02:00
|
|
|
* @param focus true if this is the focused node
|
|
|
|
*/
|
2015-02-16 03:38:54 +01:00
|
|
|
public void draw(float x, float y, float headerY, float footerY, Grade grade, boolean focus) {
|
2014-06-30 04:17:04 +02:00
|
|
|
boolean expanded = (osuFileIndex > -1);
|
|
|
|
OsuFile osu;
|
2015-01-21 01:01:18 +01:00
|
|
|
Image bg = GameImage.MENU_BUTTON_BG.getImage();
|
2015-02-16 17:34:35 +01:00
|
|
|
bg.setAlpha(0.9f);
|
2015-02-16 03:38:54 +01:00
|
|
|
Color bgColor;
|
|
|
|
Color textColor = Color.lightGray;
|
2015-02-19 01:35:26 +01:00
|
|
|
|
|
|
|
// get drawing parameters
|
2014-06-30 04:17:04 +02:00
|
|
|
if (expanded) { // expanded
|
2015-02-16 03:38:54 +01:00
|
|
|
x -= bg.getWidth() / 10f;
|
2014-06-30 04:17:04 +02:00
|
|
|
if (focus) {
|
2015-02-16 03:38:54 +01:00
|
|
|
bgColor = Color.white;
|
2014-06-30 04:17:04 +02:00
|
|
|
textColor = Color.white;
|
2014-07-11 01:13:53 +02:00
|
|
|
} else
|
2015-02-16 03:38:54 +01:00
|
|
|
bgColor = Utils.COLOR_BLUE_BUTTON;
|
2014-06-30 04:17:04 +02:00
|
|
|
osu = osuFiles.get(osuFileIndex);
|
|
|
|
} else {
|
2015-02-16 03:38:54 +01:00
|
|
|
bgColor = Utils.COLOR_ORANGE_BUTTON;
|
2014-06-30 04:17:04 +02:00
|
|
|
osu = osuFiles.get(0);
|
|
|
|
}
|
2015-02-19 01:35:26 +01:00
|
|
|
|
2015-02-16 03:38:54 +01:00
|
|
|
// crop image if necessary
|
|
|
|
if (y < headerY) {
|
|
|
|
int cropHeight = (int) (headerY - y);
|
|
|
|
Image bgCropped = bg.getSubImage(0, cropHeight, bg.getWidth(), bg.getHeight() - cropHeight);
|
|
|
|
bgCropped.draw(x, headerY, bgColor);
|
|
|
|
} else if (y + bg.getHeight() > footerY) {
|
|
|
|
int cropHeight = (int) (footerY - y);
|
|
|
|
Image bgCropped = bg.getSubImage(0, 0, bg.getWidth(), cropHeight);
|
|
|
|
bgCropped.draw(x, y, bgColor);
|
|
|
|
} else
|
|
|
|
bg.draw(x, y, bgColor);
|
2014-07-11 01:13:53 +02:00
|
|
|
|
2015-02-16 03:38:54 +01:00
|
|
|
float cx = x + (bg.getWidth() * 0.05f);
|
2014-06-30 04:17:04 +02:00
|
|
|
float cy = y + (bg.getHeight() * 0.2f) - 3;
|
|
|
|
|
2015-02-16 03:38:54 +01:00
|
|
|
// draw grade
|
2015-01-28 09:47:24 +01:00
|
|
|
if (grade != Grade.NULL) {
|
2015-01-29 01:23:02 +01:00
|
|
|
Image gradeImg = grade.getMenuImage();
|
2015-01-28 09:47:24 +01:00
|
|
|
gradeImg.drawCentered(cx - bg.getWidth() * 0.01f + gradeImg.getWidth() / 2f, y + bg.getHeight() / 2.2f);
|
|
|
|
cx += gradeImg.getWidth();
|
|
|
|
}
|
|
|
|
|
2015-02-16 03:38:54 +01:00
|
|
|
// draw text
|
2014-08-25 05:48:52 +02:00
|
|
|
Utils.FONT_MEDIUM.drawString(cx, cy, osu.getTitle(), textColor);
|
2014-07-11 01:13:53 +02:00
|
|
|
Utils.FONT_DEFAULT.drawString(cx, cy + Utils.FONT_MEDIUM.getLineHeight() - 4,
|
2014-08-25 05:48:52 +02:00
|
|
|
String.format("%s // %s", osu.getArtist(), osu.creator), textColor);
|
2014-07-11 01:13:53 +02:00
|
|
|
if (expanded || osuFiles.size() == 1)
|
|
|
|
Utils.FONT_BOLD.drawString(cx, cy + Utils.FONT_MEDIUM.getLineHeight() + Utils.FONT_DEFAULT.getLineHeight() - 8,
|
|
|
|
osu.version, textColor);
|
2014-06-30 04:17:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an array of strings containing song information.
|
|
|
|
* <ul>
|
|
|
|
* <li>0: {Artist} - {Title} [{Version}]
|
|
|
|
* <li>1: Mapped by {Creator}
|
|
|
|
* <li>2: Length: {} BPM: {} Objects: {}
|
|
|
|
* <li>3: Circles: {} Sliders: {} Spinners: {}
|
|
|
|
* <li>4: CS:{} HP:{} AR:{} OD:{}
|
|
|
|
* </ul>
|
|
|
|
*/
|
|
|
|
public String[] getInfo() {
|
|
|
|
if (osuFileIndex < 0)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
OsuFile osu = osuFiles.get(osuFileIndex);
|
|
|
|
String[] info = new String[5];
|
|
|
|
info[0] = osu.toString();
|
|
|
|
info[1] = String.format("Mapped by %s",
|
|
|
|
osu.creator);
|
2014-07-18 03:16:15 +02:00
|
|
|
info[2] = String.format("Length: %d:%02d BPM: %s Objects: %d",
|
|
|
|
TimeUnit.MILLISECONDS.toMinutes(osu.endTime),
|
2015-01-16 21:44:13 +01:00
|
|
|
TimeUnit.MILLISECONDS.toSeconds(osu.endTime) -
|
2014-07-18 03:16:15 +02:00
|
|
|
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(osu.endTime)),
|
2014-06-30 04:17:04 +02:00
|
|
|
(osu.bpmMax <= 0) ? "--" :
|
|
|
|
((osu.bpmMin == osu.bpmMax) ? osu.bpmMin : String.format("%d-%d", osu.bpmMin, osu.bpmMax)),
|
|
|
|
(osu.hitObjectCircle + osu.hitObjectSlider + osu.hitObjectSpinner));
|
|
|
|
info[3] = String.format("Circles: %d Sliders: %d Spinners: %d",
|
|
|
|
osu.hitObjectCircle, osu.hitObjectSlider, osu.hitObjectSpinner);
|
2014-06-30 10:03:39 +02:00
|
|
|
info[4] = String.format("CS:%.1f HP:%.1f AR:%.1f OD:%.1f",
|
2014-06-30 04:17:04 +02:00
|
|
|
osu.circleSize, osu.HPDrainRate, osu.approachRate, osu.overallDifficulty);
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a formatted string for the OsuFile at osuFileIndex:
|
|
|
|
* "Artist - Title [Version]" (version omitted if osuFileIndex is invalid)
|
|
|
|
* @see java.lang.Object#toString()
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
if (osuFileIndex == -1)
|
2014-08-25 05:48:52 +02:00
|
|
|
return String.format("%s - %s", osuFiles.get(0).getArtist(), osuFiles.get(0).getTitle());
|
2014-06-30 04:17:04 +02:00
|
|
|
else
|
|
|
|
return osuFiles.get(osuFileIndex).toString();
|
|
|
|
}
|
2014-07-17 07:00:28 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether the node matches a given search query.
|
|
|
|
* @param query the search term
|
|
|
|
* @return true if title, artist, creator, source, version, or tag matches query
|
|
|
|
*/
|
|
|
|
public boolean matches(String query) {
|
|
|
|
OsuFile osu = osuFiles.get(0);
|
|
|
|
|
|
|
|
// search: title, artist, creator, source, version, tags (first OsuFile)
|
|
|
|
if (osu.title.toLowerCase().contains(query) ||
|
2015-02-10 03:40:38 +01:00
|
|
|
osu.titleUnicode.toLowerCase().contains(query) ||
|
2014-07-17 07:00:28 +02:00
|
|
|
osu.artist.toLowerCase().contains(query) ||
|
2015-02-10 03:40:38 +01:00
|
|
|
osu.artistUnicode.toLowerCase().contains(query) ||
|
2014-07-17 07:00:28 +02:00
|
|
|
osu.creator.toLowerCase().contains(query) ||
|
|
|
|
osu.source.toLowerCase().contains(query) ||
|
|
|
|
osu.version.toLowerCase().contains(query) ||
|
|
|
|
osu.tags.contains(query))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// search: version, tags (remaining OsuFiles)
|
|
|
|
for (int i = 1; i < osuFiles.size(); i++) {
|
|
|
|
osu = osuFiles.get(i);
|
|
|
|
if (osu.version.toLowerCase().contains(query) ||
|
|
|
|
osu.tags.contains(query))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2014-07-17 18:49:12 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether the node matches a given condition.
|
|
|
|
* @param type the condition type (ar, cs, od, hp, bpm, length)
|
|
|
|
* @param operator the operator (=/==, >, >=, <, <=)
|
|
|
|
* @param value the value
|
|
|
|
* @return true if the condition is met
|
|
|
|
*/
|
|
|
|
public boolean matches(String type, String operator, float value) {
|
|
|
|
for (OsuFile osu : osuFiles) {
|
|
|
|
// get value
|
|
|
|
float osuValue;
|
|
|
|
switch (type) {
|
|
|
|
case "ar": osuValue = osu.approachRate; break;
|
|
|
|
case "cs": osuValue = osu.circleSize; break;
|
|
|
|
case "od": osuValue = osu.overallDifficulty; break;
|
|
|
|
case "hp": osuValue = osu.HPDrainRate; break;
|
|
|
|
case "bpm": osuValue = osu.bpmMax; break;
|
2014-07-18 03:16:15 +02:00
|
|
|
case "length": osuValue = osu.endTime / 1000; break;
|
2014-07-17 18:49:12 +02:00
|
|
|
default: return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get operator
|
|
|
|
boolean met;
|
|
|
|
switch (operator) {
|
|
|
|
case "=":
|
|
|
|
case "==": met = (osuValue == value); break;
|
|
|
|
case ">": met = (osuValue > value); break;
|
|
|
|
case ">=": met = (osuValue >= value); break;
|
|
|
|
case "<": met = (osuValue < value); break;
|
|
|
|
case "<=": met = (osuValue <= value); break;
|
|
|
|
default: return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (met)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-30 04:17:04 +02:00
|
|
|
}
|