OSDN Git Service

7cbd7a88f64db9d2b61649f3764162035e2979e3
[mikumikustudio/MikuMikuStudio.git] / engine / src / desktop / com / jme3 / asset / DesktopAssetManager.java
1 /*\r
2  * Copyright (c) 2009-2010 jMonkeyEngine\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions are\r
7  * met:\r
8  *\r
9  * * Redistributions of source code must retain the above copyright\r
10  *   notice, this list of conditions and the following disclaimer.\r
11  *\r
12  * * Redistributions in binary form must reproduce the above copyright\r
13  *   notice, this list of conditions and the following disclaimer in the\r
14  *   documentation and/or other materials provided with the distribution.\r
15  *\r
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors\r
17  *   may be used to endorse or promote products derived from this software\r
18  *   without specific prior written permission.\r
19  *\r
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\r
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  */\r
32 \r
33 package com.jme3.asset;\r
34 \r
35 import com.jme3.asset.AssetCache.SmartAssetInfo;\r
36 import com.jme3.audio.AudioKey;\r
37 import com.jme3.audio.AudioData;\r
38 import com.jme3.font.BitmapFont;\r
39 import com.jme3.material.Material;\r
40 import com.jme3.scene.Spatial;\r
41 import com.jme3.shader.Shader;\r
42 import com.jme3.shader.ShaderKey;\r
43 import com.jme3.texture.Texture;\r
44 import java.io.IOException;\r
45 import java.io.InputStream;\r
46 import java.net.URL;\r
47 import java.util.Arrays;\r
48 import java.util.logging.Level;\r
49 import java.util.logging.Logger;\r
50 \r
51 /**\r
52  * <code>AssetManager</code> is the primary method for managing and loading\r
53  * assets inside jME.\r
54  *\r
55  * @author Kirill Vainer\r
56  */\r
57 public class DesktopAssetManager implements AssetManager {\r
58 \r
59     private static final Logger logger = Logger.getLogger(AssetManager.class.getName());\r
60 \r
61     private final AssetCache cache = new AssetCache();\r
62     private final ImplHandler handler = new ImplHandler(this);\r
63 \r
64     private AssetEventListener eventListener = null;\r
65 \r
66 //    private final ThreadingManager threadingMan = new ThreadingManager(this);\r
67 //    private final Set<AssetKey> alreadyLoadingSet = new HashSet<AssetKey>();\r
68 \r
69     public DesktopAssetManager(){\r
70         this(null);\r
71     }\r
72 \r
73     @Deprecated\r
74     public DesktopAssetManager(boolean loadDefaults){\r
75         this(Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Desktop.cfg"));\r
76     }\r
77 \r
78     public DesktopAssetManager(URL configFile){\r
79         if (configFile != null){\r
80             InputStream stream = null;\r
81             try{\r
82                 AssetConfig cfg = new AssetConfig(this);\r
83                 stream = configFile.openStream();\r
84                 cfg.loadText(stream);\r
85             }catch (IOException ex){\r
86                 logger.log(Level.SEVERE, "Failed to load asset config", ex);\r
87             }finally{\r
88                 if (stream != null)\r
89                     try{\r
90                         stream.close();\r
91                     }catch (IOException ex){\r
92                     }\r
93             }\r
94         }\r
95         logger.info("DesktopAssetManager created.");\r
96     }\r
97 \r
98     public void setAssetEventListener(AssetEventListener listener){\r
99         eventListener = listener;\r
100     }\r
101 \r
102     public void registerLoader(Class<? extends AssetLoader> loader, String ... extensions){\r
103         handler.addLoader(loader, extensions);\r
104         if (logger.isLoggable(Level.FINER)){\r
105             logger.log(Level.FINER, "Registered loader: {0} for extensions {1}",\r
106               new Object[]{loader.getSimpleName(), Arrays.toString(extensions)});\r
107         }\r
108     }\r
109 \r
110     public void registerLoader(String clsName, String ... extensions){\r
111         Class<? extends AssetLoader> clazz = null;\r
112         try{\r
113             clazz = (Class<? extends AssetLoader>) Class.forName(clsName);\r
114         }catch (ClassNotFoundException ex){\r
115             logger.log(Level.WARNING, "Failed to find loader: "+clsName, ex);\r
116         }catch (NoClassDefFoundError ex){\r
117             logger.log(Level.WARNING, "Failed to find loader: "+clsName, ex);\r
118         }\r
119         if (clazz != null){\r
120             registerLoader(clazz, extensions);\r
121         }\r
122     }\r
123 \r
124     public void registerLocator(String rootPath, Class<? extends AssetLocator> locatorClass){\r
125         handler.addLocator(locatorClass, rootPath);\r
126         if (logger.isLoggable(Level.FINER)){\r
127             logger.log(Level.FINER, "Registered locator: {0}",\r
128                     locatorClass.getSimpleName());\r
129         }\r
130     }\r
131 \r
132     public void registerLocator(String rootPath, String clsName){\r
133         Class<? extends AssetLocator> clazz = null;\r
134         try{\r
135             clazz = (Class<? extends AssetLocator>) Class.forName(clsName);\r
136         }catch (ClassNotFoundException ex){\r
137             logger.log(Level.WARNING, "Failed to find locator: "+clsName, ex);\r
138         }catch (NoClassDefFoundError ex){\r
139             logger.log(Level.WARNING, "Failed to find loader: "+clsName, ex);\r
140         }\r
141         if (clazz != null){\r
142             registerLocator(rootPath, clazz);\r
143         }\r
144     }\r
145     \r
146     public void unregisterLocator(String rootPath, Class<? extends AssetLocator> clazz){\r
147         handler.removeLocator(clazz, rootPath);\r
148         if (logger.isLoggable(Level.FINER)){\r
149             logger.log(Level.FINER, "Unregistered locator: {0}",\r
150                     clazz.getSimpleName());\r
151         }\r
152     }\r
153 \r
154     public void clearCache(){\r
155         cache.deleteAllAssets();\r
156     }\r
157 \r
158     /**\r
159      * Delete an asset from the cache, returns true if it was deleted\r
160      * successfully.\r
161      * <br/><br/>\r
162      * <font color="red">Thread-safe.</font>\r
163      */\r
164     public boolean deleteFromCache(AssetKey key){\r
165         return cache.deleteFromCache(key);\r
166     }\r
167 \r
168     /**\r
169      * Adds a resource to the cache.\r
170      * <br/><br/>\r
171      * <font color="red">Thread-safe.</font>\r
172      */\r
173     public void addToCache(AssetKey key, Object asset){\r
174         cache.addToCache(key, asset);\r
175     }\r
176 \r
177     public AssetInfo locateAsset(AssetKey<?> key){\r
178         if (handler.getLocatorCount() == 0){\r
179             logger.warning("There are no locators currently"+\r
180                            " registered. Use AssetManager."+\r
181                            "registerLocator() to register a"+\r
182                            " locator.");\r
183             return null;\r
184         }\r
185 \r
186         AssetInfo info = handler.tryLocate(key);\r
187         if (info == null){\r
188             logger.log(Level.WARNING, "Cannot locate resource: {0}", key);\r
189         }\r
190 \r
191         return info;\r
192     }\r
193 \r
194     /**\r
195      * <font color="red">Thread-safe.</font>\r
196      *\r
197      * @param <T>\r
198      * @param key\r
199      * @return\r
200      */\r
201     public <T> T loadAsset(AssetKey<T> key){\r
202         if (key == null)\r
203             throw new IllegalArgumentException("key cannot be null");\r
204         \r
205         if (eventListener != null)\r
206             eventListener.assetRequested(key);\r
207 \r
208         AssetKey smartKey = null;\r
209         Object o = null;\r
210         if (key.shouldCache()){\r
211             if (key.useSmartCache()){\r
212                 SmartAssetInfo smartInfo = cache.getFromSmartCache(key);\r
213                 if (smartInfo != null){\r
214                     smartKey = smartInfo.smartKey.get();\r
215                     if (smartKey != null){\r
216                         o = smartInfo.asset;\r
217                     }\r
218                 }\r
219             }else{\r
220                 o = cache.getFromCache(key);\r
221             }\r
222         }\r
223         if (o == null){\r
224             AssetLoader loader = handler.aquireLoader(key);\r
225             if (loader == null){\r
226                 throw new IllegalStateException("No loader registered for type \"" +\r
227                                                 key.getExtension() + "\"");\r
228             }\r
229 \r
230             if (handler.getLocatorCount() == 0){\r
231                 throw new IllegalStateException("There are no locators currently"+\r
232                                                 " registered. Use AssetManager."+\r
233                                                 "registerLocator() to register a"+\r
234                                                 " locator.");\r
235             }\r
236 \r
237             AssetInfo info = handler.tryLocate(key);\r
238             if (info == null){\r
239                 throw new AssetNotFoundException(key.toString());\r
240             }\r
241 \r
242             try {\r
243                 o = loader.load(info);\r
244             } catch (IOException ex) {\r
245                 throw new AssetLoadException("An exception has occured while loading asset: " + key, ex);\r
246             }\r
247             if (o == null){\r
248                 throw new AssetLoadException("Error occured while loading asset \"" + key + "\" using" + loader.getClass().getSimpleName());\r
249             }else{\r
250                 if (logger.isLoggable(Level.FINER)){\r
251                     logger.log(Level.FINER, "Loaded {0} with {1}",\r
252                             new Object[]{key, loader.getClass().getSimpleName()});\r
253                 }\r
254                 \r
255                 // do processing on asset before caching\r
256                 o = key.postProcess(o);\r
257 \r
258                 if (key.shouldCache())\r
259                     cache.addToCache(key, o);\r
260 \r
261                 if (eventListener != null)\r
262                     eventListener.assetLoaded(key);\r
263             }\r
264         }\r
265 \r
266         // object o is the asset\r
267         // create an instance for user\r
268         T clone = (T) key.createClonedInstance(o);\r
269 \r
270         if (key.useSmartCache()){\r
271             if (smartKey != null){\r
272                 // smart asset was already cached, use original key\r
273                 ((Asset)clone).setKey(smartKey);\r
274             }else{\r
275                 // smart asset was cached on this call, use our key\r
276                 ((Asset)clone).setKey(key);\r
277             }\r
278         }\r
279         \r
280         return clone;\r
281     }\r
282 \r
283     public Object loadAsset(String name){\r
284         return loadAsset(new AssetKey(name));\r
285     }\r
286 \r
287     /**\r
288      * Loads a texture.\r
289      *\r
290      * @return\r
291      */\r
292     public Texture loadTexture(TextureKey key){\r
293         return (Texture) loadAsset(key);\r
294     }\r
295 \r
296     public Material loadMaterial(String name){\r
297         return (Material) loadAsset(new MaterialKey(name));\r
298     }\r
299 \r
300     /**\r
301      * Loads a texture.\r
302      *\r
303      * @param name\r
304      * @param generateMipmaps Enable if applying texture to 3D objects, disable\r
305      * for GUI/HUD elements.\r
306      * @return\r
307      */\r
308     public Texture loadTexture(String name, boolean generateMipmaps){\r
309         TextureKey key = new TextureKey(name, true);\r
310         key.setGenerateMips(generateMipmaps);\r
311         key.setAsCube(false);\r
312         return loadTexture(key);\r
313     }\r
314 \r
315     public Texture loadTexture(String name, boolean generateMipmaps, boolean flipY, boolean asCube, int aniso){\r
316         TextureKey key = new TextureKey(name, flipY);\r
317         key.setGenerateMips(generateMipmaps);\r
318         key.setAsCube(asCube);\r
319         key.setAnisotropy(aniso);\r
320         return loadTexture(key);\r
321     }\r
322 \r
323     public Texture loadTexture(String name){\r
324         return loadTexture(name, true);\r
325     }\r
326 \r
327     public AudioData loadAudio(AudioKey key){\r
328         return (AudioData) loadAsset(key);\r
329     }\r
330 \r
331     public AudioData loadAudio(String name){\r
332         return loadAudio(new AudioKey(name, false));\r
333     }\r
334 \r
335     /**\r
336      * Loads a bitmap font with the given name.\r
337      *\r
338      * @param name\r
339      * @return\r
340      */\r
341     public BitmapFont loadFont(String name){\r
342         return (BitmapFont) loadAsset(new AssetKey(name));\r
343     }\r
344 \r
345     public InputStream loadGLSLLibrary(AssetKey key){\r
346         return (InputStream) loadAsset(key);\r
347     }\r
348 \r
349     /**\r
350      * Load a vertex/fragment shader combo.\r
351      *\r
352      * @param key\r
353      * @return\r
354      */\r
355     public Shader loadShader(ShaderKey key){\r
356         // cache abuse in method\r
357         // that doesn't use loaders/locators\r
358         Shader s = (Shader) cache.getFromCache(key);\r
359         if (s == null){\r
360             String vertName = key.getVertName();\r
361             String fragName = key.getFragName();\r
362 \r
363             String vertSource = (String) loadAsset(new AssetKey(vertName));\r
364             String fragSource = (String) loadAsset(new AssetKey(fragName));\r
365 \r
366             s = new Shader(key.getLanguage());\r
367             s.addSource(Shader.ShaderType.Vertex,   vertName, vertSource, key.getDefines().getCompiled());\r
368             s.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled());\r
369 \r
370             cache.addToCache(key, s);\r
371         }\r
372         return s;\r
373     }\r
374 \r
375     public Spatial loadModel(ModelKey key){\r
376         return (Spatial) loadAsset(key);\r
377     }\r
378 \r
379     /**\r
380      * Load a model.\r
381      *\r
382      * @param name\r
383      * @return\r
384      */\r
385     public Spatial loadModel(String name){\r
386         return loadModel(new ModelKey(name));\r
387     }\r
388     \r
389 }\r