progress on untested framework
This commit is contained in:
@@ -36,7 +36,7 @@ public class RhythmBullet extends Game {
|
||||
private AssetManager assetManager = new AssetManager();
|
||||
private Skin skin;
|
||||
TextureAtlas skinAtlas;
|
||||
private Preferences prefs;
|
||||
private Preferences preferences;
|
||||
private RoundingResolutionHandler rRHandler;
|
||||
private Screen initialScreen;
|
||||
private AssetPack assetPack;
|
||||
@@ -58,7 +58,7 @@ public class RhythmBullet extends Game {
|
||||
|
||||
assetPack.initiateResources();
|
||||
|
||||
prefs = Gdx.app.getPreferences("RhythmBullet Preferences");
|
||||
preferences = Gdx.app.getPreferences("RhythmBullet Preferences");
|
||||
|
||||
Resolution[] resolution = {
|
||||
new Resolution(1280, 720, "1280x720"),
|
||||
@@ -78,7 +78,7 @@ public class RhythmBullet extends Game {
|
||||
assetManager.setLoader(ParticleEffect.class, new ParticleEffectLoader(genericFileFinder));
|
||||
assetManager.setLoader(Sound.class, new SoundLoader(genericFileFinder));
|
||||
|
||||
rRHandler.setResolution(getPrefs().getInteger("screen-width"), getPrefs().getInteger("screen-height"));
|
||||
rRHandler.setResolution(getPreferences().getInteger("screen-width"), getPreferences().getInteger("screen-height"));
|
||||
|
||||
|
||||
screenWidth = Gdx.graphics.getWidth();
|
||||
@@ -86,10 +86,10 @@ public class RhythmBullet extends Game {
|
||||
|
||||
pixels_per_unit = (int) (Float.valueOf(screenHeight)/Float.valueOf(WORLD_HEIGHT));
|
||||
|
||||
if (getPrefs().getBoolean("fullscreen", true)) {
|
||||
if (getPreferences().getBoolean("fullscreen", true)) {
|
||||
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
|
||||
} else {
|
||||
Gdx.graphics.setWindowedMode(getPrefs().getInteger("screen-width"), getPrefs().getInteger("screen-height"));
|
||||
Gdx.graphics.setWindowedMode(getPreferences().getInteger("screen-width"), getPreferences().getInteger("screen-height"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,9 +161,9 @@ public class RhythmBullet extends Game {
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot perform window resize on a screen that isn't using a resize ready screen.");
|
||||
}
|
||||
prefs.putInteger("screen-width", width);
|
||||
prefs.putInteger("screen-height", height);
|
||||
prefs.flush();
|
||||
preferences.putInteger("screen-width", width);
|
||||
preferences.putInteger("screen-height", height);
|
||||
preferences.flush();
|
||||
resizing = true;
|
||||
assetManager.clear();
|
||||
queueAssets();
|
||||
@@ -185,8 +185,8 @@ public class RhythmBullet extends Game {
|
||||
return skin;
|
||||
}
|
||||
|
||||
public Preferences getPrefs() {
|
||||
return prefs;
|
||||
public Preferences getPreferences() {
|
||||
return preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -31,7 +31,11 @@ public class MusicList extends Observable {
|
||||
* Also notifies listeners that are on the main thread.
|
||||
*/
|
||||
public void asyncSearch() {
|
||||
searchThread.start();
|
||||
if (!searchThread.start()) {
|
||||
searchThread.stop();
|
||||
searchThread = new RecursiveMusicSearchThread("Music Search Thread");
|
||||
searchThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSearchPath(String searchPath) {
|
||||
@@ -96,6 +100,7 @@ public class MusicList extends Observable {
|
||||
private Thread thread;
|
||||
private String threadName;
|
||||
private FileHandle directory;
|
||||
private volatile boolean work;
|
||||
|
||||
public RecursiveMusicSearchThread(String name) {
|
||||
this.threadName = name;
|
||||
@@ -107,23 +112,32 @@ public class MusicList extends Observable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
musicList = recursiveMusicSearch(directory);
|
||||
searchComplete();
|
||||
Array<FileHandle> obtainedAudioFiles = recursiveMusicSearch(directory);
|
||||
if (work) {
|
||||
musicList = obtainedAudioFiles;
|
||||
searchComplete();
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (thread == null && !thread.isAlive()) {
|
||||
public boolean start() {
|
||||
if (thread == null) {
|
||||
work = true;
|
||||
thread = new Thread(this, threadName);
|
||||
thread.start();
|
||||
return true;
|
||||
} else {
|
||||
throw new IllegalStateException("Two " + threadName + " instances (threads) were created. This is not allowed for optimization as there is no reason to have two running.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
work = false;
|
||||
}
|
||||
|
||||
private Array<FileHandle> recursiveMusicSearch(FileHandle fileHandle) {
|
||||
Array<FileHandle> musicFiles = new Array<>();
|
||||
FileHandle[] files = fileHandle.list();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
for (int i = 0; i < files.length && work; i++) {
|
||||
if (files[i].isDirectory()) {
|
||||
musicFiles.addAll(recursiveMusicSearch(files[i]));
|
||||
} else {
|
||||
|
@@ -11,7 +11,7 @@ import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
||||
import zero1hd.rhythmbullet.audio.metadata.MP3Metadata;
|
||||
import zero1hd.rhythmbullet.audio.metadata.WAVMetadata;
|
||||
|
||||
public class MusicMetadataController implements Disposable, Observer {
|
||||
public class MusicMetadataController extends Observable implements Disposable, Observer {
|
||||
private MusicList musicList;
|
||||
private Array<AudioMetadata> metadataArray;
|
||||
private MetadataLoadingThread loadingThread;
|
||||
@@ -20,6 +20,8 @@ public class MusicMetadataController implements Disposable, Observer {
|
||||
public MusicMetadataController(MusicList musicList) {
|
||||
this.musicList = musicList;
|
||||
metadataArray = new Array<>();
|
||||
loadingThread = new MetadataLoadingThread();
|
||||
musicList.addObserver(this);
|
||||
}
|
||||
|
||||
public MusicList getMusicList() {
|
||||
@@ -29,8 +31,12 @@ public class MusicMetadataController implements Disposable, Observer {
|
||||
/**
|
||||
* Non-blocking, loads on separate thread.
|
||||
*/
|
||||
public void loadSongInfo() {
|
||||
loadingThread.start();
|
||||
public void loadAudioMetadata() {
|
||||
if (!loadingThread.start()) {
|
||||
loadingThread.stop();
|
||||
loadingThread = new MetadataLoadingThread();
|
||||
loadingThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
@@ -66,6 +72,7 @@ public class MusicMetadataController implements Disposable, Observer {
|
||||
private class MetadataLoadingThread implements Runnable {
|
||||
private Thread thread;
|
||||
private String name = "Metadata-Load";
|
||||
private volatile boolean work;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -74,7 +81,7 @@ public class MusicMetadataController implements Disposable, Observer {
|
||||
metadataArray.get(i).dispose();
|
||||
}
|
||||
metadataArray.clear();
|
||||
for (int i = 0; i < musicList.getTotal(); i++) {
|
||||
for (int i = 0; i < musicList.getTotal() && work; i++) {
|
||||
FileHandle musicFile = musicList.getMusicArray().get(i);
|
||||
synchronized (this) {
|
||||
switch (SupportedFormats.valueOf(musicFile.extension().toUpperCase())) {
|
||||
@@ -90,19 +97,32 @@ public class MusicMetadataController implements Disposable, Observer {
|
||||
}
|
||||
}
|
||||
}
|
||||
searching = false;
|
||||
if (work) {
|
||||
searching = false;
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (thread != null && !thread.isAlive()) {
|
||||
public boolean start() {
|
||||
if (thread == null) {
|
||||
thread = new Thread(this, name);
|
||||
thread.start();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
work = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
// TODO Auto-generated method stub
|
||||
if (o == musicList) {
|
||||
loadingThread.stop();
|
||||
loadAudioMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,13 +2,12 @@ package zero1hd.rhythmbullet.audio.analyzer;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
|
||||
import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
|
||||
import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
|
||||
|
||||
public class AudioAnalyzer implements Runnable, Disposable {
|
||||
public class AudioAnalyzer implements Runnable {
|
||||
private Thread thread;
|
||||
private String threadName = "Audio-Analyzer";
|
||||
|
||||
@@ -38,15 +37,15 @@ public class AudioAnalyzer implements Runnable, Disposable {
|
||||
private int PUID;
|
||||
private int progress;
|
||||
|
||||
public AudioAnalyzer(AudioProcessor audioProcessor) {
|
||||
this.processor = audioProcessor;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (thread == null || !thread.isAlive()) {
|
||||
public boolean start(AudioProcessor processor) {
|
||||
if (thread == null) {
|
||||
this.processor = processor;
|
||||
work = true;
|
||||
thread = new Thread(this, threadName);
|
||||
thread.start();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,13 +281,6 @@ public class AudioAnalyzer implements Runnable, Disposable {
|
||||
public int getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (thread != null) {
|
||||
work = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
work = false;
|
||||
|
@@ -37,7 +37,13 @@ public interface AudioMetadata extends Disposable {
|
||||
*
|
||||
* @return the length of the song with proper fomatting.
|
||||
*/
|
||||
public String getLength();
|
||||
public String getDuration();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the length of the song in seconds.
|
||||
*/
|
||||
public int getLength();
|
||||
|
||||
/**
|
||||
*
|
||||
|
@@ -18,7 +18,8 @@ import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
|
||||
public class MP3Metadata implements AudioMetadata {
|
||||
private String title, author, length, genre;
|
||||
private String title, author, duration, genre;
|
||||
private int length;
|
||||
private Texture albumCover;
|
||||
private FileHandle fileHandle;
|
||||
|
||||
@@ -38,9 +39,9 @@ public class MP3Metadata implements AudioMetadata {
|
||||
|
||||
|
||||
|
||||
int lenInSec = mp3file.getAudioHeader().getTrackLength();
|
||||
int min = (int) (lenInSec/60);
|
||||
length = (lenInSec/60) + ":" + (lenInSec - (min*60));
|
||||
length = mp3file.getAudioHeader().getTrackLength();
|
||||
int min = (int) (length/60);
|
||||
duration = (length/60) + ":" + (length - (min*60));
|
||||
|
||||
author = tag.getFirst(ID3v23FieldKey.ARTIST);
|
||||
genre = tag.getFirst(ID3v23FieldKey.GENRE);
|
||||
@@ -86,7 +87,12 @@ public class MP3Metadata implements AudioMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLength() {
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,8 @@ import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
|
||||
public class WAVMetadata implements AudioMetadata {
|
||||
private String title, author, length, genre;
|
||||
private String title, author, duration, genre;
|
||||
private int length;
|
||||
private Texture albumCover;
|
||||
private FileHandle fileHandle;
|
||||
|
||||
@@ -26,9 +27,9 @@ public class WAVMetadata implements AudioMetadata {
|
||||
|
||||
try {
|
||||
AudioFile wav = AudioFileIO.read(fileHandle.file());
|
||||
int lenInSec = wav.getAudioHeader().getTrackLength();
|
||||
int min = (int) (lenInSec/60);
|
||||
this.length = (lenInSec/60) + ":" + (lenInSec - (min*60));
|
||||
length = wav.getAudioHeader().getTrackLength();
|
||||
int min = (int) (length/60);
|
||||
this.duration = (length/60) + ":" + (length - (min*60));
|
||||
|
||||
Tag tag = wav.getTag();
|
||||
title = tag.getFirst(FieldKey.TITLE);
|
||||
@@ -70,9 +71,15 @@ public class WAVMetadata implements AudioMetadata {
|
||||
return title;
|
||||
}
|
||||
@Override
|
||||
public String getLength() {
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Texture getAlbumCover() {
|
||||
return albumCover;
|
||||
|
74
core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicSelectable.java
Executable file
74
core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicSelectable.java
Executable file
@@ -0,0 +1,74 @@
|
||||
package zero1hd.rhythmbullet.graphics.ui.components;
|
||||
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
|
||||
import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
||||
|
||||
public class MusicSelectable extends Button {
|
||||
private Vector2 actualCoords;
|
||||
private Image album;
|
||||
private Table informationTable;
|
||||
private ShortenedLabel name, artist;
|
||||
private Label time;
|
||||
private float timeSinceOnScreen;
|
||||
private AudioMetadata metadata;
|
||||
private Texture defaultAlbumArt;
|
||||
|
||||
|
||||
public MusicSelectable(Skin skin, Texture defaultAlbumArt, AudioMetadata metadata) {
|
||||
super(skin, "music-selectable");
|
||||
this.metadata = metadata;
|
||||
this.defaultAlbumArt = defaultAlbumArt;
|
||||
|
||||
album = new Image(defaultAlbumArt);
|
||||
add(album).expand().left();
|
||||
|
||||
informationTable = new Table();
|
||||
name = new ShortenedLabel(metadata.getTitle(), skin, "default-font", skin.getColor("default"));
|
||||
informationTable.add(name).colspan(2).expandX();
|
||||
informationTable.row();
|
||||
artist = new ShortenedLabel(metadata.getTitle(), skin, "sub-font", skin.getColor("default"));
|
||||
informationTable.add(artist).expandX();
|
||||
time = new Label(metadata.getDuration(), skin, "sub-font", skin.getColor("default"));
|
||||
informationTable.add(time).expandX();
|
||||
add(informationTable).expand().fill();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
actualCoords.x = getX() + getParent().getX();
|
||||
actualCoords.y = getY() + getParent().getY();
|
||||
|
||||
if (actualCoords.y < 0-getHeight() || actualCoords.y > getStage().getHeight() || actualCoords.x < 0-getWidth() || actualCoords.x > getStage().getWidth()) {
|
||||
offScreenAct(delta);
|
||||
} else {
|
||||
onScreenAct(delta);
|
||||
}
|
||||
super.act(delta);
|
||||
}
|
||||
|
||||
public void onScreenAct(float delta) {
|
||||
timeSinceOnScreen = 0;
|
||||
if (metadata.getAlbumCover() == null) {
|
||||
metadata.loadAlbumCover();
|
||||
album.setDrawable(new TextureRegionDrawable(new TextureRegion(metadata.getAlbumCover())));
|
||||
}
|
||||
}
|
||||
|
||||
public void offScreenAct(float delta) {
|
||||
if (metadata.getAlbumCover() != null) {
|
||||
timeSinceOnScreen += delta;
|
||||
if (timeSinceOnScreen >= 2) {
|
||||
metadata.unloadAlbumCover();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -89,6 +89,8 @@ public class ScrollText extends Widget {
|
||||
|
||||
@Override
|
||||
public void layout() {
|
||||
super.layout();
|
||||
|
||||
if (getHeight() < (textHeight+4)) {
|
||||
setHeight(textHeight + 4);
|
||||
}
|
||||
@@ -98,7 +100,6 @@ public class ScrollText extends Widget {
|
||||
if (text1Width < clipBounds.getWidth()) {
|
||||
text1Offset = (clipBounds.getWidth()-text1Width)/2f;
|
||||
}
|
||||
super.layout();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -3,34 +3,37 @@ package zero1hd.rhythmbullet.graphics.ui.components;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
|
||||
public class ShortenedTextLabel extends Label {
|
||||
public class ShortenedLabel extends Label {
|
||||
private String originalText;
|
||||
private int targetWidth;
|
||||
private GlyphLayout gl;
|
||||
private BitmapFont font;
|
||||
private Vector2 size;
|
||||
|
||||
public ShortenedTextLabel(CharSequence text, Skin skin, String fontName, Color color) {
|
||||
super(text, skin, fontName, color);
|
||||
public ShortenedLabel(CharSequence text, Skin skin, String fontName, Color color) {
|
||||
super(null, skin, fontName, color);
|
||||
originalText = text.toString();
|
||||
font = skin.getFont(fontName);
|
||||
if (text != null) {
|
||||
gl = new GlyphLayout(skin.getFont(fontName), text);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTargetWidth(int targetWidth) {
|
||||
this.targetWidth = targetWidth;
|
||||
size = new Vector2();
|
||||
|
||||
setWrap(true);
|
||||
}
|
||||
|
||||
public void resize() {
|
||||
setToOriginalText();
|
||||
while (gl.width > targetWidth && (getText().length - 4) > 0) {
|
||||
setText(getText().substring(0, getText().length - 4).concat("..."));
|
||||
gl.setText(font, getText());
|
||||
String text = getText().toString();
|
||||
while (gl.width > targetWidth && (text.length() - 4) > 0) {
|
||||
text = text.substring(0, text.length() - 4).concat("...");
|
||||
gl.setText(font, text);
|
||||
}
|
||||
setText(text);
|
||||
}
|
||||
|
||||
public void setToOriginalText() {
|
||||
@@ -41,6 +44,10 @@ public class ShortenedTextLabel extends Label {
|
||||
@Override
|
||||
public void layout() {
|
||||
super.layout();
|
||||
size.x = getWidth();
|
||||
size.y = getHeight();
|
||||
targetWidth = (int) getStage().stageToScreenCoordinates(size).x;
|
||||
resize();
|
||||
}
|
||||
|
||||
public void setOriginalText(String originalText) {
|
Reference in New Issue
Block a user