/** * 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.robovm; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import loon.Assets; import loon.LSystem; import loon.Sound; import loon.canvas.Image; import loon.canvas.ImageImpl; import loon.utils.Scale; import loon.utils.reply.Port; import org.robovm.apple.coregraphics.CGImage; import org.robovm.apple.foundation.NSBundle; import org.robovm.apple.foundation.NSData; import org.robovm.apple.uikit.UIImage; public class RoboVMAssets extends Assets { private final static String IOS_DEF_RES = "assets/"; private RoboVMNet net; private final RoboVMGame game; private final File bundleRoot = new File(NSBundle.getMainBundle() .getBundlePath()); private File assetRoot = new File(bundleRoot, pathPrefix); public RoboVMAssets(RoboVMGame game) { super(game.asyn()); this.game = game; this.net = new RoboVMNet(game.asyn()); } public void setPathPrefix(String pathPrefix) { Assets.pathPrefix = pathPrefix; this.assetRoot = new File(bundleRoot, pathPrefix); } @Override public Image getRemoteImage(final String url, final int width, final int height) { final ImageImpl image = createImage(true, width, height, url); net.req(url).execute() .onSuccess(new Port<RoboVMAbstractNet.Response>() { public void onEmit(RoboVMAbstractNet.Response rsp) { try { image.succeed(toData(Scale.ONE, new UIImage( new NSData(rsp.payload())))); } catch (Throwable t) { game.log().warn( "Failed to decode remote image [url=" + url + "]", t); image.fail(t); } } }).onFailure(new Port<Throwable>() { public void onEmit(Throwable cause) { image.fail(cause); } }); return image; } @Override public Sound getSound(String path) { return createSound(path, false); } @Override public Sound getMusic(String path) { return createSound(path, true); } @Override public String getTextSync(String path) throws Exception { game.log().debug("Loading text " + path); return new String(getBytesSync(path), "UTF-8"); } @Override public byte[] getBytesSync(String path) throws Exception { File fullPath = resolvePath(path); game.log().debug("Loading bytes " + fullPath); FileInputStream in = new FileInputStream(fullPath); try { byte[] data = new byte[(int) fullPath.length()]; if (in.read(data) != data.length) { throw new IOException("Failed to read entire file: " + fullPath); } return data; } finally { in.close(); } } @Override protected ImageImpl.Data load(String path) throws Exception { Exception error = null; for (Scale.ScaledResource rsrc : game.graphics().scale() .getScaledResources(path)) { File fullPath = resolvePath(rsrc.path); if (!fullPath.exists()) { continue; } try { UIImage img = UIImage.getImage(fullPath.toString()); if (img != null) { return toData(rsrc.scale, img); } } catch (Exception ex) { game.log().warn("Failed to load image '" + fullPath + "'."); error = new Exception("Failed to load " + fullPath); } } if (error == null) { File fullPath = resolvePath(path); game.log().warn("Missing image '" + fullPath + "'."); error = new FileNotFoundException(fullPath.toString()); } throw error; } @Override protected ImageImpl createImage(boolean async, int rwid, int rhei, String source) { return new RoboVMImage(game, async, rwid, rhei, source); } private ImageImpl.Data toData(Scale scale, UIImage image) { CGImage bitmap = image.getCGImage(); return new ImageImpl.Data(scale, bitmap, (int) bitmap.getWidth(), (int) bitmap.getHeight()); } protected File resolvePath(String path) { File file = new File(assetRoot, path); if (!file.exists()) { path = getPath(path); if (path.startsWith(LSystem.FRAMEWORK_IMG_NAME)) { path = IOS_DEF_RES + path; } file = new File(assetRoot, path); if (!file.exists() && (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) { file = new File(assetRoot,path.substring(path.indexOf('/') + 1, path.length())); } if (!file.exists() && (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) { file = new File(LSystem.getFileName(path = file.getAbsolutePath())); } if (!file.exists()) { file = new File(LSystem.getFileName(path = (IOS_DEF_RES + path))); } } return file; } protected RoboVMAudio _audio; protected RoboVMAudio getNativeAudio() { if (_audio == null) { _audio = new RoboVMAudio(game, game.config.openALSources); } return _audio; } private Sound createSound(String path, boolean isMusic) { if (_audio == null) { _audio = new RoboVMAudio(game, game.config.openALSources); } for (String encpath : new String[] { path + ".caf", path + ".aifc", path + ".mp3" }) { File fullPath = resolvePath(encpath); if (!fullPath.exists()) { continue; } return _audio.createSound(fullPath, isMusic); } game.log().warn("Missing sound: " + path); return new Sound.Error(new FileNotFoundException(path)); } }