/// <summary>
        /// Reloads the specified asset.
        /// </summary>
        /// <typeparam name="T">The Type of asset to reload</typeparam>
        /// <param name="assetName">Name of the asset to load</param>
        /// <returns>The new reference to the reloaded asset</returns>
        public T Reload <T>(string assetName)
        {
            if (loadedAssets.ContainsKey(assetName))
            {
                AssetTracker oldAssetTracker = loadedAssets[assetName];

                // Remove tracker so Load<T>() will create a new one
                loadedAssets.Remove(assetName);
                loadedAssetNames.Remove(assetName);

                // Load it again
                T asset = Load <T>(assetName);

                // Invoke AssetChanged event
                oldAssetTracker.OnAssetChanged(asset);

                // Destroy previous tracker
                DisposeAssetTracker(oldAssetTracker, true);

                return(asset);
            }
            else
            {
                return(Load <T>(assetName));
            }
        }
        /// <summary>
        /// Force an asset to be disposed. Optionally releases child assets
        /// </summary>
        /// <param name="assetName">Name of asset to unload</param>
        /// <param name="releaseChildren">Release child assets</param>
        public void Unload(string assetName, bool releaseChildren)
        {
            if (assetName != null && loadedAssets.ContainsKey(assetName))
            {
                AssetTracker tracker = loadedAssets[assetName];

                // Fire changed event
                tracker.OnAssetChanged(null);

                // Destroy disposables
                DisposeAssetTracker(tracker, releaseChildren);

                // Remove from dictionary
                loadedAssets.Remove(assetName);
                loadedAssetNames.Remove(assetName);
            }
        }
        /// <summary>
        /// Release asset. Decrements the reference count and
        /// removes child assets when the count is zero
        /// </summary>
        /// <param name="assetName">Asset to release</param>
        public void Release(string assetName)
        {
            if (assetName != null && loadedAssets.ContainsKey(assetName))
            {
                AssetTracker tracker = loadedAssets[assetName];
                tracker.RefCount--;

                if (tracker.RefCount == 0)
                {
                    tracker.OnAssetChanged(null);
                    DisposeAssetTracker(tracker, true);

                    // Remove from dictionary
                    loadedAssets.Remove(assetName);
                    loadedAssetNames.Remove(assetName);
                }
            }
        }
        /// <summary>
        /// Destroy IDisposables that were tracked by this asset but do not
        /// exist as assets in their own right. This will also dispose the
        /// unmanaged internals like vertex and index buffers
        /// </summary>
        /// <param name="tracker">AssetTracker to dispose</param>
        /// <param name="releaseChildren">If true, child assets will be released</param>
        private void DisposeAssetTracker(AssetTracker tracker, bool releaseChildren)
        {
            // Invoke asset changed event.
            tracker.OnAssetChanged(null);

            // Mark tracker as disposed
            tracker.Status = AssetStatus.Disposed;

            // Destroy tracked disposables
            foreach (IDisposable disposable in tracker.Disposables)
            {
                disposable.Dispose();
            }

            // Dispose the actual asset, if possible
            if (tracker.Asset is IDisposable)
            {
                ((IDisposable)tracker.Asset).Dispose();
            }

            // Handle child assets
            foreach (string childAsset in tracker.RefersTo)
            {
                if (loadedAssets.ContainsKey(childAsset))
                {
                    // Maintain child reference list
                    loadedAssets[childAsset].ReferredToBy.Remove(tracker.AssetName);

                    // release child assets if requested
                    if (releaseChildren)
                    {
                        Release(childAsset);
                    }
                }
            }
        }