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);
}
}
}