/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon;
import loon.canvas.Image;
import loon.canvas.ImageImpl;
import loon.utils.TArray;
import loon.utils.reply.GoFuture;
import loon.utils.reply.GoPromise;
import loon.utils.res.ResourceLocal;
public abstract class Assets {
private TArray<Sound> soundCache = new TArray<Sound>(10);
// 为了方便直接转码到C#和C++,无法使用匿名内部类(也就是在构造内直接构造实现的方式),只能都写出类来……
// PS:别提delegate,委托那玩意写出来太不优雅了,而且大多数J2C#的工具也不能直接转换过去……
private class ImageRunnable implements Runnable {
private ImageImpl _impl;
private String _path;
private Assets _assets;
ImageRunnable(ImageImpl img, String path, Assets assets) {
this._impl = img;
this._path = path;
this._assets = assets;
}
@Override
public void run() {
try {
_impl.succeed(_assets.load(_path));
} catch (Exception e) {
_impl.fail(e);
}
}
}
private class TextRunnable implements Runnable {
private GoPromise<String> _result;
private String _path;
private Assets _assets;
TextRunnable(GoPromise<String> res, String path, Assets assets) {
this._result = res;
this._path = path;
this._assets = assets;
}
@Override
public void run() {
try {
_result.succeed(_assets.getTextSync(_path));
} catch (Throwable t) {
_result.fail(t);
}
}
}
private class ByteRunnable implements Runnable {
private GoPromise<byte[]> _result;
private String _path;
private Assets _assets;
ByteRunnable(GoPromise<byte[]> res, String path, Assets assets) {
this._result = res;
this._path = path;
this._assets = assets;
}
@Override
public void run() {
try {
_result.succeed(_assets.getBytesSync(_path));
} catch (Throwable t) {
_result.fail(t);
}
}
}
protected static String pathPrefix = "assets/";
public void setPathPrefix(String prefix) {
if (prefix.startsWith("/") || prefix.endsWith("/")) {
throw new IllegalArgumentException(
"Prefix must not start or end with '/'.");
}
pathPrefix = (prefix.length() == 0) ? prefix : (prefix + "/");
}
public String getPathPrefix() {
return pathPrefix;
}
protected static final String[] SUFFIXES = { ".wav", ".mp3", "ogg" };
protected final Asyn asyn;
public final ResourceLocal getJsonResource(String path) {
return new ResourceLocal(path);
}
public Image getImageSync(String path) {
ImageImpl image = createImage(false, 0, 0, path);
try {
image.succeed(load(path));
} catch (Exception e) {
image.fail(e);
}
return image;
}
public Image getImage(final String path) {
final ImageImpl image = createImage(true, 0, 0, path);
asyn.invokeAsync(new ImageRunnable(image, path, this));
return image;
}
public Image getRemoteImage(String url) {
return getRemoteImage(url, 0, 0);
}
public Image getRemoteImage(String url, int width, int height) {
Exception error = new Exception(
"Remote image loading not yet supported: " + url + "@" + width
+ "x" + height);
ImageImpl image = createImage(false, width, height, url);
image.fail(error);
return image;
}
public abstract Sound getSound(String path);
public Sound getMusic(String path) {
Sound sound = getSound(path);
soundCache.add(sound);
return sound;
}
public abstract String getTextSync(String path) throws Exception;
public GoFuture<String> getText(final String path) {
final GoPromise<String> result = asyn.deferredPromise();
asyn.invokeAsync(new TextRunnable(result, path, this));
return result;
}
public abstract byte[] getBytesSync(String path) throws Exception;
public GoFuture<byte[]> getBytes(final String path) {
final GoPromise<byte[]> result = asyn.deferredPromise();
asyn.invokeAsync(new ByteRunnable(result, path, this));
return result;
}
protected Assets(Asyn s) {
this.asyn = s;
}
protected abstract ImageImpl.Data load(String path) throws Exception;
protected abstract ImageImpl createImage(boolean async, int rawWidth,
int rawHeight, String source);
protected static String getPath(String path) {
if (path.indexOf(pathPrefix) == -1) {
path = pathPrefix + path;
}
int pathLen;
do {
pathLen = path.length();
path = path.replaceAll("[^/]+/\\.\\./", "");
} while (path.length() != pathLen);
return path.replace("\\", "/");
}
public void close() {
for (Sound s : soundCache) {
if (s != null) {
s.stop();
s.release();
}
}
}
}