using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnityEngine;
using Framework.Services;
using Debug = UnityEngine.Debug;
namespace Framework.Layers {
/// Manages named layer masks throughout the game
///
/// In order to keep layer masks consistent across multiple scenes and to ensure
/// this data is stored in one place only, the layer mask manager loads layer
/// masks from the resource file and lets you access them by name.
///
[ServiceScope(Scope.Global)]
public class LayerMaskManager : Service, ILayerMaskService {
/// Called when the component gets loaded into a game object
protected override void Awake() {
this.defaultMaskBuilt = new bool[32];
this.defaultMask = new int[32];
this.namedMasks = new Dictionary();
LoadLayerMaskList("DefaultLayerMasks");
LoadLayerMaskList("LayerMasks");
}
/// Loads named layer masks from the specified resource
///
/// Path of the resource containing named layer mask definitions
///
public void LoadLayerMaskList(string resourcePath) {
TextAsset layerMaskList = Resources.Load(resourcePath, typeof(TextAsset)) as TextAsset;
if(layerMaskList == null) {
Debug.LogWarning(
"Layer mask list not found at path '" + resourcePath + "'"
);
} else {
using(var reader = new StringReader(layerMaskList.text)) {
LayerMaskListParser.Read(this.namedMasks, reader);
}
}
}
/// Builds a layer mask for the specified layers
/// Layers that should be part of the mask
/// The layer mask for the specified layers
///
/// Builds a mask from the named layers.
///
public static int BuildMask(params string[] layers) {
int mask = 0;
for(int index = 0; index < layers.Length; ++index) {
int layerIndex = LayerMask.NameToLayer(layers[index]);
mask |= 1 << layerIndex;
}
return mask;
}
///
/// Looks up the default collision mask for the layer with the specified name
///
///
/// Name of the layer whose collision mask will be looked up
///
/// The default collision mask for the layer with the specified name
public int GetDefaultMask(string layerName) {
return GetDefaultMask(LayerMask.NameToLayer(layerName));
}
///
/// Looks up the default collision mask for the layer with the specified index
///
///
/// Index of the layer whose collision mask will be looked up
///
/// The default collision mask for the layer with the specified index
public int GetDefaultMask(int layerIndex) {
enforceValidLayerIndex(layerIndex);
if(!this.defaultMaskBuilt[layerIndex]) {
int mask = 0;
for(int index = 0; index < 32; ++index) {
if(!Physics.GetIgnoreLayerCollision(layerIndex, index)) {
mask |= (1 << index);
}
}
this.defaultMask[layerIndex] = mask;
this.defaultMaskBuilt[layerIndex] = true;
}
return this.defaultMask[layerIndex];
}
///
/// Invalidates the cache for the default layer mask with the specified name
///
///
/// Name of the default layer mask that will be invalidated
///
public void InvalidateDefaultMask(string layerName) {
InvalidateDefaultMask(LayerMask.NameToLayer(layerName));
}
///
/// Invalidates the cache for the default layer mask with the specified index
///
///
/// Index of the default layer mask that will be invalidated
///
public void InvalidateDefaultMask(int layerIndex) {
enforceValidLayerIndex(layerIndex);
this.defaultMaskBuilt[layerIndex] = false;
}
/// Retrieves one of the configured layer masks by its name
/// Name of the layer mask that will be retrieved
/// The layer mask with the specified name
public int GetMask(string layerMaskName) {
return this.namedMasks[layerMaskName];
}
/// Changes one of the configured layer masks
/// Name of the layer mask that will be changed
/// New layer mask to store under that given name
public void SetMask(string layerMaskName, int mask) {
this.namedMasks[layerMaskName] = mask;
}
/// Throws an exception if the layer index is not valid
/// Layer index that will be checked
[Conditional("DEBUG")]
private static void enforceValidLayerIndex(int layerIndex) {
if((layerIndex < 0) || (layerIndex >= 32)) {
throw new ArgumentException("Layer index must be in the 0-31 range", "layerIndex");
}
}
/// Named collision masks that have been defined project-wide
private IDictionary namedMasks;
/// Keeps track of which layer masks have already been queried
private bool[/*32*/] defaultMaskBuilt;
/// Stores the collision masks for each of the 32 possible layers
private int[/*32*/] defaultMask;
}
} // namespace Framework.Layers