package com.gdx.musicevents; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.JsonWriter; import com.badlogic.gdx.utils.ObjectMap; import com.gdx.musicevents.effects.StartEffect; import com.gdx.musicevents.effects.StopEffect; public class MusicEventManager { /** * Container for serialization purposes. */ private static class Container { transient String basePath = "./"; Array<MusicState> states; public Container() { } private Container(Array<MusicState> states) { this.states = states; } } private Container container = new Container(); /** * The events that the manager is able to respond to. */ private final ObjectMap<String, MusicState> states = new ObjectMap<String, MusicState>(); /** * The current event. */ private MusicState currentState; /** * Listeners in the event tool. */ private final Array<MusicEventListener> listeners = new Array<MusicEventListener>(); /** * The transitions in progress. */ private final Array<StartEffect> startTransitions = new Array<StartEffect>(); private StartEffect currentStartEffect; private final Array<StopEffect> endTransitions = new Array<StopEffect>(); private StopEffect currentEndEffect; /** * Play the state using an enum. * * @param stateName */ public void play(Enum<?> stateName) { play(stateName.name()); } public void play(String stateName) { final MusicState nextState = states.get(stateName); play(nextState); } public void play(MusicState nextState) { if (currentState != null && !currentState.isPlaying()) { currentState = null; } if (currentState != nextState) { final MusicState oldState = currentState; currentState = nextState; handleTransition(currentState, oldState); } } private void handleTransition(MusicState nextState, MusicState previousState) { startTransitions.add(nextState.enter(previousState)); if (previousState != null) { endTransitions.add(previousState.exit(nextState)); } for (int i = 0; i < listeners.size; i++) { final MusicEventListener observer = listeners.get(i); observer.stateChanged(nextState, previousState); } } /** * Update the music event manager. * * @param dt * The raw un-interpolated un-averaged delta time. */ public void update(float dt) { if(currentStartEffect != null){ currentStartEffect.update(dt); if (currentStartEffect.isDone()) { currentStartEffect = null; } } else if(startTransitions.size > 0) { currentStartEffect = startTransitions.first(); startTransitions.removeIndex(0); currentStartEffect.beginStart(); } if(currentEndEffect != null){ currentEndEffect.update(dt); if (currentEndEffect.isDone()) { currentEndEffect = null; } } else if(endTransitions.size > 0) { currentEndEffect = endTransitions.first(); currentEndEffect.beginStop(); endTransitions.removeIndex(0); } if (currentState != null) { currentState.update(dt); } } /** * Add a state. * * @param state * The state object. */ public void add(MusicState state) { state.init(container.basePath); this.states.put(state.getName(), state); for (int i = 0; i < listeners.size; i++) { final MusicEventListener observer = listeners.get(i); observer.stateAdded(state); } } /** * Remove an event. * * @param state * The state object. */ public void remove(MusicState state) { remove(state.getName()); } /** * Remove an event. * * @param stateName * The name of the event. */ public void remove(String stateName) { final MusicState event = this.states.remove(stateName); if (event != null) { for (final ObjectMap.Entry<String, MusicState> entry : this.states) { entry.value.removeEnterTransition(stateName); entry.value.removeExitTransition(stateName); } event.dispose(); if (currentState == event) { currentState = null; } for (int i = 0; i < listeners.size; i++) { final MusicEventListener observer = listeners.get(i); observer.stateRemoved(event); } } } /** * Create a new project. * * @param handle The base path. */ public void create(FileHandle handle){ this.clear(); container = new Container(); container.basePath = handle.path(); } /** * Save to a file. * * @param fileName * The path to the file. */ public void save(FileHandle file) { final Json json = new Json(JsonWriter.OutputType.json); final Container container = new Container(states.values().toArray()); file.writeString(json.prettyPrint(container), false); } /** * Load a save file. * * @param fileName * The path to the file. */ public void load(FileHandle file) { this.clear(); final Json json = new Json(JsonWriter.OutputType.json); container = json.fromJson(Container.class, file.readString()); String path = file.path(); int lastSlash = path.lastIndexOf("/"); container.basePath = path.substring(0, lastSlash); for (int i = 0; i < container.states.size; i++) { final MusicState state = container.states.get(i); add(state); } } /** * Access the current state. * * @return The state that is playing. */ public MusicState getCurrentState() { return currentState; } /** * Set the current state. * * @param musicState */ public void setCurrentState(MusicState musicState) { final MusicState oldState = currentState; this.currentState = musicState; this.handleTransition(this.currentState, oldState); } /** * Stop playing the current event. */ public void stop() { if (this.currentState != null) { currentState.stop(); } } /** * Clear the manager. Removes all events. */ public void clear() { final Array<MusicState> stateArray = states.values().toArray(); for (final MusicState state : stateArray) { state.dispose(); for (int i = 0; i < listeners.size; i++) { final MusicEventListener observer = listeners.get(i); observer.stateRemoved(state); } } states.clear(); } /** * Add observer to the manager. * * @param listener */ public void addListener(MusicEventListener listener) { this.listeners.add(listener); } /** * Remove observer from the manager. * * @param listener */ public void removeListener(MusicEventListener listener) { this.listeners.removeValue(listener, true); } /** * Access all events in the system. * * @return Copy of all events in the system. */ public Array<MusicState> getEvents() { return states.values().toArray(); } public String getBasePath() { return container.basePath; } }