using System; using System.Collections.Generic; using System.Linq; using UnityEngine.ResourceManagement; using UnityEngine.ResourceManagement.ResourceLocations; namespace UnityEngine.AddressableAssets.ResourceLocators { /// /// Simple implementation of an IResourceLocator /// public class ResourceLocationMap : IResourceLocator { /// /// Construct a new ResourceLocationMap object. /// /// The locator id. /// The expected number of items. public ResourceLocationMap(string id, int capacity = 0) { LocatorId = id; locations = new Dictionary>(capacity == 0 ? 100 : capacity); } /// /// Stores the resource locator id. /// public string LocatorId { get; private set; } /// /// Construct a new ResourceLocationMap object with a list of locations. /// /// The locator id. /// The list of locations to initialize with. public ResourceLocationMap(string id, IList locations) { LocatorId = id; if (locations == null) return; this.locations = new Dictionary>(locations.Count * 2); var locMap = new Dictionary(); var dataMap = new Dictionary(); //create and collect locations for (int i = 0; i < locations.Count; i++) { var rlData = locations[i]; if (rlData.Keys == null || rlData.Keys.Length < 1) { Addressables.LogErrorFormat("Address with id '{0}' does not have any valid keys, skipping...", rlData.InternalId); continue; } if (locMap.ContainsKey(rlData.Keys[0])) { Addressables.LogErrorFormat("Duplicate address '{0}' with id '{1}' found, skipping...", rlData.Keys[0], rlData.InternalId); continue; } var loc = new ResourceLocationBase(rlData.Keys[0], Addressables.ResolveInternalId(rlData.InternalId), rlData.Provider, rlData.ResourceType); loc.Data = rlData.Data; locMap.Add(rlData.Keys[0], loc); dataMap.Add(rlData.Keys[0], rlData); } //fix up dependencies between them foreach (var kvp in locMap) { var data = dataMap[kvp.Key]; if (data.Dependencies != null) { foreach (var d in data.Dependencies) kvp.Value.Dependencies.Add(locMap[d]); kvp.Value.ComputeDependencyHash(); } } foreach (KeyValuePair kvp in locMap) { ResourceLocationData rlData = dataMap[kvp.Key]; foreach (var k in rlData.Keys) Add(k, kvp.Value); } } /// /// The mapping of key to location lists. /// Dictionary> locations; #if ENABLE_BINARY_CATALOG /// /// Enumeration of all locations for this locator. /// public IEnumerable AllLocations => locations.SelectMany(k => k.Value); #endif /// /// Map of all locations for this locator. /// public Dictionary> Locations => locations; /// /// The keys available in this locator. /// public IEnumerable Keys { get { return locations.Keys; } } /// /// Locate all of the locations that match the given key. /// /// The key used to locate the locations. /// The resource type. /// The list of found locations. This list is shared so it should not be modified. /// Returns true if a location was found. Returns false otherwise. public bool Locate(object key, Type type, out IList locations) { IList locs = null; if (!this.locations.TryGetValue(key, out locs)) { locations = null; return false; } if (type == null) { locations = locs; return true; } var validTypeCount = 0; foreach (var l in locs) if (type.IsAssignableFrom(l.ResourceType)) validTypeCount++; if (validTypeCount == 0) { locations = null; return false; } if (validTypeCount == locs.Count) { locations = locs; return true; } locations = new List(); foreach (var l in locs) { if (type.IsAssignableFrom(l.ResourceType)) locations.Add(l); } return true; } /// /// Add a new location. /// /// The key to reference the location. /// The location to add. public void Add(object key, IResourceLocation location) { IList locations; if (!this.locations.TryGetValue(key, out locations)) this.locations.Add(key, locations = new List()); locations.Add(location); } /// /// Add a list of locations. /// /// The key to reference the locations with. /// The list of locations to store at the given key. public void Add(object key, IList locations) { this.locations.Add(key, locations); } } }