Package com.badlogic.gdx.assets

Source Code of com.badlogic.gdx.assets.AssetManager

/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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.
******************************************************************************/

package com.badlogic.gdx.assets;

import java.util.Stack;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.assets.loaders.AssetLoader;
import com.badlogic.gdx.assets.loaders.BitmapFontLoader;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.assets.loaders.I18NBundleLoader;
import com.badlogic.gdx.assets.loaders.MusicLoader;
import com.badlogic.gdx.assets.loaders.ParticleEffectLoader;
import com.badlogic.gdx.assets.loaders.PixmapLoader;
import com.badlogic.gdx.assets.loaders.SkinLoader;
import com.badlogic.gdx.assets.loaders.SoundLoader;
import com.badlogic.gdx.assets.loaders.TextureAtlasLoader;
import com.badlogic.gdx.assets.loaders.TextureLoader;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.PolygonRegion;
import com.badlogic.gdx.graphics.g2d.PolygonRegionLoader;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.loader.G3dModelLoader;
import com.badlogic.gdx.graphics.g3d.loader.ObjLoader;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.I18NBundle;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.Logger;
import com.badlogic.gdx.utils.ObjectIntMap;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectSet;
import com.badlogic.gdx.utils.TimeUtils;
import com.badlogic.gdx.utils.UBJsonReader;
import com.badlogic.gdx.utils.async.AsyncExecutor;
import com.badlogic.gdx.utils.async.ThreadUtils;
import com.badlogic.gdx.utils.reflect.ClassReflection;

/** Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.
* @author mzechner */
public class AssetManager implements Disposable {
  final ObjectMap<Class, ObjectMap<String, RefCountedContainer>> assets = new ObjectMap();
  final ObjectMap<String, Class> assetTypes = new ObjectMap();
  final ObjectMap<String, Array<String>> assetDependencies = new ObjectMap();
  final ObjectSet<String> injected = new ObjectSet();

  final ObjectMap<Class, ObjectMap<String, AssetLoader>> loaders = new ObjectMap();
  final Array<AssetDescriptor> loadQueue = new Array();
  final AsyncExecutor executor;

  final Stack<AssetLoadingTask> tasks = new Stack();
  AssetErrorListener listener = null;
  int loaded = 0;
  int toLoad = 0;

  Logger log = new Logger("AssetManager", Application.LOG_NONE);

  /** Creates a new AssetManager with all default loaders. */
  public AssetManager () {
    this(new InternalFileHandleResolver());
  }

  /** Creates a new AssetManager with all default loaders. */
  public AssetManager (FileHandleResolver resolver) {
    setLoader(BitmapFont.class, new BitmapFontLoader(resolver));
    setLoader(Music.class, new MusicLoader(resolver));
    setLoader(Pixmap.class, new PixmapLoader(resolver));
    setLoader(Sound.class, new SoundLoader(resolver));
    setLoader(TextureAtlas.class, new TextureAtlasLoader(resolver));
    setLoader(Texture.class, new TextureLoader(resolver));
    setLoader(Skin.class, new SkinLoader(resolver));
    setLoader(ParticleEffect.class, new ParticleEffectLoader(resolver));
    setLoader(PolygonRegion.class, new PolygonRegionLoader(resolver));
    setLoader(I18NBundle.class, new I18NBundleLoader(resolver));
    setLoader(Model.class, ".g3dj", new G3dModelLoader(new JsonReader(), resolver));
    setLoader(Model.class, ".g3db", new G3dModelLoader(new UBJsonReader(), resolver));
    setLoader(Model.class, ".obj", new ObjLoader(resolver));
    executor = new AsyncExecutor(1);
  }

