VR4Medical/ICI/Library/PackageCache/com.unity.learn.iet-framework@4bd5247958fc/Editor/Criteria/PrefabInstanceCountCriterion.cs
2025-07-29 13:45:50 +03:00

183 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;
namespace Unity.Tutorials.Core.Editor
{
/// <summary>
/// Criterion for checking that a specific amount of prefab instances are created.
/// </summary>
public class PrefabInstanceCountCriterion : Criterion
{
/// <summary>
/// Different comparison modes.
/// </summary>
public enum InstanceCountComparison
{
/// <summary>
/// At least X amount of instances required.
/// </summary>
AtLeast,
/// <summary>
/// Exactly X amount of instances required.
/// </summary>
Exactly,
/// <summary>
/// No more than X amount of instances required.
/// </summary>
NoMoreThan,
}
/// <summary>
/// The prefab of instances we want to count.
/// </summary>
[FormerlySerializedAs("prefabParent")]
public GameObject PrefabParent;
/// <summary>
/// The wanted comparison mode.
/// </summary>
[FormerlySerializedAs("comparisonMode")]
public InstanceCountComparison ComparisonMode = InstanceCountComparison.AtLeast;
/// <summary>
/// The desired amount of instances.
/// </summary>
[Range(0, 100)]
[FormerlySerializedAs("instanceCount")]
public int InstanceCount = 1;
[SerializeField, HideInInspector]
FutureObjectReference m_FutureReference;
/// <summary>
/// Starts testing of the criterion.
/// </summary>
public override void StartTesting()
{
base.StartTesting();
UpdateCompletion();
Selection.selectionChanged += UpdateCompletion;
}
/// <summary>
/// Stops testing of the criterion.
/// </summary>
public override void StopTesting()
{
base.StopTesting();
Selection.selectionChanged -= UpdateCompletion;
}
/// <summary>
/// Evaluates if the criterion is completed.
/// </summary>
/// <returns>True if the prefab where created, false otherwise</returns>
protected override bool EvaluateCompletion()
{
if (PrefabParent == null)
return false;
var matches = EditorFindObjectUtils.FindObjectsByTypeSorted<GameObject>().Where(go => PrefabUtilityShim.GetCorrespondingObjectFromSource(go) == PrefabParent);
var count = matches.Count();
switch (ComparisonMode)
{
case InstanceCountComparison.AtLeast:
return count >= InstanceCount;
case InstanceCountComparison.Exactly:
var complete = count == InstanceCount;
if (complete && InstanceCount == 1 && m_FutureReference != null)
m_FutureReference.SceneObjectReference.Update(matches.First());
return complete;
case InstanceCountComparison.NoMoreThan:
return count <= InstanceCount;
default:
return false;
}
}
/// <summary>
/// Returns FutureObjectReference for this Criterion.
/// </summary>
/// <returns>The FutureObjectReference when it becomes available</returns>
protected override IEnumerable<FutureObjectReference> GetFutureObjectReferences()
{
if (m_FutureReference == null)
yield break;
yield return m_FutureReference;
}
/// <summary>
/// Destroys unused future reference assets and updates future references.
/// </summary>
protected override void OnValidate()
{
// Destroy unreferenced future reference assets
base.OnValidate();
// Update future reference
var needsUpdate = false;
if (ComparisonMode == InstanceCountComparison.Exactly && InstanceCount == 1)
{
if (m_FutureReference == null)
{
m_FutureReference = CreateFutureObjectReference();
m_FutureReference.ReferenceName = "Prefab Instance";
needsUpdate = true;
}
}
else
DestroyImmediate(m_FutureReference, true);
if (needsUpdate)
UpdateFutureObjectReferenceNames();
}
/// <summary>
/// Auto-completes the criterion.
/// </summary>
/// <returns>True if the auto-completion succeeded.</returns>
public override bool AutoComplete()
{
var prefabInstances = EditorFindObjectUtils.FindObjectsByTypeSorted<GameObject>().Where(go => PrefabUtilityShim.GetCorrespondingObjectFromSource(go) == PrefabParent);
var actualInstanceCount = prefabInstances.Count();
var difference = actualInstanceCount - InstanceCount;
if (difference == 0)
return true;
switch (ComparisonMode)
{
case InstanceCountComparison.AtLeast:
difference = Math.Min(0, difference);
break;
case InstanceCountComparison.NoMoreThan:
difference = Math.Max(0, difference);
break;
}
if (difference < 0)
{
for (var i = 0; i < -difference; i++)
PrefabUtility.InstantiatePrefab(PrefabParent);
}
else
{
foreach (var prefabInstance in prefabInstances.Take(difference))
DestroyImmediate(prefabInstance);
}
return true;
}
}
}