progress on adding base layer
This commit is contained in:
13
old/desktop/.classpath
Normal file
13
old/desktop/.classpath
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="bin/main" path="src">
|
||||
<attributes>
|
||||
<attribute name="gradle_scope" value="main"/>
|
||||
<attribute name="gradle_used_by_scope" value="main,test"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry exported="true" kind="con" path="org.springsource.ide.eclipse.gradle.classpathcontainer"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/RhythmBullet-core"/>
|
||||
<classpathentry kind="output" path="bin/default"/>
|
||||
</classpath>
|
25
old/desktop/.project
Normal file
25
old/desktop/.project
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>RhythmBullet-desktop</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springsource.ide.eclipse.gradle.core.nature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>assets</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-1-PROJECT_LOC/android/assets</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
@@ -0,0 +1,4 @@
|
||||
#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences
|
||||
#Mon Sep 10 00:40:48 CDT 2018
|
||||
org.springsource.ide.eclipse.gradle.linkedresources=assets/;
|
||||
org.springsource.ide.eclipse.gradle.rootprojectloc=..
|
@@ -0,0 +1,8 @@
|
||||
#org.springsource.ide.eclipse.gradle.core.actions.GradleRefreshPreferences
|
||||
#Mon Sep 10 00:40:48 CDT 2018
|
||||
addResourceFilters=true
|
||||
afterTasks=afterEclipseImport;
|
||||
beforeTasks=cleanEclipse;eclipse;
|
||||
enableAfterTasks=true
|
||||
enableBeforeTasks=true
|
||||
useHierarchicalNames=false
|
11
old/desktop/.settings/org.eclipse.jdt.core.prefs
Normal file
11
old/desktop/.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,11 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
55
old/desktop/build.gradle
Normal file
55
old/desktop/build.gradle
Normal file
@@ -0,0 +1,55 @@
|
||||
apply plugin: "java"
|
||||
|
||||
sourceCompatibility = 1.6
|
||||
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||
|
||||
project.ext.mainClassName = "zero1hd.rhythmbullet.desktop.DesktopLauncher"
|
||||
project.ext.assetsDir = new File("../android/assets");
|
||||
|
||||
task run(dependsOn: classes, type: JavaExec) {
|
||||
main = project.mainClassName
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
standardInput = System.in
|
||||
workingDir = project.assetsDir
|
||||
ignoreExitValue = true
|
||||
}
|
||||
|
||||
task debug(dependsOn: classes, type: JavaExec) {
|
||||
main = project.mainClassName
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
standardInput = System.in
|
||||
workingDir = project.assetsDir
|
||||
ignoreExitValue = true
|
||||
debug = true
|
||||
}
|
||||
|
||||
task dist(type: Jar) {
|
||||
from files(sourceSets.main.output.classesDir)
|
||||
from files(sourceSets.main.output.resourcesDir)
|
||||
from {configurations.compile.collect {zipTree(it)}}
|
||||
from files(project.assetsDir);
|
||||
|
||||
manifest {
|
||||
attributes 'Main-Class': project.mainClassName
|
||||
}
|
||||
}
|
||||
|
||||
dist.dependsOn classes
|
||||
|
||||
eclipse {
|
||||
project {
|
||||
name = appName + "-desktop"
|
||||
linkedResource name: 'assets', type: '2', location: 'PARENT-1-PROJECT_LOC/android/assets'
|
||||
}
|
||||
}
|
||||
|
||||
task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
|
||||
doLast {
|
||||
def classpath = new XmlParser().parse(file(".classpath"))
|
||||
new Node(classpath, "classpathentry", [ kind: 'src', path: 'assets' ]);
|
||||
def writer = new FileWriter(file(".classpath"))
|
||||
def printer = new XmlNodePrinter(new PrintWriter(writer))
|
||||
printer.setPreserveWhitespace(true)
|
||||
printer.print(classpath)
|
||||
}
|
||||
}
|
45
old/desktop/src/zero1hd/rhythmbullet/desktop/Controls.java
Normal file
45
old/desktop/src/zero1hd/rhythmbullet/desktop/Controls.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package zero1hd.rhythmbullet.desktop;
|
||||
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
|
||||
public enum Controls {
|
||||
UP("Forward", Keys.UP), DOWN("Backwards", Keys.DOWN), LEFT("Left", Keys.LEFT), RIGHT("Right", Keys.RIGHT), SHOOT("Shoot", Keys.SPACE), ACCELERATE("Boost", Keys.SHIFT_LEFT);
|
||||
private int keycode;
|
||||
private final String friendly;
|
||||
private final int defectKey;
|
||||
|
||||
private Controls(String friendly, int defectKey) {
|
||||
this.friendly = friendly;
|
||||
this.defectKey = defectKey;
|
||||
this.keycode = defectKey;
|
||||
}
|
||||
|
||||
public Controls setKeycode(int keycode) {
|
||||
Controls[] controls = Controls.values();
|
||||
for (int i = 0; i < controls.length; i++) {
|
||||
if (controls[i] != this && controls[i].getKeycode() == keycode) {
|
||||
return controls[i];
|
||||
}
|
||||
}
|
||||
this.keycode = keycode;
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getKeycode() {
|
||||
return keycode;
|
||||
}
|
||||
|
||||
public void loadKeyFromPreferences(Preferences preferences) {
|
||||
setKeycode(preferences.getInteger(name(), defectKey));
|
||||
}
|
||||
|
||||
public void saveKeyToPreferences(Preferences preferences) {
|
||||
preferences.putInteger(name(), keycode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return friendly;
|
||||
}
|
||||
}
|
@@ -0,0 +1,238 @@
|
||||
package zero1hd.rhythmbullet.desktop;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.audio.Sound;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton.ImageButtonStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.List.ListStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar.ProgressBarStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane.ScrollPaneStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox.SelectBoxStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Slider.SliderStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
|
||||
|
||||
import zero1hd.rhythmbullet.util.AssetPack;
|
||||
|
||||
public class DesktopAssetPack implements AssetPack {
|
||||
private FreeTypeFontGenerator default_fontGenerator;
|
||||
private FreeTypeFontGenerator darktech_ldr_fontGenerator;
|
||||
|
||||
@Override
|
||||
public void initiate() {
|
||||
default_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/Gasalt-Regular.ttf"));
|
||||
darktech_ldr_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/darktech_ldr.ttf"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueTextures(AssetManager assetManager) {
|
||||
assetManager.load("uiskin.atlas", TextureAtlas.class);
|
||||
assetManager.load("Tech-Circle1.png", Texture.class);
|
||||
assetManager.load("polyjet-standard.png", Texture.class);
|
||||
assetManager.load("keyboard.atlas", TextureAtlas.class);
|
||||
assetManager.load("cybercircle3B.png", Texture.class);
|
||||
assetManager.load("title.png", Texture.class);
|
||||
assetManager.load("cybercircle1.png", Texture.class);
|
||||
assetManager.load("defaultCover.png", Texture.class);
|
||||
assetManager.load("laser.png", Texture.class);
|
||||
assetManager.load("pellet.png", Texture.class);
|
||||
assetManager.load("shard.png", Texture.class);
|
||||
assetManager.load("bar.png", Texture.class);
|
||||
assetManager.load("flake.png", Texture.class);
|
||||
assetManager.load("void_circle.png", Texture.class);
|
||||
assetManager.load("tpSelector.png", Texture.class);
|
||||
assetManager.load("backgrounds/mainBG.png", Texture.class);
|
||||
assetManager.load("magic1.png", Texture.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueSFX(AssetManager assetManager) {
|
||||
assetManager.load("pop_open.ogg", Sound.class);
|
||||
assetManager.load("pop_close.ogg", Sound.class);
|
||||
assetManager.load("laser.ogg", Sound.class);
|
||||
assetManager.load("explosion.ogg", Sound.class);
|
||||
assetManager.load("disintegrate.ogg", Sound.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueParticles(AssetManager assetManager) {
|
||||
assetManager.load("standard_thrust.p", ParticleEffect.class);
|
||||
assetManager.load("teleport-cloak.p", ParticleEffect.class);
|
||||
assetManager.load("explosion-s.p", ParticleEffect.class);
|
||||
assetManager.load("beateffect.p", ParticleEffect.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupSkin(Skin skin) {
|
||||
skin.add("default", Color.WHITE);
|
||||
skin.add("inverse", Color.BLACK);
|
||||
|
||||
TextButtonStyle defaultTextButton = new TextButtonStyle();
|
||||
defaultTextButton.up = skin.getDrawable("rect");
|
||||
defaultTextButton.down = skin.getDrawable("rect-down");
|
||||
defaultTextButton.font = skin.getFont("default-font");
|
||||
defaultTextButton.fontColor = skin.getColor("default");
|
||||
defaultTextButton.disabled = skin.getDrawable("rect-disabled");
|
||||
skin.add("default", defaultTextButton);
|
||||
|
||||
TextButtonStyle subTextbutton = new TextButtonStyle(defaultTextButton);
|
||||
subTextbutton.font = skin.getFont("sub-font");
|
||||
skin.add("sub", subTextbutton);
|
||||
|
||||
TextButtonStyle windowTextButton = new TextButtonStyle(defaultTextButton);
|
||||
windowTextButton.font = skin.getFont("window-font");
|
||||
skin.add("window", windowTextButton);
|
||||
|
||||
SliderStyle defaultSlider = new SliderStyle(skin.getDrawable("default-slider"), skin.getDrawable("default-slider-knob"));
|
||||
skin.add("default-horizontal", defaultSlider);
|
||||
|
||||
SliderStyle vertSlider = new SliderStyle(defaultSlider);
|
||||
vertSlider.knob = skin.getDrawable("vertical-slider-knob");
|
||||
skin.add("default-vertical", vertSlider);
|
||||
|
||||
ProgressBarStyle defaultProgressBar = new ProgressBarStyle(skin.getDrawable("default-slider"), skin.getDrawable("progress-slider-knob"));
|
||||
|
||||
LabelStyle defaultLabel = new LabelStyle();
|
||||
defaultLabel.font = skin.getFont("default-font");
|
||||
defaultLabel.fontColor = skin.getColor("default");
|
||||
skin.add("default", defaultLabel);
|
||||
|
||||
TextFieldStyle defaultTextField = new TextFieldStyle(skin.getFont("sub-font"), skin.getColor("default"), skin.getDrawable("cursor"), skin.getDrawable("selection"), skin.getDrawable("textfield"));
|
||||
skin.add("default", defaultTextField);
|
||||
|
||||
TextFieldStyle uiTextField = new TextFieldStyle(defaultTextField);
|
||||
uiTextField.font = skin.getFont("window-font");
|
||||
skin.add("ui", uiTextField);
|
||||
|
||||
WindowStyle defaultWindow = new WindowStyle(skin.getFont("window-font"), skin.getColor("default"), skin.getDrawable("default-window"));
|
||||
skin.add("default", defaultWindow);
|
||||
|
||||
WindowStyle tintedWindow = new WindowStyle(defaultWindow);
|
||||
tintedWindow.titleFontColor = skin.getColor("inverse");
|
||||
tintedWindow.background = skin.getDrawable("tinted-window");
|
||||
skin.add("tinted", tintedWindow);
|
||||
|
||||
ListStyle defaultList = new ListStyle(skin.getFont("window-font"), skin.getColor("inverse"), skin.getColor("default"), skin.getDrawable("selection"));
|
||||
skin.add("default", defaultList);
|
||||
|
||||
ScrollPaneStyle defaultScrollPane = new ScrollPaneStyle();
|
||||
defaultScrollPane.vScroll = skin.getDrawable("default-scroll");
|
||||
defaultScrollPane.hScrollKnob = skin.getDrawable("default-round-large");
|
||||
defaultScrollPane.hScroll = skin.getDrawable("default-scroll");
|
||||
defaultScrollPane.vScrollKnob = skin.getDrawable("default-round-large");
|
||||
skin.add("default", defaultScrollPane);
|
||||
|
||||
CheckBoxStyle defaultCheckBox = new CheckBoxStyle(skin.getDrawable("check-off"), skin.getDrawable("check-on"), skin.getFont("window-font"), skin.getColor("default"));
|
||||
defaultCheckBox.checkboxOffDisabled = skin.getDrawable("check-disabled");
|
||||
skin.add("default", defaultCheckBox);
|
||||
|
||||
SelectBoxStyle defaultSelectBox = new SelectBoxStyle(skin.getFont("default-font"), skin.getColor("default"), skin.getDrawable("default-select"), defaultScrollPane, defaultList);
|
||||
skin.add("default", defaultSelectBox);
|
||||
|
||||
Gdx.app.debug("Prelaunch Debug Info", "UI Skin has been defined.");
|
||||
|
||||
CheckBoxStyle playButtonStyle = new CheckBoxStyle(defaultCheckBox);
|
||||
playButtonStyle.checkboxOn = skin.getDrawable("play-down");
|
||||
playButtonStyle.checkboxOff = skin.getDrawable("play");
|
||||
skin.add("play-button", playButtonStyle);
|
||||
|
||||
ImageButtonStyle pauseButtonStyle = new ImageButtonStyle();
|
||||
pauseButtonStyle.down = skin.getDrawable("pause-down");
|
||||
pauseButtonStyle.up = skin.getDrawable("pause");
|
||||
skin.add("pause-button", pauseButtonStyle);
|
||||
|
||||
ImageButtonStyle fastForwardButtonStyle = new ImageButtonStyle();
|
||||
fastForwardButtonStyle.down = skin.getDrawable("fast-forward-down");
|
||||
fastForwardButtonStyle.up = skin.getDrawable("fast-forward");
|
||||
skin.add("fast-forward-button", fastForwardButtonStyle);
|
||||
|
||||
ImageButtonStyle reverseButtonStyle = new ImageButtonStyle();
|
||||
reverseButtonStyle.down = skin.getDrawable("rewind-down");
|
||||
reverseButtonStyle.up = skin.getDrawable("rewind");
|
||||
skin.add("rewind-button", reverseButtonStyle);
|
||||
|
||||
CheckBoxStyle shuffleButtonStyle = new CheckBoxStyle(defaultCheckBox);
|
||||
shuffleButtonStyle.checkboxOff = skin.getDrawable("shuffle");
|
||||
shuffleButtonStyle.checkboxOn = skin.getDrawable("shuffle-down");
|
||||
skin.add("shuffle-button", shuffleButtonStyle);
|
||||
|
||||
ButtonStyle selectableButton = new ButtonStyle();
|
||||
selectableButton.checked = skin.getDrawable("holo-pane-down");
|
||||
selectableButton.up = skin.getDrawable("holo-pane");
|
||||
skin.add("selectable-button", selectableButton);
|
||||
|
||||
ButtonStyle selectableCleanButton = new ButtonStyle();
|
||||
skin.add("selectable-clean-button", selectableCleanButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateFonts(Skin skin) {
|
||||
int height = Gdx.graphics.getHeight();
|
||||
|
||||
skin.add("window-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
|
||||
{
|
||||
size = 18;
|
||||
}
|
||||
}));
|
||||
skin.add("sub-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
|
||||
{
|
||||
size = fontScale(0.05f, height);
|
||||
}
|
||||
}));
|
||||
skin.add("default-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
|
||||
{
|
||||
size = fontScale(0.07f, height);
|
||||
}
|
||||
}));
|
||||
skin.add("large-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
|
||||
{
|
||||
size = fontScale(0.085f, height);
|
||||
}
|
||||
}));
|
||||
skin.add("special-font", darktech_ldr_fontGenerator.generateFont(new FreeTypeFontParameter() {
|
||||
{
|
||||
size = fontScale(0.075f, height);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public int fontScale(float fontSize, int height) {
|
||||
int size = MathUtils.round(Gdx.graphics.getDensity()*(fontSize*height));
|
||||
if (size >= 200) {
|
||||
size = 200;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(AssetManager assetManager) {
|
||||
assetManager.get("standard_thrust.p", ParticleEffect.class).flipY();
|
||||
|
||||
Preferences controlsPrefs = Gdx.app.getPreferences("RhythmBullet_Controls");
|
||||
Controls.UP.loadKeyFromPreferences(controlsPrefs);
|
||||
Controls.DOWN.loadKeyFromPreferences(controlsPrefs);
|
||||
Controls.LEFT.loadKeyFromPreferences(controlsPrefs);
|
||||
Controls.RIGHT.loadKeyFromPreferences(controlsPrefs);
|
||||
Controls.SHOOT.loadKeyFromPreferences(controlsPrefs);
|
||||
Controls.ACCELERATE.loadKeyFromPreferences(controlsPrefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
darktech_ldr_fontGenerator.dispose();
|
||||
default_fontGenerator.dispose();
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package zero1hd.rhythmbullet.desktop;
|
||||
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||
|
||||
import zero1hd.rhythmbullet.RhythmBullet;
|
||||
import zero1hd.rhythmbullet.desktop.screens.SplashScreen;
|
||||
|
||||
public class DesktopLauncher {
|
||||
|
||||
public static void main (String[] arg) {
|
||||
RhythmBullet core;
|
||||
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
|
||||
DesktopScreenConfiguration screenConfig = new DesktopScreenConfiguration(config);
|
||||
|
||||
config.title = "Rhythm Bullet";
|
||||
config.resizable = false;
|
||||
config.useHDPI = true;
|
||||
config.samples = 2;
|
||||
config.width = 320;
|
||||
config.height = 320;
|
||||
config.allowSoftwareMode = true;
|
||||
core = new RhythmBullet();
|
||||
core.setup(new SplashScreen(), new DesktopAssetPack(), screenConfig);
|
||||
|
||||
LwjglApplication app = new LwjglApplication(core, config);
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
package zero1hd.rhythmbullet.desktop;
|
||||
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||
|
||||
import zero1hd.rhythmbullet.util.ScreenConfiguration;
|
||||
|
||||
public class DesktopScreenConfiguration implements ScreenConfiguration {
|
||||
private LwjglApplicationConfiguration configuration;
|
||||
private boolean vSync;
|
||||
|
||||
public DesktopScreenConfiguration(LwjglApplicationConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
vSync = configuration.vSyncEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFramesPerSecond(int fps) {
|
||||
configuration.foregroundFPS = fps;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getTargetFramesPerSecond() {
|
||||
return configuration.foregroundFPS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVsync(boolean useVsync) {
|
||||
configuration.vSyncEnabled = useVsync;
|
||||
Display.setVSyncEnabled(useVsync);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVsync() {
|
||||
return vSync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenWidth() {
|
||||
return Display.getDesktopDisplayMode().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenHeight() {
|
||||
return Display.getDesktopDisplayMode().getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindowPosX() {
|
||||
return Display.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindowPosY() {
|
||||
return Display.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWindowLocationX(int x) {
|
||||
Display.setLocation(x, getWindowPosY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWindowLocationY(int y) {
|
||||
Display.setLocation(getWindowPosX(), y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWindowLocation(int x, int y) {
|
||||
Display.setLocation(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueBorderless(boolean borderless) {
|
||||
System.setProperty("org.lwjgl.opengl.Window.undecorated", String.valueOf(borderless));
|
||||
}
|
||||
}
|
@@ -0,0 +1,269 @@
|
||||
package zero1hd.rhythmbullet.desktop.audio;
|
||||
|
||||
import static org.lwjgl.openal.AL10.alGetSourcef;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import org.lwjgl.openal.AL;
|
||||
import org.lwjgl.openal.AL11;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.backends.lwjgl.audio.OpenALMusic;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||
import com.badlogic.gdx.utils.reflect.Field;
|
||||
import com.badlogic.gdx.utils.reflect.ReflectionException;
|
||||
|
||||
import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.audio.visualizer.PCMSystem;
|
||||
|
||||
public class PCMObtainer implements Observer, PCMSystem {
|
||||
private int windowSize = 1024;
|
||||
private int sampleRate;
|
||||
private long millisPerWindow;
|
||||
private boolean songChanged;
|
||||
private DecimalFormat df;
|
||||
private float[] PCM = new float[windowSize];
|
||||
private float[] frequencyBins = new float[windowSize / 2];
|
||||
private FloatFFT_1D fft = new FloatFFT_1D(windowSize);
|
||||
private ShortBuffer playingBuffer;
|
||||
private ShortBuffer intermediateBuffer;
|
||||
private ShortBuffer buffer;
|
||||
private volatile int sourceID;
|
||||
private int channelCount;
|
||||
private MusicController mc;
|
||||
private BufferStreamReadThread streamReadThread;
|
||||
private int windowsRead;
|
||||
private int currentPlaybackWindow;
|
||||
private volatile boolean updated;
|
||||
|
||||
public PCMObtainer(MusicController musicController) {
|
||||
this.mc = musicController;
|
||||
mc.addObserver(this);
|
||||
try {
|
||||
Field bufferField = ClassReflection.getDeclaredField(OpenALMusic.class, "tempBuffer");
|
||||
bufferField.setAccessible(true);
|
||||
buffer = ((ByteBuffer) bufferField.get(null)).asShortBuffer().asReadOnlyBuffer();
|
||||
playingBuffer = ShortBuffer.allocate(buffer.capacity());
|
||||
intermediateBuffer = ShortBuffer.allocate(buffer.capacity());
|
||||
} catch (IllegalArgumentException | SecurityException | ReflectionException e) {
|
||||
Gdx.app.debug("Visualizer reflection", "Failed attempt at retrieving tempBuffer field.", e);
|
||||
Gdx.app.exit();
|
||||
}
|
||||
|
||||
streamReadThread = new BufferStreamReadThread();
|
||||
|
||||
df = new DecimalFormat("#.###");
|
||||
df.setRoundingMode(RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
private boolean calcPCMData() {
|
||||
synchronized (PCM) {
|
||||
boolean empty = true;
|
||||
short chanVal;
|
||||
for (int sid = 0; sid < PCM.length && sid < playingBuffer.remaining(); sid++) {
|
||||
PCM[sid] = 0;
|
||||
for (int channel = 0; channel < channelCount; channel++) {
|
||||
if (PCM[sid] < (chanVal = playingBuffer.get())) {
|
||||
PCM[sid] = chanVal;
|
||||
}
|
||||
}
|
||||
PCM[sid] /= Short.MAX_VALUE + 1f;
|
||||
|
||||
if (PCM[sid] != 0) {
|
||||
empty = false;
|
||||
}
|
||||
|
||||
}
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkValidityOfPlaybackBuffer() {
|
||||
// Begin comparison
|
||||
buffer.rewind();
|
||||
if (intermediateBuffer.compareTo(buffer) != 0) {
|
||||
bufferChanged();
|
||||
|
||||
// Begin copying current buffer to the comparison buffer
|
||||
intermediateBuffer.clear();
|
||||
intermediateBuffer.put(buffer);
|
||||
intermediateBuffer.flip();
|
||||
}
|
||||
}
|
||||
|
||||
private void bufferChanged() {
|
||||
playingBuffer.rewind();
|
||||
playingBuffer.put(intermediateBuffer);
|
||||
playingBuffer.rewind();
|
||||
synchronizeBufferWithPlayback();
|
||||
}
|
||||
|
||||
private int calculateBufferPosition() {
|
||||
int offset = (int) alGetSourcef(sourceID, AL11.AL_SAMPLE_OFFSET);
|
||||
offset = (offset / windowSize) * windowSize;
|
||||
return offset;
|
||||
}
|
||||
|
||||
private boolean synchronizeBufferWithPlayback() {
|
||||
int bufferPos = calculateBufferPosition();
|
||||
synchronized (this) {
|
||||
if (bufferPos <= playingBuffer.limit() && bufferPos >= 0) {
|
||||
playingBuffer.position(bufferPos);
|
||||
windowsRead = (int) ((mc.getCurrentPosition() * sampleRate) / windowSize);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMusic() {
|
||||
Gdx.app.debug("PCMObtainer", "music loaded.");
|
||||
sourceID = -1;
|
||||
|
||||
channelCount = mc.getCurrentMusicHeader().getChannelCount();
|
||||
sampleRate = mc.getCurrentMusicHeader().getSampleRate();
|
||||
String millisPerWindowF = df.format(windowSize/(float) sampleRate);
|
||||
millisPerWindow = (long) (Float.valueOf(millisPerWindowF)*1000);
|
||||
songChanged = true;
|
||||
|
||||
intermediateBuffer.clear();
|
||||
playingBuffer.clear();
|
||||
begin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getFrequencyBins() {
|
||||
if (mc.isPlaying()) {
|
||||
if (updated) {
|
||||
synchronized (PCM) {
|
||||
fft.realForward(PCM);
|
||||
System.arraycopy(PCM, 1, frequencyBins, 0, frequencyBins.length);
|
||||
}
|
||||
updated = false;
|
||||
}
|
||||
} else {
|
||||
for (int freqID = 0; freqID < frequencyBins.length; freqID++) {
|
||||
frequencyBins[freqID] = 0;
|
||||
}
|
||||
}
|
||||
return frequencyBins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindowSize() {
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class BufferStreamReadThread implements Runnable {
|
||||
private String name = "PCM-Audio-Processing";
|
||||
private Thread thread;
|
||||
private volatile boolean run = true;
|
||||
private long timeOfLastRead;
|
||||
private long waitTime;
|
||||
@Override
|
||||
public void run() {
|
||||
while (run) {
|
||||
if (mc.isPlaying()) {
|
||||
//record time of read
|
||||
timeOfLastRead = TimeUtils.millis();
|
||||
|
||||
//calculate current pcm data and notify that there is new data
|
||||
checkValidityOfPlaybackBuffer();
|
||||
updated = !calcPCMData();
|
||||
windowsRead++;
|
||||
|
||||
//contemplate synchronization
|
||||
currentPlaybackWindow = MathUtils.round((mc.getCurrentPosition() * sampleRate) / windowSize);
|
||||
if (windowsRead != currentPlaybackWindow) {
|
||||
synchronizeBufferWithPlayback();
|
||||
}
|
||||
//wait for a bit before reading again depending on the speed at which the system does playback.
|
||||
waitTime = Math.max(0, millisPerWindow - TimeUtils.timeSinceMillis(timeOfLastRead));
|
||||
try {
|
||||
Thread.sleep(waitTime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Gdx.app.debug(thread.getName(), "stopped");
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (thread == null) {
|
||||
thread = new Thread(this, name);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
} else {
|
||||
synchronized (this) {
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
run = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
if (o == mc) {
|
||||
if (arg == mc.states.LOADED) {
|
||||
loadMusic();
|
||||
} else if (arg == mc.states.PLAYING) {
|
||||
begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void begin() {
|
||||
if (mc.isPlaying()) {
|
||||
if (sourceID == -1) {
|
||||
try {
|
||||
Field sourceIDField = ClassReflection.getDeclaredField(OpenALMusic.class, "sourceID");
|
||||
sourceIDField.setAccessible(true);
|
||||
sourceID = (int) sourceIDField.get(mc.getCurrentMusic());
|
||||
} catch (ReflectionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
streamReadThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
streamReadThread.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAudioChanged() {
|
||||
if (songChanged) {
|
||||
songChanged = false;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package zero1hd.rhythmbullet.desktop.audio.processor;
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
|
||||
import zero1hd.rhythmbullet.audio.AudioProcessorFactory;
|
||||
import zero1hd.rhythmbullet.audio.MinimalAudioHeader;
|
||||
import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
|
||||
|
||||
public class DesktopAudioProcessorFactory implements AudioProcessorFactory {
|
||||
@Override
|
||||
public AudioProcessor newMP3AudioProcessor(FileHandle fileHandle) {
|
||||
return new MP3AudioProcessor(fileHandle, new MinimalAudioHeader(fileHandle));
|
||||
}
|
||||
}
|
@@ -0,0 +1,158 @@
|
||||
package zero1hd.rhythmbullet.desktop.audio.processor;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
|
||||
import javazoom.jl.decoder.Bitstream;
|
||||
import javazoom.jl.decoder.BitstreamException;
|
||||
import javazoom.jl.decoder.DecoderException;
|
||||
import javazoom.jl.decoder.Header;
|
||||
import javazoom.jl.decoder.MP3Decoder;
|
||||
import javazoom.jl.decoder.OutputBuffer;
|
||||
import zero1hd.rhythmbullet.audio.MinimalAudioHeader;
|
||||
import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
|
||||
|
||||
|
||||
public class MP3AudioProcessor implements AudioProcessor {
|
||||
private boolean stereo;
|
||||
private int sampleRate;
|
||||
private long sampleFrames;
|
||||
private FileHandle fileHandle;
|
||||
private byte[] currentByteSet;
|
||||
private byte[] workset;
|
||||
Bitstream bitstream;
|
||||
MP3Decoder decoder;
|
||||
OutputBuffer sampleBuffer;
|
||||
private int indexHead = -1;
|
||||
|
||||
|
||||
public MP3AudioProcessor(FileHandle fileHandle, MinimalAudioHeader minimalAudioHeader) {
|
||||
this.fileHandle = fileHandle;
|
||||
|
||||
bitstream = new Bitstream(fileHandle.read());
|
||||
|
||||
|
||||
stereo = minimalAudioHeader.getChannelCount() == 1 ? false : true;
|
||||
sampleRate = minimalAudioHeader.getSampleRate();
|
||||
sampleFrames = minimalAudioHeader.estimateSampleFrames();
|
||||
|
||||
decoder = new MP3Decoder();
|
||||
sampleBuffer = new OutputBuffer(stereo ? 2 : 1, false);
|
||||
decoder.setOutputBuffer(sampleBuffer);
|
||||
workset = new byte[(stereo ? 2 : 1)*2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStereo() {
|
||||
return stereo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSampleRate() {
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readSamples(short[] pcm) {
|
||||
int samplesRead = 0;
|
||||
for (int sid = 0; sid < pcm.length; sid++) {
|
||||
for (int wsid = 0; wsid < workset.length; wsid++) {
|
||||
workset[wsid] = nextByte();
|
||||
}
|
||||
if (currentByteSet != null) {
|
||||
pcm[sid] += (workset[1] << 8) + (workset[0] & 0x00ff);
|
||||
if (stereo) {
|
||||
short altChan = (short) ((workset[3] << 8) + (workset[2] & 0x00ff));
|
||||
sid++;
|
||||
pcm[sid] = altChan;
|
||||
}
|
||||
samplesRead ++;
|
||||
}
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readFrames(float[] pcm) {
|
||||
int framesRead = 0;
|
||||
for (int sid = 0; sid < pcm.length; sid++) {
|
||||
for (int wsid = 0; wsid < workset.length; wsid++) {
|
||||
workset[wsid] = nextByte();
|
||||
}
|
||||
if (currentByteSet != null) {
|
||||
pcm[sid] += (workset[1] << 8) + (workset[0] & 0x00ff);
|
||||
if (stereo) {
|
||||
short altChan = (short) ((workset[3] << 8) + (workset[2] & 0x00ff));
|
||||
pcm[sid] = altChan > pcm[sid] ? altChan : pcm[sid];
|
||||
}
|
||||
framesRead++;
|
||||
pcm[sid] /= Short.MAX_VALUE+1;
|
||||
}
|
||||
}
|
||||
return framesRead;
|
||||
}
|
||||
|
||||
public byte nextByte() {
|
||||
indexHead++;
|
||||
if (currentByteSet == null || indexHead >= currentByteSet.length) {
|
||||
loadNextBuffer();
|
||||
if (currentByteSet == null) {
|
||||
return 0;
|
||||
}
|
||||
indexHead = 0;
|
||||
}
|
||||
|
||||
return currentByteSet[indexHead];
|
||||
}
|
||||
|
||||
public int loadNextBuffer() {
|
||||
if (bitstream != null) {
|
||||
int bytesRead = 0;
|
||||
try {
|
||||
Header header = bitstream.readFrame();
|
||||
if (header != null) {
|
||||
|
||||
try {
|
||||
decoder.decodeFrame(header, bitstream);
|
||||
} catch (ArrayIndexOutOfBoundsException ae) {
|
||||
Gdx.app.debug("Mp3Manager", "Last buffer reached since array was out of bounds.");
|
||||
} catch (DecoderException de) {
|
||||
Gdx.app.error("MP3 Decoder Error", de.toString());
|
||||
}
|
||||
bitstream.closeFrame();
|
||||
bytesRead = sampleBuffer.reset();
|
||||
currentByteSet = sampleBuffer.getBuffer();
|
||||
} else {
|
||||
currentByteSet = null;
|
||||
}
|
||||
} catch (BitstreamException be) {
|
||||
be.printStackTrace();
|
||||
}
|
||||
return bytesRead;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileHandle getMusicFileHandle() {
|
||||
return fileHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSampleFrames() {
|
||||
return sampleFrames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Gdx.app.debug("MP3Manager", "Disposing...");
|
||||
try {
|
||||
bitstream.close();
|
||||
bitstream = null;
|
||||
} catch (BitstreamException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
package zero1hd.rhythmbullet.desktop.graphics.ui.components;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
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.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
|
||||
public class GraphicsOptions extends Table {
|
||||
private Label resolutions;
|
||||
|
||||
private ResolutionButton
|
||||
_3840x2160,
|
||||
_2560x1440,
|
||||
_1920x1200,
|
||||
_1920x1080,
|
||||
_1280x800,
|
||||
_1280x720,
|
||||
_1366x768;
|
||||
|
||||
|
||||
public GraphicsOptions(Skin skin, final Preferences prefs) {
|
||||
align(Align.center);
|
||||
defaults().space(10f);
|
||||
resolutions = new Label("Resolutions: ", skin);
|
||||
add(resolutions).left();
|
||||
row();
|
||||
|
||||
|
||||
TextButton fullscreen = new TextButton("Fullscreen", skin);
|
||||
fullscreen.addListener(new ChangeListener() {
|
||||
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
if (!Gdx.graphics.isFullscreen()) {
|
||||
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
|
||||
prefs.putBoolean("fullscreen", true);
|
||||
prefs.flush();
|
||||
}
|
||||
}
|
||||
});
|
||||
add(fullscreen).fillX();
|
||||
row();
|
||||
|
||||
_3840x2160 = new ResolutionButton(3840, 2160, skin, prefs);
|
||||
add(_3840x2160).fillX();
|
||||
row();
|
||||
|
||||
_2560x1440 = new ResolutionButton(2560, 1440, skin, prefs);
|
||||
add(_2560x1440).fillX();
|
||||
row();
|
||||
|
||||
_1920x1200 = new ResolutionButton(1920, 1200, skin, prefs);
|
||||
add(_1920x1200).fillX();
|
||||
row();
|
||||
|
||||
_1920x1080 = new ResolutionButton(1920, 1080, skin, prefs);
|
||||
add(_1920x1080).fillX();
|
||||
row();
|
||||
|
||||
_1280x800 = new ResolutionButton(1280, 800, skin, prefs);
|
||||
add(_1280x800).fillX();
|
||||
row();
|
||||
|
||||
_1366x768 = new ResolutionButton(1366, 768, skin, prefs);
|
||||
add(_1366x768).fillX();
|
||||
row();
|
||||
|
||||
_1280x720 = new ResolutionButton(1280, 720, skin, prefs);
|
||||
add(_1280x720).fillX();
|
||||
row();
|
||||
pack();
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package zero1hd.rhythmbullet.desktop.graphics.ui.components;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
|
||||
public class ResolutionButton extends TextButton {
|
||||
|
||||
public ResolutionButton(int width, int height, Skin skin, Preferences prefs) {
|
||||
super(width + "x" + height, skin);
|
||||
|
||||
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
|
||||
if (screenDim.getWidth() < width || screenDim.getHeight() < height) {
|
||||
setDisabled(true);
|
||||
}
|
||||
|
||||
addListener(new ChangeListener() {
|
||||
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
Gdx.graphics.setWindowedMode(width, height);
|
||||
prefs.putInteger("screen-width", width);
|
||||
prefs.putInteger("screen-height", height);
|
||||
prefs.putBoolean("fullscreen", false);
|
||||
prefs.flush();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens;
|
||||
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
|
||||
public class EndScreen extends ScreenAdapter {
|
||||
public EndScreen() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.utils.viewport.ExtendViewport;
|
||||
|
||||
import zero1hd.rhythmbullet.RhythmBullet;
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.audio.visualizer.CircularVisualizer;
|
||||
import zero1hd.rhythmbullet.desktop.audio.PCMObtainer;
|
||||
|
||||
public class GameScreen extends ScreenAdapter {
|
||||
private AssetManager assets;
|
||||
private SpriteBatch batch;
|
||||
private ExtendViewport viewport;
|
||||
private CircularVisualizer circleVisualizer;
|
||||
|
||||
public GameScreen(AssetManager assets, Preferences prefs, MusicController musicController) {
|
||||
this.assets = assets;
|
||||
batch = new SpriteBatch();
|
||||
viewport = new ExtendViewport(RhythmBullet.WORLD_WIDTH, RhythmBullet.WORLD_HEIGHT);
|
||||
circleVisualizer = new CircularVisualizer(new PCMObtainer(musicController));
|
||||
circleVisualizer.setCenter(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
|
||||
circleVisualizer.setCamera(viewport.getCamera());
|
||||
circleVisualizer.setColor(Color.CYAN.toFloatBits());
|
||||
circleVisualizer.applyPositionChanges();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
Gdx.gl.glClearColor(0.22f, 0.22f, 0.22f, 1f);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
circleVisualizer.drawVisualizer();
|
||||
super.render(delta);
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
|
||||
import zero1hd.rhythmbullet.RhythmBullet;
|
||||
import zero1hd.rhythmbullet.desktop.screens.main.MainScreen;
|
||||
import zero1hd.rhythmbullet.util.InitialScreen;
|
||||
|
||||
public class SplashScreen extends ScreenAdapter implements InitialScreen {
|
||||
private Texture splashTexture;
|
||||
private SpriteBatch batch;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
batch = new SpriteBatch();
|
||||
splashTexture = new Texture(Gdx.files.internal("splash_texture.png"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
batch.begin();
|
||||
batch.draw(splashTexture, 0, 0);
|
||||
batch.end();
|
||||
|
||||
super.render(delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
splashTexture.dispose();
|
||||
super.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAssetLoad() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAssetLoad() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
super.resize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Screen advance(RhythmBullet game) {
|
||||
return new MainScreen(game);
|
||||
}
|
||||
}
|
@@ -0,0 +1,157 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
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.Slider;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
|
||||
import zero1hd.rhythmbullet.audio.AudioMetadataController;
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.audio.analyzer.AudioAnalyzerSection;
|
||||
import zero1hd.rhythmbullet.audio.analyzer.DynamicAudioAnalyzer;
|
||||
import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
|
||||
public class AnalysisPage extends Page {
|
||||
private TextButton backButton;
|
||||
private DynamicAudioAnalyzer audioAnalyzer;
|
||||
private Table table;
|
||||
private Table adjustment;
|
||||
private Label difficultyModLabel, healthModLabel, speedModLabel;
|
||||
private Slider difficultyModifierSlider, healthModifierSlider, speedModifierSlider;
|
||||
private Label diffModPercentLabel, heltModPercentLabel, speeModPercentLabel;
|
||||
private Label progressLabel;
|
||||
private TextButton confirmButton;
|
||||
private Image albumImage;
|
||||
private AudioMetadataController amc;
|
||||
private MusicController mc;
|
||||
|
||||
public AnalysisPage(MusicController mc, AudioMetadataController amc, Skin skin, ChangeListener backButtonListener, ChangeListener confirmedButtonListener) {
|
||||
super(2, 0);
|
||||
table = new Table();
|
||||
table.setFillParent(true);
|
||||
table.defaults().space(10f);
|
||||
addActor(table);
|
||||
adjustment = new Table();
|
||||
this.mc = mc;
|
||||
this.amc = amc;
|
||||
|
||||
difficultyModLabel = new Label("Difficulty Modifier: ", skin, "sub-font", skin.getColor("default"));
|
||||
difficultyModifierSlider = new Slider(1, 3, 0.5f, false, skin);
|
||||
diffModPercentLabel = new Label(String.valueOf(difficultyModifierSlider.getValue()) + "x", skin);
|
||||
difficultyModifierSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
diffModPercentLabel.setText(String.valueOf(difficultyModifierSlider.getValue()) + "x");
|
||||
}
|
||||
});
|
||||
|
||||
adjustment.add(difficultyModLabel);
|
||||
adjustment.add(difficultyModifierSlider).minWidth(0.5f*getWidth());
|
||||
adjustment.add(diffModPercentLabel).spaceLeft(10f).center().expandX().fill();
|
||||
adjustment.row();
|
||||
healthModLabel = new Label("Health Modifier: ", skin, "sub-font", skin.getColor("default"));
|
||||
healthModifierSlider = new Slider(1f, 3f, 0.5f, false, skin);
|
||||
heltModPercentLabel = new Label(String.valueOf(healthModifierSlider.getValue()) + "x", skin);
|
||||
healthModifierSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
heltModPercentLabel.setText(String.valueOf(healthModifierSlider.getValue()) + "x");
|
||||
}
|
||||
});
|
||||
adjustment.add(healthModLabel);
|
||||
adjustment.add(healthModifierSlider).fillX();
|
||||
adjustment.add(heltModPercentLabel).spaceLeft(10f);
|
||||
adjustment.row();
|
||||
speedModLabel = new Label("Speed Modifier: ", skin, "sub-font", skin.getColor("default"));
|
||||
speedModifierSlider = new Slider(1, 3, 0.5f, false, skin);
|
||||
speeModPercentLabel = new Label(String.valueOf(speedModifierSlider.getValue()) + "x", skin);
|
||||
speedModifierSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
speeModPercentLabel.setText(String.valueOf(speedModifierSlider.getValue()) + "x");
|
||||
}
|
||||
});
|
||||
adjustment.add(speedModLabel);
|
||||
adjustment.add(speedModifierSlider).fillX();
|
||||
adjustment.add(speeModPercentLabel).spaceLeft(10f);
|
||||
adjustment.row();
|
||||
|
||||
confirmButton = new TextButton("Confirm", skin);
|
||||
confirmButton.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
confirmButton.setDisabled(true);
|
||||
speedModifierSlider.setDisabled(true);
|
||||
healthModifierSlider.setDisabled(true);
|
||||
difficultyModifierSlider.setDisabled(true);
|
||||
|
||||
progressLabel.setText("Loading...");
|
||||
}
|
||||
});
|
||||
confirmButton.addListener(confirmedButtonListener);
|
||||
|
||||
adjustment.add(confirmButton).colspan(3).fillX();
|
||||
adjustment.row();
|
||||
progressLabel = new Label("Please confirm... ", skin);
|
||||
adjustment.add(progressLabel).colspan(2).left().spaceTop(20f);
|
||||
|
||||
backButton = new TextButton("Cancel", skin);
|
||||
backButton.setWidth(backButton.getWidth() + 20);
|
||||
backButton.addListener(backButtonListener);
|
||||
backButton.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
if (audioAnalyzer != null) {
|
||||
audioAnalyzer.stop();
|
||||
audioAnalyzer = null;
|
||||
albumImage.setDrawable(null);
|
||||
mc.setLoop(false);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
backButton.setPosition(15, getHeight()-backButton.getHeight()-25);
|
||||
addActor(backButton);
|
||||
|
||||
}
|
||||
|
||||
public void processSong() {
|
||||
mc.setLoop(true);
|
||||
AudioMetadata metadata = amc.getAudioMetadata(mc.getCurrentMusicFileHandle());
|
||||
metadata.loadAlbumCover();
|
||||
albumImage = new Image(metadata.getAlbumCover());
|
||||
table.clear();
|
||||
table.add(albumImage).size(adjustment.getMinHeight());
|
||||
table.row();
|
||||
table.add(adjustment);
|
||||
|
||||
AudioAnalyzerSection bass = new AudioAnalyzerSection(1, 5, 1.7f, 3);
|
||||
AudioAnalyzerSection midSection = new AudioAnalyzerSection(7, 25, 1.5f, 3);
|
||||
|
||||
audioAnalyzer = new DynamicAudioAnalyzer(mc.getMusicList().newAudioProcessor(mc.getCurrentMusicFileHandle()), bass, midSection);
|
||||
audioAnalyzer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCameraPositionToPage(Vector3 cameraPosition) {
|
||||
confirmButton.setDisabled(false);
|
||||
speedModifierSlider.setDisabled(false);
|
||||
healthModifierSlider.setDisabled(false);
|
||||
difficultyModifierSlider.setDisabled(false);
|
||||
|
||||
processSong();
|
||||
|
||||
super.setCameraPositionToPage(cameraPosition);
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
|
||||
public class CreditsPage extends Page {
|
||||
|
||||
public CreditsPage(Skin skin) {
|
||||
super(0, 1);
|
||||
|
||||
Label title = new Label("Credits", skin, "large-font", skin.getColor("default"));
|
||||
title.setPosition(15, getHeight()-title.getHeight()-15);
|
||||
addActor(title);
|
||||
|
||||
Label subtitle = new Label("This game wouldn't be possible without these people.", skin, "sub-font", skin.getColor("default"));
|
||||
subtitle.setPosition(title.getX(), title.getY()-subtitle.getHeight());
|
||||
addActor(subtitle);
|
||||
|
||||
Label listOfNames = new Label(
|
||||
"TheClimbingHippo (texture)\n"
|
||||
+ "Crepitus (sound effects)\n"
|
||||
+ "Neoqueto - Darktech LDR (font)\n"
|
||||
+ "Rémi Lagast - Gasalt (font)\n"
|
||||
+ "Timour Jgenti - Iron Maiden (font)", skin, "sub-font", skin.getColor("default"));
|
||||
listOfNames.setPosition(subtitle.getX()+16, subtitle.getY()-listOfNames.getHeight()-10);
|
||||
addActor(listOfNames);
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
|
||||
import zero1hd.rhythmbullet.desktop.graphics.ui.components.GraphicsOptions;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
|
||||
public class GraphicsPage extends Page {
|
||||
private ScrollPane scrollPane;
|
||||
private GraphicsOptions graphicsTable;
|
||||
private TextButton backButton;
|
||||
|
||||
public GraphicsPage(Skin skin, Preferences preferences, ChangeListener backButtonListener) {
|
||||
super(-1, 1);
|
||||
graphicsTable = new GraphicsOptions(skin, preferences);
|
||||
scrollPane = new ScrollPane(graphicsTable, skin);
|
||||
scrollPane.setFadeScrollBars(false);
|
||||
scrollPane.setFillParent(true);
|
||||
addActor(scrollPane);
|
||||
|
||||
backButton = new TextButton("Back", skin);
|
||||
backButton.setPosition(10, getHeight() - 10 - backButton.getHeight());
|
||||
backButton.setWidth(backButton.getWidth() + 20);
|
||||
backButton.addListener(backButtonListener);
|
||||
|
||||
addActor(backButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float parentAlpha) {
|
||||
super.draw(batch, parentAlpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
super.act(delta);
|
||||
}
|
||||
}
|
@@ -0,0 +1,224 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable;
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import zero1hd.rhythmbullet.desktop.Controls;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
|
||||
public class KeybindPage extends Page {
|
||||
private ButtonGroup<KeyChangeButton> buttonOptions;
|
||||
private VerticalGroup group;
|
||||
private ScrollPane scrollPane;
|
||||
private Skin skin;
|
||||
TextureAtlas keyTextures;
|
||||
private Preferences keyBindPrefs;
|
||||
private InputListener inputListener;
|
||||
private ChangeListener checkedListener;
|
||||
|
||||
public KeybindPage(AssetManager assetManager, Skin skin, ChangeListener backButtonListener) {
|
||||
super(-1, -1);
|
||||
setTouchable(Touchable.enabled);
|
||||
this.skin = skin;
|
||||
keyTextures = assetManager.get("keyboard.atlas", TextureAtlas.class);
|
||||
this.keyBindPrefs = Gdx.app.getPreferences("PolyJet_Controls");
|
||||
TextButton backButton = new TextButton("Back", skin);
|
||||
backButton.setWidth(backButton.getWidth()+20f);
|
||||
backButton.setPosition(getWidth()-backButton.getWidth()-15f, getHeight() - backButton.getHeight() - 15f);
|
||||
backButton.addListener(backButtonListener);
|
||||
addActor(backButton);
|
||||
|
||||
inputListener = new InputListener() {
|
||||
@Override
|
||||
public boolean keyUp(InputEvent event, int keycode) {
|
||||
KeyChangeButton button = buttonOptions.getChecked();
|
||||
if (button != null) {
|
||||
if (keycode != Keys.ESCAPE) {
|
||||
button.attemptSetKeycode(keycode);
|
||||
}
|
||||
getStage().setKeyboardFocus(null);
|
||||
}
|
||||
return super.keyUp(event, keycode);
|
||||
}
|
||||
};
|
||||
|
||||
checkedListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
KeyChangeButton button = (KeyChangeButton) actor;
|
||||
if (button.isChecked()) {
|
||||
button.ready();
|
||||
} else {
|
||||
button.done();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
buttonOptions = new ButtonGroup<>();
|
||||
buttonOptions.setMinCheckCount(0);
|
||||
buttonOptions.setMaxCheckCount(1);
|
||||
group = new VerticalGroup();
|
||||
group.setTouchable(Touchable.childrenOnly);
|
||||
group.space(15f);
|
||||
Controls[] controls = Controls.values();
|
||||
for (int i = 0; i < controls.length; i++) {
|
||||
KeyChangeButton button = new KeyChangeButton(controls[i]);
|
||||
buttonOptions.add(button);
|
||||
group.addActor(button);
|
||||
}
|
||||
scrollPane = new ScrollPane(group);
|
||||
scrollPane.setHeight(Math.min(getHeight(), group.getPrefHeight()));
|
||||
scrollPane.setWidth(group.getPrefWidth());
|
||||
scrollPane.setPosition((getWidth()-scrollPane.getWidth())/2f, (getHeight()-scrollPane.getHeight())/2f);
|
||||
scrollPane.setTouchable(Touchable.childrenOnly);
|
||||
addActor(scrollPane);
|
||||
addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
if (hit(x, y, true) == event.getListenerActor()) {
|
||||
simpleDebug("unchecking selected key change buttons.");
|
||||
buttonOptions.uncheckAll();
|
||||
}
|
||||
super.clicked(event, x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCameraPositionToPage(Vector3 cameraPosition) {
|
||||
getStage().setScrollFocus(scrollPane);
|
||||
super.setCameraPositionToPage(cameraPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
save();
|
||||
super.dispose();
|
||||
}
|
||||
public void save() {
|
||||
keyBindPrefs.flush();
|
||||
}
|
||||
|
||||
public class KeyChangeButton extends Button {
|
||||
private Image keyImage;
|
||||
private Label nameLabel;
|
||||
private Controls control;
|
||||
private boolean error;
|
||||
|
||||
public KeyChangeButton(Controls control) {
|
||||
super(skin, "selectable-clean-button");
|
||||
this.control = control;
|
||||
nameLabel = new Label(control.toString(), skin);
|
||||
keyImage = new Image(getIcon(control.getKeycode()));
|
||||
|
||||
add(nameLabel).expandX().left().spaceRight(20f);
|
||||
add(keyImage).expandX().right();
|
||||
|
||||
addListener(inputListener);
|
||||
addListener(checkedListener);
|
||||
}
|
||||
|
||||
public void attemptSetKeycode(int keycode) {
|
||||
simpleDebug("Attempting to set keycode to " + keycode);
|
||||
TextureRegion textureRegion = getIcon(keycode);
|
||||
if (textureRegion != null) {
|
||||
setKeycode(keycode, textureRegion);
|
||||
error = false;
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
setChecked(false);
|
||||
}
|
||||
|
||||
public void setKeycode(int keycode, TextureRegion texture) {
|
||||
|
||||
Controls conflict = control.setKeycode(keycode);
|
||||
if (conflict != null) {
|
||||
Array<KeyChangeButton> buttons = buttonOptions.getButtons();
|
||||
for (int i = 0; i < buttons.size; i++) {
|
||||
System.out.println(buttons.get(i).getControl());
|
||||
if (buttons.get(i).getControl() == conflict) {
|
||||
KeyChangeButton b = buttons.get(i);
|
||||
scrollPane.scrollTo(b.getX(), b.getY(), b.getWidth(), b.getHeight());
|
||||
b.done(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
TextureRegion textureRegion = getIcon(keycode);
|
||||
if (textureRegion != null) {
|
||||
keyImage.setDrawable(new TextureRegionDrawable(texture));
|
||||
control.saveKeyToPreferences(keyBindPrefs);
|
||||
}
|
||||
}
|
||||
|
||||
public void ready() {
|
||||
getStage().setKeyboardFocus(this);
|
||||
keyImage.setColor(Color.ORANGE);
|
||||
}
|
||||
|
||||
public void done() {
|
||||
done(error);
|
||||
}
|
||||
|
||||
public void done(boolean error) {
|
||||
if (error) {
|
||||
keyImage.addAction(Actions.repeat(3, Actions.sequence(Actions.color(Color.RED, 0.2f), Actions.color(Color.WHITE, 0.1f))));
|
||||
} else {
|
||||
keyImage.addAction(Actions.color(Color.WHITE, 0.2f));
|
||||
}
|
||||
}
|
||||
|
||||
public Controls getControl() {
|
||||
return control;
|
||||
}
|
||||
}
|
||||
|
||||
public TextureRegion getIcon(int keycode) {
|
||||
switch (keycode) {
|
||||
case Keys.ALT_LEFT:
|
||||
case Keys.ALT_RIGHT:
|
||||
return keyTextures.findRegion("Keyboard_Black_Alt");
|
||||
case Keys.SHIFT_LEFT:
|
||||
case Keys.SHIFT_RIGHT:
|
||||
return keyTextures.findRegion("Keyboard_Black_Shift");
|
||||
case Keys.LEFT_BRACKET:
|
||||
return keyTextures.findRegion("Keyboard_Black_Bracket_Left");
|
||||
case Keys.RIGHT_BRACKET:
|
||||
return keyTextures.findRegion("Keyboard_Black_Bracket_Right");
|
||||
case Keys.SEMICOLON:
|
||||
return keyTextures.findRegion("Keyboard_Black_Semicolon");
|
||||
case Keys.SLASH:
|
||||
return keyTextures.findRegion("Keyboard_Black_Slash");
|
||||
case Keys.NUM:
|
||||
return keyTextures.findRegion("Keyboard_Black_Num_Lock");
|
||||
case Keys.ESCAPE:
|
||||
return null;
|
||||
default:
|
||||
return keyTextures.findRegion("Keyboard_Black_" + Keys.toString(keycode).replace(' ', '_'));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,209 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
|
||||
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool;
|
||||
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool.PooledEffect;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
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.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import zero1hd.rhythmbullet.RhythmBullet;
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.audio.AudioMetadataController;
|
||||
import zero1hd.rhythmbullet.audio.visualizer.DoubleHorizontalVisualizer;
|
||||
import zero1hd.rhythmbullet.desktop.audio.PCMObtainer;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
import zero1hd.rhythmbullet.graphics.ui.components.MusicControls;
|
||||
import zero1hd.rhythmbullet.graphics.ui.components.ScrollingText;
|
||||
import zero1hd.rhythmbullet.util.ScreenConfiguration;
|
||||
|
||||
public class MainPage extends Page implements Observer {
|
||||
private MusicController mc;
|
||||
private AudioMetadataController amc;
|
||||
|
||||
private Label versionLabel;
|
||||
private Image title;
|
||||
|
||||
private Table menuTable;
|
||||
private TextButton playButton;
|
||||
private TextButton optionsButton;
|
||||
private TextButton quitButton;
|
||||
|
||||
private MusicControls musicControls;
|
||||
private ScrollingText scrollText;
|
||||
|
||||
private DoubleHorizontalVisualizer dhv;
|
||||
|
||||
private boolean playParticles = true;
|
||||
private ParticleEffectPool particlePool;
|
||||
private Array<PooledEffect> particles;
|
||||
private float particleScale;
|
||||
|
||||
public MainPage(MusicController musicController, AudioMetadataController mmc, AssetManager assetManager, Skin skin, ScreenConfiguration screenConfiguration, ChangeListener playButtonListener, ChangeListener optionsButtonListener) {
|
||||
super(0, 0);
|
||||
this.mc = musicController;
|
||||
this.mc.addObserver(this);
|
||||
mc.getMusicList().addObserver(this);
|
||||
this.amc = mmc;
|
||||
this.amc.addObserver(this);
|
||||
|
||||
dhv = new DoubleHorizontalVisualizer((int) getWidth(), (int) 0, getHeight(), 0, screenConfiguration.getTargetFramesPerSecond(), mc, new PCMObtainer(mc));
|
||||
dhv.setPosition(0, (int) ((getHeight() - dhv.getHeight())/2f));
|
||||
|
||||
title = new Image(assetManager.get("title.png", Texture.class));
|
||||
title.setScale((getHeight()/3f)/title.getHeight());
|
||||
if (title.getWidth()*title.getScaleX() > getWidth() - getWidth()*0.075f) {
|
||||
title.setScale((getWidth()*(1f-0.075f))/title.getWidth()*getScaleX());
|
||||
}
|
||||
title.setPosition((getWidth()-title.getWidth()*title.getScaleX())/2f, (getHeight()-title.getHeight()*title.getScaleY())/2f);
|
||||
addActor(title);
|
||||
|
||||
versionLabel = new Label("Version: " + RhythmBullet.VERSION, skin, "sub-font", skin.getColor("default"));
|
||||
versionLabel.setPosition(3, 3);
|
||||
addActor(versionLabel);
|
||||
|
||||
menuTable = new Table();
|
||||
menuTable.setSize(getWidth(), title.getY());
|
||||
menuTable.align(Align.center);
|
||||
menuTable.defaults().space(10f);
|
||||
addActor(menuTable);
|
||||
playButton = new TextButton("Start!", skin);
|
||||
playButton.addListener(playButtonListener);
|
||||
menuTable.add(playButton).width(Gdx.graphics.getWidth()*0.2f);
|
||||
|
||||
menuTable.row();
|
||||
|
||||
optionsButton = new TextButton("Options", skin, "sub");
|
||||
optionsButton.addListener(optionsButtonListener);
|
||||
menuTable.add(optionsButton).fillX();
|
||||
|
||||
menuTable.row();
|
||||
|
||||
quitButton = new TextButton("Quit", skin, "sub");
|
||||
quitButton.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
Gdx.app.exit();
|
||||
}
|
||||
});
|
||||
menuTable.add(quitButton).fillX();
|
||||
|
||||
musicControls = new MusicControls(skin, mc);
|
||||
musicControls.setPosition((getWidth()-musicControls.getWidth() - 15f), 15f);
|
||||
addActor(musicControls);
|
||||
|
||||
scrollText = new ScrollingText("...", "...", skin, false, true, 1f/screenConfiguration.getTargetFramesPerSecond());
|
||||
scrollText.setWidth(0.5f*getWidth());
|
||||
scrollText.setPosition(15, getHeight() - scrollText.getHeight()-30f);
|
||||
addActor(scrollText);
|
||||
|
||||
if (mc.getMusicList().isSearched() && amc.isSameSizeMusicList()) {
|
||||
scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
|
||||
dhv.updateMusic();
|
||||
}
|
||||
|
||||
particles = new Array<>();
|
||||
ParticleEffect particle = assetManager.get("beateffect.p", ParticleEffect.class);
|
||||
particleScale = getWidth()/particle.findEmitter("main").getSpawnWidth().getHighMax();
|
||||
particlePool = new ParticleEffectPool(assetManager.get("beateffect.p", ParticleEffect.class), 0, 16);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
dhv.act(delta);
|
||||
super.act(delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float parentAlpha) {
|
||||
dhv.draw(batch, parentAlpha);
|
||||
updateParticles(batch);
|
||||
super.draw(batch, parentAlpha);
|
||||
}
|
||||
|
||||
private void updateParticles(Batch batch) {
|
||||
if (playParticles) {
|
||||
if (particles.size < 16 && dhv.isSignificantBeat()) {
|
||||
PooledEffect particle = particlePool.obtain();
|
||||
particle.scaleEffect(particleScale);
|
||||
particles.add(particle);
|
||||
}
|
||||
if (particles.size > 0) {
|
||||
for (int i = particles.size - 1; i >= 0 && particles.size > 0; i--) {
|
||||
PooledEffect particle = particles.get(i);
|
||||
particle.draw(batch, Gdx.graphics.getDeltaTime());
|
||||
if (particle.isComplete()) {
|
||||
particles.removeIndex(i);
|
||||
particle.free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopParticles() {
|
||||
playParticles = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
dhv.dispose();
|
||||
mc.getMusicList().deleteObserver(this);
|
||||
for (int i = particles.size - 1; i >= 0 && particles.size > 0; i--) {
|
||||
particles.get(i).free();
|
||||
particles.clear();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCameraPositionToPage(Vector3 cameraPosition) {
|
||||
getStage().setScrollFocus(null);
|
||||
playParticles = true;
|
||||
super.setCameraPositionToPage(cameraPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
if (o == mc) {
|
||||
if (arg == mc.states.LOADED) {
|
||||
if (amc.isSameSizeMusicList()) {
|
||||
scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
|
||||
} else {
|
||||
scrollText.setText("Currently playing: " + mc.getCurrentMusicFileHandle().nameWithoutExtension().replace('_', ' '), null);
|
||||
}
|
||||
} else if (arg == mc.states.PAUSED) {
|
||||
if (amc.isSameSizeMusicList()) {
|
||||
scrollText.setText("Currently paused: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
|
||||
} else {
|
||||
scrollText.setText("Currently paused: " + mc.getCurrentMusicFileHandle().nameWithoutExtension().replace('_', ' '), null);
|
||||
}
|
||||
}
|
||||
} else if (o == amc) {
|
||||
if (amc.isSameSizeMusicList()) {
|
||||
scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
|
||||
}
|
||||
} else if (o == mc.getMusicList()) {
|
||||
if (arg == mc.getMusicList().states.EMPTY) {
|
||||
scrollText.setText("Couldn't find MP3/WAV files", null);
|
||||
} else if (arg == mc.getMusicList().states.LOADING) {
|
||||
scrollText.setText("Loading...", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,248 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
||||
|
||||
import zero1hd.rhythmbullet.RhythmBullet;
|
||||
import zero1hd.rhythmbullet.audio.AudioMetadataController;
|
||||
import zero1hd.rhythmbullet.audio.MusicList;
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.desktop.audio.processor.DesktopAudioProcessorFactory;
|
||||
import zero1hd.rhythmbullet.graphics.shaders.BloomShader;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
import zero1hd.rhythmbullet.util.ResizeReadyScreen;
|
||||
|
||||
public class MainScreen extends ScreenAdapter implements ResizeReadyScreen {
|
||||
private Stage stage;
|
||||
private Vector3 cameraPosition;
|
||||
private PageChangeListeners listeners;
|
||||
private String selectedPage;
|
||||
private MainPage mainPage;
|
||||
private OptionsPage optionsPage;
|
||||
private KeybindPage keybindPage;
|
||||
private GraphicsPage graphicsPage;
|
||||
private CreditsPage creditsPage;
|
||||
private MusicSelectionPage musicSelectionPage;
|
||||
private AnalysisPage analysisPage;
|
||||
|
||||
private MusicController musicController;
|
||||
private AudioMetadataController musicMetadataController;
|
||||
|
||||
private RhythmBullet rhythmBullet;
|
||||
|
||||
private BloomShader bloomShader;
|
||||
|
||||
private Texture background;
|
||||
|
||||
private Batch screenBatch;
|
||||
private boolean resizing;
|
||||
|
||||
public MainScreen(RhythmBullet core) {
|
||||
this.rhythmBullet = core;
|
||||
stage = new Stage(new ScreenViewport());
|
||||
cameraPosition = new Vector3(stage.getCamera().position);
|
||||
|
||||
MusicList musicList = new MusicList(new DesktopAudioProcessorFactory(), core.getPreferences().getString("music dir"));
|
||||
musicController = new MusicController(musicList, core.getPreferences());
|
||||
musicController.setAutoPlay(true);
|
||||
musicController.setShuffle(true);
|
||||
musicMetadataController = new AudioMetadataController(musicList);
|
||||
|
||||
listeners = new PageChangeListeners();
|
||||
screenBatch = new SpriteBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (!resizing) {
|
||||
stage.act(delta);
|
||||
if (bloomShader != null) {
|
||||
bloomShader.begin();
|
||||
draw();
|
||||
bloomShader.end(stage.getWidth(), stage.getHeight());
|
||||
} else {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
if (stage.getCamera().position.x != cameraPosition.x || stage.getCamera().position.y != cameraPosition.y) {
|
||||
stage.getCamera().position.lerp(cameraPosition, 0.15f);
|
||||
stage.getViewport().apply();
|
||||
}
|
||||
super.render(delta);
|
||||
}
|
||||
|
||||
private void draw() {
|
||||
stage.getViewport().apply();
|
||||
screenBatch.begin();
|
||||
screenBatch.draw(background, 0, 0, stage.getViewport().getScreenWidth(), stage.getViewport().getScreenHeight());
|
||||
screenBatch.end();
|
||||
stage.draw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAssetLoad() {
|
||||
resizing = true;
|
||||
stage.clear();
|
||||
if (bloomShader != null) {
|
||||
bloomShader.dispose();
|
||||
bloomShader = null;
|
||||
}
|
||||
background = null;
|
||||
musicController.deleteObservers();
|
||||
musicMetadataController.deleteObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAssetLoad() {
|
||||
resizing = false;
|
||||
bloomShader = new BloomShader(screenBatch);
|
||||
|
||||
background = rhythmBullet.getAssetManager().get("backgrounds/mainBG.png", Texture.class);
|
||||
|
||||
mainPage = new MainPage(musicController, musicMetadataController, rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), rhythmBullet.getScreenConfiguration(), listeners.musicSelectionPageButtonListener, listeners.optionsPageButtonListener);
|
||||
stage.addActor(mainPage);
|
||||
//End main menu
|
||||
|
||||
optionsPage = new OptionsPage(musicController, rhythmBullet.getSkin(), rhythmBullet.getPreferences(), listeners.returnToMainPageListener, listeners.graphicsPageButtonListener, listeners.keybindPageButtonListener);
|
||||
stage.addActor(optionsPage);
|
||||
|
||||
keybindPage = new KeybindPage(rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), listeners.optionsPageButtonListener);
|
||||
stage.addActor(keybindPage);
|
||||
|
||||
graphicsPage = new GraphicsPage(rhythmBullet.getSkin(), rhythmBullet.getPreferences(), listeners.optionsPageButtonListener);
|
||||
stage.addActor(graphicsPage);
|
||||
|
||||
creditsPage = new CreditsPage(rhythmBullet.getSkin());
|
||||
stage.addActor(creditsPage);
|
||||
|
||||
musicSelectionPage = new MusicSelectionPage(rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), musicController, musicMetadataController, rhythmBullet.getScreenConfiguration(), listeners.returnToMainPageListener, listeners.analysisPageButtonListener);
|
||||
stage.addActor(musicSelectionPage);
|
||||
|
||||
analysisPage = new AnalysisPage(musicController, musicMetadataController, rhythmBullet.getSkin(), listeners.musicSelectionPageButtonListener, listeners.confirmedSongListener);
|
||||
stage.addActor(analysisPage);
|
||||
|
||||
musicController.getMusicList().attemptAsyncSearch(false);
|
||||
|
||||
if (selectedPage != null) {
|
||||
for (Actor actor : stage.getActors().items) {
|
||||
if (actor.getName().equals(selectedPage)) {
|
||||
setDisplayedPage((Page) actor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
Gdx.input.setInputProcessor(stage);
|
||||
super.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
saveAll();
|
||||
super.hide();
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
if (optionsPage != null) {
|
||||
optionsPage.saveOptions();
|
||||
rhythmBullet.getPreferences().flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
stage.getViewport().update(width, height, false);
|
||||
super.resize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Gdx.app.debug("Mainscreen", "disposing...");
|
||||
stage.dispose();
|
||||
musicMetadataController.dispose();
|
||||
screenBatch.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void setDisplayedPage(Page page) {
|
||||
Gdx.app.debug("Mainscreen", "Switching to " + page.getName());
|
||||
page.setCameraPositionToPage(cameraPosition);
|
||||
this.selectedPage = page.getName();
|
||||
}
|
||||
|
||||
private class PageChangeListeners {
|
||||
ChangeListener musicSelectionPageButtonListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(musicSelectionPage);
|
||||
mainPage.stopParticles();
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener analysisPageButtonListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(analysisPage);
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener returnToMainPageListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(mainPage);
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener optionsPageButtonListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(optionsPage);
|
||||
mainPage.stopParticles();
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener graphicsPageButtonListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(graphicsPage);
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener keybindPageButtonListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(keybindPage);
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener creditPageButtonListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
setDisplayedPage(creditsPage);
|
||||
mainPage.stopParticles();
|
||||
}
|
||||
};
|
||||
|
||||
ChangeListener confirmedSongListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,585 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import zero1hd.rhythmbullet.audio.AudioMetadataController;
|
||||
import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
import zero1hd.rhythmbullet.graphics.ui.components.ScrollingText;
|
||||
import zero1hd.rhythmbullet.util.ScreenConfiguration;
|
||||
|
||||
public class MusicSelectionPage extends Page implements Observer {
|
||||
Preferences musicFileAnnotation;
|
||||
|
||||
private MusicController mc;
|
||||
private AudioMetadataController mmc;
|
||||
private MusicSelectableButtonGroup selectables;
|
||||
private VerticalGroup vGroup;
|
||||
private TextButton back;
|
||||
private ScrollPane scrollPane;
|
||||
private ScreenConfiguration screenConfig;
|
||||
|
||||
private musicSelectionLoaderThread selectionLoaderThread;
|
||||
|
||||
private InformationTable musicInfoTable;
|
||||
|
||||
private AssetManager assets;
|
||||
private Skin skin;
|
||||
|
||||
private boolean down, up;
|
||||
|
||||
private boolean frameUsed;
|
||||
|
||||
private TextButton beginButton;
|
||||
|
||||
private float scrollTimer, scrollDelay = 0.2f, scrollDelMod, songSelectionTimer;
|
||||
private float musicSelectDelay;
|
||||
|
||||
public MusicSelectionPage(AssetManager assetManager, Skin skin, MusicController musicController, AudioMetadataController musicMetadataController, ScreenConfiguration screenConfiguration, ChangeListener backButtonListener, ChangeListener beginButtonListener) {
|
||||
super(1, 0);
|
||||
this.assets = assetManager;
|
||||
this.mc = musicController;
|
||||
this.mmc = musicMetadataController;
|
||||
this.skin = skin;
|
||||
vGroup = new VerticalGroup();
|
||||
vGroup.space(10f);
|
||||
selectables = new MusicSelectableButtonGroup();
|
||||
selectables.setMinCheckCount(0);
|
||||
musicFileAnnotation = Gdx.app.getPreferences("music_file_annotation");
|
||||
this.screenConfig = screenConfiguration;
|
||||
scrollPane = new ScrollPane(vGroup, skin);
|
||||
scrollPane.setSize(0.45f*getWidth(), getHeight());
|
||||
scrollPane.setOverscroll(false, false);
|
||||
scrollPane.setColor(Color.BLUE);
|
||||
addActor(scrollPane);
|
||||
back = new TextButton("Back", skin);
|
||||
back.setWidth(back.getWidth()+20f);
|
||||
back.setPosition(getWidth()-back.getWidth()-15f, getHeight() - back.getHeight() - 15f);
|
||||
back.addListener(backButtonListener);
|
||||
addActor(back);
|
||||
back.toFront();
|
||||
|
||||
addListener(new InputListener() {
|
||||
@Override
|
||||
public boolean keyDown(InputEvent event, int keycode) {
|
||||
scrollTimer = 0;
|
||||
scrollDelMod = 1f;
|
||||
if (keycode == Keys.DOWN) {
|
||||
down = true;
|
||||
}
|
||||
if (keycode == Keys.UP) {
|
||||
up = true;
|
||||
}
|
||||
return super.keyDown(event, keycode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyUp(InputEvent event, int keycode) {
|
||||
if (keycode == Keys.DOWN) {
|
||||
down = false;
|
||||
}
|
||||
|
||||
if (keycode == Keys.UP) {
|
||||
up = false;
|
||||
}
|
||||
return super.keyUp(event, keycode);
|
||||
}
|
||||
});
|
||||
|
||||
musicInfoTable = new InformationTable(getWidth()-scrollPane.getWidth(), getHeight());
|
||||
addActor(musicInfoTable);
|
||||
|
||||
beginButton = new TextButton("Begin", skin);
|
||||
beginButton.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
if (musicSelectDelay != 0) {
|
||||
mc.setMusicByFileHandle(getSelectedMusic());
|
||||
musicSelectDelay = 0f;
|
||||
}
|
||||
}
|
||||
});
|
||||
beginButton.addListener(beginButtonListener);
|
||||
mmc.addObserver(this);
|
||||
mc.addObserver(this);
|
||||
mc.getMusicList().addObserver(this);
|
||||
selectionLoaderThread = new musicSelectionLoaderThread();
|
||||
|
||||
musicInfoTable.setToDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
|
||||
if (frameUsed) {
|
||||
frameUsed = false;
|
||||
}
|
||||
|
||||
if (down) {
|
||||
if (scrollDelMod > 0.25f) {
|
||||
scrollDelMod -= delta/0.5f;
|
||||
}
|
||||
if (scrollTimer <= 0) {
|
||||
scrollTimer = scrollDelay*scrollDelMod;
|
||||
scrollDown();
|
||||
|
||||
} else {
|
||||
scrollTimer -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (up) {
|
||||
if (scrollDelMod > 0.25f) {
|
||||
scrollDelMod -= delta/0.5f;
|
||||
}
|
||||
if (scrollTimer <= 0) {
|
||||
scrollTimer = scrollDelay*scrollDelMod;
|
||||
scrollUp();
|
||||
} else {
|
||||
scrollTimer -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (songSelectionTimer > 0f) {
|
||||
songSelectionTimer -= delta;
|
||||
if (songSelectionTimer <= 0f) {
|
||||
}
|
||||
}
|
||||
if (mc.getMusicList().isSearched()) {
|
||||
if (mc.getMusicList().getTotal() != 0) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
updateList(delta);
|
||||
|
||||
super.act(delta);
|
||||
}
|
||||
|
||||
private synchronized void updateList(float delta) {
|
||||
if (mc.getMusicList().isSearched()) {
|
||||
if (mc.getMusicList().getTotal() != 0) {
|
||||
if (mmc.isSameSizeMusicList() && !mmc.isSearching()) {
|
||||
if (selectables.size() != mmc.size()) {
|
||||
MusicSelectable selectable = new MusicSelectable(mmc.getAudioMetadata(selectables.size()));
|
||||
selectables.add(selectable);
|
||||
} else if (selectables.size() != vGroup.getChildren().size) {
|
||||
vGroup.addActor(selectables.getButtons().get(vGroup.getChildren().size));
|
||||
} else {
|
||||
if (selectables.getChecked() == null) {
|
||||
selectables.setMinCheckCount(1);
|
||||
selectables.setChecked(mc.getCurrentMusicFileHandle());
|
||||
scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
|
||||
} else if (selectables.getChecked().getMetadata().getFileHandle() != mc.getCurrentMusicFileHandle()) {
|
||||
musicSelectDelay += delta;
|
||||
if (musicSelectDelay >= 1f) {
|
||||
mc.setMusicByFileHandle(selectables.getChecked().getMetadata().getFileHandle());
|
||||
musicSelectDelay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
//TODO: Error message reporting empty music list or something
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollDown() {
|
||||
if (selectables.selectNext()) {
|
||||
scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollUp() {
|
||||
if (selectables.selectPrevious()) {
|
||||
scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
public FileHandle getSelectedMusic() {
|
||||
return selectables.getChecked().getMetadata().getFileHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
mc.getMusicList().deleteObserver(this);
|
||||
selectionLoaderThread.stop();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
if (o == mmc) {
|
||||
selectionLoaderThread.start();
|
||||
} else if (o == mc) {
|
||||
if (selectables.getChecked() != null && mc.getMusicList().getTotal() == selectables.size() && mc.getCurrentMusicFileHandle() != selectables.getChecked().getMetadata().getFileHandle()) {
|
||||
selectables.setChecked(mc.getCurrentMusicFileHandle());
|
||||
}
|
||||
} else if (o == mc.getMusicList()) {
|
||||
if (arg == mc.getMusicList().states.LOADING) {
|
||||
synchronized (this) {
|
||||
vGroup.clear();
|
||||
selectables.clear();
|
||||
musicInfoTable.setToDefault();
|
||||
selectionLoaderThread.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCameraPositionToPage(Vector3 cameraPosition) {
|
||||
getStage().setKeyboardFocus(this);
|
||||
getStage().setScrollFocus(scrollPane);
|
||||
super.setCameraPositionToPage(cameraPosition);
|
||||
}
|
||||
|
||||
private class musicSelectionLoaderThread implements Runnable {
|
||||
private Thread thread;
|
||||
private String name = "Music-Selection-Loader-Thread";
|
||||
private volatile boolean work = true;
|
||||
private LinkedBlockingQueue<MusicSelectable> queue;
|
||||
public musicSelectionLoaderThread() {
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (work) {
|
||||
try {
|
||||
MusicSelectable selectable = queue.take();
|
||||
if (!selectable.isOffScreen()) {
|
||||
selectable.getMetadata().loadAlbumCover();
|
||||
selectable.loadAttempted();
|
||||
simpleDebug("Loaded album cover of " + selectable.getMetadata().getTitle());
|
||||
} else {
|
||||
simpleDebug("Skipping " + selectable.getMetadata().getTitle());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
simpleDebug("Thread was interupted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
if (thread == null) {
|
||||
thread = new Thread(this, name);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
clear();
|
||||
if (thread != null) {
|
||||
thread.interrupt();
|
||||
}
|
||||
work = false;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
public void queue(MusicSelectable selectable) {
|
||||
queue.add(selectable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MusicSelectable extends Button {
|
||||
private Vector2 actualCoords;
|
||||
private Image albumCoverImage;
|
||||
private Table informationTable;
|
||||
private Label name, artist;
|
||||
private Label time;
|
||||
private float timeSinceChanged;
|
||||
private AudioMetadata metadata;
|
||||
private Texture defaultAlbumArt;
|
||||
private TextureRegion albumArtTexture;
|
||||
private volatile boolean offScreen, albumArtDisplayed, albumArtQueued, noReset;
|
||||
|
||||
public MusicSelectable(AudioMetadata metadata) {
|
||||
super(skin, "selectable-button");
|
||||
|
||||
this.metadata = metadata;
|
||||
this.defaultAlbumArt = assets.get("defaultCover.png");
|
||||
albumArtTexture = new TextureRegion(defaultAlbumArt);
|
||||
|
||||
albumCoverImage = new Image();
|
||||
updateAlbumArtImage(defaultAlbumArt);
|
||||
|
||||
informationTable = new Table();
|
||||
informationTable.row().width(0.75f*getWidth());
|
||||
name = new Label(metadata.getTitle(), skin, "default-font", skin.getColor("default"));
|
||||
name.setEllipsis(true);
|
||||
informationTable.add(name).colspan(2).left().expand();
|
||||
informationTable.row();
|
||||
artist = new Label(metadata.getAuthor(), skin, "sub-font", skin.getColor("default"));
|
||||
artist.setEllipsis(true);
|
||||
informationTable.add(artist).left().width(getWidth()*0.375f);
|
||||
time = new Label(metadata.getDuration(), skin, "sub-font", skin.getColor("default"));
|
||||
informationTable.add(time).right();
|
||||
add(informationTable).spaceRight(15f).padLeft(15f);
|
||||
|
||||
add(albumCoverImage).right().expandX().size(informationTable.getMinHeight());
|
||||
|
||||
albumCoverImage.setSize(100, 100);
|
||||
actualCoords = new Vector2();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
actualCoords.x = getX() + getParent().getX();
|
||||
actualCoords.y = getY() + getParent().getY();
|
||||
|
||||
if ((actualCoords.y < 0 - getHeight() - getStage().getHeight()*0.5f || actualCoords.y > getStage().getHeight()*1.5f) && selectables.getChecked() != this) {
|
||||
offScreenAct(delta);
|
||||
} else {
|
||||
onScreenAct(delta);
|
||||
}
|
||||
super.act(delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float parentAlpha) {
|
||||
super.draw(batch, parentAlpha);
|
||||
}
|
||||
|
||||
public void onScreenAct(float delta) {
|
||||
if (offScreen) {
|
||||
offScreen = false;
|
||||
timeSinceChanged = 0;
|
||||
} else if (timeSinceChanged < 0.05f) {
|
||||
timeSinceChanged += delta;
|
||||
} else {
|
||||
if (!frameUsed && metadata.getAlbumCover() != null && !albumArtDisplayed) {
|
||||
updateAlbumArtImage(metadata.getAlbumCover());
|
||||
albumArtDisplayed = true;
|
||||
frameUsed = true;
|
||||
} else if (!albumArtQueued) {
|
||||
selectionLoaderThread.queue(this);
|
||||
albumArtQueued = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAlbumArtImage(Texture texture) {
|
||||
if (texture == null) throw new IllegalArgumentException("Texture can't be null!");
|
||||
albumArtTexture.setRegion(texture);
|
||||
albumCoverImage.setDrawable(new TextureRegionDrawable(albumArtTexture));
|
||||
}
|
||||
|
||||
public void offScreenAct(float delta) {
|
||||
if (!offScreen) {
|
||||
offScreen = true;
|
||||
timeSinceChanged = 0;
|
||||
}
|
||||
if (metadata.getAlbumCover() != null) {
|
||||
timeSinceChanged += delta;
|
||||
if (timeSinceChanged >= 2) {
|
||||
updateAlbumArtImage(defaultAlbumArt);
|
||||
metadata.unloadAlbumCover();
|
||||
albumArtDisplayed = false;
|
||||
albumArtQueued = false;
|
||||
noReset = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AudioMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public FileHandle getFileHandle() {
|
||||
return metadata.getFileHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPrefWidth() {
|
||||
return scrollPane.getScrollWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPrefHeight() {
|
||||
return super.getPrefHeight();
|
||||
}
|
||||
|
||||
public TextureRegion getAlbumArtTexture() {
|
||||
return albumArtTexture;
|
||||
}
|
||||
|
||||
public boolean isOffScreen() {
|
||||
if (offScreen && !noReset) {
|
||||
albumArtDisplayed = false;
|
||||
albumArtQueued = false;
|
||||
}
|
||||
return offScreen;
|
||||
}
|
||||
|
||||
public void loadAttempted() {
|
||||
noReset = true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MusicSelectableButtonGroup extends ButtonGroup<MusicSelectable> {
|
||||
private Array<MusicSelectable> buttons;
|
||||
|
||||
public MusicSelectableButtonGroup() {
|
||||
buttons = getButtons();
|
||||
}
|
||||
|
||||
public void setChecked(FileHandle fileHandle) {
|
||||
if (fileHandle == null) throw new IllegalArgumentException("fileHandle can't be null.");
|
||||
MusicSelectable button;
|
||||
for (int i = 0; i < buttons.size; i++) {
|
||||
button = buttons.get(i);
|
||||
if (button.getFileHandle() == fileHandle) {
|
||||
button.setChecked(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean selectNext() {
|
||||
int index = getCheckedIndex() + 1;
|
||||
if (index == buttons.size) {
|
||||
return false;
|
||||
}
|
||||
buttons.get(index).setChecked(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean selectPrevious() {
|
||||
int index = getCheckedIndex() - 1;
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
buttons.get(index).setChecked(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCheck(MusicSelectable button, boolean newState) {
|
||||
if (newState) {
|
||||
musicInfoTable.setDisplayedSelectable(button);
|
||||
musicSelectDelay = 0f;
|
||||
}
|
||||
return super.canCheck(button, newState);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return buttons.size;
|
||||
}
|
||||
}
|
||||
|
||||
private class InformationTable extends Table {
|
||||
private ScrollingText songTitle;
|
||||
private Label author;
|
||||
private Label musicDuration;
|
||||
private Label previousTop;
|
||||
private Label ratedDifficulty;
|
||||
private Image albumCover;
|
||||
|
||||
private Table subInformation;
|
||||
|
||||
public InformationTable(float width, float height) {
|
||||
defaults().center();
|
||||
setPosition(scrollPane.getWidth() + scrollPane.getX(), 0);
|
||||
setSize(width, height);
|
||||
subInformation = new Table(skin);
|
||||
albumCover = new Image(assets.get("defaultCover.png", Texture.class));
|
||||
songTitle = new ScrollingText("", null, skin, true, true, 1f/screenConfig.getTargetFramesPerSecond());
|
||||
author = new Label(null, skin, "sub-font", skin.getColor("default"));
|
||||
musicDuration = new Label(null, skin, "sub-font", skin.getColor("default"));
|
||||
previousTop = new Label(null, skin, "sub-font", skin.getColor("default"));
|
||||
ratedDifficulty = new Label(null, skin, "sub-font", skin.getColor("default"));
|
||||
}
|
||||
|
||||
public void setDisplayedSelectable(MusicSelectable displayedSelectable) {
|
||||
if (displayedSelectable != null) {
|
||||
AudioMetadata metadata = displayedSelectable.getMetadata();
|
||||
albumCover.setDrawable(new TextureRegionDrawable(displayedSelectable.getAlbumArtTexture()));
|
||||
songTitle.setText(metadata.getTitle(), null);
|
||||
author.setText(metadata.getAuthor());
|
||||
musicDuration.setText(metadata.getDuration());
|
||||
//TODO previous top
|
||||
//TODO rated difficulty
|
||||
beginButton.setDisabled(false);
|
||||
} else {
|
||||
albumCover.setDrawable(new TextureRegionDrawable(new TextureRegion(assets.get("defaultCover.png", Texture.class))));
|
||||
songTitle.setText("loading...", null);
|
||||
author.setText("...");
|
||||
musicDuration.setText("...");
|
||||
previousTop.setText("...");
|
||||
ratedDifficulty.setText("...");
|
||||
}
|
||||
}
|
||||
|
||||
public void setToDefault() {
|
||||
clear();
|
||||
subInformation.clear();
|
||||
|
||||
albumCover.setDrawable(new TextureRegionDrawable(new TextureRegion(assets.get("defaultCover.png", Texture.class))));
|
||||
add(albumCover).size(getWidth()/2f).spaceBottom(25f);
|
||||
row();
|
||||
songTitle.setText("...", null);
|
||||
add(songTitle).width(getWidth()*0.6f).spaceBottom(30f);
|
||||
row();
|
||||
author.setText("...");
|
||||
author.setEllipsis(true);
|
||||
author.setAlignment(Align.center);
|
||||
subInformation.add(author).expand();
|
||||
subInformation.row();
|
||||
musicDuration.setText("...");
|
||||
subInformation.add(musicDuration);
|
||||
subInformation.row();
|
||||
previousTop.setText("...");
|
||||
subInformation.add(previousTop);
|
||||
subInformation.row();
|
||||
ratedDifficulty.setText("...");
|
||||
subInformation.add(ratedDifficulty);
|
||||
add(subInformation).width(0.4f*getWidth());
|
||||
row();
|
||||
add(beginButton).spaceTop(20f).fillX();
|
||||
beginButton.setDisabled(true);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,163 @@
|
||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
|
||||
import zero1hd.rhythmbullet.audio.MusicController;
|
||||
import zero1hd.rhythmbullet.graphics.ui.Page;
|
||||
|
||||
public class OptionsPage extends Page {
|
||||
Table optionsTable;
|
||||
private ProgressBar musicVolSlider;
|
||||
private ProgressBar fxVolSlider;
|
||||
private TextField directoryField;
|
||||
private float musicSearchTimer;
|
||||
private Preferences prefs;
|
||||
private NumberFormat percentFormat;
|
||||
|
||||
public OptionsPage(MusicController musicController, Skin skin, Preferences preferences, ChangeListener backButtonListener, ChangeListener graphicsButtonListener, ChangeListener controlsButtonListener) {
|
||||
super(-1, 0, "General", skin);
|
||||
this.prefs = preferences;
|
||||
percentFormat = NumberFormat.getPercentInstance();
|
||||
percentFormat.setMaximumFractionDigits(1);
|
||||
|
||||
//Back button
|
||||
TextButton backButton = new TextButton("Back", skin);
|
||||
backButton.addListener(backButtonListener);
|
||||
backButton.setWidth(backButton.getWidth() + 20);
|
||||
backButton.setPosition(getWidth() - backButton.getWidth() - 10, getHeightBelowTitle() + 5);
|
||||
addActor(backButton);
|
||||
|
||||
optionsTable = new Table();
|
||||
optionsTable.defaults().space(10f);
|
||||
|
||||
addActor(optionsTable);
|
||||
|
||||
Label musicVolSliderLabel = new Label("Music Volume: ", skin);
|
||||
optionsTable.add(musicVolSliderLabel);
|
||||
musicVolSlider = new Slider(0, 100, 1f, false, skin);
|
||||
musicVolSlider.setValue(preferences.getFloat("music vol", 100f));
|
||||
optionsTable.add(musicVolSlider).minWidth(0.3f*getWidth());
|
||||
final Label musicVolPercentage = new Label(percentFormat.format(musicVolSlider.getPercent()), skin);
|
||||
musicVolSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
musicVolPercentage.setText(percentFormat.format(musicVolSlider.getPercent()));
|
||||
musicController.getCurrentMusic().setVolume(musicVolSlider.getPercent());
|
||||
preferences.putFloat("music vol", musicVolSlider.getValue());
|
||||
}
|
||||
});
|
||||
optionsTable.add(musicVolPercentage).expandX().left();
|
||||
|
||||
optionsTable.row();
|
||||
|
||||
Label fxVolSliderLabel = new Label("FX Volume: ", skin);
|
||||
optionsTable.add(fxVolSliderLabel);
|
||||
fxVolSlider = new Slider(0, 100, 1f, false, skin);
|
||||
fxVolSlider.setValue(preferences.getFloat("fx vol", 100f));
|
||||
optionsTable.add(fxVolSlider).fillX();
|
||||
final Label fxVolPercentage = new Label(percentFormat.format(fxVolSlider.getPercent()), skin);
|
||||
fxVolSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
fxVolPercentage.setText(percentFormat.format(fxVolSlider.getPercent()));
|
||||
preferences.putFloat("fx vol", fxVolSlider.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
optionsTable.add(fxVolPercentage).left();
|
||||
|
||||
optionsTable.row();
|
||||
|
||||
Label musicDirectoryLabel = new Label("Music Directory: ", skin);
|
||||
optionsTable.add(musicDirectoryLabel);
|
||||
directoryField = new TextField(null, skin ) {
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
if (musicSearchTimer > 0) {
|
||||
musicSearchTimer -= delta;
|
||||
if (musicSearchTimer <= 0) {
|
||||
musicController.getMusicList().setSearchPath(directoryField.getText());
|
||||
musicController.getMusicList().attemptAsyncSearch(false);
|
||||
}
|
||||
}
|
||||
super.act(delta);
|
||||
}
|
||||
};
|
||||
directoryField.setText(preferences.getString("music dir", System.getProperty("user.home")+System.getProperty("file.separator")+"Music"));
|
||||
directoryField.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
musicSearchTimer = 2;
|
||||
}
|
||||
});
|
||||
optionsTable.add(directoryField).fillX();
|
||||
|
||||
optionsTable.row();
|
||||
|
||||
TextButton keybindSettings = new TextButton("Set Controls", skin);
|
||||
keybindSettings.addListener(controlsButtonListener);
|
||||
optionsTable.add(keybindSettings).colspan(2).fillX();
|
||||
|
||||
optionsTable.row();
|
||||
|
||||
TextButton graphicsSettings = new TextButton("Graphics", skin);
|
||||
graphicsSettings.addListener(graphicsButtonListener);
|
||||
optionsTable.add(graphicsSettings).colspan(2).fillX();
|
||||
|
||||
optionsTable.row();
|
||||
|
||||
Label fpsLabel = new Label("", skin) {
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
setText("Current FPS: " + Gdx.graphics.getFramesPerSecond());
|
||||
super.act(delta);
|
||||
}
|
||||
};
|
||||
optionsTable.add(fpsLabel).colspan(2);
|
||||
|
||||
optionsTable.row();
|
||||
|
||||
Label usageLabel = new Label("Current Usage (JVM): ", skin) {
|
||||
float refreshTime = 20;
|
||||
@Override
|
||||
public void act(float delta) {
|
||||
refreshTime -= delta;
|
||||
if (refreshTime <= 0) {
|
||||
refreshTime = 4;
|
||||
String formatted = percentFormat.format(((float)(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/(float)Runtime.getRuntime().totalMemory()));
|
||||
setText("Current usage (JVM): " + formatted);
|
||||
}
|
||||
super.act(delta);
|
||||
}
|
||||
};
|
||||
|
||||
optionsTable.add(usageLabel).colspan(2);
|
||||
|
||||
optionsTable.pack();
|
||||
optionsTable.setX((getWidth()-optionsTable.getWidth())/2f);
|
||||
optionsTable.setSize(getWidth() - optionsTable.getX(), backButton.getY());
|
||||
}
|
||||
|
||||
public void saveOptions() {
|
||||
prefs.putString("music dir", directoryField.getText());
|
||||
Gdx.app.debug("Preferences", "Saved all basic options page values.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
saveOptions();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user