  /** @param fileName the asset file name
   * @return the asset */
  public synchronized <T> T get (String fileName) {
    Class<T> type = assetTypes.get(fileName);
    if (type == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
    if (assetsByType == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    RefCountedContainer assetContainer = assetsByType.get(fileName);
    if (assetContainer == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    T asset = assetContainer.getObject(type);
    if (asset == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    return asset;
  }

  /** @param fileName the asset file name
   * @param type the asset type
   * @return the asset */
  public synchronized <T> T get (String fileName, Class<T> type) {
    ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
    if (assetsByType == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    RefCountedContainer assetContainer = assetsByType.get(fileName);
    if (assetContainer == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    T asset = assetContainer.getObject(type);
    if (asset == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    return asset;
  }
 
  /** @param type the asset type
   * @return all the assets matching the specified type */
  public synchronized <T> Array<T> getAll (Class<T> type, Array<T> out) {
    ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
    if (assetsByType != null){
      for(ObjectMap.Entry<String, RefCountedContainer> asset : assetsByType.entries()){
        out.add(asset.value.getObject(type));
      }
    }
    return out;
  }

  /** @param assetDescriptor the asset descriptor
   * @return the asset */
  public synchronized <T> T get (AssetDescriptor<T> assetDescriptor) {
    return get(assetDescriptor.fileName, assetDescriptor.type);
  }

  /** Removes the asset and all its dependencies, if they are not used by other assets.
   * @param fileName the file name */
  public synchronized void unload (String fileName) {
    // check if it's in the queue
    int foundIndex = -1;
    for (int i = 0; i < loadQueue.size; i++) {
      if (loadQueue.get(i).fileName.equals(fileName)) {
        foundIndex = i;
        break;
      }
    }
    if (foundIndex != -1) {
      toLoad--;
      loadQueue.removeIndex(foundIndex);
      log.debug("Unload (from queue): " + fileName);
      return;
    }

    // check if it's currently processed (and the first element in the stack, thus not a dependency)
    // and cancel if necessary
    if (tasks.size() > 0) {
      AssetLoadingTask currAsset = tasks.firstElement();
      if (currAsset.assetDesc.fileName.equals(fileName)) {
        currAsset.cancel = true;
        log.debug("Unload (from tasks): " + fileName);
        return;
      }
    }

    // get the asset and its type
    Class type = assetTypes.get(fileName);
    if (type == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);

    RefCountedContainer assetRef = assets.get(type).get(fileName);

    // if it is reference counted, decrement ref count and check if we can really get rid of it.
    assetRef.decRefCount();
    if (assetRef.getRefCount() <= 0) {
      log.debug("Unload (dispose): " + fileName);

      // if it is disposable dispose it
      if (assetRef.getObject(Object.class) instanceof Disposable) ((Disposable)assetRef.getObject(Object.class)).dispose();

      // remove the asset from the manager.
      assetTypes.remove(fileName);
      assets.get(type).remove(fileName);
    } else {
      log.debug("Unload (decrement): " + fileName);
    }

    // remove any dependencies (or just decrement their ref count).
    Array<String> dependencies = assetDependencies.get(fileName);
    if (dependencies != null) {
      for (String dependency : dependencies) {
        if (isLoaded(dependency)) unload(dependency);
      }
    }
    // remove dependencies if ref count < 0
    if (assetRef.getRefCount() <= 0) {
      assetDependencies.remove(fileName);
    }
  }

  /** @param asset the asset
   * @return whether the asset is contained in this manager */
  public synchronized <T> boolean containsAsset (T asset) {
    ObjectMap<String, RefCountedContainer> typedAssets = assets.get(asset.getClass());
    if (typedAssets == null) return false;
    for (String fileName : typedAssets.keys()) {
      T otherAsset = (T)typedAssets.get(fileName).getObject(Object.class);
      if (otherAsset == asset || asset.equals(otherAsset)) return true;
    }
    return false;
  }

  /** @param asset the asset
   * @return the filename of the asset or null */
  public synchronized <T> String getAssetFileName (T asset) {
    for (Class assetType : assets.keys()) {
      ObjectMap<String, RefCountedContainer> typedAssets = assets.get(assetType);
      for (String fileName : typedAssets.keys()) {
        T otherAsset = (T)typedAssets.get(fileName).getObject(Object.class);
        if (otherAsset == asset || asset.equals(otherAsset)) return fileName;
      }
    }
    return null;
  }

  /** @param fileName the file name of the asset
   * @return whether the asset is loaded */
  public synchronized boolean isLoaded (String fileName) {
    if (fileName == null) return false;
    return assetTypes.containsKey(fileName);
  }

  /** @param fileName the file name of the asset
   * @return whether the asset is loaded */
  public synchronized boolean isLoaded (String fileName, Class type) {
    ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
    if (assetsByType == null) return false;
    RefCountedContainer assetContainer = assetsByType.get(fileName);
    if (assetContainer == null) return false;
    return assetContainer.getObject(type) != null;
  }

  /** Returns the default loader for the given type
   * @param type The type of the loader to get
   * @return The loader capable of loading the type, or null if none exists */
  public <T> AssetLoader getLoader (final Class<T> type) {
    return getLoader(type, null);
  }

  /** Returns the loader for the given type and the specified filename. If no loader exists for the specific filename, the default
   * loader for that type is returned.
   * @param type The type of the loader to get
   * @param fileName The filename of the asset to get a loader for, or null to get the default loader
   * @return The loader capable of loading the type and filename, or null if none exists */
  public <T> AssetLoader getLoader (final Class<T> type, final String fileName) {
    final ObjectMap<String, AssetLoader> loaders = this.loaders.get(type);
    if (loaders == null || loaders.size < 1) return null;
    if (fileName == null) return loaders.get("");
    AssetLoader result = null;
    int l = -1;
    for (ObjectMap.Entry<String, AssetLoader> entry : loaders.entries()) {
      if (entry.key.length() > l && fileName.endsWith(entry.key)) {
        result = entry.value;
        l = entry.key.length();
      }
    }
    return result;
  }

  /** Adds the given asset to the loading queue of the AssetManager.
   * @param fileName the file name (interpretation depends on {@link AssetLoader})
   * @param type the type of the asset. */
  public synchronized <T> void load (String fileName, Class<T> type) {
    load(fileName, type, null);
  }

  /** Adds the given asset to the loading queue of the AssetManager.
   * @param fileName the file name (interpretation depends on {@link AssetLoader})
   * @param type the type of the asset.
   * @param parameter parameters for the AssetLoader. */
  public synchronized <T> void load (String fileName, Class<T> type, AssetLoaderParameters<T> parameter) {
    AssetLoader loader = getLoader(type, fileName);
    if (loader == null) throw new GdxRuntimeException("No loader for type: " + ClassReflection.getSimpleName(type));

    // reset stats
    if (loadQueue.size == 0) {
      loaded = 0;
      toLoad = 0;
    }

    // check if an asset with the same name but a different type has already been added.

    // check preload queue
    for (int i = 0; i < loadQueue.size; i++) {
      AssetDescriptor desc = loadQueue.get(i);
      if (desc.fileName.equals(fileName) && !desc.type.equals(type))
        throw new GdxRuntimeException("Asset with name '" + fileName
          + "' already in preload queue, but has different type (expected: " + ClassReflection.getSimpleName(type)
          + ", found: " + ClassReflection.getSimpleName(desc.type) + ")");
    }

    // check task list
    for (int i = 0; i < tasks.size(); i++) {
      AssetDescriptor desc = tasks.get(i).assetDesc;
      if (desc.fileName.equals(fileName) && !desc.type.equals(type))
        throw new GdxRuntimeException("Asset with name '" + fileName
          + "' already in task list, but has different type (expected: " + ClassReflection.getSimpleName(type) + ", found: "
          + ClassReflection.getSimpleName(desc.type) + ")");
    }

    // check loaded assets
    Class otherType = assetTypes.get(fileName);
    if (otherType != null && !otherType.equals(type))
      throw new GdxRuntimeException("Asset with name '" + fileName + "' already loaded, but has different type (expected: "
        + ClassReflection.getSimpleName(type) + ", found: " + ClassReflection.getSimpleName(otherType) + ")");

    toLoad++;
    AssetDescriptor assetDesc = new AssetDescriptor(fileName, type, parameter);
    loadQueue.add(assetDesc);
    log.debug("Queued: " + assetDesc);
  }

  /** Adds the given asset to the loading queue of the AssetManager.
   * @param desc the {@link AssetDescriptor} */
  public synchronized void load (AssetDescriptor desc) {
    load(desc.fileName, desc.type, desc.params);
  }

  /** Disposes the given asset and all its dependencies recursively, depth first.
   * @param fileName */
  private void disposeDependencies (String fileName) {
    Array<String> dependencies = assetDependencies.get(fileName);
    if (dependencies != null) {
      for (String dependency : dependencies) {
        disposeDependencies(dependency);
      }
    }

    Class type = assetTypes.get(fileName);
    Object asset = assets.get(type).get(fileName).getObject(Object.class);
    if (asset instanceof Disposable) ((Disposable)asset).dispose();
  }

  /** Updates the AssetManager, keeping it loading any assets in the preload queue.
   * @return true if all loading is finished. */
  public synchronized boolean update () {
    try {
      if (tasks.size() == 0) {
        // loop until we have a new task ready to be processed
        while (loadQueue.size != 0 && tasks.size() == 0) {
          nextTask();
        }
        // have we not found a task? We are done!
        if (tasks.size() == 0) return true;
      }
      return updateTask() && loadQueue.size == 0 && tasks.size() == 0;
    } catch (Throwable t) {
      handleTaskError(t);
      return loadQueue.size == 0;
    }
  }

  /** Updates the AssetManager continuously for the specified number of milliseconds, yielding the CPU to the loading thread
   * between updates. This may block for less time if all loading tasks are complete. This may block for more time if the portion
   * of a single task that happens in the GL thread takes a long time.
   * @return true if all loading is finished. */
  public boolean update (int millis) {
    long endTime = TimeUtils.millis() + millis;
    while (true) {
      boolean done = update();
      if (done || TimeUtils.millis() > endTime) return done;
      ThreadUtils.yield();
    }
  }

  /** blocks until all assets are loaded. */
  public void finishLoading () {
    log.debug("Waiting for loading to complete...");
    while (!update())
      ThreadUtils.yield();
    log.debug("Loading complete.");
  }

  synchronized void injectDependencies (String parentAssetFilename, Array<AssetDescriptor> dependendAssetDescs) {
    ObjectSet<String> injected = this.injected;
    for (AssetDescriptor desc : dependendAssetDescs) {
      if (injected.contains(desc.fileName)) continue; // Ignore subsequent dependencies if there are duplicates.
      injected.add(desc.fileName);
      injectDependency(parentAssetFilename, desc);
    }
    injected.clear();
  }

  private synchronized void injectDependency (String parentAssetFilename, AssetDescriptor dependendAssetDesc) {
    // add the asset as a dependency of the parent asset
    Array<String> dependencies = assetDependencies.get(parentAssetFilename);
    if (dependencies == null) {
      dependencies = new Array();
      assetDependencies.put(parentAssetFilename, dependencies);
    }
    dependencies.add(dependendAssetDesc.fileName);

    // if the asset is already loaded, increase its reference count.
    if (isLoaded(dependendAssetDesc.fileName)) {
      log.debug("Dependency already loaded: " + dependendAssetDesc);
      Class type = assetTypes.get(dependendAssetDesc.fileName);
      RefCountedContainer assetRef = assets.get(type).get(dependendAssetDesc.fileName);
      assetRef.incRefCount();
      incrementRefCountedDependencies(dependendAssetDesc.fileName);
    }
    // else add a new task for the asset.
    else {
      log.info("Loading dependency: " + dependendAssetDesc);
      addTask(dependendAssetDesc);
    }
  }

  /** Removes a task from the loadQueue and adds it to the task stack. If the asset is already loaded (which can happen if it was
   * a dependency of a previously loaded asset) its reference count will be increased. */
  private void nextTask () {
    AssetDescriptor assetDesc = loadQueue.removeIndex(0);

    // if the asset not meant to be reloaded and is already loaded, increase its reference count
    if (isLoaded(assetDesc.fileName)) {
      log.debug("Already loaded: " + assetDesc);
      Class type = assetTypes.get(assetDesc.fileName);
      RefCountedContainer assetRef = assets.get(type).get(assetDesc.fileName);
      assetRef.incRefCount();
      incrementRefCountedDependencies(assetDesc.fileName);
            if (assetDesc.params != null && assetDesc.params.loadedCallback != null) {
                assetDesc.params.loadedCallback.finishedLoading(this, assetDesc.fileName, assetDesc.type);
            }
      loaded++;
    } else {
      // else add a new task for the asset.
      log.info("Loading: " + assetDesc);
      addTask(assetDesc);
    }
  }

  /** Adds a {@link AssetLoadingTask} to the task stack for the given asset.
   * @param assetDesc */
  private void addTask (AssetDescriptor assetDesc) {
    AssetLoader loader = getLoader(assetDesc.type, assetDesc.fileName);
    if (loader == null) throw new GdxRuntimeException("No loader for type: " + ClassReflection.getSimpleName(assetDesc.type));
    tasks.push(new AssetLoadingTask(this, assetDesc, loader, executor));
  }

  /** Adds an asset to this AssetManager */
  protected <T> void addAsset (final String fileName, Class<T> type, T asset) {
    // add the asset to the filename lookup
    assetTypes.put(fileName, type);

    // add the asset to the type lookup
    ObjectMap<String, RefCountedContainer> typeToAssets = assets.get(type);
    if (typeToAssets == null) {
      typeToAssets = new ObjectMap<String, RefCountedContainer>();
      assets.put(type, typeToAssets);
    }
    typeToAssets.put(fileName, new RefCountedContainer(asset));
  }

  /** Updates the current task on the top of the task stack.
   * @return true if the asset is loaded. */
  private boolean updateTask () {
    AssetLoadingTask task = tasks.peek();
    // if the task has finished loading
    if (task.update()) {
      addAsset(task.assetDesc.fileName, task.assetDesc.type, task.getAsset());

      // increase the number of loaded assets and pop the task from the stack
      if (tasks.size() == 1) loaded++;
      tasks.pop();

      // remove the asset if it was canceled.
      if (task.cancel) {
        unload(task.assetDesc.fileName);
      } else {
        // otherwise, if a listener was found in the parameter invoke it
        if (task.assetDesc.params != null && task.assetDesc.params.loadedCallback != null) {
          task.assetDesc.params.loadedCallback.finishedLoading(this, task.assetDesc.fileName, task.assetDesc.type);
        }

        long endTime = TimeUtils.nanoTime();
        log.debug("Loaded: " + (endTime - task.startTime) / 1000000f + "ms " + task.assetDesc);
      }

      return true;
    } else {
      return false;
    }
  }

  private void incrementRefCountedDependencies (String parent) {
    Array<String> dependencies = assetDependencies.get(parent);
    if (dependencies == null) return;

    for (String dependency : dependencies) {
      Class type = assetTypes.get(dependency);
      RefCountedContainer assetRef = assets.get(type).get(dependency);
      assetRef.incRefCount();
      incrementRefCountedDependencies(dependency);
    }
  }

  /** Handles a runtime/loading error in {@link #update()} by optionally invoking the {@link AssetErrorListener}.
   * @param t */
  private void handleTaskError (Throwable t) {
    log.error("Error loading asset.", t);

    if (tasks.isEmpty()) throw new GdxRuntimeException(t);

    // pop the faulty task from the stack
    AssetLoadingTask task = tasks.pop();
    AssetDescriptor assetDesc = task.assetDesc;

    // remove all dependencies
    if (task.dependenciesLoaded && task.dependencies != null) {
      for (AssetDescriptor desc : task.dependencies) {
        unload(desc.fileName);
      }
    }

    // clear the rest of the stack
    tasks.clear();

    // inform the listener that something bad happened
    if (listener != null) {
      listener.error(assetDesc, t);
    } else {
      throw new GdxRuntimeException(t);
    }
  }

  /** Sets a new {@link AssetLoader} for the given type.
   * @param type the type of the asset
   * @param loader the loader */
  public synchronized <T, P extends AssetLoaderParameters<T>> void setLoader (Class<T> type, AssetLoader<T, P> loader) {
    setLoader(type, null, loader);
  }

  /** Sets a new {@link AssetLoader} for the given type.
   * @param type the type of the asset
   * @param suffix the suffix the filename must have for this loader to be used or null to specify the default loader.
   * @param loader the loader */
  public synchronized <T, P extends AssetLoaderParameters<T>> void setLoader (Class<T> type, String suffix,
    AssetLoader<T, P> loader) {
    if (type == null) throw new IllegalArgumentException("type cannot be null.");
    if (loader == null) throw new IllegalArgumentException("loader cannot be null.");
    log.debug("Loader set: " + ClassReflection.getSimpleName(type) + " -> " + ClassReflection.getSimpleName(loader.getClass()));
    ObjectMap<String, AssetLoader> loaders = this.loaders.get(type);
    if (loaders == null) this.loaders.put(type, loaders = new ObjectMap<String, AssetLoader>());
    loaders.put(suffix == null ? "" : suffix, loader);
  }

  /** @return the number of loaded assets */
  public synchronized int getLoadedAssets () {
    return assetTypes.size;
  }

  /** @return the number of currently queued assets */
  public synchronized int getQueuedAssets () {
    return loadQueue.size + (tasks.size());
  }

  /** @return the progress in percent of completion. */
  public synchronized float getProgress () {
    if (toLoad == 0) return 1;
    return Math.min(1, loaded / (float)toLoad);
  }

  /** Sets an {@link AssetErrorListener} to be invoked in case loading an asset failed.
   * @param listener the listener or null */
  public synchronized void setErrorListener (AssetErrorListener listener) {
    this.listener = listener;
  }

  /** Disposes all assets in the manager and stops all asynchronous loading. */
  public synchronized void dispose () {
    log.debug("Disposing.");
    clear();
    executor.dispose();
  }

  /** Clears and disposes all assets and the preloading queue. */
  public synchronized void clear () {
    loadQueue.clear();
    while (!update())
      ;

    ObjectIntMap<String> dependencyCount = new ObjectIntMap<String>();
    while (assetTypes.size > 0) {
      // for each asset, figure out how often it was referenced
      dependencyCount.clear();
      Array<String> assets = assetTypes.keys().toArray();
      for (String asset : assets) {
        dependencyCount.put(asset, 0);
      }

      for (String asset : assets) {
        Array<String> dependencies = assetDependencies.get(asset);
        if (dependencies == null) continue;
        for (String dependency : dependencies) {
          int count = dependencyCount.get(dependency, 0);
          count++;
          dependencyCount.put(dependency, count);
        }
      }

      // only dispose of assets that are root assets (not referenced)
      for (String asset : assets) {
        if (dependencyCount.get(asset, 0) == 0) {
          unload(asset);
        }
      }
    }

    this.assets.clear();
    this.assetTypes.clear();
    this.assetDependencies.clear();
    this.loaded = 0;
    this.toLoad = 0;
    this.loadQueue.clear();
    this.tasks.clear();
  }

  /** @return the {@link Logger} used by the {@link AssetManager} */
  public Logger getLogger () {
    return log;
  }

  public void setLogger (Logger logger) {
    log = logger;
  }

  /** Returns the reference count of an asset.
   * @param fileName */
  public synchronized int getReferenceCount (String fileName) {
    Class type = assetTypes.get(fileName);
    if (type == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    return assets.get(type).get(fileName).getRefCount();
  }

  /** Sets the reference count of an asset.
   * @param fileName */
  public synchronized void setReferenceCount (String fileName, int refCount) {
    Class type = assetTypes.get(fileName);
    if (type == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
    assets.get(type).get(fileName).setRefCount(refCount);
  }

  /** @return a string containing ref count and dependency information for all assets. */
  public synchronized String getDiagnostics () {
    StringBuffer buffer = new StringBuffer();
    for (String fileName : assetTypes.keys()) {
      buffer.append(fileName);
      buffer.append(", ");

      Class type = assetTypes.get(fileName);
      RefCountedContainer assetRef = assets.get(type).get(fileName);
      Array<String> dependencies = assetDependencies.get(fileName);

      buffer.append(ClassReflection.getSimpleName(type));

      buffer.append(", refs: ");
      buffer.append(assetRef.getRefCount());

      if (dependencies != null) {
        buffer.append(", deps: [");
        for (String dep : dependencies) {
          buffer.append(dep);
          buffer.append(",");
        }
        buffer.append("]");
      }
      buffer.append("\n");
    }
    return buffer.toString();
  }

  /** @return the file names of all loaded assets. */
  public synchronized Array<String> getAssetNames () {
    return assetTypes.keys().toArray();
  }

  /** @return the dependencies of an asset or null if the asset has no dependencies. */
  public synchronized Array<String> getDependencies (String fileName) {
    return assetDependencies.get(fileName);
  }

  /** @return the type of a loaded asset. */
  public synchronized Class getAssetType (String fileName) {
    return assetTypes.get(fileName);
  }

}
TOP

Related Classes of com.badlogic.gdx.assets.AssetManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.