WuhuIslandTesting/Library/PackageCache/com.unity.addressables@1.21.12/Runtime/ResourceManager/AsyncOperations/GroupOperation.cs
2025-01-07 02:06:59 +01:00

231 lines
7.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Security;
using UnityEngine.ResourceManagement.Exceptions;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.ResourceManagement.Util;
namespace UnityEngine.ResourceManagement.AsyncOperations
{
class GroupOperation : AsyncOperationBase<IList<AsyncOperationHandle>>, ICachable
{
[Flags]
public enum GroupOperationSettings
{
None = 0,
ReleaseDependenciesOnFailure = 1,
AllowFailedDependencies = 2
}
Action<AsyncOperationHandle> m_InternalOnComplete;
int m_LoadedCount;
GroupOperationSettings m_Settings;
string debugName = null;
private const int k_MaxDisplayedLocationLength = 45;
public GroupOperation()
{
m_InternalOnComplete = OnOperationCompleted;
Result = new List<AsyncOperationHandle>();
}
///<inheritdoc />
protected override bool InvokeWaitForCompletion()
{
//If Result is null then we've auto released and need to return
if (IsDone || Result == null)
return true;
foreach (var r in Result)
{
r.WaitForCompletion();
if (Result == null)
return true;
}
m_RM?.Update(Time.unscaledDeltaTime);
if (!IsDone && Result != null)
Execute();
m_RM?.Update(Time.unscaledDeltaTime);
return IsDone;
}
IOperationCacheKey ICachable.Key { get; set; }
internal IList<AsyncOperationHandle> GetDependentOps()
{
return Result;
}
/// <inheritdoc />
public override void GetDependencies(List<AsyncOperationHandle> deps)
{
deps.AddRange(Result);
}
internal override void ReleaseDependencies()
{
for (int i = 0; i < Result.Count; i++)
if (Result[i].IsValid())
Result[i].Release();
Result.Clear();
}
internal override DownloadStatus GetDownloadStatus(HashSet<object> visited)
{
var status = new DownloadStatus() {IsDone = IsDone};
for (int i = 0; i < Result.Count; i++)
{
if (Result[i].IsValid())
{
var depStatus = Result[i].InternalGetDownloadStatus(visited);
status.DownloadedBytes += depStatus.DownloadedBytes;
status.TotalBytes += depStatus.TotalBytes;
}
}
return status;
}
HashSet<string> m_CachedDependencyLocations = new HashSet<string>();
private bool DependenciesAreUnchanged(List<AsyncOperationHandle> deps)
{
if (m_CachedDependencyLocations.Count != deps.Count) return false;
foreach (var d in deps)
if (!m_CachedDependencyLocations.Contains(d.LocationName))
return false;
return true;
}
protected override string DebugName
{
get
{
List<AsyncOperationHandle> deps = new List<AsyncOperationHandle>();
GetDependencies(deps);
if (deps.Count == 0)
return "Dependencies";
//Only recalculate DebugName if a name hasn't been generated for currently held dependencies
if (debugName != null && DependenciesAreUnchanged(deps))
return debugName;
m_CachedDependencyLocations.Clear();
string toBeDisplayed = "Dependencies [";
for (var i = 0; i < deps.Count; i++)
{
var d = deps[i];
var locationString = d.LocationName;
m_CachedDependencyLocations.Add(locationString);
if (locationString == null)
continue;
//Prevent location display from being excessively long
if (locationString.Length > k_MaxDisplayedLocationLength)
{
locationString = AsyncOperationBase<object>.ShortenPath(locationString, true);
locationString = locationString.Substring(0, Math.Min(k_MaxDisplayedLocationLength, locationString.Length)) + "...";
}
if (i == deps.Count - 1)
toBeDisplayed += locationString;
else
toBeDisplayed += locationString + ", ";
}
toBeDisplayed += "]";
debugName = toBeDisplayed;
return debugName;
}
}
protected override void Execute()
{
m_LoadedCount = 0;
for (int i = 0; i < Result.Count; i++)
{
if (Result[i].IsDone)
m_LoadedCount++;
else
Result[i].Completed += m_InternalOnComplete;
}
CompleteIfDependenciesComplete();
}
private void CompleteIfDependenciesComplete()
{
if (m_LoadedCount == Result.Count)
{
bool success = true;
OperationException ex = null;
if (!m_Settings.HasFlag(GroupOperationSettings.AllowFailedDependencies))
{
for (int i = 0; i < Result.Count; i++)
{
if (Result[i].Status != AsyncOperationStatus.Succeeded)
{
success = false;
ex = new OperationException("GroupOperation failed because one of its dependencies failed", Result[i].OperationException);
break;
}
}
}
Complete(Result, success, ex, m_Settings.HasFlag(GroupOperationSettings.ReleaseDependenciesOnFailure));
}
}
protected override void Destroy()
{
ReleaseDependencies();
}
protected override float Progress
{
get
{
float total = 0f;
for (int i = 0; i < Result.Count; i++)
{
var handle = Result[i];
if (!handle.IsDone)
total += handle.PercentComplete;
else
total++;
}
return total / Result.Count;
}
}
public void Init(List<AsyncOperationHandle> operations, bool releaseDependenciesOnFailure = true, bool allowFailedDependencies = false)
{
Result = new List<AsyncOperationHandle>(operations);
m_Settings = releaseDependenciesOnFailure ? GroupOperationSettings.ReleaseDependenciesOnFailure : GroupOperationSettings.None;
if (allowFailedDependencies)
m_Settings |= GroupOperationSettings.AllowFailedDependencies;
}
public void Init(List<AsyncOperationHandle> operations, GroupOperationSettings settings)
{
Result = new List<AsyncOperationHandle>(operations);
m_Settings = settings;
}
void OnOperationCompleted(AsyncOperationHandle op)
{
m_LoadedCount++;
CompleteIfDependenciesComplete();
}
}
}