using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
namespace SLSUtilities.General
{
///
/// 一个复合布尔值类,支持多来源修改和优先级系统。
/// 可以将多个来源对布尔值的修改综合起来,由高优先级的修改决定最终结果。
///
[InlineProperty]
[HideReferenceObjectPicker]
public class CompoundBool
{
///
/// 返回当前生效优先级层级的计数。
///
[ShowInInspector]
[LabelText("True Count"), LabelWidth(70)]
[HorizontalGroup("Stats", Width = 100)]
public int TrueCount => GetEffectiveCount();
private SortedList counts = new SortedList();
private bool isDirty = true;
private bool cachedValue;
///
/// 获取最终计算出的布尔值。
///
[ShowInInspector]
[LabelText("Value"), LabelWidth(50)]
[HorizontalGroup("Stats", Width = 100)]
public bool Value
{
get
{
if (isDirty) RecalculateValue();
return cachedValue;
}
}
///
/// 初始化 CompoundBool。
///
/// 初始值。如果为 true,将在优先级 0 初始化计数为 1。
public CompoundBool(bool initialValue = false)
{
if (initialValue) Modify(true, 0);
}
///
/// 在指定的优先级层级修改布尔值。
/// 高优先级的值会覆盖低优先级的值。
/// 如果某个非零优先级的计数变为零,将自动移除该优先级层级。
///
/// 修改意图(true 增加计数,false 减少计数)。
/// 优先级,默认为 0。数字越大优先级越高。
public void Modify(bool marker, int priority = 0)
{
if (counts.TryGetValue(priority, out int currentCount))
{
counts[priority] = marker ? currentCount + 1 : currentCount - 1;
}
else
{
counts.Add(priority, marker ? 1 : -1);
}
if(priority != 0 && counts[priority] == 0)
{
counts.Remove(priority);
}
isDirty = true;
}
///
/// 重置所有修改,恢复到默认状态(false)。
///
public void Reset()
{
counts.Clear();
isDirty = true;
}
private void RecalculateValue()
{
// 从最高优先级(列表末尾)向最低优先级迭代
for (int i = counts.Count - 1; i >= 0; i--)
{
int count = counts.Values[i];
if (count != 0)
{
cachedValue = count > 0;
isDirty = false;
return;
}
}
// 如果所有计数都为零或列表为空,则默认为 false
cachedValue = false;
isDirty = false;
}
private int GetEffectiveCount()
{
// 从最高优先级向最低优先级迭代
for (int i = counts.Count - 1; i >= 0; i--)
{
int count = counts.Values[i];
if (count != 0) return count;
}
return 0;
}
}
}