package tk.amberide.ide.data.res;
import tk.amberide.engine.al.Audio;
import tk.amberide.ide.data.Workspace;
import tk.amberide.ide.data.io.FileIO;
import tk.amberide.engine.gl.model.obj.WavefrontObject;
import tk.amberide.ide.gui.misc.ErrorHandler;
import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import static tk.amberide.ide.data.res.ResourceListener.*;
import static tk.amberide.ide.data.res.Resource.*;
import tk.amberide.engine.gl.model.obj.Material;
/**
*
* @author Tudor
*/
public abstract class AbstractResourceManager implements IResourceManager {
protected Workspace workspace;
protected File imgDir, audioDir, modelDir;
protected HashMap<String, Resource<Tileset>> tilesets = new HashMap<String, Resource<Tileset>>();
protected HashMap<String, Resource<Audio>> clips = new HashMap<String, Resource<Audio>>();
protected HashMap<String, Resource<WavefrontObject>> models = new HashMap<String, Resource<WavefrontObject>>();
protected ArrayList<IResourceListener> listeners = new ArrayList<IResourceListener>();
/**
* Constructs a new AbstractResourceManager object for the given Workspace
*
* @param space the Workspace
*/
public AbstractResourceManager(Workspace space) {
workspace = space;
imgDir = new File(workspace.getDataDirectory(), "graphics");
if (!imgDir.exists()) {
imgDir.mkdir();
}
audioDir = new File(workspace.getDataDirectory(), "audio");
if (!audioDir.exists()) {
audioDir.mkdir();
}
modelDir = new File(workspace.getDataDirectory(), "models");
if (!modelDir.exists()) {
modelDir.mkdir();
}
}
public void importTileset(String name, Tileset sheet, File source) {
Resource<Tileset> resource = new Resource<Tileset>(sheet, name, source, Resource.TILESET);
tilesets.put(name, resource);
doCopy(resource, imgDir);
emitResourcesSafe();
for (IResourceListener listener : listeners) {
listener.tilesetImported(resource);
}
}
public void removeTileset(String name) {
Resource<Tileset> removed = tilesets.remove(name);
doDelete(name, imgDir);
emitResourcesSafe();
for (IResourceListener listener : listeners) {
listener.tilesetRemoved(removed);
}
}
public void importAudio(String name, Audio clip, File source) {
Resource<Audio> resource = new Resource<Audio>(clip, name, source, Resource.AUDIO);
clips.put(name, resource);
doCopy(resource, audioDir);
emitResourcesSafe();
for (IResourceListener listener : listeners) {
listener.audioImported(resource);
}
}
public void removeAudio(String name) {
Resource<Audio> removed = clips.remove(name);
doDelete(name, audioDir);
emitResourcesSafe();
for (IResourceListener listener : listeners) {
listener.audioRemoved(removed);
}
}
public void importModel(String name, WavefrontObject model, File source) {
Resource<WavefrontObject> resource = new Resource<WavefrontObject>(model, name, source, Resource.MODEL);
models.put(name, resource);
try {
File objDir = new File(modelDir, name);
objDir.mkdirs();
File to = new File(objDir, name + "." + FileIO.getFileExtension(source));
if (!to.equals(source)) {
FileIO.copy(source, to);
File context = source.getParentFile();
for (Material m : model.getMaterials().values()) {
FileIO.copy(new File(context, m.getTextureName()), new File(objDir, m.getTextureName()));
}
File mtllib = model.getMaterialsFile();
if (mtllib != null) {
FileIO.copy(mtllib, new File(objDir, mtllib.getName()));
}
}
} catch (Exception ex) {
ErrorHandler.alert(ex);
}
emitResourcesSafe();
for (IResourceListener listener : listeners) {
listener.modelImported(resource);
}
}
public void removeModel(String name) {
Resource<WavefrontObject> removed = models.remove(name);
doDelete(name, modelDir);
emitResourcesSafe();
for (IResourceListener listener : listeners) {
listener.modelRemoved(removed);
}
}
public Tileset getTileset(String name) {
Resource<Tileset> res = getTilesetResource(name);
return res != null ? res.get() : null;
}
public Audio getAudio(String name) {
Resource<Audio> res = getAudioResource(name);
return res != null ? res.get() : null;
}
public WavefrontObject getModel(String name) {
Resource<WavefrontObject> res = getModelResource(name);
return res != null ? res.get() : null;
}
public Resource<Tileset> getTilesetResource(String name) {
return tilesets.get(name);
}
public Resource<Audio> getAudioResource(String name) {
return clips.get(name);
}
public Resource<WavefrontObject> getModelResource(String name) {
return models.get(name);
}
private void doCopy(Resource res, File dir) {
try {
File from = res.getSource();
File to = new File(dir, res.getName() + "." + FileIO.getFileExtension(res.getSource()));
if (!from.equals(to)) {
FileIO.copy(from, to);
}
} catch (Exception ex) {
ErrorHandler.alert(ex);
}
}
private void doDelete(String name, File dir) {
try {
FileIO.getFilesByName(name, dir)[0].delete();
} catch (Exception ex) {
ErrorHandler.alert(ex);
}
}
public Collection<Resource<Tileset>> getTilesets() {
return tilesets.values();
}
public Collection<Resource<Audio>> getClips() {
return clips.values();
}
public Collection<Resource<WavefrontObject>> getModels() {
return models.values();
}
public Collection<IResourceListener> getResourceListeners() {
return listeners;
}
public void addResourceListener(IResourceListener listener) {
listeners.add(listener);
}
public void removeResourceListener(IResourceListener listener) {
listeners.remove(listener);
}
public void registerResourceListener(Object listener) {
Object parent = null;
Class owner = listener instanceof Class ? (Class) listener : (parent = listener).getClass();
for (Method m : owner.getDeclaredMethods()) {
ResourceListener rl = m.getAnnotation(ResourceListener.class);
if (rl
!= null) {
if ((Modifier.isStatic(m.getModifiers()) && parent == null) || parent != null) {
listeners.add(new ReflectiveResourceListener(m, parent, rl.type(), rl.event()));
}
}
}
}
public void unregisterResourceListener(Object listener) {
Object parent = null;
Class owner = listener instanceof Class ? (Class) listener : (parent = listener).getClass();
for (int i = 0; i != listeners.size(); i++) {
IResourceListener l = listeners.get(i);
if (l instanceof ReflectiveResourceListener) {
ReflectiveResourceListener rrl = (ReflectiveResourceListener) l;
Method m = rrl.listener;
if (m.getClass() == owner && Modifier.isStatic(m.getModifiers()) || rrl.parent == parent) {
listeners.remove(l);
}
}
}
}
private final void emitResourcesSafe() {
try {
emitResources();
} catch (Exception ex) {
ErrorHandler.alert(ex);
}
}
static class ReflectiveResourceListener implements IResourceListener {
Method listener;
Object parent;
private int type;
private int event;
public ReflectiveResourceListener(Method listener, Object parent, int type, int event) {
if (!Modifier.isStatic(listener.getModifiers()) && parent == null) {
throw new IllegalArgumentException("listener method " + listener + " is static, but parent is null");
}
this.listener = listener;
this.parent = parent;
this.type = type;
this.event = event;
}
public void tilesetImported(Resource<Tileset> sheet) {
if ((event & IMPORT) > 0 && (type & TILESET) > 0) {
doExec(sheet, event);
}
}
public void tilesetRemoved(Resource<Tileset> sheet) {
if ((event & DELETE) > 0 && (type & TILESET) > 0) {
doExec(sheet, event);
}
}
public void audioImported(Resource<Audio> clip) {
if ((event & IMPORT) > 0 && (type & AUDIO) > 0) {
doExec(clip, event);
}
}
public void audioRemoved(Resource<Audio> clip) {
if ((event & DELETE) > 0 && (type & AUDIO) > 0) {
doExec(clip, event);
}
}
public void modelImported(Resource<WavefrontObject> model) {
if ((event & IMPORT) > 0 && (type & MODEL) > 0) {
doExec(model, event);
}
}
public void modelRemoved(Resource<WavefrontObject> model) {
if ((event & DELETE) > 0 && (type & MODEL) > 0) {
doExec(model, event);
}
}
private void doExec(Resource res, int type) {
try {
if (listener.getParameterTypes().length == 1) {
listener.invoke(parent, res);
} else if (listener.getParameterTypes().length == 2) {
listener.invoke(parent, res, type);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}