improved initializer resolver
This commit is contained in:
@@ -19,50 +19,50 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
|
||||
|
||||
/**
|
||||
* Set listener position
|
||||
*
|
||||
* @param pos listener position
|
||||
*/
|
||||
public abstract void setListenerPos(Vect pos);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get current listener position
|
||||
*
|
||||
* @return listener position
|
||||
*/
|
||||
public abstract Vect getListenerPos();
|
||||
|
||||
|
||||
// -- instance --
|
||||
|
||||
|
||||
private final Volume masterVolume = new Volume(1D);
|
||||
private final Volume effectsVolume = new JointVolume(masterVolume);
|
||||
private final Volume loopsVolume = new JointVolume(masterVolume);
|
||||
|
||||
|
||||
private final List<LoopPlayer> loopPlayers = new ArrayList<>();
|
||||
private final List<DeferredAudio> resources = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
for (final DeferredAudio r : resources) {
|
||||
r.destroy();
|
||||
}
|
||||
|
||||
|
||||
deinitSoundSystem();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deinitialize the soud system, release resources etc.<br>
|
||||
* Audio resources are already destroyed.
|
||||
*/
|
||||
protected abstract void deinitSoundSystem();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
@@ -70,8 +70,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
lp.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create effect resource
|
||||
*
|
||||
@@ -82,8 +82,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
{
|
||||
return new EffectPlayer(createAudioResource(resource), effectsVolume);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register loop resource (music / effect loop)
|
||||
*
|
||||
@@ -96,8 +96,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
loopPlayers.add(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create {@link DeferredAudio} for a resource, request deferred load and
|
||||
* add to the resources list.<br>
|
||||
@@ -115,8 +115,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
resources.add(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a backend-specific deferred audio resource.<br>
|
||||
* The actual resource instance should be created here. Registering, loading
|
||||
@@ -126,8 +126,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
* @return Deferred Audio
|
||||
*/
|
||||
protected abstract DeferredAudio doCreateResource(String res);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade out all loops (= fade out the currently playing loops)
|
||||
*/
|
||||
@@ -137,8 +137,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
p.fadeOut();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Pause all loops (leave volume unchanged)
|
||||
*/
|
||||
@@ -148,8 +148,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
p.pause();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set level of master volume (volume multiplier)
|
||||
*
|
||||
@@ -159,8 +159,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
{
|
||||
masterVolume.set(volume);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set level of effects volume (volume multiplier)
|
||||
*
|
||||
@@ -170,8 +170,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
{
|
||||
effectsVolume.set(volume);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set level of loops volume (volume multiplier)
|
||||
*
|
||||
@@ -181,8 +181,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
{
|
||||
loopsVolume.set(volume);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get level of master volume (volume multiplier)
|
||||
*
|
||||
@@ -192,8 +192,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
{
|
||||
return masterVolume.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get level of effects volume (volume multiplier)
|
||||
*
|
||||
@@ -203,8 +203,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
{
|
||||
return effectsVolume.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get level of loops volume (volume multiplier)
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
*/
|
||||
@Alias(name = "Audio")
|
||||
public abstract class DeferredAudio extends BaseDeferredResource implements IAudio {
|
||||
|
||||
|
||||
/**
|
||||
* Create audio
|
||||
*
|
||||
@@ -24,22 +24,22 @@ public abstract class DeferredAudio extends BaseDeferredResource implements IAud
|
||||
{
|
||||
super(resourceName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void play(double gain, double pitch, boolean loop)
|
||||
{
|
||||
play(gain, pitch, loop, App.sound().getListenerPos());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void play(double gain, double pitch, boolean loop, double x, double y)
|
||||
{
|
||||
play(gain, pitch, loop, x, y, App.sound().getListenerPos().z());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void play(double gain, double pitch, boolean loop, Vect pos)
|
||||
{
|
||||
|
||||
@@ -11,19 +11,19 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface IAudio extends Destroyable {
|
||||
|
||||
|
||||
/**
|
||||
* Pause loop (remember position and stop playing) - if was looping
|
||||
*/
|
||||
void pauseLoop();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resume loop (if was looping and paused)
|
||||
*/
|
||||
void resumeLoop();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adjust gain for the currently playing effect (can be used for fading
|
||||
* music)
|
||||
@@ -31,27 +31,27 @@ public interface IAudio extends Destroyable {
|
||||
* @param gain gain to set 0..1
|
||||
*/
|
||||
void adjustGain(double gain);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Stop audio playback, free source. Meaningful for loops, may not work
|
||||
* properly for effects.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the audio is playing
|
||||
*/
|
||||
boolean isPlaying();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return trie if the audio is paused
|
||||
*/
|
||||
boolean isPaused();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play as sound effect at listener position
|
||||
*
|
||||
@@ -60,8 +60,8 @@ public interface IAudio extends Destroyable {
|
||||
* @param loop looping
|
||||
*/
|
||||
void play(double gain, double pitch, boolean loop);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play as sound effect at given position
|
||||
*
|
||||
@@ -73,8 +73,8 @@ public interface IAudio extends Destroyable {
|
||||
* @param z
|
||||
*/
|
||||
void play(double gain, double pitch, boolean loop, double x, double y, double z);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play as sound effect at given X-Y position
|
||||
*
|
||||
@@ -85,8 +85,8 @@ public interface IAudio extends Destroyable {
|
||||
* @param y
|
||||
*/
|
||||
void play(double gain, double pitch, boolean loop, double x, double y);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play as sound effect at given position
|
||||
*
|
||||
@@ -96,8 +96,8 @@ public interface IAudio extends Destroyable {
|
||||
* @param pos coord
|
||||
*/
|
||||
void play(double gain, double pitch, boolean loop, Vect pos);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if this audio is currently active (ie. playing or paused, not
|
||||
* stopped)
|
||||
@@ -105,5 +105,5 @@ public interface IAudio extends Destroyable {
|
||||
* @return is active
|
||||
*/
|
||||
boolean isActive();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import mightypork.utils.math.Calc;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class JointVolume extends Volume {
|
||||
|
||||
|
||||
private final Volume[] volumes;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create joint volume with master gain of 1
|
||||
*
|
||||
@@ -25,8 +25,8 @@ public class JointVolume extends Volume {
|
||||
super(1D);
|
||||
this.volumes = volumes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get combined gain (multiplied)
|
||||
*/
|
||||
@@ -36,11 +36,11 @@ public class JointVolume extends Volume {
|
||||
double d = super.get();
|
||||
for (final Volume v : volumes)
|
||||
d *= v.get();
|
||||
|
||||
|
||||
return Calc.clamp(d, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set master gain
|
||||
*/
|
||||
|
||||
@@ -16,11 +16,11 @@ import mightypork.utils.exceptions.KeyAlreadyExistsException;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class SoundRegistry {
|
||||
|
||||
|
||||
private final Map<String, EffectPlayer> effects = new HashMap<>();
|
||||
private final Map<String, LoopPlayer> loops = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register effect resource
|
||||
*
|
||||
@@ -33,16 +33,16 @@ public class SoundRegistry {
|
||||
public EffectPlayer addEffect(String key, String resourcePath, double gain, double pitch)
|
||||
{
|
||||
final EffectPlayer effect = App.sound().createEffect(resourcePath);
|
||||
|
||||
|
||||
effect.setPitch(pitch);
|
||||
effect.setGain(gain);
|
||||
|
||||
|
||||
addEffect(key, effect);
|
||||
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register effect resource
|
||||
*
|
||||
@@ -52,11 +52,11 @@ public class SoundRegistry {
|
||||
public void addEffect(String key, EffectPlayer effect)
|
||||
{
|
||||
if (effects.containsKey(key)) throw new KeyAlreadyExistsException();
|
||||
|
||||
|
||||
effects.put(key, effect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register loop resource (music / effect loop)
|
||||
*
|
||||
@@ -71,17 +71,17 @@ public class SoundRegistry {
|
||||
public LoopPlayer addLoop(String key, String resourcePath, double gain, double pitch, double fadeIn, double fadeOut)
|
||||
{
|
||||
final LoopPlayer loop = App.sound().createLoop(resourcePath);
|
||||
|
||||
|
||||
loop.setPitch(pitch);
|
||||
loop.setGain(gain);
|
||||
loop.setFadeTimes(fadeIn, fadeOut);
|
||||
|
||||
|
||||
addLoop(key, loop);
|
||||
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register loop resource (music / effect loop)
|
||||
*
|
||||
@@ -91,11 +91,11 @@ public class SoundRegistry {
|
||||
public void addLoop(String key, LoopPlayer loop)
|
||||
{
|
||||
if (loops.containsKey(key)) throw new KeyAlreadyExistsException();
|
||||
|
||||
|
||||
loops.put(key, loop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a loop player for key
|
||||
*
|
||||
@@ -110,8 +110,8 @@ public class SoundRegistry {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a effect player for key
|
||||
*
|
||||
|
||||
@@ -11,7 +11,7 @@ import mightypork.utils.struct.Mutable;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class Volume extends Mutable<Double> {
|
||||
|
||||
|
||||
/**
|
||||
* @param d initial value
|
||||
*/
|
||||
@@ -19,12 +19,12 @@ public class Volume extends Mutable<Double> {
|
||||
{
|
||||
super(d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void set(Double d)
|
||||
{
|
||||
super.set(Calc.clamp(d, 0, 1));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ import mightypork.utils.interfaces.Destroyable;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class AudioPlayer implements Destroyable {
|
||||
|
||||
|
||||
/** the track */
|
||||
private final IAudio audio;
|
||||
|
||||
|
||||
/** base gain for sfx */
|
||||
private double baseGain;
|
||||
|
||||
|
||||
/** base pitch for sfx */
|
||||
private double basePitch;
|
||||
|
||||
|
||||
/** dedicated volume control */
|
||||
private final Volume gainMultiplier;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param track audio resource
|
||||
* @param volume colume control
|
||||
@@ -33,20 +33,20 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
public AudioPlayer(IAudio track, Volume volume)
|
||||
{
|
||||
this.audio = track;
|
||||
|
||||
|
||||
if (volume == null) volume = new Volume(1D);
|
||||
|
||||
|
||||
this.gainMultiplier = volume;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
audio.destroy();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return audio resource
|
||||
*/
|
||||
@@ -54,8 +54,8 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
{
|
||||
return audio;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get play gain, computed based on volume and given multiplier
|
||||
*
|
||||
@@ -66,8 +66,8 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
{
|
||||
return baseGain * gainMultiplier.get() * multiplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get pitch
|
||||
*
|
||||
@@ -78,8 +78,8 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
{
|
||||
return basePitch * multiplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get if audio is valid
|
||||
*
|
||||
@@ -89,8 +89,8 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
{
|
||||
return (audio != null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set base gain. 1 is original volume, 0 is silence.
|
||||
*
|
||||
@@ -100,8 +100,8 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
{
|
||||
this.baseGain = gain;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set base pitch. 1 is original pitch, less is deeper, more is higher.
|
||||
*
|
||||
@@ -111,5 +111,5 @@ public abstract class AudioPlayer implements Destroyable {
|
||||
{
|
||||
this.basePitch = pitch;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class EffectPlayer extends AudioPlayer {
|
||||
|
||||
|
||||
/**
|
||||
* @param track audio resource
|
||||
* @param volume volume control
|
||||
@@ -21,8 +21,8 @@ public class EffectPlayer extends AudioPlayer {
|
||||
{
|
||||
super(track, volume);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play at listener
|
||||
*
|
||||
@@ -32,11 +32,11 @@ public class EffectPlayer extends AudioPlayer {
|
||||
public void play(double gain, double pitch)
|
||||
{
|
||||
if (!hasAudio()) return;
|
||||
|
||||
|
||||
getAudio().play(computeGain(gain), computePitch(pitch), false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play at listener
|
||||
*
|
||||
@@ -46,8 +46,8 @@ public class EffectPlayer extends AudioPlayer {
|
||||
{
|
||||
play(gain, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play at given position
|
||||
*
|
||||
@@ -58,8 +58,8 @@ public class EffectPlayer extends AudioPlayer {
|
||||
{
|
||||
play(gain, 1, pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play at given position
|
||||
*
|
||||
@@ -70,8 +70,8 @@ public class EffectPlayer extends AudioPlayer {
|
||||
public void play(double gain, double pitch, Vect pos)
|
||||
{
|
||||
if (!hasAudio()) return;
|
||||
|
||||
|
||||
getAudio().play(computeGain(gain), computePitch(pitch), false, pos);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,22 +14,22 @@ import mightypork.utils.math.animation.NumAnimated;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
|
||||
|
||||
/** animator for fade in and fade out */
|
||||
private final NumAnimated fadeAnim = new NumAnimated(0);
|
||||
|
||||
|
||||
private double lastUpdateGain = 0;
|
||||
|
||||
|
||||
/** flag that track is paused */
|
||||
private boolean paused = true;
|
||||
|
||||
|
||||
/** Default fadeIn time */
|
||||
private double inTime = 1;
|
||||
|
||||
|
||||
/** Default fadeOut time */
|
||||
private double outTime = 1;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param track audio resource
|
||||
* @param volume volume control
|
||||
@@ -37,11 +37,11 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
public LoopPlayer(DeferredAudio track, Volume volume)
|
||||
{
|
||||
super(track, volume);
|
||||
|
||||
|
||||
paused = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set fading duration (seconds)
|
||||
*
|
||||
@@ -53,8 +53,8 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
inTime = in;
|
||||
outTime = out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void initLoop()
|
||||
{
|
||||
if (hasAudio() && !getAudio().isActive()) {
|
||||
@@ -62,27 +62,27 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
getAudio().pauseLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void pause()
|
||||
{
|
||||
if (!hasAudio() || paused) return;
|
||||
|
||||
|
||||
initLoop();
|
||||
|
||||
|
||||
getAudio().pauseLoop();
|
||||
paused = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPaused()
|
||||
{
|
||||
return paused;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Alias to resume (more meaningful name)
|
||||
*/
|
||||
@@ -90,40 +90,40 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
{
|
||||
resume();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void resume()
|
||||
{
|
||||
if (!hasAudio() || !paused) return;
|
||||
|
||||
|
||||
initLoop();
|
||||
|
||||
|
||||
paused = false;
|
||||
|
||||
|
||||
getAudio().adjustGain(computeGain(fadeAnim.value()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
if (!hasAudio() || paused) return;
|
||||
|
||||
|
||||
initLoop();
|
||||
|
||||
|
||||
fadeAnim.update(delta);
|
||||
|
||||
|
||||
final double gain = computeGain(fadeAnim.value());
|
||||
if (!paused && gain != lastUpdateGain) {
|
||||
getAudio().adjustGain(gain);
|
||||
lastUpdateGain = gain;
|
||||
}
|
||||
|
||||
|
||||
if (gain == 0 && !paused) pause(); // pause on zero volume
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resume if paused, and fade in (pick up from current volume).
|
||||
*
|
||||
@@ -132,13 +132,13 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
public void fadeIn(double fadeTime)
|
||||
{
|
||||
if (!hasAudio()) return;
|
||||
|
||||
|
||||
if (isPaused()) fadeAnim.setTo(0);
|
||||
resume();
|
||||
fadeAnim.fadeIn(fadeTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade out and pause when reached zero volume
|
||||
*
|
||||
@@ -150,8 +150,8 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
if (isPaused()) return;
|
||||
fadeAnim.fadeOut(fadeTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade in with default duration
|
||||
*/
|
||||
@@ -159,8 +159,8 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
{
|
||||
fadeIn(inTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade out with default duration
|
||||
*/
|
||||
@@ -168,5 +168,5 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
|
||||
{
|
||||
fadeOut(outTime);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,29 @@
|
||||
package mightypork.gamecore.core;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import mightypork.gamecore.audio.AudioModule;
|
||||
import mightypork.gamecore.core.config.Config;
|
||||
import mightypork.gamecore.core.events.ShutdownEvent;
|
||||
import mightypork.gamecore.core.events.MainLoopRequest;
|
||||
import mightypork.gamecore.core.events.ShutdownRequest;
|
||||
import mightypork.gamecore.core.init.InitSequence;
|
||||
import mightypork.gamecore.core.init.InitTask;
|
||||
import mightypork.gamecore.core.init.InitTaskBackend;
|
||||
import mightypork.gamecore.core.init.InitTaskCrashHandler;
|
||||
import mightypork.gamecore.core.init.InitTaskIonizables;
|
||||
import mightypork.gamecore.core.init.InitTaskLog;
|
||||
import mightypork.gamecore.core.init.InitTaskLogHeader;
|
||||
import mightypork.gamecore.core.init.InitTaskMainLoop;
|
||||
import mightypork.gamecore.core.init.InitTaskResourceLoaderAsync;
|
||||
import mightypork.gamecore.core.init.InitTaskWorkdir;
|
||||
import mightypork.gamecore.core.plugins.AppPlugin;
|
||||
import mightypork.gamecore.graphics.GraphicsModule;
|
||||
import mightypork.gamecore.graphics.Renderable;
|
||||
import mightypork.gamecore.input.InputModule;
|
||||
import mightypork.utils.Str;
|
||||
import mightypork.utils.annotations.Stub;
|
||||
import mightypork.utils.eventbus.EventBus;
|
||||
import mightypork.utils.eventbus.clients.BusNode;
|
||||
@@ -26,25 +38,25 @@ import mightypork.utils.logging.Log;
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class App extends BusNode {
|
||||
|
||||
|
||||
private static App instance;
|
||||
|
||||
|
||||
private final AppBackend backend;
|
||||
private final EventBus eventBus = new EventBus();
|
||||
private boolean started = false;
|
||||
private boolean inited = false;
|
||||
|
||||
|
||||
/** List of installed App plugins */
|
||||
protected final DelegatingList plugins = new DelegatingList();
|
||||
/** List of initializers */
|
||||
protected final List<InitTask> initializers = new ArrayList<>();
|
||||
|
||||
protected final InitSequence initTasks = new InitSequence();
|
||||
|
||||
/** The used main loop instance */
|
||||
protected MainLoop mainLoop;
|
||||
|
||||
|
||||
private Renderable mainRenderable;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create an app with given backend.
|
||||
*
|
||||
@@ -55,24 +67,39 @@ public class App extends BusNode {
|
||||
if (App.instance != null) {
|
||||
throw new IllegalStateException("App already initialized");
|
||||
}
|
||||
|
||||
|
||||
// store current instance in static field
|
||||
App.instance = this;
|
||||
|
||||
|
||||
// join the bus
|
||||
this.eventBus.subscribe(this);
|
||||
|
||||
|
||||
// create plugin registry attached to bus
|
||||
this.eventBus.subscribe(this.plugins);
|
||||
|
||||
addChildClient(this.plugins);
|
||||
|
||||
// initialize and use backend
|
||||
this.backend = backend;
|
||||
this.backend.bind(this);
|
||||
this.eventBus.subscribe(backend);
|
||||
this.backend.initialize();
|
||||
addChildClient(backend);
|
||||
|
||||
addDefaultInitTasks();
|
||||
this.backend.addInitTasks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void addDefaultInitTasks()
|
||||
{
|
||||
addInitTask(new InitTaskCrashHandler());
|
||||
addInitTask(new InitTaskWorkdir(new File("."), true));
|
||||
addInitTask(new InitTaskLog());
|
||||
addInitTask(new InitTaskBackend());
|
||||
addInitTask(new InitTaskIonizables());
|
||||
addInitTask(new InitTaskMainLoop());
|
||||
addInitTask(new InitTaskResourceLoaderAsync());
|
||||
addInitTask(new InitTaskLogHeader());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a plugin to the app. Plugins can eg. listen to bus events and react
|
||||
* to them.
|
||||
@@ -86,8 +113,8 @@ public class App extends BusNode {
|
||||
plugin.bind(this);
|
||||
plugin.initialize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an initializer to the app.
|
||||
*
|
||||
@@ -98,11 +125,11 @@ public class App extends BusNode {
|
||||
if (started) {
|
||||
throw new IllegalStateException("App already started, cannot add initializers.");
|
||||
}
|
||||
|
||||
initializers.add(initializer);
|
||||
|
||||
initTasks.addTask(initializer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the main loop implementation
|
||||
*
|
||||
@@ -111,10 +138,10 @@ public class App extends BusNode {
|
||||
public void setMainLoop(MainLoop loop)
|
||||
{
|
||||
this.mainLoop = loop;
|
||||
bus().subscribe(loop); // ?
|
||||
addChildClient(loop); // ?
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the main renderable
|
||||
*
|
||||
@@ -124,8 +151,8 @@ public class App extends BusNode {
|
||||
{
|
||||
this.mainRenderable = renderable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get current backend
|
||||
*
|
||||
@@ -135,8 +162,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return backend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the App and start operating.<br>
|
||||
* This method should be called after adding all required initializers and
|
||||
@@ -148,60 +175,67 @@ public class App extends BusNode {
|
||||
throw new IllegalStateException("Already started.");
|
||||
}
|
||||
started = true;
|
||||
|
||||
|
||||
Log.i("Starting init...");
|
||||
init();
|
||||
|
||||
|
||||
if (mainLoop == null) {
|
||||
throw new IllegalStateException("The app has no main loop assigned.");
|
||||
}
|
||||
|
||||
|
||||
Log.i("Starting main loop...");
|
||||
mainLoop.setRootRenderable(mainRenderable);
|
||||
mainLoop.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void init()
|
||||
{
|
||||
|
||||
|
||||
if (inited) {
|
||||
throw new IllegalStateException("Already inited.");
|
||||
}
|
||||
inited = true;
|
||||
|
||||
|
||||
// pre-init hook, just in case anyone wanted to have one.
|
||||
Log.f2("Calling pre-init hook...");
|
||||
preInit();
|
||||
|
||||
|
||||
Log.f2("Running init tasks...");
|
||||
|
||||
// sort initializers based on dependencies
|
||||
final List<InitTask> orderedInitializers = initTasks.getSequence();
|
||||
|
||||
// sort initializers by order.
|
||||
final List<InitTask> orderedInitializers = InitTask.inOrder(initializers);
|
||||
|
||||
// detailed logging
|
||||
Log.f3("=== Task overview ===");
|
||||
for (final InitTask t : orderedInitializers) {
|
||||
Log.f3("Task " + Str.pad(t.getName(), 20) + " class = " + Str.pad(Str.val(t), 30) + " prio = " + Str.pad("" + t.getPriority(), 12) + " deps = "
|
||||
+ Arrays.toString(t.getDependencies()));
|
||||
}
|
||||
|
||||
for (final InitTask initTask : orderedInitializers) {
|
||||
Log.f1("Running init task \"" + initTask.getName() + "\"...");
|
||||
|
||||
|
||||
initTask.bind(this);
|
||||
|
||||
|
||||
// set the task options
|
||||
initTask.init();
|
||||
|
||||
|
||||
initTask.before();
|
||||
|
||||
|
||||
// main task action
|
||||
initTask.run();
|
||||
|
||||
|
||||
// after hook for extra actions immeditaely after the task completes
|
||||
initTask.after();
|
||||
}
|
||||
|
||||
|
||||
// user can now start the main loop etc.
|
||||
Log.f2("Calling post-init hook...");
|
||||
postInit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hook called before the initialization sequence starts.
|
||||
*/
|
||||
@@ -209,8 +243,8 @@ public class App extends BusNode {
|
||||
protected void preInit()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hook called after the initialization sequence is finished.
|
||||
*/
|
||||
@@ -218,44 +252,60 @@ public class App extends BusNode {
|
||||
protected void postInit()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Shut down the running instance.<br>
|
||||
* Deinitialize backend modules and terminate the JVM.
|
||||
*/
|
||||
public static void requestShutdown()
|
||||
{
|
||||
if (instance == null) {
|
||||
Log.w("App is not running.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
Log.i("Sending a shutdown request...");
|
||||
bus().send(new ShutdownRequest());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shut down the running instance.<br>
|
||||
* Deinitialize backend modules and terminate the JVM.
|
||||
*/
|
||||
public static void shutdown()
|
||||
{
|
||||
if (instance != null) {
|
||||
Log.i("Dispatching Shutdown event...");
|
||||
|
||||
bus().send(new ShutdownEvent(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
final EventBus bus = bus();
|
||||
if (bus != null) {
|
||||
bus.send(new DestroyEvent());
|
||||
bus.destroy();
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
Log.i("Shutdown completed.");
|
||||
System.exit(0);
|
||||
}
|
||||
}));
|
||||
|
||||
} else {
|
||||
if (instance == null) {
|
||||
Log.w("App is not running.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// It's safer to shutdown in rendering context
|
||||
// (LWJGL backend has problems otherwise)
|
||||
|
||||
App.bus().send(new MainLoopRequest(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
final EventBus bus = bus();
|
||||
if (bus != null) {
|
||||
bus.send(new DestroyEvent());
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}, true));
|
||||
|
||||
|
||||
Log.i("Shutdown completed.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the currently running App instance.
|
||||
*
|
||||
@@ -265,8 +315,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get graphics module from the running app's backend
|
||||
*
|
||||
@@ -276,8 +326,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return instance.backend.getGraphics();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get audio module from the running app's backend
|
||||
*
|
||||
@@ -287,8 +337,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return instance.backend.getAudio();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get input module from the running app's backend
|
||||
*
|
||||
@@ -298,8 +348,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return instance.backend.getInput();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get event bus instance.
|
||||
*
|
||||
@@ -309,8 +359,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return instance.eventBus;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the main config, if initialized.
|
||||
*
|
||||
@@ -321,8 +371,8 @@ public class App extends BusNode {
|
||||
{
|
||||
return cfg("main");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a config by alias.
|
||||
*
|
||||
|
||||
@@ -2,8 +2,10 @@ package mightypork.gamecore.core;
|
||||
|
||||
|
||||
import mightypork.gamecore.audio.AudioModule;
|
||||
import mightypork.gamecore.core.init.InitTaskBackend;
|
||||
import mightypork.gamecore.graphics.GraphicsModule;
|
||||
import mightypork.gamecore.input.InputModule;
|
||||
import mightypork.utils.annotations.Stub;
|
||||
import mightypork.utils.eventbus.clients.BusNode;
|
||||
|
||||
|
||||
@@ -11,16 +13,17 @@ import mightypork.utils.eventbus.clients.BusNode;
|
||||
* Application backend interface (set of core modules).<br>
|
||||
* The goal of this abstraction is to allow easy migration to different
|
||||
* environment with different libraries etc. It should be as simple as using
|
||||
* different backend.
|
||||
* different backend.<br>
|
||||
* The backend is initialized using {@link InitTaskBackend}.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class AppBackend extends BusNode {
|
||||
|
||||
|
||||
/** App instance assigned using <code>bind()</code> */
|
||||
protected App app;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assign the initialized app instance to an "app" field.
|
||||
*
|
||||
@@ -35,28 +38,41 @@ public abstract class AppBackend extends BusNode {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add backend-specific init tasks or init task configurations.<br>
|
||||
* This is run after default init tasks have been added, and before the init
|
||||
* sequence is started.<br>
|
||||
* The backend is already binded to the app.
|
||||
*/
|
||||
@Stub
|
||||
public void addInitTasks()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize backend modules, add them to event bus.
|
||||
*/
|
||||
public abstract void initialize();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get graphics module (screen manager, texture and font loader, renderer)
|
||||
*
|
||||
* @return graphics module
|
||||
*/
|
||||
public abstract GraphicsModule getGraphics();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get audio module (
|
||||
*
|
||||
* @return audio module
|
||||
*/
|
||||
public abstract AudioModule getAudio();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get input module
|
||||
*
|
||||
|
||||
@@ -12,7 +12,7 @@ import mightypork.utils.interfaces.Destroyable;
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class BackendModule extends BusNode implements Destroyable {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the backend module.<br>
|
||||
* Any initialization that would normally be done in constructor shall be
|
||||
@@ -20,8 +20,8 @@ public abstract class BackendModule extends BusNode implements Destroyable {
|
||||
* "call to overridable method from constructor"
|
||||
*/
|
||||
public abstract void init();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Stub
|
||||
public void destroy()
|
||||
|
||||
+30
-27
@@ -18,76 +18,79 @@ import mightypork.utils.math.timing.TimerDelta;
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class DeltaMainLoop extends BusNode implements MainLoop {
|
||||
|
||||
public class BasicMainLoop extends BusNode implements MainLoop {
|
||||
|
||||
/**
|
||||
* Max time spent on main loop tasks per cycle (s)
|
||||
*/
|
||||
protected double MAX_TIME_TASKS = 1 / 30D;
|
||||
|
||||
|
||||
/**
|
||||
* Max delta time (s) per frame.<br>
|
||||
* If delta is larger than this, it's clamped to it.
|
||||
*/
|
||||
protected double MAX_DELTA = 1 / 20D;
|
||||
|
||||
|
||||
private final Deque<Runnable> tasks = new ConcurrentLinkedDeque<>();
|
||||
private TimerDelta timer;
|
||||
private Renderable rootRenderable;
|
||||
private volatile boolean running = true;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setRootRenderable(Renderable rootRenderable)
|
||||
{
|
||||
this.rootRenderable = rootRenderable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
timer = new TimerDelta();
|
||||
|
||||
|
||||
while (running) {
|
||||
App.gfx().beginFrame();
|
||||
|
||||
|
||||
double delta = timer.getDelta();
|
||||
if (delta > MAX_DELTA) {
|
||||
Log.f3("(timing) Clamping delta: was " + delta + " s, MAX_DELTA = " + MAX_DELTA + " s");
|
||||
delta = MAX_DELTA;
|
||||
}
|
||||
|
||||
|
||||
// dispatch update event
|
||||
App.bus().sendDirect(new UpdateEvent(delta));
|
||||
|
||||
|
||||
// run main loop tasks
|
||||
Runnable r;
|
||||
final long t = Profiler.begin();
|
||||
|
||||
|
||||
while ((r = tasks.poll()) != null) {
|
||||
Log.f3(" * Main loop task.");
|
||||
r.run();
|
||||
|
||||
|
||||
if (Profiler.end(t) > MAX_TIME_TASKS) {
|
||||
Log.f3("! Time's up, postponing task to next cycle.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// halt if tasks terminated the app.
|
||||
if (!running) break;
|
||||
|
||||
beforeRender();
|
||||
|
||||
|
||||
if (rootRenderable != null) {
|
||||
rootRenderable.render();
|
||||
}
|
||||
|
||||
|
||||
afterRender();
|
||||
|
||||
|
||||
App.gfx().endFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called before render
|
||||
*/
|
||||
@@ -96,8 +99,8 @@ public class DeltaMainLoop extends BusNode implements MainLoop {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called after render
|
||||
*/
|
||||
@@ -106,15 +109,15 @@ public class DeltaMainLoop extends BusNode implements MainLoop {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void queueTask(Runnable task, boolean skipQueue)
|
||||
{
|
||||
@@ -124,5 +127,5 @@ public class DeltaMainLoop extends BusNode implements MainLoop {
|
||||
tasks.addLast(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import mightypork.utils.interfaces.Destroyable;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface MainLoop extends Destroyable {
|
||||
|
||||
|
||||
/**
|
||||
* Set primary renderable
|
||||
*
|
||||
@@ -20,19 +20,19 @@ public interface MainLoop extends Destroyable {
|
||||
* {@link ScreenRegistry}
|
||||
*/
|
||||
public abstract void setRootRenderable(Renderable rootRenderable);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Start the loop. The loop should be terminated when the destroy() method
|
||||
* is called.
|
||||
*/
|
||||
public abstract void start();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void destroy();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a task to queue to be executed in the main loop (in rendering
|
||||
* context). This may be eg. loading textures.
|
||||
@@ -41,5 +41,5 @@ public interface MainLoop extends Destroyable {
|
||||
* @param skipQueue true to skip the queue
|
||||
*/
|
||||
public abstract void queueTask(Runnable task, boolean skipQueue);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ package mightypork.gamecore.core.config;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import mightypork.gamecore.core.events.ShutdownEvent;
|
||||
import mightypork.gamecore.core.events.ShutdownListener;
|
||||
import mightypork.gamecore.core.events.ShutdownRequest;
|
||||
import mightypork.gamecore.core.events.ShutdownRequestListener;
|
||||
import mightypork.gamecore.input.Key;
|
||||
import mightypork.gamecore.input.KeyStroke;
|
||||
import mightypork.utils.config.propmgr.Property;
|
||||
@@ -21,16 +21,16 @@ import mightypork.utils.logging.Log;
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class Config implements ShutdownListener {
|
||||
|
||||
public class Config implements ShutdownRequestListener {
|
||||
|
||||
/** Array of configs registered for the app */
|
||||
protected static Map<String, Config> configs = new HashMap<>();
|
||||
|
||||
|
||||
private final Map<String, KeyStrokeProperty> strokes = new HashMap<>();
|
||||
|
||||
|
||||
private final PropertyManager propertyManager;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a config from the static map, by given alias
|
||||
*
|
||||
@@ -40,15 +40,15 @@ public class Config implements ShutdownListener {
|
||||
public static Config forAlias(String alias)
|
||||
{
|
||||
final Config c = configs.get(alias);
|
||||
|
||||
|
||||
if (c == null) {
|
||||
throw new IllegalArgumentException("There is no config with alias \"" + alias + "\"");
|
||||
}
|
||||
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register a config by alias.
|
||||
*
|
||||
@@ -60,11 +60,11 @@ public class Config implements ShutdownListener {
|
||||
if (configs.get(alias) != null) {
|
||||
throw new IllegalArgumentException("The alias \"" + alias + "\" is already used.");
|
||||
}
|
||||
|
||||
|
||||
configs.put(alias, config);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize property manager for a file
|
||||
*
|
||||
@@ -75,8 +75,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
this(new PropertyFile(WorkDir.getFile(file), headComment));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize property manager for a given store
|
||||
*
|
||||
@@ -86,8 +86,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager = new PropertyManager(store);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a keystroke property
|
||||
*
|
||||
@@ -101,8 +101,8 @@ public class Config implements ShutdownListener {
|
||||
strokes.put(prefixKeyStroke(key), kprop);
|
||||
propertyManager.addProperty(kprop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a boolean property (flag)
|
||||
*
|
||||
@@ -114,8 +114,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager.addBoolean(key, defval, comment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an integer property
|
||||
*
|
||||
@@ -127,8 +127,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager.addInteger(key, defval, comment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a double property
|
||||
*
|
||||
@@ -140,8 +140,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager.addDouble(key, defval, comment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a string property
|
||||
*
|
||||
@@ -153,8 +153,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager.addString(key, defval, comment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an arbitrary property (can be custom type)
|
||||
*
|
||||
@@ -164,8 +164,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager.addProperty(prop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load config from file
|
||||
*/
|
||||
@@ -173,8 +173,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
propertyManager.load();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save config to file
|
||||
*/
|
||||
@@ -183,8 +183,8 @@ public class Config implements ShutdownListener {
|
||||
Log.f3("Saving config.");
|
||||
propertyManager.save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get an option for key
|
||||
*
|
||||
@@ -197,14 +197,14 @@ public class Config implements ShutdownListener {
|
||||
if (propertyManager.getProperty(key) == null) {
|
||||
throw new IllegalArgumentException("No such property: " + key);
|
||||
}
|
||||
|
||||
|
||||
return propertyManager.getValue(key);
|
||||
} catch (final ClassCastException cce) {
|
||||
throw new RuntimeException("Property of incompatible type: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set option to a value. Call the save() method to make the change
|
||||
* permanent.
|
||||
@@ -217,11 +217,11 @@ public class Config implements ShutdownListener {
|
||||
if (propertyManager.getProperty(key) == null) {
|
||||
throw new IllegalArgumentException("No such property: " + key);
|
||||
}
|
||||
|
||||
|
||||
propertyManager.setValue(key, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add "key." before the given config file key
|
||||
*
|
||||
@@ -232,8 +232,8 @@ public class Config implements ShutdownListener {
|
||||
{
|
||||
return "key." + cfgKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get keystroke for name
|
||||
*
|
||||
@@ -246,11 +246,11 @@ public class Config implements ShutdownListener {
|
||||
if (kp == null) {
|
||||
throw new IllegalArgumentException("No such stroke: " + cfgKey);
|
||||
}
|
||||
|
||||
|
||||
return kp.getValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set a keystroke for name
|
||||
*
|
||||
@@ -264,13 +264,13 @@ public class Config implements ShutdownListener {
|
||||
if (kp == null) {
|
||||
throw new IllegalArgumentException("No such stroke: " + cfgKey);
|
||||
}
|
||||
|
||||
|
||||
kp.getValue().setTo(key, mod);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onShutdown(ShutdownEvent event)
|
||||
public void onShutdownRequested(ShutdownRequest event)
|
||||
{
|
||||
save(); // save changes done to the config
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import mightypork.utils.config.propmgr.Property;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class KeyStrokeProperty extends Property<KeyStroke> {
|
||||
|
||||
|
||||
/**
|
||||
* Make a keystroke property
|
||||
*
|
||||
@@ -28,32 +28,32 @@ public class KeyStrokeProperty extends Property<KeyStroke> {
|
||||
{
|
||||
super(key, defaultValue, comment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void fromString(String string)
|
||||
{
|
||||
if (string != null) {
|
||||
// keep the same instance
|
||||
|
||||
|
||||
final Key backup_key = value.getKey();
|
||||
final int backup_mod = value.getMod();
|
||||
|
||||
|
||||
value.loadFromString(string);
|
||||
if (value.getKey() == Keys.NONE) {
|
||||
value.setTo(backup_key, backup_mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return value.saveToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setValue(Object value)
|
||||
{
|
||||
|
||||
@@ -13,11 +13,11 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
*/
|
||||
@SingleReceiverEvent
|
||||
public class MainLoopRequest extends BusEvent<MainLoop> {
|
||||
|
||||
|
||||
private final Runnable task;
|
||||
private final boolean priority;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param task task to run on main thread in rendering context
|
||||
*/
|
||||
@@ -25,8 +25,8 @@ public class MainLoopRequest extends BusEvent<MainLoop> {
|
||||
{
|
||||
this(task, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param task task to run on main thread in rendering context
|
||||
* @param priority if true, skip other tasks in queue
|
||||
@@ -36,8 +36,8 @@ public class MainLoopRequest extends BusEvent<MainLoop> {
|
||||
this.task = task;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(MainLoop handler)
|
||||
{
|
||||
|
||||
+4
-17
@@ -15,26 +15,13 @@ import mightypork.utils.logging.Log;
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ShutdownEvent extends BusEvent<ShutdownListener> {
|
||||
|
||||
private final Runnable shutdownTask;
|
||||
|
||||
|
||||
/**
|
||||
* Make a shutdown event
|
||||
*
|
||||
* @param doShutdown Task that does the actual shutdown
|
||||
*/
|
||||
public ShutdownEvent(Runnable doShutdown)
|
||||
{
|
||||
this.shutdownTask = doShutdown;
|
||||
}
|
||||
public class ShutdownRequest extends BusEvent<ShutdownRequestListener> {
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleBy(ShutdownListener handler)
|
||||
protected void handleBy(ShutdownRequestListener handler)
|
||||
{
|
||||
handler.onShutdown(this);
|
||||
handler.onShutdownRequested(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +31,7 @@ public class ShutdownEvent extends BusEvent<ShutdownListener> {
|
||||
if (!isConsumed()) {
|
||||
Log.i("Shutting down...");
|
||||
|
||||
App.bus().send(new MainLoopRequest(shutdownTask, true));
|
||||
App.shutdown();
|
||||
|
||||
} else {
|
||||
Log.i("Shutdown aborted.");
|
||||
+4
-4
@@ -6,13 +6,13 @@ package mightypork.gamecore.core.events;
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface ShutdownListener {
|
||||
public interface ShutdownRequestListener {
|
||||
|
||||
/**
|
||||
* Intercept quit request.<br>
|
||||
* Consume the event to abort shutdown (ie. ask user to save)
|
||||
* Intercept shutdown request.<br>
|
||||
* Consume the event to abort shutdown (ie. ask user to save).
|
||||
*
|
||||
* @param event quit request event.
|
||||
*/
|
||||
void onShutdown(ShutdownEvent event);
|
||||
void onShutdownRequested(ShutdownRequest event);
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.utils.Reflect;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
* initialization sequence that takes care of task dependencies and ordering.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitSequence {
|
||||
|
||||
private final Map<String, InitTask> taskMap = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Add a task. If a task with the name already exists, replace it.
|
||||
*
|
||||
* @param task task to add
|
||||
*/
|
||||
public void addTask(InitTask task)
|
||||
{
|
||||
final String name = task.getName();
|
||||
|
||||
// detailed logging
|
||||
// if (taskMap.containsKey(name)) {
|
||||
// Log.f3("REPL init " + Str.pad("\"" + name + "\"", 20) + " <" + Str.val(task) + ">");
|
||||
// } else {
|
||||
// Log.f3("ADD init " + Str.pad("\"" + name + "\"", 20) + " <" + Str.val(task) + ">");
|
||||
// }
|
||||
|
||||
taskMap.put(name, task);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get task sequence in proper order.
|
||||
*
|
||||
* @return initialization sequence
|
||||
*/
|
||||
public List<InitTask> getSequence()
|
||||
{
|
||||
final List<InitTask> remainingTasks = new ArrayList<>(taskMap.values());
|
||||
|
||||
final List<InitTask> orderedTasks = new ArrayList<>();
|
||||
final Set<String> loadedTaskNames = new HashSet<>();
|
||||
|
||||
// resolve task order
|
||||
InitTask taskToAdd = null;
|
||||
do {
|
||||
taskToAdd = null;
|
||||
|
||||
for (final InitTask task : remainingTasks) {
|
||||
|
||||
String[] deps = task.getDependencies();
|
||||
if (deps == null) deps = new String[] {};
|
||||
|
||||
int missingDeps = deps.length;
|
||||
|
||||
for (final String d : deps) {
|
||||
if (loadedTaskNames.contains(d)) missingDeps--;
|
||||
}
|
||||
|
||||
if (missingDeps == 0) {
|
||||
if (taskToAdd == null || taskToAdd.getPriority() < task.getPriority()) {
|
||||
taskToAdd = task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (taskToAdd != null) {
|
||||
orderedTasks.add(taskToAdd);
|
||||
loadedTaskNames.add(taskToAdd.getName());
|
||||
remainingTasks.remove(taskToAdd);
|
||||
}
|
||||
|
||||
} while (taskToAdd != null);
|
||||
|
||||
checkLeftovers(loadedTaskNames, remainingTasks);
|
||||
|
||||
return orderedTasks;
|
||||
}
|
||||
|
||||
|
||||
public List<InitTask> getSequenceOldImpl()
|
||||
{
|
||||
final List<InitTask> remainingTasks = new ArrayList<>(taskMap.values());
|
||||
|
||||
final List<InitTask> orderedTasks = new ArrayList<>();
|
||||
final Set<String> loadedTaskNames = new HashSet<>();
|
||||
|
||||
// resolve task order
|
||||
int addedThisIteration = 0;
|
||||
do {
|
||||
addedThisIteration = 0;
|
||||
for (final Iterator<InitTask> i = remainingTasks.iterator(); i.hasNext();) {
|
||||
final InitTask task = i.next();
|
||||
|
||||
String[] deps = task.getDependencies();
|
||||
if (deps == null) deps = new String[] {};
|
||||
|
||||
int missingDeps = deps.length;
|
||||
|
||||
for (final String d : deps) {
|
||||
if (loadedTaskNames.contains(d)) missingDeps--;
|
||||
}
|
||||
|
||||
if (missingDeps == 0) {
|
||||
orderedTasks.add(task);
|
||||
loadedTaskNames.add(task.getName());
|
||||
i.remove();
|
||||
addedThisIteration++;
|
||||
}
|
||||
}
|
||||
} while (addedThisIteration > 0);
|
||||
|
||||
checkLeftovers(loadedTaskNames, remainingTasks);
|
||||
|
||||
return orderedTasks;
|
||||
}
|
||||
|
||||
|
||||
private void checkLeftovers(Collection<String> loadedTaskNames, Collection<InitTask> remainingTasks)
|
||||
{
|
||||
// check if any tasks are left out
|
||||
if (remainingTasks.size() > 0) {
|
||||
|
||||
// build error message for each bad task
|
||||
int badInitializers = 0;
|
||||
for (final InitTask task : remainingTasks) {
|
||||
|
||||
if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
badInitializers++;
|
||||
|
||||
String notSatisfied = "";
|
||||
|
||||
for (final String d : task.getDependencies()) {
|
||||
if (!loadedTaskNames.contains(d)) {
|
||||
|
||||
if (!notSatisfied.isEmpty()) {
|
||||
notSatisfied += ", ";
|
||||
}
|
||||
|
||||
notSatisfied += d;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied);
|
||||
}
|
||||
|
||||
if (badInitializers > 0) throw new RuntimeException("Some InitTask dependencies could not be satisfied.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,8 @@
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.gamecore.core.App;
|
||||
import mightypork.utils.Reflect;
|
||||
import mightypork.utils.annotations.Stub;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
@@ -21,11 +13,17 @@ import mightypork.utils.logging.Log;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InitTask {
|
||||
|
||||
|
||||
protected static final int PRIO_FIRST = Integer.MAX_VALUE;
|
||||
protected static final int PRIO_EARLY = 9000;
|
||||
protected static final int PRIO_DEFAULT = 0;
|
||||
protected static final int PRIO_LATE = -9000;
|
||||
protected static final int PRIO_LAST = Integer.MIN_VALUE;
|
||||
|
||||
/** App instance assigned using <code>bind()</code> */
|
||||
protected App app;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assign the initialized app instance to an "app" field.
|
||||
*
|
||||
@@ -35,8 +33,8 @@ public abstract class InitTask {
|
||||
{
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An init method that is called before the <code>run()</code> method.<br>
|
||||
* This method should be left unimplemented in the task, and can be used to
|
||||
@@ -47,8 +45,8 @@ public abstract class InitTask {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hook for extra action before the main task action.<br>
|
||||
* Can be overridden during app configuration to "bake-in" extra actions.
|
||||
@@ -58,14 +56,14 @@ public abstract class InitTask {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run the initializer on app.
|
||||
*/
|
||||
public abstract void run();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hook executed after the "run()" method.<br>
|
||||
* Can be overridden during app configuration to "bake-in" extra actions.
|
||||
@@ -75,8 +73,8 @@ public abstract class InitTask {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get name of this initializer (for dependency resolver).<br>
|
||||
* The name should be short, snake_case and precise.
|
||||
@@ -84,8 +82,8 @@ public abstract class InitTask {
|
||||
* @return name
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get what other initializers must be already loaded before this can load.<br>
|
||||
* Depending on itself or creating a circular dependency will cause error.<br>
|
||||
@@ -99,78 +97,17 @@ public abstract class InitTask {
|
||||
{
|
||||
return new String[] {};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Order init tasks so that all dependencies are loaded before thye are
|
||||
* needed by the tasks.
|
||||
* Get priority in the init sequence. Tasks with higher priority are loaded
|
||||
* earlier (but only after their dependencies are loaded).
|
||||
*
|
||||
* @param tasks task list
|
||||
* @return task list ordered
|
||||
* @return priority, higher = runs earlier
|
||||
*/
|
||||
public static List<InitTask> inOrder(List<InitTask> tasks)
|
||||
@Stub
|
||||
public int getPriority()
|
||||
{
|
||||
final List<InitTask> remaining = new ArrayList<>(tasks);
|
||||
|
||||
final List<InitTask> ordered = new ArrayList<>();
|
||||
final Set<String> loaded = new HashSet<>();
|
||||
|
||||
// resolve task order
|
||||
int addedThisIteration = 0;
|
||||
do {
|
||||
addedThisIteration = 0;
|
||||
for (final Iterator<InitTask> i = remaining.iterator(); i.hasNext();) {
|
||||
final InitTask task = i.next();
|
||||
|
||||
String[] deps = task.getDependencies();
|
||||
if (deps == null) deps = new String[] {};
|
||||
|
||||
int unmetDepsCount = deps.length;
|
||||
|
||||
for (final String d : deps) {
|
||||
if (loaded.contains(d)) unmetDepsCount--;
|
||||
}
|
||||
|
||||
if (unmetDepsCount == 0) {
|
||||
ordered.add(task);
|
||||
loaded.add(task.getName());
|
||||
i.remove();
|
||||
addedThisIteration++;
|
||||
}
|
||||
}
|
||||
} while (addedThisIteration > 0);
|
||||
|
||||
// check if any tasks are left out
|
||||
if (remaining.size() > 0) {
|
||||
|
||||
// build error message for each bad task
|
||||
int badInitializers = 0;
|
||||
for (final InitTask task : remaining) {
|
||||
if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
badInitializers++;
|
||||
|
||||
String notSatisfied = "";
|
||||
|
||||
for (final String d : task.getDependencies()) {
|
||||
if (!loaded.contains(d)) {
|
||||
|
||||
if (!notSatisfied.isEmpty()) {
|
||||
notSatisfied += ", ";
|
||||
}
|
||||
|
||||
notSatisfied += d;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied);
|
||||
}
|
||||
|
||||
if (badInitializers > 0) throw new RuntimeException("Some InitTask dependencies could not be satisfied.");
|
||||
}
|
||||
|
||||
return ordered;
|
||||
return PRIO_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import mightypork.gamecore.core.App;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize backend. The main point of postponing this is to make sure the
|
||||
* init is logged properly.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskBackend extends InitTask {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
App.instance().getBackend().initialize();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "backend";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
return new String[] { "log" };
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_EARLY;
|
||||
}
|
||||
}
|
||||
+9
-2
@@ -1,7 +1,7 @@
|
||||
package mightypork.gamecore.core.config;
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import mightypork.gamecore.core.init.InitTask;
|
||||
import mightypork.gamecore.core.config.Config;
|
||||
import mightypork.utils.annotations.Stub;
|
||||
|
||||
|
||||
@@ -72,4 +72,11 @@ public abstract class InitTaskConfig extends InitTask {
|
||||
return new String[] { "workdir" };
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_FIRST;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,14 +16,14 @@ import mightypork.utils.logging.Log;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskCrashHandler extends InitTask implements UncaughtExceptionHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Stub
|
||||
public void uncaughtException(Thread thread, Throwable throwable)
|
||||
@@ -31,11 +31,18 @@ public class InitTaskCrashHandler extends InitTask implements UncaughtExceptionH
|
||||
Log.e("The game has crashed.", throwable);
|
||||
App.shutdown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "crash_handler";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_FIRST;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,39 +8,39 @@ package mightypork.gamecore.core.init;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InitTaskCustom extends InitTask {
|
||||
|
||||
|
||||
private final String name;
|
||||
private final String[] deps;
|
||||
|
||||
|
||||
|
||||
|
||||
public InitTaskCustom(String name)
|
||||
{
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public InitTaskCustom(String name, String[] dependencies)
|
||||
{
|
||||
this.name = name;
|
||||
this.deps = dependencies;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void run();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
return deps;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import mightypork.gamecore.graphics.GraphicsModule;
|
||||
|
||||
|
||||
/**
|
||||
* Setup main window.
|
||||
* Setup main window / display with rendering context.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
|
||||
@@ -12,26 +12,26 @@ import mightypork.utils.math.algo.Move;
|
||||
|
||||
|
||||
/**
|
||||
* Register extra ionizables added by the game library (non-native ION types).<br>
|
||||
* This initializer can be called anywhere in the initialization sequence.
|
||||
* Register extra ionizables. More ionizables can be registered ie. in the
|
||||
* <code>after()</code> hook.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskIonizables extends InitTask {
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Ion.registerIndirect(255, new IonizerBinary<Coord>() {
|
||||
|
||||
|
||||
@Override
|
||||
public void save(Coord object, IonOutput out) throws IOException
|
||||
{
|
||||
out.writeInt(object.x);
|
||||
out.writeInt(object.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Coord load(IonInput in) throws IOException
|
||||
{
|
||||
@@ -39,19 +39,19 @@ public class InitTaskIonizables extends InitTask {
|
||||
final int y = in.readInt();
|
||||
return new Coord(x, y);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
Ion.registerIndirect(254, new IonizerBinary<Move>() {
|
||||
|
||||
|
||||
@Override
|
||||
public void save(Move object, IonOutput out) throws IOException
|
||||
{
|
||||
out.writeInt(object.x());
|
||||
out.writeInt(object.y());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Move load(IonInput in) throws IOException
|
||||
{
|
||||
@@ -59,15 +59,22 @@ public class InitTaskIonizables extends InitTask {
|
||||
final int y = in.readInt();
|
||||
return new Move(x, y);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "ionizables";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
public int getPriority()
|
||||
{
|
||||
return "ion";
|
||||
return PRIO_EARLY;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,28 +4,27 @@ package mightypork.gamecore.core.init;
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import mightypork.utils.Str;
|
||||
import mightypork.utils.files.WorkDir;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.logging.writers.LogWriter;
|
||||
import mightypork.utils.string.StringUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Init main logger and console log printing.<br>
|
||||
* Must be called after workdir is initialized.
|
||||
* Init logging system.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskLog extends InitTask {
|
||||
|
||||
private String logDir = "log";
|
||||
|
||||
private String logDir = ".";
|
||||
private String logName = "runtime";
|
||||
private int archiveCount = 5;
|
||||
|
||||
|
||||
private Level levelWrite = Level.ALL;
|
||||
private Level levelPrint = Level.ALL;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set log directory (relative to workdir).<br>
|
||||
* Defaults to "log".
|
||||
@@ -36,8 +35,8 @@ public class InitTaskLog extends InitTask {
|
||||
{
|
||||
this.logDir = logDir;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set log name. This name is used as a prefix for archived log files.<br>
|
||||
* Should contain only valid filename characters.<br>
|
||||
@@ -47,14 +46,14 @@ public class InitTaskLog extends InitTask {
|
||||
*/
|
||||
public void setLogName(String logName)
|
||||
{
|
||||
if (!StringUtil.isValidFilenameString(logName)) {
|
||||
if (!Str.isValidFilenameString(logName)) {
|
||||
throw new IllegalArgumentException("Invalid log name.");
|
||||
}
|
||||
|
||||
|
||||
this.logName = logName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set number of logs to keep in the logs directory.<br>
|
||||
* Set to 0 to keep just the last log, -1 to keep unlimited number of logs.<br>
|
||||
@@ -66,8 +65,8 @@ public class InitTaskLog extends InitTask {
|
||||
{
|
||||
this.archiveCount = archiveCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set logging levels (minimal level of message to be accepted)<br>
|
||||
* Defaults to ALL, ALL.
|
||||
@@ -80,8 +79,8 @@ public class InitTaskLog extends InitTask {
|
||||
this.levelWrite = levelWrite;
|
||||
this.levelPrint = levelPrint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -90,18 +89,25 @@ public class InitTaskLog extends InitTask {
|
||||
Log.setLevel(levelWrite);
|
||||
Log.setSysoutLevel(levelPrint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "log";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
return new String[] { "workdir" };
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_FIRST;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +49,11 @@ public class InitTaskLogHeader extends InitTask {
|
||||
{
|
||||
return new String[] { "log", "workdir" };
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_FIRST;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,52 @@
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import mightypork.gamecore.core.BasicMainLoop;
|
||||
import mightypork.gamecore.core.MainLoop;
|
||||
import mightypork.utils.annotations.Stub;
|
||||
|
||||
|
||||
/**
|
||||
* Task to add a resource loader.<br>
|
||||
* By default the async resource loader is used
|
||||
* Task to add a main loop.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InitTaskMainLoop extends InitTask {
|
||||
|
||||
/** The loader. */
|
||||
public class InitTaskMainLoop extends InitTask {
|
||||
|
||||
/** The loop, can be accessed in the after() method. */
|
||||
protected MainLoop loop;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
loop = getLoopImpl();
|
||||
app.setMainLoop(loop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a loader impl
|
||||
* Create a main loop
|
||||
*
|
||||
* @return loader
|
||||
*/
|
||||
protected abstract MainLoop getLoopImpl();
|
||||
|
||||
|
||||
@Stub
|
||||
protected MainLoop getLoopImpl()
|
||||
{
|
||||
return new BasicMainLoop();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "main_loop";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_EARLY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public abstract class InitTaskResourceLoader extends InitTask {
|
||||
{
|
||||
loader = getLoaderImpl();
|
||||
if (loader != null) loader.init();
|
||||
app.addChildClient(loader);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,13 +6,12 @@ import mightypork.gamecore.resources.loading.ResourceLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Task to add a resource loader.<br>
|
||||
* By default the async resource loader is used
|
||||
* Add Async resource loader.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskResourceLoaderAsync extends InitTaskResourceLoader {
|
||||
|
||||
|
||||
/**
|
||||
* Create a loader impl
|
||||
*
|
||||
@@ -21,10 +20,6 @@ public class InitTaskResourceLoaderAsync extends InitTaskResourceLoader {
|
||||
@Override
|
||||
protected ResourceLoader getLoaderImpl()
|
||||
{
|
||||
final AsyncResourceLoader loader = new AsyncResourceLoader();
|
||||
|
||||
// could now configure the loader
|
||||
|
||||
return loader;
|
||||
return new AsyncResourceLoader();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ import mightypork.gamecore.resources.loading.ResourceLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Task to add a resource loader.<br>
|
||||
* By default the async resource loader is used
|
||||
* Add no resource loader. That will cause resources to be loaded on-demand. May
|
||||
* cause lag if the resources are too large.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskResourceLoaderNone extends InitTaskResourceLoader {
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected ResourceLoader getLoaderImpl()
|
||||
{
|
||||
|
||||
@@ -11,24 +11,28 @@ import mightypork.gamecore.resources.ResourceInitializer;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InitTaskResources extends InitTask implements ResourceInitializer {
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Res.load(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "resources";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
// main loop handles resource load rewuests that run in rendering context
|
||||
// must be before, otherwise the requests would get lost.
|
||||
return new String[] { "resource_loader", "main_loop" };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import mightypork.gamecore.graphics.Renderable;
|
||||
|
||||
|
||||
/**
|
||||
* Task to init renderable screens (part of the main loop).<br>
|
||||
* Resources must already be ready.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InitTaskScreens extends InitTask {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
app.setMainRenderable(getMainRenderableImpl());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a loader impl
|
||||
*
|
||||
* @return loader
|
||||
*/
|
||||
protected abstract Renderable getMainRenderableImpl();
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "renderables";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
return new String[] { "resources", "main_loop" };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package mightypork.gamecore.core.init;
|
||||
|
||||
|
||||
import mightypork.gamecore.graphics.Renderable;
|
||||
import mightypork.gamecore.resources.Res;
|
||||
|
||||
|
||||
/**
|
||||
* Task to init main renderable (UI).<br>
|
||||
* Resources are already registered in {@link Res}.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InitTaskUI extends InitTask {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
app.setMainRenderable(createMainRenderable());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a loader impl
|
||||
*
|
||||
* @return loader
|
||||
*/
|
||||
protected abstract Renderable createMainRenderable();
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "ui";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
// main loop queues layout change events, would lose them otherwise
|
||||
return new String[] { "resources", "main_loop" };
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_LAST;
|
||||
}
|
||||
}
|
||||
@@ -133,4 +133,11 @@ public class InitTaskWorkdir extends InitTask {
|
||||
{
|
||||
return "workdir";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return PRIO_EARLY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ import mightypork.utils.eventbus.clients.BusNode;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class AppPlugin extends BusNode {
|
||||
|
||||
|
||||
/** App instance assigned using <code>bind()</code> */
|
||||
protected App app;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assign the initialized app instance to an "app" field.
|
||||
*
|
||||
@@ -28,8 +28,8 @@ public class AppPlugin extends BusNode {
|
||||
{
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the plugin for the given App.<br>
|
||||
* The plugin is already attached to the event bus.
|
||||
|
||||
@@ -12,10 +12,10 @@ import mightypork.utils.files.WorkDir;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class InitTaskPluginScreenshot extends InitTask {
|
||||
|
||||
|
||||
private String screenshotDir;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize to use the "screenshots" directory
|
||||
*/
|
||||
@@ -23,8 +23,8 @@ public class InitTaskPluginScreenshot extends InitTask {
|
||||
{
|
||||
this("screenshots");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize to use the given directory for saving.
|
||||
*
|
||||
@@ -34,8 +34,8 @@ public class InitTaskPluginScreenshot extends InitTask {
|
||||
{
|
||||
this.screenshotDir = dir;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set screenshot directory
|
||||
*
|
||||
@@ -45,33 +45,33 @@ public class InitTaskPluginScreenshot extends InitTask {
|
||||
{
|
||||
this.screenshotDir = dir;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
WorkDir.addPath("_screenshot_dir", screenshotDir);
|
||||
app.addPlugin(getPluginImpl());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected AppPlugin getPluginImpl()
|
||||
{
|
||||
return new ScreenshotPlugin();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "plugin_screenshot";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
return new String[] { "workdir" };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import mightypork.utils.Support;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ScreenshotPlugin extends AppPlugin implements ScreenshotRequestListener {
|
||||
|
||||
|
||||
/**
|
||||
* Take screenshot. Called by the trigger event.
|
||||
*/
|
||||
@@ -23,7 +23,7 @@ public class ScreenshotPlugin extends AppPlugin implements ScreenshotRequestList
|
||||
public void onScreenshotRequest()
|
||||
{
|
||||
App.bus().send(new MainLoopRequest(new Runnable() {
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
|
||||
@@ -12,11 +12,11 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
*/
|
||||
@SingleReceiverEvent
|
||||
public class ScreenshotRequest extends BusEvent<ScreenshotRequestListener> {
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleBy(ScreenshotRequestListener handler)
|
||||
{
|
||||
handler.onScreenshotRequest();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ package mightypork.gamecore.core.plugins.screenshot;
|
||||
|
||||
|
||||
public interface ScreenshotRequestListener {
|
||||
|
||||
|
||||
void onScreenshotRequest();
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ import mightypork.utils.logging.Log;
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class TaskTakeScreenshot implements Runnable {
|
||||
|
||||
|
||||
private final Screenshot scr;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Take screenshot. Must be called in render thread.
|
||||
*/
|
||||
@@ -30,16 +30,16 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
{
|
||||
scr = App.gfx().takeScreenshot();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// generate unique filename
|
||||
final File file = getScreenshotFile();
|
||||
|
||||
|
||||
Log.f3("Saving screenshot to file: " + file);
|
||||
|
||||
|
||||
// save to disk
|
||||
try {
|
||||
scr.save(file);
|
||||
@@ -47,8 +47,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
Log.e("Failed to save screenshot.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return File to save the screenshot to.
|
||||
*/
|
||||
@@ -57,8 +57,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
final String fname = getBaseFilename();
|
||||
return findFreeFile(fname);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return directory for screenshots
|
||||
*/
|
||||
@@ -66,8 +66,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
{
|
||||
return WorkDir.getDir("_screenshot_dir");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get base filename for the screenshot, without extension.
|
||||
*
|
||||
@@ -77,8 +77,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
{
|
||||
return Support.getTime("yyyy-MM-dd_HH-mm-ss");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find first free filename for the screenshot, by adding -NUMBER after the
|
||||
* base filename and before extension.
|
||||
@@ -97,5 +97,5 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
*/
|
||||
@SingleReceiverEvent
|
||||
public class FullscreenToggleRequest extends BusEvent<GraphicsModule> {
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleBy(GraphicsModule handler)
|
||||
{
|
||||
|
||||
@@ -22,23 +22,23 @@ import mightypork.utils.math.timing.FpsMeter;
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class GraphicsModule extends BackendModule {
|
||||
|
||||
|
||||
/** X axis vector */
|
||||
protected static final VectConst AXIS_X = Vect.make(1, 0, 0);
|
||||
/** Y axis vector */
|
||||
protected static final VectConst AXIS_Y = Vect.make(0, 1, 0);
|
||||
/** Z axis vector */
|
||||
protected static final VectConst AXIS_Z = Vect.make(0, 0, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set drawing color
|
||||
*
|
||||
* @param color color
|
||||
*/
|
||||
public abstract void setColor(Color color);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set drawing color, adjust alpha
|
||||
*
|
||||
@@ -46,8 +46,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param alpha alpha multiplier
|
||||
*/
|
||||
public abstract void setColor(Color color, double alpha);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Translate by x, y
|
||||
*
|
||||
@@ -55,8 +55,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param y y offset
|
||||
*/
|
||||
public abstract void translate(double x, double y);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Translate by x, y, z
|
||||
*
|
||||
@@ -65,24 +65,24 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param z z offset
|
||||
*/
|
||||
public abstract void translate(double x, double y, double z);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Translate by offset vector
|
||||
*
|
||||
* @param offset offset coordinate
|
||||
*/
|
||||
public abstract void translate(Vect offset);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Translate by offset vector, ignore Z
|
||||
*
|
||||
* @param offset offset coordinate
|
||||
*/
|
||||
public abstract void translateXY(Vect offset);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set scale for translations and coordinates
|
||||
*
|
||||
@@ -90,8 +90,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param y y scale
|
||||
*/
|
||||
public abstract void scale(double x, double y);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set scale for translations and coordinates
|
||||
*
|
||||
@@ -100,72 +100,72 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param z z scale
|
||||
*/
|
||||
public abstract void scale(double x, double y, double z);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set scale for translations and coordinates
|
||||
*
|
||||
* @param scale vector
|
||||
*/
|
||||
public abstract void scale(Vect scale);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set scale for translations and coordinates (same value for X and Y scale)
|
||||
*
|
||||
* @param scale scaling factor
|
||||
*/
|
||||
public abstract void scaleXY(double scale);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set X scale for translations and coordinates
|
||||
*
|
||||
* @param scale scaling factor
|
||||
*/
|
||||
public abstract void scaleX(double scale);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set Y scale for translations and coordinates
|
||||
*
|
||||
* @param scale scaling factor
|
||||
*/
|
||||
public abstract void scaleY(double scale);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set Z scale for translations and coordinates
|
||||
*
|
||||
* @param scale scaling factor
|
||||
*/
|
||||
public abstract void scaleZ(double scale);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rotate coordinate system around X axis
|
||||
*
|
||||
* @param angle rotation (in degrees)
|
||||
*/
|
||||
public abstract void rotateX(double angle);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rotate coordinate system around Y axis
|
||||
*
|
||||
* @param angle rotation (in degrees)
|
||||
*/
|
||||
public abstract void rotateY(double angle);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rotate coordinate system around Z axis
|
||||
*
|
||||
* @param angle rotation (in degrees)
|
||||
*/
|
||||
public abstract void rotateZ(double angle);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rotate coordinate system around given axis
|
||||
*
|
||||
@@ -173,54 +173,54 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param axis rotation axis (unit vector)
|
||||
*/
|
||||
public abstract void rotate(double angle, Vect axis);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Store render state on stack<br>
|
||||
* This includes pushGeometry and pushColor.
|
||||
*/
|
||||
public abstract void pushState();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Restore state from stack (must be pushed first)<br>
|
||||
* This includes popColor and popGeometry.
|
||||
*/
|
||||
public abstract void popState();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Store current rotation and translation on stack
|
||||
*/
|
||||
public abstract void pushGeometry();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Restore rotation and translation from stack
|
||||
*/
|
||||
public abstract void popGeometry();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Store color on stack (so it can later be restored)
|
||||
*/
|
||||
public abstract void pushColor();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Restore color from stack (must be pushed first)
|
||||
*/
|
||||
public abstract void popColor();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render 2D quad with currently set color
|
||||
*
|
||||
* @param rect drawn rect
|
||||
*/
|
||||
public abstract void quad(Rect rect);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render 2D quad with given color.<br>
|
||||
* This may change current drawing color.
|
||||
@@ -229,8 +229,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param color draw color
|
||||
*/
|
||||
public abstract void quad(Rect rect, Color color);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render 2D quad with gradient.<br>
|
||||
* This may change current drawing color.
|
||||
@@ -239,8 +239,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param grad gradient
|
||||
*/
|
||||
public abstract void quad(Rect rect, Grad grad);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render textured quad with current color
|
||||
*
|
||||
@@ -248,8 +248,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param txquad texture quad
|
||||
*/
|
||||
public abstract void quad(Rect rect, TxQuad txquad);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render textured quad with given color
|
||||
*
|
||||
@@ -258,14 +258,14 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param color color tint
|
||||
*/
|
||||
public abstract void quad(Rect rect, TxQuad txquad, Color color);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Setup projection for 2D graphics, using current screen size
|
||||
*/
|
||||
public abstract void setupProjection();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get backend-flavoured deferred PNG texture.
|
||||
*
|
||||
@@ -273,8 +273,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @return the deferred font
|
||||
*/
|
||||
public abstract DeferredTexture createTextureResource(String path);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get backend-flavoured deferred TTF font.
|
||||
*
|
||||
@@ -282,8 +282,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @return the deferred font
|
||||
*/
|
||||
public abstract DeferredFont createFontResource(String path);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get backend-flavoured deferred TTF font.
|
||||
*
|
||||
@@ -298,11 +298,11 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
final DeferredFont font = createFontResource(path);
|
||||
font.setChars(chars);
|
||||
font.setSize(size);
|
||||
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set target fps (for syncing in endFrame() call).<br>
|
||||
* With vsync enabled, the target fps may not be met.
|
||||
@@ -310,8 +310,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param fps requested fps
|
||||
*/
|
||||
public abstract void setTargetFps(int fps);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set fullscreen. The fullscreen state will be changed when possible (eg.
|
||||
* at the end of the current frame) and a {@link ViewportChangeEvent} will
|
||||
@@ -320,14 +320,14 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param fs true for fullscreen
|
||||
*/
|
||||
public abstract void setFullscreen(boolean fs);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Request fullscreen toggle. See setFullscreen() for more info)
|
||||
*/
|
||||
public abstract void switchFullscreen();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get fullscreen state (note that methods changing fullscreen may not have
|
||||
* immediate effect, so this method may report the old state if the
|
||||
@@ -336,8 +336,8 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @return is fullscreen
|
||||
*/
|
||||
public abstract boolean isFullscreen();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Take screenshot (expensive processing should be done in separate thread
|
||||
* when screenshot is saved).<br>
|
||||
@@ -346,20 +346,20 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @return screenshot object
|
||||
*/
|
||||
public abstract Screenshot takeScreenshot();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Start a render frame - clear buffers, prepare rendering context etc.
|
||||
*/
|
||||
public abstract void beginFrame();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* End a render frame: flip buffers, sync to fps...
|
||||
*/
|
||||
public abstract void endFrame();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set display dimensions
|
||||
*
|
||||
@@ -367,76 +367,76 @@ public abstract class GraphicsModule extends BackendModule {
|
||||
* @param height display height (pixels)
|
||||
*/
|
||||
public abstract void setSize(int width, int height);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set window titlebar text
|
||||
*
|
||||
* @param title titlebar text
|
||||
*/
|
||||
public abstract void setTitle(String title);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable VSync
|
||||
*
|
||||
* @param vsync true for vsync enabled
|
||||
*/
|
||||
public abstract void setVSync(boolean vsync);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set window resizable / fixed
|
||||
*
|
||||
* @param resizable true for resizable
|
||||
*/
|
||||
public abstract void setResizable(boolean resizable);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get screen rect. Should always return the same Rect instance.
|
||||
*
|
||||
* @return the rect
|
||||
*/
|
||||
public abstract Rect getRect();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get current FPS (eg. measured by a {@link FpsMeter})
|
||||
*
|
||||
* @return current FPS
|
||||
*/
|
||||
public abstract long getFps();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get screen center. Should always return the same {@link Vect} instance.
|
||||
*
|
||||
* @return screen center.
|
||||
*/
|
||||
public abstract Vect getCenter();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get screen size. Should always return the same {@link Vect} instance.
|
||||
*
|
||||
* @return size
|
||||
*/
|
||||
public abstract Vect getSize();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return screen width
|
||||
*/
|
||||
public abstract int getWidth();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return screen height
|
||||
*/
|
||||
public abstract int getHeight();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the display (window) based on current settings.
|
||||
*/
|
||||
|
||||
@@ -7,10 +7,10 @@ package mightypork.gamecore.graphics;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface Renderable {
|
||||
|
||||
|
||||
/**
|
||||
* Render on screen.
|
||||
*/
|
||||
void render();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.io.IOException;
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface Screenshot {
|
||||
|
||||
|
||||
/**
|
||||
* Process byte buffer and write image to a file.<br>
|
||||
* Image can be cached for future save.
|
||||
|
||||
@@ -11,42 +11,42 @@ import mightypork.gamecore.resources.BaseDeferredResource;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class DeferredFont extends BaseDeferredResource implements IFont {
|
||||
|
||||
|
||||
/**
|
||||
* Requested font size. For bitmap fonts, this should match the actual font
|
||||
* size (in pixels). The font can be scaled after loaded, but it may be
|
||||
* cached with this size.
|
||||
*/
|
||||
protected double size = 12;
|
||||
|
||||
|
||||
/** Requested font style. If not applicable, fall back to PLAIN */
|
||||
protected FontStyle style = FontStyle.PLAIN;
|
||||
|
||||
|
||||
/**
|
||||
* Chars that are required to be loaded in the font. A space glyph must be
|
||||
* also added when loading.
|
||||
*/
|
||||
protected String chars = Glyphs.basic;
|
||||
|
||||
|
||||
/** Requested filtering mode */
|
||||
protected FilterMode filter = FilterMode.NEAREST;
|
||||
|
||||
|
||||
/** Whether to use anti-aliasing for the font. */
|
||||
protected boolean antialias = false;
|
||||
|
||||
|
||||
/**
|
||||
* Ratio of the font to discard at the top (how much of the glyphs height is
|
||||
* blank from top)
|
||||
*/
|
||||
protected double discardTop = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Ratio of the font to discard at the bottom (how much of the glyphs height
|
||||
* is blank from bottom)
|
||||
*/
|
||||
protected double discardBottom = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a font from resource
|
||||
*
|
||||
@@ -56,8 +56,8 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
{
|
||||
super(resource);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set font size. If the font is backed by a texture, this is the size at
|
||||
* which the font is rendered to the texture. For bitmap fonts, this should
|
||||
@@ -69,8 +69,8 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set desired font style
|
||||
*
|
||||
@@ -80,8 +80,8 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
{
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set what chars are to be loaded. The space glyph will be loaded always.
|
||||
*
|
||||
@@ -91,8 +91,8 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
{
|
||||
this.chars = chars;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set texture filtering mode. For bitmap fonts, set to NEAREST.
|
||||
*
|
||||
@@ -102,8 +102,8 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
{
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to use antialiasing.
|
||||
*
|
||||
@@ -113,27 +113,27 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
{
|
||||
this.antialias = antialias;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void setDiscardRatio(double top, double bottom)
|
||||
{
|
||||
discardTop = top;
|
||||
discardBottom = bottom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final double getTopDiscardRatio()
|
||||
{
|
||||
return discardTop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final double getBottomDiscardRatio()
|
||||
{
|
||||
return discardBottom;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ import mightypork.utils.eventbus.clients.BusNode;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class FontRegistry extends BusNode {
|
||||
|
||||
|
||||
private final HashMap<String, IFont> fonts = new HashMap<>();
|
||||
private final HashMap<String, String> aliases = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load a {@link DeferredFont}
|
||||
*
|
||||
@@ -28,11 +28,11 @@ public class FontRegistry extends BusNode {
|
||||
public void addFont(String key, DeferredFont font)
|
||||
{
|
||||
App.bus().send(new ResourceLoadRequest(font));
|
||||
|
||||
|
||||
fonts.put(key, font);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a {@link IFont} to the bank.
|
||||
*
|
||||
@@ -43,8 +43,8 @@ public class FontRegistry extends BusNode {
|
||||
{
|
||||
fonts.put(key, font);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a font alias. Useful to specify fonts to use for various parts of the
|
||||
* app, without having to change the aliases throughout the app whenever the
|
||||
@@ -58,8 +58,8 @@ public class FontRegistry extends BusNode {
|
||||
{
|
||||
aliases.put(alias_key, font_key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a loaded {@link IFont}
|
||||
*
|
||||
@@ -69,14 +69,14 @@ public class FontRegistry extends BusNode {
|
||||
public IFont getFont(String key)
|
||||
{
|
||||
IFont f = fonts.get(key);
|
||||
|
||||
|
||||
if (f == null) f = fonts.get(aliases.get(key));
|
||||
|
||||
|
||||
if (f == null) {
|
||||
throw new RuntimeException("There's no font called " + key + "!");
|
||||
}
|
||||
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class FontRenderer {
|
||||
|
||||
|
||||
private IFont font;
|
||||
|
||||
|
||||
private Color color;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param font used font
|
||||
*/
|
||||
@@ -28,8 +28,8 @@ public class FontRenderer {
|
||||
{
|
||||
this(font, RGB.WHITE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param font used font
|
||||
* @param color drawing color
|
||||
@@ -39,8 +39,8 @@ public class FontRenderer {
|
||||
this.font = font;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get region needed to draw text at size
|
||||
*
|
||||
@@ -52,8 +52,8 @@ public class FontRenderer {
|
||||
{
|
||||
return font.getNeededSpace(text).mul(getScale(height));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get width needed to draw text at size
|
||||
*
|
||||
@@ -65,14 +65,14 @@ public class FontRenderer {
|
||||
{
|
||||
return getNeededSpace(text, height).x();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private double getScale(double height)
|
||||
{
|
||||
return height / font.getLineHeight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change drawing font
|
||||
*
|
||||
@@ -82,8 +82,8 @@ public class FontRenderer {
|
||||
{
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set drawing color
|
||||
*
|
||||
@@ -93,8 +93,8 @@ public class FontRenderer {
|
||||
{
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
@@ -106,18 +106,18 @@ public class FontRenderer {
|
||||
public void draw(String text, Vect pos, double height, Color color)
|
||||
{
|
||||
App.gfx().pushGeometry();
|
||||
|
||||
|
||||
final double sc = getScale(height);
|
||||
|
||||
|
||||
App.gfx().translate(pos.x(), pos.y());
|
||||
App.gfx().scaleXY(sc);
|
||||
|
||||
|
||||
font.draw(text, color);
|
||||
|
||||
|
||||
App.gfx().popGeometry();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
@@ -130,8 +130,8 @@ public class FontRenderer {
|
||||
{
|
||||
this.draw(text, bounds, align, this.color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
@@ -144,26 +144,26 @@ public class FontRenderer {
|
||||
public void draw(String text, Rect bounds, AlignX align, Color color)
|
||||
{
|
||||
Vect start;
|
||||
|
||||
|
||||
switch (align) {
|
||||
case LEFT:
|
||||
start = bounds.topLeft();
|
||||
break;
|
||||
|
||||
|
||||
case CENTER:
|
||||
start = bounds.topCenter();
|
||||
break;
|
||||
|
||||
|
||||
case RIGHT:
|
||||
default:
|
||||
start = bounds.topRight();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
draw(text, start, bounds.height().value(), align, color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
@@ -176,8 +176,8 @@ public class FontRenderer {
|
||||
{
|
||||
draw(text, pos, height, align, this.color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
@@ -189,27 +189,27 @@ public class FontRenderer {
|
||||
*/
|
||||
public void draw(String text, Vect pos, double height, AlignX align, Color color)
|
||||
{
|
||||
|
||||
|
||||
final double w = getWidth(text, height);
|
||||
|
||||
|
||||
Vect start;
|
||||
|
||||
|
||||
switch (align) {
|
||||
case LEFT:
|
||||
start = pos;
|
||||
break;
|
||||
|
||||
|
||||
case CENTER:
|
||||
start = pos.sub(w / 2D, 0);
|
||||
break;
|
||||
|
||||
|
||||
case RIGHT:
|
||||
default:
|
||||
start = pos.sub(w, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
draw(text, start, height, color);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ public enum FontStyle
|
||||
ITALIC(2),
|
||||
/** Bond and italic together */
|
||||
BOLD_ITALIC(1 + 2);
|
||||
|
||||
|
||||
/** Number associated with the style */
|
||||
public int numval;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Font style
|
||||
*
|
||||
|
||||
@@ -8,35 +8,35 @@ package mightypork.gamecore.graphics.fonts;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class Glyphs {
|
||||
|
||||
|
||||
/** A-Z a-z */
|
||||
public static final String latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
|
||||
/** Extra variants of latin glyphs */
|
||||
public static final String latin_extra = "ŒÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜŸÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĚŠČŘŽŤŇĎŮěščřžťňďůŁłđ";
|
||||
|
||||
|
||||
/** 0-9 */
|
||||
public static final String numbers = "0123456789";
|
||||
|
||||
|
||||
/** Commonly used punctuation symbols */
|
||||
public static final String punctuation = ".-,.?!:;\"'";
|
||||
|
||||
|
||||
/** Less common punctuation symbols */
|
||||
public static final String punctuation_extra = "()¿¡»«›‹“”‘’„…";
|
||||
|
||||
|
||||
/** Commonly used symbols (that are not included in punctuation) */
|
||||
public static final String symbols = "[]{}#$%&§*+/<=>@\\^_|~°";
|
||||
|
||||
|
||||
/** Less common symbols */
|
||||
public static final String symbols_extra = "¥€£¢`ƒ†‡ˆ‰•¤¦¨ªº¹²³¬¯±´µ¶·¸¼½¾×÷™©®→↓←↑";
|
||||
|
||||
|
||||
/** Latin, numbers, punctuation and symbols */
|
||||
public static final String basic = latin + numbers + punctuation + symbols;
|
||||
|
||||
|
||||
/** Extra glyphs to accompany "basic" */
|
||||
public static final String extra = latin_extra + punctuation_extra + symbols_extra;
|
||||
|
||||
|
||||
/** Basic + Extra */
|
||||
public static final String all = basic + extra;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface IFont {
|
||||
|
||||
|
||||
/**
|
||||
* Draw without scaling at (0, 0) in given color.
|
||||
*
|
||||
@@ -19,8 +19,8 @@ public interface IFont {
|
||||
* @param color draw color
|
||||
*/
|
||||
void draw(String text, Color color);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get suize needed to render give string
|
||||
*
|
||||
@@ -28,27 +28,27 @@ public interface IFont {
|
||||
* @return coord (width, height)
|
||||
*/
|
||||
Vect getNeededSpace(String text);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return font height
|
||||
*/
|
||||
int getLineHeight();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param text texted text
|
||||
* @return space needed
|
||||
*/
|
||||
int getWidth(String text);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return specified font size
|
||||
*/
|
||||
int getFontSize();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set what vertical ratio of the font size is blank and should be cut off
|
||||
* when rendering
|
||||
@@ -57,16 +57,16 @@ public interface IFont {
|
||||
* @param bottom bottom ratio (0-1)
|
||||
*/
|
||||
void setDiscardRatio(double top, double bottom);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get top discard ratio (blank unused space)
|
||||
*
|
||||
* @return ratio
|
||||
*/
|
||||
double getTopDiscardRatio();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get bottom discard ratio (blank unused space)
|
||||
*
|
||||
|
||||
@@ -15,13 +15,13 @@ import mightypork.utils.math.constraints.rect.Rect;
|
||||
@Alias(name = "Texture")
|
||||
@MustLoadInRenderingContext
|
||||
public abstract class DeferredTexture extends BaseDeferredResource implements ITexture {
|
||||
|
||||
|
||||
/** Used filtering mode */
|
||||
protected FilterMode filter = FilterMode.NEAREST;
|
||||
/** Used wrapping mode */
|
||||
protected WrapMode wrap = WrapMode.CLAMP;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param resourcePath resource path
|
||||
*/
|
||||
@@ -29,29 +29,29 @@ public abstract class DeferredTexture extends BaseDeferredResource implements IT
|
||||
{
|
||||
super(resourcePath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public TxQuad makeQuad(Rect uvs)
|
||||
{
|
||||
return new TxQuad(this, uvs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setFilter(FilterMode filterMin)
|
||||
{
|
||||
this.filter = filterMin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setWrap(WrapMode wrapping)
|
||||
{
|
||||
this.wrap = wrapping;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public QuadGrid grid(int x, int y)
|
||||
{
|
||||
|
||||
@@ -11,21 +11,21 @@ import mightypork.utils.math.constraints.rect.Rect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface ITexture extends Destroyable {
|
||||
|
||||
|
||||
/**
|
||||
* Set filter for scaling
|
||||
*
|
||||
* @param filter filter
|
||||
*/
|
||||
void setFilter(FilterMode filter);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param wrapping wrap mode
|
||||
*/
|
||||
void setWrap(WrapMode wrapping);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a quad from this texture of given position/size
|
||||
*
|
||||
@@ -33,8 +33,8 @@ public interface ITexture extends Destroyable {
|
||||
* @return the quad
|
||||
*/
|
||||
TxQuad makeQuad(Rect uvs);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a grid for given number of tiles
|
||||
*
|
||||
@@ -43,20 +43,20 @@ public interface ITexture extends Destroyable {
|
||||
* @return grid
|
||||
*/
|
||||
QuadGrid grid(int x, int y);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return source image width (corresponding to width01)
|
||||
*/
|
||||
int getImageWidth();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return source image height (corresponding to height01)
|
||||
*/
|
||||
int getImageHeight();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the image is RGBA
|
||||
*/
|
||||
|
||||
@@ -11,14 +11,14 @@ import mightypork.utils.math.constraints.rect.Rect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class QuadGrid {
|
||||
|
||||
|
||||
private final ITexture tx;
|
||||
private final int txHeight;
|
||||
private final int txWidth;
|
||||
private final double tileW;
|
||||
private final double tileH;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param tx backing texture
|
||||
* @param tilesX number of tile columns
|
||||
@@ -32,8 +32,8 @@ public class QuadGrid {
|
||||
this.tileW = 1D / tilesX;
|
||||
this.tileH = 1D / tilesY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make square quad at given coords (one grid cell)
|
||||
*
|
||||
@@ -46,11 +46,11 @@ public class QuadGrid {
|
||||
if (x < 0 || x >= txWidth || y < 0 || y >= txHeight) {
|
||||
throw new IndexOutOfBoundsException("Requested invalid txquad coordinates.");
|
||||
}
|
||||
|
||||
|
||||
return makeQuad(x, y, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make square quad at given coords, with arbitrary size. Coordinates are
|
||||
* multiples of cell size.
|
||||
@@ -66,15 +66,15 @@ public class QuadGrid {
|
||||
if (x < 0 || x >= txWidth || y < 0 || y >= txHeight) {
|
||||
throw new IndexOutOfBoundsException("Requested invalid txquad coordinates.");
|
||||
}
|
||||
|
||||
|
||||
if (x + width > txWidth || y + height > txHeight) {
|
||||
throw new IndexOutOfBoundsException("Requested invalid txquad size (would go beyond texture size).");
|
||||
}
|
||||
|
||||
|
||||
return tx.makeQuad(Rect.make(tileW * x, tileH * y, tileW * width, tileH * height));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a sheet.
|
||||
*
|
||||
@@ -89,11 +89,11 @@ public class QuadGrid {
|
||||
if (x < 0 || x >= txWidth || y < 0 || y >= txHeight) {
|
||||
throw new IndexOutOfBoundsException("Requested invalid txquad coordinates.");
|
||||
}
|
||||
|
||||
|
||||
if (x + width > txWidth || y + height > txHeight) {
|
||||
throw new IndexOutOfBoundsException("Requested invalid txsheet size (would go beyond texture size).");
|
||||
}
|
||||
|
||||
|
||||
return makeQuad(x, y).makeSheet(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ import mightypork.utils.math.constraints.rect.Rect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TextureRegistry {
|
||||
|
||||
|
||||
private final Map<String, ITexture> textures = new HashMap<>();
|
||||
private final Map<String, TxSheet> sheets = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load a texture from resource.
|
||||
*
|
||||
@@ -35,13 +35,13 @@ public class TextureRegistry {
|
||||
final DeferredTexture texture = App.gfx().createTextureResource(resourcePath);
|
||||
texture.setFilter(filter);
|
||||
texture.setWrap(wrap);
|
||||
|
||||
App.bus().send(new ResourceLoadRequest(texture));
|
||||
|
||||
App.bus().send(new ResourceLoadRequest(texture));
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load a texture from resource; if key is not null, the texture will be
|
||||
* added to the bank.
|
||||
@@ -55,18 +55,18 @@ public class TextureRegistry {
|
||||
public ITexture addTexture(String key, String resourcePath, FilterMode filter, WrapMode wrap)
|
||||
{
|
||||
if (key != null) if (textures.containsKey(key)) throw new KeyAlreadyExistsException();
|
||||
|
||||
|
||||
final ITexture texture = loadTexture(resourcePath, filter, wrap);
|
||||
|
||||
|
||||
if (key != null) {
|
||||
textures.put(key, texture);
|
||||
add(key, texture.makeQuad(Rect.ONE));
|
||||
}
|
||||
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add already created quad to the quad registry
|
||||
*
|
||||
@@ -76,11 +76,11 @@ public class TextureRegistry {
|
||||
public void add(String quadKey, TxQuad quad)
|
||||
{
|
||||
if (sheets.containsKey(quadKey)) throw new KeyAlreadyExistsException();
|
||||
|
||||
|
||||
sheets.put(quadKey, quad.makeSheet(1, 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an already created sheet
|
||||
*
|
||||
@@ -90,11 +90,11 @@ public class TextureRegistry {
|
||||
public void add(String sheetKey, TxSheet sheet)
|
||||
{
|
||||
if (sheets.containsKey(sheetKey)) throw new KeyAlreadyExistsException();
|
||||
|
||||
|
||||
sheets.put(sheetKey, sheet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a {@link TxQuad} for key; if it was added as sheet, the first quad
|
||||
* ofthe sheet is returned.
|
||||
@@ -106,8 +106,8 @@ public class TextureRegistry {
|
||||
{
|
||||
return getSheet(key).getQuad(0); // get the first
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a loaded {@link ITexture}
|
||||
*
|
||||
@@ -117,13 +117,13 @@ public class TextureRegistry {
|
||||
public ITexture getTexture(String key)
|
||||
{
|
||||
final ITexture tx = textures.get(key);
|
||||
|
||||
|
||||
if (tx == null) throw new RuntimeException("There's no texture called \"" + key + "\"!");
|
||||
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a {@link TxSheet} for key
|
||||
*
|
||||
@@ -133,12 +133,12 @@ public class TextureRegistry {
|
||||
public TxSheet getSheet(String key)
|
||||
{
|
||||
final TxSheet sh = sheets.get(key);
|
||||
|
||||
|
||||
if (sh == null) {
|
||||
throw new RuntimeException("There's no sheet called \"" + key + "\"!");
|
||||
}
|
||||
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ import mightypork.utils.math.constraints.rect.RectConst;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TxQuad {
|
||||
|
||||
|
||||
/** The texture */
|
||||
public final ITexture tx;
|
||||
/** Coords in texture (0-1) */
|
||||
public final RectConst uvs;
|
||||
|
||||
|
||||
private boolean flipX;
|
||||
private boolean flipY;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TxQuad from origin and size in pixels
|
||||
*
|
||||
@@ -35,11 +35,11 @@ public class TxQuad {
|
||||
{
|
||||
final double w = tx.getImageWidth();
|
||||
final double h = tx.getImageHeight();
|
||||
|
||||
|
||||
return fromSize(tx, xPx / w, yPx / h, widthPx / w, heightPx / h);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TxQuad from origin and size 0-1
|
||||
*
|
||||
@@ -54,8 +54,8 @@ public class TxQuad {
|
||||
{
|
||||
return new TxQuad(tx, x1, y1, x1 + width, y1 + height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make of coords
|
||||
*
|
||||
@@ -69,8 +69,8 @@ public class TxQuad {
|
||||
{
|
||||
this(tx, Rect.make(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param tx Texture
|
||||
* @param uvs Rect of texture UVs (0-1); will be frozen.
|
||||
@@ -80,8 +80,8 @@ public class TxQuad {
|
||||
this.tx = tx;
|
||||
this.uvs = uvs.freeze();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clone another
|
||||
*
|
||||
@@ -94,8 +94,8 @@ public class TxQuad {
|
||||
this.flipX = txQuad.flipX;
|
||||
this.flipY = txQuad.flipY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get copy
|
||||
*
|
||||
@@ -105,8 +105,8 @@ public class TxQuad {
|
||||
{
|
||||
return new TxQuad(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a sheet starting with this quad, spannign to right and down.
|
||||
*
|
||||
@@ -118,8 +118,8 @@ public class TxQuad {
|
||||
{
|
||||
return new TxSheet(this, (int) Math.round(width), (int) Math.round(height));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return copy flipped X
|
||||
*/
|
||||
@@ -129,8 +129,8 @@ public class TxQuad {
|
||||
copy.flipX ^= true;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return copy flipped Y
|
||||
*/
|
||||
@@ -140,8 +140,8 @@ public class TxQuad {
|
||||
copy.flipY ^= true;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the quad is to be rendered flipped vertically
|
||||
*/
|
||||
@@ -149,8 +149,8 @@ public class TxQuad {
|
||||
{
|
||||
return flipY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the quad is to be rendered flipped horizontally
|
||||
*/
|
||||
@@ -158,8 +158,8 @@ public class TxQuad {
|
||||
{
|
||||
return flipX;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Use the same flit/other attributes as the original txQuad
|
||||
*
|
||||
|
||||
@@ -13,16 +13,16 @@ import mightypork.utils.logging.Log;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TxSheet {
|
||||
|
||||
|
||||
private final TxQuad original;
|
||||
private final TxQuad[] sprites;
|
||||
private final int width;
|
||||
|
||||
|
||||
private final Random rand = new Random();
|
||||
private final Random randForSeed = new Random();
|
||||
private final int count;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a sprite sheet
|
||||
*
|
||||
@@ -35,11 +35,11 @@ public class TxSheet {
|
||||
this.original = tx;
|
||||
this.width = width;
|
||||
this.count = width * height;
|
||||
|
||||
|
||||
this.sprites = new TxQuad[count];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return number of quads
|
||||
*/
|
||||
@@ -47,8 +47,8 @@ public class TxSheet {
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a quad based on ratio 0-1 (0: first, 1: last)
|
||||
*
|
||||
@@ -59,8 +59,8 @@ public class TxSheet {
|
||||
{
|
||||
return getQuad((int) Math.round((count - 1) * ratio));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get quad of index
|
||||
*
|
||||
@@ -73,25 +73,25 @@ public class TxSheet {
|
||||
Log.w("Index out of bounds: " + index + ", allowed: 0.." + count);
|
||||
index = index % count;
|
||||
}
|
||||
|
||||
|
||||
// lazy - init only when needed
|
||||
if (sprites[index] == null) {
|
||||
final int x = index % width;
|
||||
final int y = index / width;
|
||||
|
||||
|
||||
final double origW = original.uvs.width().value();
|
||||
final double origH = original.uvs.height().value();
|
||||
|
||||
|
||||
final TxQuad txq = new TxQuad(original.tx, original.uvs.move(x * origW, y * origH));
|
||||
txq.dupeAttrs(original);
|
||||
|
||||
|
||||
sprites[index] = txq;
|
||||
}
|
||||
|
||||
|
||||
return sprites[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get entirely random TxQuad from this sheet
|
||||
*
|
||||
@@ -101,8 +101,8 @@ public class TxSheet {
|
||||
{
|
||||
return getQuad(rand.nextInt(count));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get random TxQuad from this sheet
|
||||
*
|
||||
@@ -114,8 +114,8 @@ public class TxSheet {
|
||||
randForSeed.setSeed(seed);
|
||||
return getQuad(randForSeed.nextInt(count));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get random TxQuad from this sheet
|
||||
*
|
||||
|
||||
@@ -10,10 +10,10 @@ import mightypork.utils.interfaces.Enableable;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class Action implements Runnable, Enableable {
|
||||
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enable the action
|
||||
*
|
||||
@@ -24,8 +24,8 @@ public abstract class Action implements Runnable, Enableable {
|
||||
{
|
||||
this.enabled = enable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if this action is enabled.
|
||||
*/
|
||||
@@ -34,8 +34,8 @@ public abstract class Action implements Runnable, Enableable {
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run the action, if it's enabled.
|
||||
*/
|
||||
@@ -44,11 +44,11 @@ public abstract class Action implements Runnable, Enableable {
|
||||
{
|
||||
if (enabled) execute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do the work.
|
||||
*/
|
||||
protected abstract void execute();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ import mightypork.utils.interfaces.Enableable;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ActionGroup implements Enableable {
|
||||
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
private final Set<Enableable> groupMembers = new HashSet<>();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
@@ -27,15 +27,15 @@ public class ActionGroup implements Enableable {
|
||||
for (final Enableable e : groupMembers)
|
||||
e.setEnabled(yes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an {@link Enableable} to the group
|
||||
*
|
||||
@@ -45,8 +45,8 @@ public class ActionGroup implements Enableable {
|
||||
{
|
||||
groupMembers.add(member);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Remove a group member
|
||||
*
|
||||
@@ -56,5 +56,5 @@ public class ActionGroup implements Enableable {
|
||||
{
|
||||
groupMembers.remove(member);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package mightypork.gamecore.gui;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface HasAction {
|
||||
|
||||
|
||||
/**
|
||||
* Assign an action
|
||||
*
|
||||
|
||||
@@ -5,7 +5,7 @@ import mightypork.gamecore.core.App;
|
||||
import mightypork.gamecore.graphics.Renderable;
|
||||
import mightypork.gamecore.gui.events.LayoutChangeEvent;
|
||||
import mightypork.gamecore.gui.events.LayoutChangeListener;
|
||||
import mightypork.utils.Support;
|
||||
import mightypork.utils.Str;
|
||||
import mightypork.utils.annotations.Stub;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.math.color.Color;
|
||||
@@ -23,15 +23,15 @@ import mightypork.utils.math.constraints.rect.proxy.RectProxy;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class BaseComponent extends AbstractRectCache implements Component, LayoutChangeListener {
|
||||
|
||||
|
||||
private Rect source;
|
||||
private boolean visible = true;
|
||||
private boolean enabled = true;
|
||||
private int indirectDisableLevel = 0;
|
||||
|
||||
|
||||
private Num alphaMul = Num.ONE;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a base component.<br>
|
||||
* By default, disable caching to avoid problems with updating. Caching can
|
||||
@@ -41,113 +41,113 @@ public abstract class BaseComponent extends AbstractRectCache implements Compone
|
||||
{
|
||||
enableCaching(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setRect(RectBound rect)
|
||||
{
|
||||
this.source = new RectProxy(rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isVisible()
|
||||
{
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void setVisible(boolean visible)
|
||||
{
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final Rect getCacheSource()
|
||||
{
|
||||
return source.round(); // round to avoid visual artifacts in fonts and such
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void render()
|
||||
{
|
||||
if (!isVisible()) return;
|
||||
|
||||
|
||||
Color.pushAlpha(alphaMul);
|
||||
renderComponent();
|
||||
Color.popAlpha();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void onLayoutChanged()
|
||||
{
|
||||
try {
|
||||
poll();
|
||||
} catch (final NullPointerException e) {
|
||||
Log.e("Component is missing a bounding rect, at: " + Support.str(getClass()));
|
||||
Log.e("Component is missing a bounding rect, at: " + Str.val(getClass()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void onConstraintChanged()
|
||||
{
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isMouseOver()
|
||||
{
|
||||
return App.input().getMousePos().isInside(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw the component (it's visible)
|
||||
*/
|
||||
protected abstract void renderComponent();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Stub
|
||||
public void updateLayout()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
enabled = yes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled && isIndirectlyEnabled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void setAlpha(Num alpha)
|
||||
{
|
||||
this.alphaMul = alpha;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void setAlpha(double alpha)
|
||||
{
|
||||
this.alphaMul = Num.make(alpha);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
@@ -157,15 +157,15 @@ public abstract class BaseComponent extends AbstractRectCache implements Compone
|
||||
if (indirectDisableLevel > 0) indirectDisableLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isIndirectlyEnabled()
|
||||
{
|
||||
return indirectDisableLevel == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDirectlyEnabled()
|
||||
{
|
||||
|
||||
@@ -12,43 +12,43 @@ import mightypork.utils.math.constraints.num.Num;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface Component extends Enableable, Hideable, PluggableRenderable {
|
||||
|
||||
|
||||
/**
|
||||
* Render the component, if it is visible.
|
||||
*/
|
||||
@Override
|
||||
void render();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The bounding rect was changed. The component should now update any cached
|
||||
* constraints derived from it.
|
||||
*/
|
||||
void updateLayout();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if mouse is currently over the component
|
||||
*/
|
||||
boolean isMouseOver();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set alpha multiplier for this and nested components
|
||||
*
|
||||
* @param alpha alpha multiplier (dynamic value)
|
||||
*/
|
||||
void setAlpha(Num alpha);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set alpha multiplier for this and nested components
|
||||
*
|
||||
* @param alpha alpha multiplier (constant value)
|
||||
*/
|
||||
void setAlpha(double alpha);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Indirectly enable / disable, used for nested hierarchies.<br>
|
||||
* When component is twice indirectly disabled, it needs to be twice
|
||||
@@ -57,8 +57,8 @@ public interface Component extends Enableable, Hideable, PluggableRenderable {
|
||||
* @param yes
|
||||
*/
|
||||
void setIndirectlyEnabled(boolean yes);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the compionent is not indirectly disabled. May still be directly
|
||||
* disabled.
|
||||
@@ -66,8 +66,8 @@ public interface Component extends Enableable, Hideable, PluggableRenderable {
|
||||
* @return indirectly enabled
|
||||
*/
|
||||
boolean isIndirectlyEnabled();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the component is directly enabled (set by setEnabled()). May
|
||||
* still be indirectly disabled.
|
||||
@@ -75,16 +75,16 @@ public interface Component extends Enableable, Hideable, PluggableRenderable {
|
||||
* @return directly enabled
|
||||
*/
|
||||
boolean isDirectlyEnabled();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set directly enabled (must be both directly and indirectly enabled to be
|
||||
* enabled completely)
|
||||
*/
|
||||
@Override
|
||||
public void setEnabled(boolean yes);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the component is both directly and indirectly enabled
|
||||
*
|
||||
|
||||
@@ -8,7 +8,7 @@ package mightypork.gamecore.gui.components;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface DynamicWidthComponent extends Component {
|
||||
|
||||
|
||||
/**
|
||||
* Get current width, if the element has specified height
|
||||
*
|
||||
|
||||
@@ -10,7 +10,7 @@ import mightypork.utils.eventbus.clients.ToggleableClient;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InputComponent extends BaseComponent implements ToggleableClient {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
|
||||
@@ -15,11 +15,11 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class LayoutComponent extends BaseComponent implements ClientHub {
|
||||
|
||||
|
||||
private final DelegatingList clientList;
|
||||
final LinkedList<Component> components = new LinkedList<>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Layout component with the given context (container)
|
||||
*
|
||||
@@ -31,8 +31,8 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
setRect(context);
|
||||
enableCaching(true); // layout is typically updated only when screen resizes.
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Component without context (can be assigned a context using
|
||||
* <code>setRect()</code>)
|
||||
@@ -41,56 +41,56 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<Object> getChildClients()
|
||||
{
|
||||
return clientList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
return clientList.doesDelegate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
return clientList.isListening();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addChildClient(Object client)
|
||||
{
|
||||
clientList.add(client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void removeChildClient(Object client)
|
||||
{
|
||||
clientList.remove(client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
if (isDirectlyEnabled() != yes) {
|
||||
super.setEnabled(yes);
|
||||
|
||||
|
||||
for (final Component c : components) {
|
||||
c.setIndirectlyEnabled(yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connect to bus and add to element list
|
||||
*
|
||||
@@ -102,12 +102,12 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
if (component == this) {
|
||||
throw new IllegalArgumentException("Uruboros. (infinite recursion evaded)");
|
||||
}
|
||||
|
||||
|
||||
components.add(component);
|
||||
addChildClient(component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renderComponent()
|
||||
{
|
||||
@@ -115,8 +115,8 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
cmp.render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void updateLayout()
|
||||
{
|
||||
@@ -124,13 +124,13 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
cmp.updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
super.setIndirectlyEnabled(yes);
|
||||
|
||||
|
||||
for (final Component cmp : components) {
|
||||
cmp.setIndirectlyEnabled(yes);
|
||||
}
|
||||
|
||||
@@ -15,36 +15,36 @@ import mightypork.utils.math.constraints.vect.proxy.VectAdapter;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class LinearComponent extends BaseComponent implements DynamicWidthComponent {
|
||||
|
||||
|
||||
private final Rect rect = new Rect() {
|
||||
|
||||
|
||||
@Override
|
||||
public Vect size()
|
||||
{
|
||||
return new Vect() {
|
||||
|
||||
|
||||
@Override
|
||||
public double x()
|
||||
{
|
||||
return computeWidth(y());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double y()
|
||||
{
|
||||
return height.value();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Vect origin()
|
||||
{
|
||||
return new VectAdapter() {
|
||||
|
||||
|
||||
@Override
|
||||
protected Vect getSource()
|
||||
{
|
||||
@@ -53,11 +53,11 @@ public abstract class LinearComponent extends BaseComponent implements DynamicWi
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Vect origin;
|
||||
private Num height;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a linear component
|
||||
*/
|
||||
@@ -65,15 +65,15 @@ public abstract class LinearComponent extends BaseComponent implements DynamicWi
|
||||
{
|
||||
super.setRect(rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setRect(RectBound rect)
|
||||
{
|
||||
throw new RuntimeException("Cannot assign a rect to a linear component. Set origin and height instead.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set component's height
|
||||
*
|
||||
@@ -83,8 +83,8 @@ public abstract class LinearComponent extends BaseComponent implements DynamicWi
|
||||
{
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set component's origin
|
||||
*
|
||||
|
||||
@@ -13,16 +13,16 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface PluggableRenderable extends Renderable, PluggableRectBound {
|
||||
|
||||
|
||||
@Override
|
||||
void render();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
Rect getRect();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
void setRect(RectBound rect);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,40 +9,40 @@ import mightypork.gamecore.input.events.MouseButtonHandler;
|
||||
|
||||
|
||||
public abstract class ClickableComponent extends InputComponent implements HasAction, MouseButtonHandler {
|
||||
|
||||
|
||||
protected boolean btnDownOver;
|
||||
private Action action;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setAction(Action action)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected void triggerAction()
|
||||
{
|
||||
if (action != null && isEnabled()) action.run();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(MouseButtonEvent event)
|
||||
{
|
||||
if (!event.isButtonEvent()) return;
|
||||
|
||||
|
||||
if (event.isDown()) {
|
||||
btnDownOver = event.isOver(this);
|
||||
}
|
||||
|
||||
|
||||
if (event.isUp()) {
|
||||
|
||||
|
||||
if (btnDownOver && event.isOver(this)) {
|
||||
triggerAction();
|
||||
event.consume();
|
||||
}
|
||||
|
||||
|
||||
btnDownOver = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,41 +9,41 @@ import mightypork.utils.eventbus.clients.DelegatingClient;
|
||||
|
||||
|
||||
public class ClickableWrapper extends ClickableComponent implements DelegatingClient {
|
||||
|
||||
|
||||
private final Component wrapped;
|
||||
private final ClientList list;
|
||||
|
||||
|
||||
|
||||
|
||||
public ClickableWrapper(Component wrapped)
|
||||
{
|
||||
this.wrapped = wrapped;
|
||||
wrapped.setRect(this);
|
||||
|
||||
|
||||
list = new ClientList(wrapped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<?> getChildClients()
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
wrapped.render();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
@@ -52,13 +52,13 @@ public class ClickableWrapper extends ClickableComponent implements DelegatingCl
|
||||
wrapped.setIndirectlyEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
super.setIndirectlyEnabled(yes);
|
||||
wrapped.setIndirectlyEnabled(yes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,31 +18,31 @@ import mightypork.utils.math.constraints.vect.var.VectVar;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TextButton extends ClickableComponent implements DynamicWidthComponent {
|
||||
|
||||
|
||||
public final TextPainter textPainter;
|
||||
|
||||
|
||||
private final VectVar offset = Vect.makeVar();
|
||||
|
||||
|
||||
public Vect offsetPassive = height().div(16).toVectXY();
|
||||
public Vect offsetOver = height().div(20).toVectXY();
|
||||
public Vect offsetUnder = height().div(32).toVectXY();
|
||||
|
||||
|
||||
private final Color color;
|
||||
|
||||
|
||||
private boolean hoverMove = true;
|
||||
|
||||
|
||||
|
||||
|
||||
public TextButton(IFont font, String text, Color color)
|
||||
{
|
||||
this.color = color;
|
||||
|
||||
|
||||
this.textPainter = new TextPainter(font, AlignX.CENTER, this.color, text);
|
||||
this.textPainter.setRect(this);
|
||||
this.textPainter.setShadow(RGB.BLACK_30, offset);
|
||||
textPainter.setVPaddingPercent(5);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
@@ -55,11 +55,11 @@ public class TextButton extends ClickableComponent implements DynamicWidthCompon
|
||||
} else {
|
||||
offset.setTo(offsetPassive);
|
||||
}
|
||||
|
||||
|
||||
textPainter.render();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disable offset change on hover
|
||||
*/
|
||||
@@ -67,12 +67,12 @@ public class TextButton extends ClickableComponent implements DynamicWidthCompon
|
||||
{
|
||||
hoverMove = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
return textPainter.computeWidth(height);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,37 +6,37 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
|
||||
|
||||
public class ColumnLayout extends GridLayout {
|
||||
|
||||
|
||||
private int col = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
public ColumnLayout(int rows)
|
||||
{
|
||||
this(null, rows);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public ColumnLayout(RectBound context, int cols)
|
||||
{
|
||||
super(context, 1, cols);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add(final Component elem)
|
||||
{
|
||||
add(elem, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add(final Component elem, int colSpan)
|
||||
{
|
||||
if (elem == null) return;
|
||||
|
||||
|
||||
put(elem, 0, col, 1, colSpan);
|
||||
col += colSpan;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void skip(int cols)
|
||||
{
|
||||
col += cols;
|
||||
|
||||
@@ -12,18 +12,18 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ConstraintLayout extends LayoutComponent {
|
||||
|
||||
|
||||
public ConstraintLayout()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public ConstraintLayout(RectBound context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a component to the layout.<br>
|
||||
* The component's rect must be set up manually.
|
||||
@@ -34,5 +34,5 @@ public class ConstraintLayout extends LayoutComponent {
|
||||
{
|
||||
attach(component);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class FlowColumnLayout extends LayoutComponent {
|
||||
|
||||
|
||||
private int col = 0;
|
||||
private Num elementWidth;
|
||||
private final AlignX align;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param context context
|
||||
* @param elementWidth width of all elements
|
||||
@@ -31,13 +31,13 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
super(context);
|
||||
this.elementWidth = elementWidth;
|
||||
this.align = align;
|
||||
|
||||
|
||||
if (align != AlignX.LEFT && align != AlignX.RIGHT) {
|
||||
throw new IllegalArgumentException("Can align only left or right.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* make a new holder.<br>
|
||||
* Context must be assigned before rendering.
|
||||
@@ -49,8 +49,8 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
{
|
||||
this(null, elementWidth, align);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an item
|
||||
*
|
||||
@@ -59,9 +59,9 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
public void add(final Component elem)
|
||||
{
|
||||
if (elem == null) return;
|
||||
|
||||
|
||||
final Rect r;
|
||||
|
||||
|
||||
switch (align) {
|
||||
case LEFT:
|
||||
r = leftEdge().growRight(elementWidth).moveX(elementWidth.mul(col++));
|
||||
@@ -72,16 +72,16 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad align.");
|
||||
}
|
||||
|
||||
|
||||
elem.setRect(r);
|
||||
|
||||
|
||||
attach(elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setElementWidth(Num elementWidth)
|
||||
{
|
||||
this.elementWidth = elementWidth;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class FlowRowLayout extends LayoutComponent {
|
||||
|
||||
|
||||
private int row = 0;
|
||||
private Num elementHeight;
|
||||
private final AlignY align;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param context context
|
||||
* @param elementHeight height of all elements
|
||||
@@ -31,13 +31,13 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
super(context);
|
||||
this.elementHeight = elementHeight;
|
||||
this.align = align;
|
||||
|
||||
|
||||
if (align != AlignY.TOP && align != AlignY.BOTTOM) {
|
||||
throw new IllegalArgumentException("Can align only to top or bottom.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* make a new holder.<br>
|
||||
* Context must be assigned before rendering.
|
||||
@@ -49,8 +49,8 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
{
|
||||
this(null, elementHeight, align);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an item
|
||||
*
|
||||
@@ -59,9 +59,9 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
public void add(final Component elem)
|
||||
{
|
||||
if (elem == null) return;
|
||||
|
||||
|
||||
final Rect r;
|
||||
|
||||
|
||||
switch (align) {
|
||||
case TOP:
|
||||
r = topEdge().growDown(elementHeight).moveY(elementHeight.mul(row++));
|
||||
@@ -72,13 +72,13 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad align.");
|
||||
}
|
||||
|
||||
|
||||
elem.setRect(r);
|
||||
|
||||
|
||||
attach(elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setElementHeight(Num elementHeight)
|
||||
{
|
||||
this.elementHeight = elementHeight;
|
||||
|
||||
@@ -13,10 +13,10 @@ import mightypork.utils.math.constraints.rect.builders.TiledRect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class GridLayout extends LayoutComponent {
|
||||
|
||||
|
||||
private final TiledRect tiler;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param context context
|
||||
* @param rows number of rows
|
||||
@@ -27,8 +27,8 @@ public class GridLayout extends LayoutComponent {
|
||||
super(context);
|
||||
this.tiler = tiles(cols, rows);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* make a new holder.<br>
|
||||
* Context must be assigned before rendering.
|
||||
@@ -40,8 +40,8 @@ public class GridLayout extends LayoutComponent {
|
||||
{
|
||||
this(null, rows, cols);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a row to the holder.
|
||||
*
|
||||
@@ -52,13 +52,13 @@ public class GridLayout extends LayoutComponent {
|
||||
public void put(Component elem, int row, int column)
|
||||
{
|
||||
if (elem == null) return;
|
||||
|
||||
|
||||
elem.setRect(tiler.tile(column, row));
|
||||
|
||||
|
||||
attach(elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put with span
|
||||
*
|
||||
@@ -71,10 +71,10 @@ public class GridLayout extends LayoutComponent {
|
||||
public void put(Component elem, int row, int column, int rowspan, int colspan)
|
||||
{
|
||||
if (elem == null) return;
|
||||
|
||||
|
||||
elem.setRect(tiler.span(column, row, colspan, rowspan));
|
||||
|
||||
|
||||
attach(elem);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import mightypork.gamecore.gui.components.BaseComponent;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class NullComponent extends BaseComponent {
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
|
||||
@@ -6,37 +6,37 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
|
||||
|
||||
public class RowLayout extends GridLayout {
|
||||
|
||||
|
||||
private int row = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
public RowLayout(int rows)
|
||||
{
|
||||
this(null, rows);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public RowLayout(RectBound context, int rows)
|
||||
{
|
||||
super(context, rows, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add(final Component elem)
|
||||
{
|
||||
add(elem, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add(final Component elem, int rowSpan)
|
||||
{
|
||||
if (elem == null) return;
|
||||
|
||||
|
||||
put(elem, row, 0, rowSpan, 1);
|
||||
row += rowSpan;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void skip(int rows)
|
||||
{
|
||||
row += rows;
|
||||
|
||||
@@ -15,11 +15,11 @@ import mightypork.utils.eventbus.clients.DelegatingClient;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class AbstractLinearWrapper extends LinearComponent implements DelegatingClient {
|
||||
|
||||
|
||||
protected final Component wrapped;
|
||||
private final ClientList list;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param wrapped wrapped component. Can be null.
|
||||
*/
|
||||
@@ -34,32 +34,32 @@ public abstract class AbstractLinearWrapper extends LinearComponent implements D
|
||||
wrapped.setRect(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
list = new ClientList(wrapped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
if (wrapped != null) wrapped.render();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<?> getChildClients()
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
@@ -68,8 +68,8 @@ public abstract class AbstractLinearWrapper extends LinearComponent implements D
|
||||
wrapped.setIndirectlyEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
|
||||
@@ -11,13 +11,13 @@ import mightypork.utils.math.constraints.num.Num;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class LinearGap extends LinearRectangle {
|
||||
|
||||
|
||||
public LinearGap(Num width)
|
||||
{
|
||||
super(new NullComponent(), width);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public LinearGap(double heightPercent)
|
||||
{
|
||||
this(Num.ZERO);
|
||||
|
||||
@@ -20,27 +20,27 @@ import mightypork.utils.math.constraints.vect.proxy.VectAdapter;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class LinearLayout extends LayoutComponent {
|
||||
|
||||
|
||||
public LinearLayout(AlignX align)
|
||||
{
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public LinearLayout(RectBound context, AlignX align)
|
||||
{
|
||||
super(context);
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
|
||||
private final NumSum totalWidth = new NumSum();
|
||||
|
||||
|
||||
private final Vect leftAlignOrigin = LinearLayout.this.origin();
|
||||
private final Vect centerAlignOrigin = LinearLayout.this.topCenter().sub(totalWidth.half(), Num.ZERO);
|
||||
private final Vect rightAlignOrigin = LinearLayout.this.topRight().sub(totalWidth, Num.ZERO);
|
||||
|
||||
|
||||
private final Vect leftMostOrigin = new VectAdapter() {
|
||||
|
||||
|
||||
@Override
|
||||
protected Vect getSource()
|
||||
{
|
||||
@@ -55,18 +55,18 @@ public class LinearLayout extends LayoutComponent {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Vect nextOrigin = leftMostOrigin;
|
||||
|
||||
|
||||
private AlignX align = AlignX.LEFT;
|
||||
|
||||
|
||||
|
||||
|
||||
public void add(DynamicWidthComponent dwcomp)
|
||||
{
|
||||
add(new LinearWrapper(dwcomp));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add(LinearComponent lincomp)
|
||||
{
|
||||
lincomp.setHeight(height());
|
||||
@@ -75,14 +75,14 @@ public class LinearLayout extends LayoutComponent {
|
||||
totalWidth.addSummand(lincomp.width());
|
||||
attach(lincomp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setAlign(AlignX align)
|
||||
{
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a gap.
|
||||
*
|
||||
|
||||
@@ -6,27 +6,27 @@ import mightypork.utils.math.constraints.num.Num;
|
||||
|
||||
|
||||
public class LinearRectangle extends AbstractLinearWrapper {
|
||||
|
||||
|
||||
private Num width;
|
||||
|
||||
|
||||
|
||||
|
||||
public LinearRectangle(Component wrapped, Num width)
|
||||
{
|
||||
super(wrapped);
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setWidth(Num width)
|
||||
{
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
return this.width.value();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ import mightypork.gamecore.gui.components.Component;
|
||||
|
||||
|
||||
public class LinearSquare extends AbstractLinearWrapper {
|
||||
|
||||
|
||||
public LinearSquare(Component wrapped)
|
||||
{
|
||||
super(wrapped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ import mightypork.gamecore.gui.components.DynamicWidthComponent;
|
||||
|
||||
|
||||
public class LinearWrapper extends AbstractLinearWrapper {
|
||||
|
||||
|
||||
public LinearWrapper(DynamicWidthComponent wrapped)
|
||||
{
|
||||
super(wrapped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
return ((DynamicWidthComponent) wrapped).computeWidth(height);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import mightypork.gamecore.gui.components.DynamicWidthComponent;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ImagePainter extends BaseComponent implements DynamicWidthComponent {
|
||||
|
||||
|
||||
private TxQuad txQuad;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param txQuad drawn image
|
||||
*/
|
||||
@@ -24,22 +24,22 @@ public class ImagePainter extends BaseComponent implements DynamicWidthComponent
|
||||
{
|
||||
this.txQuad = txQuad;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renderComponent()
|
||||
{
|
||||
App.gfx().quad(this, txQuad);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
return (height / txQuad.uvs.height().value()) * txQuad.uvs.width().value();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set drawn {@link TxQuad}
|
||||
*
|
||||
|
||||
@@ -14,23 +14,23 @@ import mightypork.utils.math.color.Grad;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class QuadPainter extends BaseComponent {
|
||||
|
||||
|
||||
@FactoryMethod
|
||||
public static QuadPainter gradH(Color colorLeft, Color colorRight)
|
||||
{
|
||||
return new QuadPainter(colorLeft, colorRight, colorRight, colorLeft);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@FactoryMethod
|
||||
public static QuadPainter gradV(Color colorTop, Color colorBottom)
|
||||
{
|
||||
return new QuadPainter(colorTop, colorTop, colorBottom, colorBottom);
|
||||
}
|
||||
|
||||
|
||||
private final Grad grad;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Painter with solid color
|
||||
*
|
||||
@@ -40,8 +40,8 @@ public class QuadPainter extends BaseComponent {
|
||||
{
|
||||
this.grad = new Grad(color, color, color, color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Painter with coloured vertices.
|
||||
*
|
||||
@@ -54,8 +54,8 @@ public class QuadPainter extends BaseComponent {
|
||||
{
|
||||
this.grad = new Grad(leftTop, rightTop, rightBottom, leftBottom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renderComponent()
|
||||
{
|
||||
|
||||
@@ -22,20 +22,20 @@ import mightypork.utils.string.StringWrapper;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TextPainter extends BaseComponent implements DynamicWidthComponent {
|
||||
|
||||
|
||||
private static final boolean DEBUG_FONT_RENDER = false;
|
||||
private final FontRenderer font;
|
||||
private Color color;
|
||||
private AlignX align;
|
||||
private StringProvider text;
|
||||
private boolean shadow;
|
||||
|
||||
|
||||
private double yPaddingPerc = 0;
|
||||
|
||||
|
||||
private Color shadowColor = RGB.BLACK;
|
||||
private Vect shadowOffset = Vect.make(2, 2);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param font font to use
|
||||
*/
|
||||
@@ -43,32 +43,32 @@ public class TextPainter extends BaseComponent implements DynamicWidthComponent
|
||||
{
|
||||
this(font, AlignX.LEFT, RGB.WHITE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public TextPainter(IFont font, Color color, String text)
|
||||
{
|
||||
this(font, AlignX.LEFT, color, new StringWrapper(text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public TextPainter(IFont font, Color color, StringProvider text)
|
||||
{
|
||||
this(font, AlignX.LEFT, color, text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public TextPainter(IFont font, Color color)
|
||||
{
|
||||
this(font, AlignX.LEFT, color, (StringProvider) null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public TextPainter(IFont font, AlignX align, Color color, String text)
|
||||
{
|
||||
this(font, align, color, new StringWrapper(text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public TextPainter(IFont font, AlignX align, Color color, StringProvider text)
|
||||
{
|
||||
this.font = new FontRenderer(font);
|
||||
@@ -76,92 +76,92 @@ public class TextPainter extends BaseComponent implements DynamicWidthComponent
|
||||
this.align = align;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public TextPainter(IFont font, AlignX align, Color color)
|
||||
{
|
||||
this(font, align, color, (StringProvider) null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renderComponent()
|
||||
{
|
||||
if (text == null) return;
|
||||
|
||||
|
||||
final String str = text.getString();
|
||||
|
||||
|
||||
final Num shrY = height().perc(yPaddingPerc);
|
||||
|
||||
|
||||
final Rect rect = getRect().shrink(Num.ZERO, shrY);
|
||||
|
||||
|
||||
if (shadow) {
|
||||
font.draw(str, rect.round(), align, shadowColor);
|
||||
}
|
||||
|
||||
|
||||
final Rect r = (shadow ? rect.move(shadowOffset.neg()) : rect).round();
|
||||
font.draw(str, r, align, color);
|
||||
|
||||
|
||||
if (DEBUG_FONT_RENDER) App.gfx().quad(r, RGB.PINK.withAlpha(0.4));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setShadow(Color color, Vect offset)
|
||||
{
|
||||
setShadow(true);
|
||||
setShadowColor(color);
|
||||
setShadowOffset(offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setShadow(boolean shadow)
|
||||
{
|
||||
this.shadow = shadow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setShadowColor(Color shadowColor)
|
||||
{
|
||||
this.shadowColor = shadowColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setShadowOffset(Vect shadowOffset)
|
||||
{
|
||||
this.shadowOffset = shadowOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setColor(Color color)
|
||||
{
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setAlign(AlignX align)
|
||||
{
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setText(String text)
|
||||
{
|
||||
this.text = new StringWrapper(text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setText(StringProvider text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setVPaddingPercent(double percY)
|
||||
{
|
||||
yPaddingPerc = percY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ import mightypork.utils.eventbus.events.flags.NonRejectableEvent;
|
||||
@NonConsumableEvent
|
||||
@NonRejectableEvent
|
||||
public class LayoutChangeEvent extends BusEvent<LayoutChangeListener> {
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(LayoutChangeListener handler)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ package mightypork.gamecore.gui.events;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface LayoutChangeListener {
|
||||
|
||||
|
||||
/**
|
||||
* Triggered when display size changed and GUI should be recalculated.
|
||||
*/
|
||||
|
||||
@@ -13,10 +13,10 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
*/
|
||||
@SingleReceiverEvent
|
||||
public class ScreenRequest extends BusEvent<ScreenRequestListener> {
|
||||
|
||||
|
||||
private final String scrName;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a request to change screen
|
||||
*
|
||||
@@ -26,12 +26,12 @@ public class ScreenRequest extends BusEvent<ScreenRequestListener> {
|
||||
{
|
||||
scrName = screenKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(ScreenRequestListener handler)
|
||||
{
|
||||
handler.showScreen(scrName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package mightypork.gamecore.gui.events;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface ScreenRequestListener {
|
||||
|
||||
|
||||
/**
|
||||
* @param key screen to show
|
||||
*/
|
||||
|
||||
@@ -15,10 +15,10 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
@NonConsumableEvent
|
||||
@NotLoggedEvent
|
||||
public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> {
|
||||
|
||||
|
||||
private final Vect screenSize;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param size new screen size
|
||||
*/
|
||||
@@ -26,8 +26,8 @@ public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> {
|
||||
{
|
||||
this.screenSize = size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return new screen size
|
||||
*/
|
||||
@@ -35,8 +35,8 @@ public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> {
|
||||
{
|
||||
return screenSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(ViewportChangeListener handler)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ package mightypork.gamecore.gui.events;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface ViewportChangeListener {
|
||||
|
||||
|
||||
/**
|
||||
* Handle event
|
||||
*
|
||||
|
||||
@@ -17,36 +17,36 @@ import mightypork.utils.eventbus.clients.DelegatingClient;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class LayeredScreen extends Screen {
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for delegating client, to use custom client ordering.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
private class LayersClient implements DelegatingClient {
|
||||
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public Collection getChildClients()
|
||||
{
|
||||
return layersByEventPriority;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private final List<ScreenLayer> layersByZIndex = new ArrayList<>();
|
||||
private final List<ScreenLayer> layersByEventPriority = new ArrayList<>();
|
||||
|
||||
|
||||
private final LayersClient layersClient = new LayersClient();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a layered screen
|
||||
*/
|
||||
@@ -54,8 +54,8 @@ public abstract class LayeredScreen extends Screen {
|
||||
{
|
||||
addChildClient(layersClient);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderScreen()
|
||||
{
|
||||
@@ -63,8 +63,8 @@ public abstract class LayeredScreen extends Screen {
|
||||
if (layer.isVisible()) layer.render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a layer to the screen.
|
||||
*
|
||||
@@ -74,29 +74,29 @@ public abstract class LayeredScreen extends Screen {
|
||||
{
|
||||
this.layersByZIndex.add(layer);
|
||||
this.layersByEventPriority.add(layer);
|
||||
|
||||
|
||||
Collections.sort(layersByEventPriority, new Comparator<Overlay>() {
|
||||
|
||||
|
||||
@Override
|
||||
public int compare(Overlay o1, Overlay o2)
|
||||
{
|
||||
return o2.getEventPriority() - o1.getEventPriority();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
Collections.sort(layersByZIndex, new Comparator<Overlay>() {
|
||||
|
||||
|
||||
@Override
|
||||
public int compare(Overlay o1, Overlay o2)
|
||||
{
|
||||
return o1.getZIndex() - o2.getZIndex();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onScreenEnter()
|
||||
{
|
||||
@@ -104,8 +104,8 @@ public abstract class LayeredScreen extends Screen {
|
||||
layer.onScreenEnter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onScreenLeave()
|
||||
{
|
||||
@@ -113,5 +113,5 @@ public abstract class LayeredScreen extends Screen {
|
||||
layer.onScreenLeave();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -29,62 +29,62 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class Overlay extends BusNode implements Comparable<Overlay>, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener {
|
||||
|
||||
|
||||
private boolean visible = true;
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
private final KeyBindingPool keybindings = new KeyBindingPool();
|
||||
|
||||
|
||||
/** Root layout, rendered and attached to the event bus. */
|
||||
protected final ConstraintLayout root;
|
||||
|
||||
|
||||
/** Constraint: Mouse position. */
|
||||
protected final Vect mouse;
|
||||
|
||||
|
||||
/** Extra rendered items (outside root) */
|
||||
protected final Collection<Renderable> rendered = new ArrayList<>();
|
||||
|
||||
|
||||
/** Extra updated items (not members of the component tree) */
|
||||
protected final Collection<Updateable> updated = new ArrayList<>();
|
||||
private Num alphaMul = Num.ONE;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create an overlay over the screen
|
||||
*/
|
||||
public Overlay()
|
||||
{
|
||||
this.mouse = App.input().getMousePos();
|
||||
|
||||
|
||||
this.root = new ConstraintLayout(App.gfx().getRect());
|
||||
addChildClient(root);
|
||||
addChildClient(keybindings);
|
||||
|
||||
|
||||
rendered.add(root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void bindKey(KeyStroke stroke, Trigger edge, Runnable task)
|
||||
{
|
||||
keybindings.bindKey(stroke, edge, task);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void unbindKey(KeyStroke stroke)
|
||||
{
|
||||
keybindings.unbindKey(stroke);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isVisible()
|
||||
{
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible)
|
||||
{
|
||||
@@ -93,8 +93,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
root.setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
@@ -103,15 +103,15 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
root.setEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get rendering layer
|
||||
*
|
||||
@@ -119,8 +119,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
*/
|
||||
@Stub
|
||||
public abstract int getZIndex();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get event bus listening priority - useful to block incoming events.
|
||||
*
|
||||
@@ -130,8 +130,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
{
|
||||
return getZIndex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render the overlay. The caller MUST check for visibility himself.
|
||||
*/
|
||||
@@ -139,34 +139,34 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
public void render()
|
||||
{
|
||||
if (!isVisible()) return;
|
||||
|
||||
|
||||
Color.pushAlpha(alphaMul);
|
||||
for (final Renderable r : rendered) {
|
||||
r.render();
|
||||
}
|
||||
|
||||
|
||||
Color.popAlpha();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
if (!isEnabled()) return;
|
||||
|
||||
|
||||
for (final Updateable u : updated) {
|
||||
u.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Overlay o)
|
||||
{
|
||||
return o.getEventPriority() - getEventPriority();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Screen size changed.
|
||||
@@ -182,8 +182,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
public void onLayoutChanged()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set overlay's alpha multiplier
|
||||
*
|
||||
@@ -193,8 +193,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
{
|
||||
this.alphaMul = alpha;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set overlay's alpha multiplier
|
||||
*
|
||||
@@ -204,8 +204,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
{
|
||||
this.alphaMul = Num.make(alpha);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Show and set enabled
|
||||
*/
|
||||
@@ -214,8 +214,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
setVisible(true);
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hide and set disabled
|
||||
*/
|
||||
@@ -224,15 +224,15 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
setVisible(false);
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
return (isVisible() || isEnabled());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
|
||||
@@ -21,13 +21,13 @@ import mightypork.utils.math.constraints.rect.RectBound;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class Screen extends BusNode implements Renderable, RectBound, KeyBinder, LayoutChangeListener {
|
||||
|
||||
|
||||
private final KeyBindingPool keybindings = new KeyBindingPool();
|
||||
|
||||
|
||||
private volatile boolean active;
|
||||
private volatile boolean needSetupViewport = false;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a screen. The screen will initially not listen to the bus, which is
|
||||
* changed once the setActive method is set to true.
|
||||
@@ -36,31 +36,31 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
{
|
||||
// disable events initially
|
||||
setListening(false);
|
||||
|
||||
|
||||
addChildClient(keybindings);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void fireLayoutChangeEvent()
|
||||
{
|
||||
App.bus().sendDirectToChildren(this, new LayoutChangeEvent());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void bindKey(KeyStroke stroke, Trigger edge, Runnable task)
|
||||
{
|
||||
keybindings.bindKey(stroke, edge, task);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void unbindKey(KeyStroke stroke)
|
||||
{
|
||||
keybindings.unbindKey(stroke);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prepare for being shown
|
||||
*
|
||||
@@ -71,24 +71,24 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
if (shown) {
|
||||
active = true;
|
||||
needSetupViewport = true;
|
||||
|
||||
|
||||
fireLayoutChangeEvent();
|
||||
onScreenEnter();
|
||||
|
||||
|
||||
// enable events
|
||||
setListening(true);
|
||||
|
||||
|
||||
} else {
|
||||
onScreenLeave();
|
||||
|
||||
|
||||
active = false;
|
||||
|
||||
|
||||
// disable events
|
||||
setListening(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if screen is the current screen
|
||||
*/
|
||||
@@ -96,41 +96,41 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onLayoutChanged()
|
||||
{
|
||||
if (!isActive()) return;
|
||||
|
||||
|
||||
needSetupViewport = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final Rect getRect()
|
||||
{
|
||||
return App.gfx().getRect();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void render()
|
||||
{
|
||||
if (!isActive()) return;
|
||||
|
||||
|
||||
if (needSetupViewport) {
|
||||
App.gfx().setupProjection();
|
||||
}
|
||||
|
||||
|
||||
App.gfx().pushState();
|
||||
|
||||
|
||||
renderScreen();
|
||||
|
||||
|
||||
App.gfx().popState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen becomes active
|
||||
*/
|
||||
@@ -139,8 +139,8 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen is no longer active
|
||||
*/
|
||||
@@ -149,11 +149,11 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render screen contents (context is ready for 2D rendering)
|
||||
*/
|
||||
protected abstract void renderScreen();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import mightypork.utils.annotations.Stub;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class ScreenLayer extends Overlay {
|
||||
|
||||
|
||||
private final Screen screen;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param screen parent screen
|
||||
*/
|
||||
@@ -21,8 +21,8 @@ public abstract class ScreenLayer extends Overlay {
|
||||
{
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return parent screen instance
|
||||
*/
|
||||
@@ -30,8 +30,8 @@ public abstract class ScreenLayer extends Overlay {
|
||||
{
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen becomes active
|
||||
*/
|
||||
@@ -39,8 +39,8 @@ public abstract class ScreenLayer extends Overlay {
|
||||
protected void onScreenEnter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen is no longer active
|
||||
*/
|
||||
|
||||
@@ -22,12 +22,12 @@ import mightypork.utils.logging.Log;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ScreenRegistry extends BusNode implements ScreenRequestListener, ViewportChangeListener, Renderable {
|
||||
|
||||
|
||||
private final Map<String, Screen> screens = new HashMap<>();
|
||||
private final Collection<Overlay> overlays = new TreeSet<>();
|
||||
private volatile Screen active = null;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a screen
|
||||
*
|
||||
@@ -39,8 +39,8 @@ public class ScreenRegistry extends BusNode implements ScreenRequestListener, Vi
|
||||
screens.put(name, screen);
|
||||
addChildClient(screen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an overlay
|
||||
*
|
||||
@@ -51,56 +51,56 @@ public class ScreenRegistry extends BusNode implements ScreenRequestListener, Vi
|
||||
overlays.add(overlay);
|
||||
addChildClient(overlay);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void showScreen(String key)
|
||||
{
|
||||
Log.f3("Request to show screen \"" + key + "\"");
|
||||
|
||||
|
||||
// find screen to show
|
||||
final Screen toShow = screens.get(key);
|
||||
if (toShow == null) {
|
||||
throw new RuntimeException("Screen " + key + " not defined.");
|
||||
}
|
||||
|
||||
|
||||
// deactivate last screen
|
||||
if (active != null) {
|
||||
active.setActive(false);
|
||||
}
|
||||
|
||||
|
||||
// activate new screen
|
||||
toShow.setActive(true);
|
||||
|
||||
|
||||
active = toShow;
|
||||
|
||||
|
||||
fireLayoutUpdateEvent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void render()
|
||||
{
|
||||
if (active != null) {
|
||||
active.render();
|
||||
|
||||
|
||||
for (final Overlay overlay : overlays) {
|
||||
if (overlay.isVisible()) overlay.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewportChanged(ViewportChangeEvent event)
|
||||
{
|
||||
if (active != null) fireLayoutUpdateEvent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void fireLayoutUpdateEvent()
|
||||
{
|
||||
App.bus().sendDirectToChildren(this, new LayoutChangeEvent());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@ import mightypork.utils.math.timing.TimedTask;
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class CrossfadeOverlay extends Overlay {
|
||||
|
||||
|
||||
private static final double T_IN = 0.4;
|
||||
private static final double T_OUT = 0.6;
|
||||
|
||||
|
||||
NumAnimated alpha = new NumAnimated(0);
|
||||
String requestedScreenName;
|
||||
|
||||
|
||||
TimedTask revealTask = new TimedTask() {
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -39,8 +39,8 @@ public class CrossfadeOverlay extends Overlay {
|
||||
alpha.fadeOut(T_OUT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create new crossfade overlay
|
||||
*/
|
||||
@@ -49,21 +49,21 @@ public class CrossfadeOverlay extends Overlay {
|
||||
final QuadPainter qp = new QuadPainter(RGB.BLACK); // TODO allow custom colors
|
||||
qp.setRect(root);
|
||||
root.add(qp);
|
||||
|
||||
|
||||
updated.add(alpha);
|
||||
updated.add(revealTask);
|
||||
|
||||
|
||||
setAlpha(alpha);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getZIndex()
|
||||
{
|
||||
return 10000; // not too high, so app can put something on top
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Go to specified screen
|
||||
*
|
||||
@@ -73,21 +73,21 @@ public class CrossfadeOverlay extends Overlay {
|
||||
public void goToScreen(String screen, boolean fromDark)
|
||||
{
|
||||
requestedScreenName = screen;
|
||||
|
||||
|
||||
if (screen == null) {
|
||||
// going for halt
|
||||
App.sound().fadeOutAllLoops();
|
||||
}
|
||||
|
||||
|
||||
if (fromDark) {
|
||||
alpha.setTo(1);
|
||||
revealTask.run();
|
||||
} else {
|
||||
revealTask.start(T_IN);
|
||||
|
||||
|
||||
alpha.setEasing(Easing.SINE_IN);
|
||||
alpha.fadeIn(T_IN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user