/// <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));
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Constructor for convenience
 /// </summary>
 internal LoadAsyncParams(Type type, string name, AssetLoaded loadedMethod)
 {
     AssetType = type;
     ItemLoadedMethods.Add(loadedMethod);
     Tracker           = new AssetTracker();
     Tracker.AssetName = name;
     Tracker.RefCount  = 1;
     Tracker.Status    = AssetStatus.Loading;
 }
        /// <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);
                    }
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Asyncronously loads the specified asset
        /// </summary>
        /// <typeparam name="T">Generic type parameter</typeparam>
        /// <param name="assetName">Name of asset to laod</param>
        /// <param name="itemLoadedMethod">Method to call once load is completed</param>
        /// <returns>AssetTracker of asset to be loaded. Allows
        /// users to poll the asset status if desired</returns>
        public AssetTracker LoadAsync <T>(string assetName, AssetLoaded itemLoadedMethod)
        {
            AssetTracker tracker = null;

            // Check if asset is already loaded
            if (loadedAssets.ContainsKey(assetName))
            {
                tracker = loadedAssets[assetName];

                // Increment reference count
                tracker.RefCount++;

                // Call the specified item loaded method
                if (itemLoadedMethod != null)
                {
                    itemLoadedMethod(tracker.Asset);
                }
            }
            else
            {
                if (loadThread == null)
                {
                    // First time LoadAsync has been called so
                    // initialise thread, reset event and queue
                    loadThread      = new Thread(new ThreadStart(LoadingThreadWorker));
                    loadThread.Name = "File Loading Worker";

                    loadItemsQueue = new Queue <LoadAsyncParams>();
                    loadResetEvent = new AutoResetEvent(false);

                    //reset the request flag to close the thread
                    mCloseRequested = false;

                    // Start thread. It will wait once queue is empty
                    loadThread.Start();
                }

                // Create the async argument structure and enqueue it for async load.
                lock (loadItemsQueue)
                {
                    // first check if this item is already enqueued
                    Queue <LoadAsyncParams> .Enumerator enumer = loadItemsQueue.GetEnumerator();
                    while (enumer.MoveNext())
                    {
                        if (enumer.Current.Tracker.AssetName == assetName)
                        {
                            // Register the itemLoaded method
                            enumer.Current.ItemLoadedMethods.Add(itemLoadedMethod);
                            tracker = enumer.Current.Tracker;
                            tracker.RefCount++;
                            break;
                        }
                    }

                    // Item not already queued for loading
                    if (tracker == null)
                    {
                        LoadAsyncParams args = new LoadAsyncParams(typeof(T), assetName, itemLoadedMethod);
                        tracker = args.Tracker;
                        loadItemsQueue.Enqueue(args);
                    }
                }

                // Tell loading thread to stop waiting
                loadResetEvent.Set();
            }

            // Return tracker. Allows async caller to poll loaded status
            return(tracker);
        }
        /// <summary>
        /// Return the specified asset. Read it from disk if not available
        /// </summary>
        /// <typeparam name="T">The Type of asset to load</typeparam>
        /// <param name="assetName">Name of the asset to load</param>
        /// <param name="tracker">An AssetTracker to use when loading this asset. May be null</param>
        /// <param name="forceReadAsset">if set to <c>true</c> [force read asset].</param>
        /// <returns>
        /// A reference to the loaded asset
        /// </returns>
        public T LoadToTracker <T>(string assetName, AssetTracker tracker, bool forceReadAsset)
        {
            // Return asset if currently loaded
            if (!forceReadAsset && loadedAssets.ContainsKey(assetName))
            {
                // Get asset tracker
                AssetTracker trackerExisting = loadedAssets[assetName];

                // Get asset as correct type
                T asset = (T)trackerExisting.Asset;

                // Increment tracker's reference count after the cast as the cast will
                // throw an exception if the incorrect generic type parameter is given
                trackerExisting.RefCount++;

                // Maintain the reference lists to show that this asset was loaded by
                // the asset on the top of the stack
                if (loadingAssetsStack.Count > 0)
                {
                    loadingAssetsStack.Peek().RefersTo.Add(assetName);
                    trackerExisting.ReferredToBy.Add(loadingAssetsStack.Peek().AssetName);
                }

                return(asset);
            }

            // Need to load the asset. Create an AssetTracker to track it
            // unless we have been passed an existing AssetTracker
            if (tracker == null)
            {
                // Initialise tracker
                tracker           = new AssetTracker();
                tracker.RefCount  = 1;
                tracker.AssetName = assetName;
            }

            // Stack count will be zero if called by user.
            // Otherwise, Load<T> was called internally by ReadAsset<T>
            if (loadingAssetsStack.Count > 0)
            {
                // Maintain the reference lists

                // The asset on the top of the stack refers to this asset
                loadingAssetsStack.Peek().RefersTo.Add(assetName);

                // This asset was loaded by the asset on the top of the stack
                tracker.ReferredToBy.Add(loadingAssetsStack.Peek().AssetName);
            }

            // Put current asset tracker on top of the stack
            // for next call to Load<T>
            loadingAssetsStack.Push(tracker);

            try
            {
                // Preparation complete. Now finally read the asset from disk.
                // This is where the internal magic happens.
#if WINDOWS
                string fileName;
                if (UseSourceAssets && TrySearchForValidAssetSource <T>(assetName, out fileName))
                {
                    tracker.Asset = SourceAssetLoaders[typeof(T)].loadAssetDelegate(fileName);
                }
                else
#endif
                tracker.Asset = ReadAsset <T>(assetName, tracker.TrackDisposableAsset);

                // Ensure the list of disposables doesn't refer to the
                // actual asset, or to any assets in the loadedAssets Dictionary.
                // Best to do this now to avoid multiple disposing later
                tracker.Disposables.RemoveAll(delegate(IDisposable d)
                {
                    string tmp = "";
                    return(tracker.Asset == d || SearchForAsset(d, out tmp));
                });
            }
            finally
            {
                // Asset has been loaded so the top tracker is not needed on the stack
                loadingAssetsStack.Pop();
            }

            // Store the asset and it's disposables list
            if (forceReadAsset)
            {
                untrackedAssets.Add(tracker);
            }
            else
            {
                loadedAssets.Add(assetName, tracker);
                loadedAssetNames.Add(assetName);
            }

            // Mark tracker as ready to use
            tracker.Status = AssetStatus.Active;

            // Return loaded asset
            return((T)tracker.Asset);
        }