/// <summary> /// Changes the <see cref="ContentLevel"/> of an asset. This should only be called from a block /// locked by <see cref="_assetSync"/>. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="oldLevel">The old <see cref="ContentLevel"/>.</param> /// <param name="newLevel">The new <see cref="ContentLevel"/>.</param> /// <returns>True if the change was successful; false if the asset is not loaded or was not /// in the <paramref name="oldLevel"/>.</returns> bool ChangeAssetLevelNoLock(string assetName, ContentLevel oldLevel, ContentLevel newLevel) { if (oldLevel == newLevel) { return(false); } // Grab from the old dictionary var oldDict = _loadedAssets[(int)oldLevel]; IMyLazyAsset asset; if (!oldDict.TryGetValue(assetName, out asset)) { return(false); } // Remove if (!oldDict.Remove(assetName)) { Debug.Fail("Uhm... how the hell...?"); } // Add to the new dictionary var newDict = _loadedAssets[(int)newLevel]; newDict.Add(assetName, asset); return(true); }
/// <summary> /// Loads an asset that has been created through the Content Pipeline. /// </summary> /// <param name="contentManager">The <see cref="IContentManager"/> to use to load the asset.</param> /// <param name="contentAssetName">The name of the asset to load.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns> /// The asset loaded from the <paramref name="contentManager"/>, or null if the loading failed. /// </returns> public static Image LoadImage(this IContentManager contentManager, ContentAssetName contentAssetName, ContentLevel level) { if (contentManager == null || contentAssetName == null) return null; return contentManager.LoadImage(contentAssetName.Value, level); }
/// <summary> /// Sets the level of an asset only if the specified level is lower than the current level. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="level">The new <see cref="ContentLevel"/>.</param> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c> or empty.</exception> public void SetLevelMin(string assetName, ContentLevel level) { if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException("assetName"); } assetName = SanitizeAssetName(assetName); lock (_assetSync) { IMyLazyAsset asset; ContentLevel currLevel; if (!IsAssetLoaded(assetName, out asset, out currLevel)) { return; } if (currLevel >= level) { return; } ChangeAssetLevelNoLock(assetName, currLevel, level); } }
/// <summary> /// Loads an asset that has been created through the Content Pipeline. /// </summary> /// <param name="contentManager">The <see cref="IContentManager"/> to use to load the asset.</param> /// <param name="contentAssetName">The name of the asset to load.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns> /// The asset loaded from the <paramref name="contentManager"/>, or null if the loading failed. /// </returns> public static Font LoadFont(this IContentManager contentManager, ContentAssetName contentAssetName, int fontSize, ContentLevel level) { if (contentManager == null || contentAssetName == null) return null; return contentManager.LoadFont(contentAssetName.Value, fontSize, level); }
/// <summary> /// Unloads all content from the specified <see cref="ContentLevel"/>, and all levels /// below that level. /// </summary> /// <param name="level">The level of the content to unload. The content at this level, and all levels below it will be /// unloaded. The default is <see cref="ContentLevel.Global"/> to unload content from all levels.</param> /// <param name="ignoreTime">If true, the content in the <paramref name="level"/> will be forced to be unloaded even /// if it was recently used. By default, this is false to prevent excessive reloading. Usually you will only set this /// value to true if you are processing a lot of content at the same time just once, which usually only happens /// in the editors.</param> public void Unload(ContentLevel level = ContentLevel.Global, bool ignoreTime = false) { if (IsDisposed) { return; } DoUnload(level, ignoreTime); }
/// <summary> /// Loads an asset that has been created through the Content Pipeline. /// </summary> /// <param name="contentManager">The <see cref="IContentManager"/> to use to load the asset.</param> /// <param name="contentAssetName">The name of the asset to load.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns> /// The asset loaded from the <paramref name="contentManager"/>, or null if the loading failed. /// </returns> public static Font LoadFont(this IContentManager contentManager, ContentAssetName contentAssetName, int fontSize, ContentLevel level) { if (contentManager == null || contentAssetName == null) { return(null); } return(contentManager.LoadFont(contentAssetName.Value, fontSize, level)); }
/// <summary> /// Loads a <see cref="SoundBuffer"/> asset. /// </summary> /// <param name="assetName">The name of the asset to load.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c> or empty.</exception> public SoundBuffer LoadSoundBuffer(string assetName, ContentLevel level) { if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException("assetName"); } assetName = SanitizeAssetName(assetName); var ret = Load(assetName, level, x => (IMyLazyAsset)ReadAssetSoundBuffer(x)); return((SoundBuffer)ret); }
/// <summary> /// Loads an <see cref="Texture"/> asset. /// </summary> /// <param name="assetName">The name of the asset to load.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c>.</exception> public Texture LoadImage(string assetName, ContentLevel level) { if (assetName == null) { throw new ArgumentNullException("assetName"); } assetName = SanitizeAssetName(assetName); var ret = Load(assetName, level, x => (IMyLazyAsset)ReadAssetImage(x)); return((Texture)ret); }
/// <summary> /// Loads a <see cref="Font"/> asset. /// </summary> /// <param name="assetName">The name of the asset to load.</param> /// <param name="fontSize">The size of the font.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c>.</exception> public Font LoadFont(string assetName, int fontSize, ContentLevel level) { if (assetName == null) { throw new ArgumentNullException("assetName"); } assetName = SanitizeAssetName(assetName); assetName += "|" + fontSize; var ret = Load(assetName, level, x => (IMyLazyAsset)ReadAssetFont(x, fontSize)); return((Font)ret); }
/// <summary> /// Checks if an asset is loaded. /// </summary> /// <param name="assetName">The name of the asset to look for.</param> /// <param name="asset">When this method returns true, contains the asset instance.</param> /// <param name="level">When this method returns true, contains the asset's <see cref="ContentLevel"/>.</param> /// <returns>True if the asset is loaded; otherwise false.</returns> bool IsAssetLoaded(string assetName, out IMyLazyAsset asset, out ContentLevel level) { for (var i = 0; i < _loadedAssets.Length; i++) { if (_loadedAssets[i].TryGetValue(assetName, out asset)) { level = (ContentLevel)i; return(true); } } asset = null; level = 0; return(false); }
/// <summary> /// Gets the content level of an asset. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="level">When this method returns true, contains the <see cref="ContentLevel"/> /// of the asset.</param> /// <returns>True if the asset was found; otherwise false.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c> or empty.</exception> public bool TryGetContentLevel(string assetName, out ContentLevel level) { if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException("assetName"); } assetName = SanitizeAssetName(assetName); lock (_assetSync) { IMyLazyAsset o; return(IsAssetLoaded(assetName, out o, out level)); } }
/// <summary> /// Loads an asset. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <param name="loader">The loader.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ObjectDisposedException"><c>ObjectDisposedException</c>.</exception> /// <exception cref="ArgumentNullException">Argument is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><c>level</c> is out of range.</exception> IMyLazyAsset Load(string assetName, ContentLevel level, Func <string, IMyLazyAsset> loader) { if (IsDisposed) { throw new ObjectDisposedException(ToString()); } if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException("assetName"); } var levelInt = (int)level; if (levelInt >= _loadedAssets.Length || levelInt < 0) { throw new ArgumentOutOfRangeException("level", string.Format("Invalid ContentLevel `{0}` value specified.", level)); } lock (_assetSync) { // Check if the asset is already loaded IMyLazyAsset existingAsset; ContentLevel existingLevel; if (IsAssetLoaded(assetName, out existingAsset, out existingLevel)) { // If the specified level parameter is greater than the asset's current level, promote it if (level < existingLevel) { var success = ChangeAssetLevelNoLock(assetName, existingLevel, level); Debug.Assert(success); } return(existingAsset); } // Load a new asset and add it into the appropriate level var asset = loader(assetName); _loadedAssets[levelInt].Add(assetName, asset); if (IsTrackingLoads && !_trackedLoads.ContainsKey(assetName)) { _trackedLoads.Add(assetName, asset); } return(asset); } }
/// <summary> /// Changes the <see cref="ContentLevel"/> of an asset. This should only be called from a block /// locked by <see cref="_assetSync"/>. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="oldLevel">The old <see cref="ContentLevel"/>.</param> /// <param name="newLevel">The new <see cref="ContentLevel"/>.</param> /// <returns>True if the change was successful; false if the asset is not loaded or was not /// in the <paramref name="oldLevel"/>.</returns> bool ChangeAssetLevelNoLock(string assetName, ContentLevel oldLevel, ContentLevel newLevel) { if (oldLevel == newLevel) return false; // Grab from the old dictionary var oldDict = _loadedAssets[(int)oldLevel]; IMyLazyAsset asset; if (!oldDict.TryGetValue(assetName, out asset)) return false; // Remove if (!oldDict.Remove(assetName)) Debug.Fail("Uhm... how the hell...?"); // Add to the new dictionary var newDict = _loadedAssets[(int)newLevel]; newDict.Add(assetName, asset); return true; }
/// <summary> /// Does the actual work of unloading assets. /// </summary> /// <param name="level">The <see cref="ContentLevel"/> of the content to unload.</param> /// <param name="ignoreTime">If true, the last-used time will be ignored.</param> void DoUnload(ContentLevel level, bool ignoreTime) { var currTime = TickCount.Now; lock (_assetSync) { // Loop through the given level and all levels below it for (var i = (int)level; i < _loadedAssets.Length; i++) { // Get the dictionary for the level var dic = _loadedAssets[i]; // Dispose all items that haven't been used for the needed amount of time foreach (var asset in dic.Values) { try { if (!ignoreTime && (currTime - asset.LastUsedTime < _minElapsedTimeToUnload)) { continue; } asset.Dispose(); } catch (Exception ex) { const string errmsg = "Failed to dispose asset `{0}`: {1}"; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, asset, ex); } Debug.Fail(string.Format(errmsg, asset, ex)); } } } } }
/// <summary> /// Does the actual work of unloading assets. /// </summary> /// <param name="level">The <see cref="ContentLevel"/> of the content to unload.</param> /// <param name="ignoreTime">If true, the last-used time will be ignored.</param> void DoUnload(ContentLevel level, bool ignoreTime) { var currTime = TickCount.Now; lock (_assetSync) { // Loop through the given level and all levels below it for (var i = (int)level; i < _loadedAssets.Length; i++) { // Get the dictionary for the level var dic = _loadedAssets[i]; // Dispose all items that haven't been used for the needed amount of time foreach (var asset in dic.Values) { try { if (!ignoreTime && (currTime - asset.LastUsedTime < _minElapsedTimeToUnload)) continue; asset.Dispose(); } catch (Exception ex) { const string errmsg = "Failed to dispose asset `{0}`: {1}"; if (log.IsWarnEnabled) log.WarnFormat(errmsg, asset, ex); Debug.Fail(string.Format(errmsg, asset, ex)); } } } } }
/// <summary> /// Checks if an asset is loaded. /// </summary> /// <param name="assetName">The name of the asset to look for.</param> /// <param name="asset">When this method returns true, contains the asset instance.</param> /// <param name="level">When this method returns true, contains the asset's <see cref="ContentLevel"/>.</param> /// <returns>True if the asset is loaded; otherwise false.</returns> bool IsAssetLoaded(string assetName, out IMyLazyAsset asset, out ContentLevel level) { for (var i = 0; i < _loadedAssets.Length; i++) { if (_loadedAssets[i].TryGetValue(assetName, out asset)) { level = (ContentLevel)i; return true; } } asset = null; level = 0; return false; }
/// <summary> /// Loads an asset that has been created through the Content Pipeline. /// </summary> /// <param name="contentManager">The <see cref="IContentManager"/> to use to load the asset.</param> /// <param name="contentAssetName">The name of the asset to load.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns> /// The asset loaded from the <paramref name="contentManager"/>, or null if the loading failed. /// </returns> public static Image LoadImage(this IContentManager contentManager, ContentAssetName contentAssetName, ContentLevel level) { if (contentManager == null || contentAssetName == null) { return(null); } return(contentManager.LoadImage(contentAssetName.Value, level)); }
/// <summary> /// Gets the content level of an asset. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="level">When this method returns true, contains the <see cref="ContentLevel"/> /// of the asset.</param> /// <returns>True if the asset was found; otherwise false.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c> or empty.</exception> public bool TryGetContentLevel(string assetName, out ContentLevel level) { if (string.IsNullOrEmpty(assetName)) throw new ArgumentNullException("assetName"); assetName = SanitizeAssetName(assetName); lock (_assetSync) { IMyLazyAsset o; return IsAssetLoaded(assetName, out o, out level); } }
/// <summary> /// Unloads all content from the specified <see cref="ContentLevel"/>, and all levels /// below that level. /// </summary> /// <param name="level">The level of the content to unload. The content at this level, and all levels below it will be /// unloaded. The default is <see cref="ContentLevel.Global"/> to unload content from all levels.</param> /// <param name="ignoreTime">If true, the content in the <paramref name="level"/> will be forced to be unloaded even /// if it was recently used. By default, this is false to prevent excessive reloading. Usually you will only set this /// value to true if you are processing a lot of content at the same time just once, which usually only happens /// in the editors.</param> public void Unload(ContentLevel level = ContentLevel.Global, bool ignoreTime = false) { if (IsDisposed) return; DoUnload(level, ignoreTime); }
/// <summary> /// Sets the level of an asset only if the specified level is lower than the current level. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="level">The new <see cref="ContentLevel"/>.</param> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c> or empty.</exception> public void SetLevelMin(string assetName, ContentLevel level) { if (string.IsNullOrEmpty(assetName)) throw new ArgumentNullException("assetName"); assetName = SanitizeAssetName(assetName); lock (_assetSync) { IMyLazyAsset asset; ContentLevel currLevel; if (!IsAssetLoaded(assetName, out asset, out currLevel)) return; if (currLevel >= level) return; ChangeAssetLevelNoLock(assetName, currLevel, level); } }
/// <summary> /// Loads a <see cref="SoundBuffer"/> asset. /// </summary> /// <param name="assetName">The name of the asset to load.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c> or empty.</exception> public SoundBuffer LoadSoundBuffer(string assetName, ContentLevel level) { if (string.IsNullOrEmpty(assetName)) throw new ArgumentNullException("assetName"); assetName = SanitizeAssetName(assetName); var ret = Load(assetName, level, x => (IMyLazyAsset)ReadAssetSoundBuffer(x)); return (SoundBuffer)ret; }
/// <summary> /// Loads an <see cref="Texture"/> asset. /// </summary> /// <param name="assetName">The name of the asset to load.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c>.</exception> public Texture LoadImage(string assetName, ContentLevel level) { if (assetName == null) throw new ArgumentNullException("assetName"); assetName = SanitizeAssetName(assetName); var ret = Load(assetName, level, x => (IMyLazyAsset)ReadAssetImage(x)); return (Texture)ret; }
/// <summary> /// Loads a <see cref="Font"/> asset. /// </summary> /// <param name="assetName">The name of the asset to load.</param> /// <param name="fontSize">The size of the font.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ArgumentNullException"><paramref name="assetName" /> is <c>null</c>.</exception> public Font LoadFont(string assetName, int fontSize, ContentLevel level) { if (assetName == null) throw new ArgumentNullException("assetName"); assetName = SanitizeAssetName(assetName); assetName += "|" + fontSize; var ret = Load(assetName, level, x => (IMyLazyAsset)ReadAssetFont(x, fontSize)); return (Font)ret; }
/// <summary> /// Loads an asset. /// </summary> /// <param name="assetName">The name of the asset.</param> /// <param name="level">The <see cref="ContentLevel"/> to load the asset into.</param> /// <param name="loader">The loader.</param> /// <returns>The loaded asset.</returns> /// <exception cref="ObjectDisposedException"><c>ObjectDisposedException</c>.</exception> /// <exception cref="ArgumentNullException">Argument is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><c>level</c> is out of range.</exception> IMyLazyAsset Load(string assetName, ContentLevel level, Func<string, IMyLazyAsset> loader) { if (IsDisposed) throw new ObjectDisposedException(ToString()); if (string.IsNullOrEmpty(assetName)) throw new ArgumentNullException("assetName"); var levelInt = (int)level; if (levelInt >= _loadedAssets.Length || levelInt < 0) throw new ArgumentOutOfRangeException("level", string.Format("Invalid ContentLevel `{0}` value specified.", level)); lock (_assetSync) { // Check if the asset is already loaded IMyLazyAsset existingAsset; ContentLevel existingLevel; if (IsAssetLoaded(assetName, out existingAsset, out existingLevel)) { // If the specified level parameter is greater than the asset's current level, promote it if (level < existingLevel) { var success = ChangeAssetLevelNoLock(assetName, existingLevel, level); Debug.Assert(success); } return existingAsset; } // Load a new asset and add it into the appropriate level var asset = loader(assetName); _loadedAssets[levelInt].Add(assetName, asset); if (IsTrackingLoads && !_trackedLoads.ContainsKey(assetName)) _trackedLoads.Add(assetName, asset); return asset; } }