2025-08-20 06:22:08 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.ComponentModel;
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using UnityEngine;
|
|
|
|
|
2025-08-20 08:04:51 +00:00
|
|
|
namespace DDD
|
2025-08-20 06:22:08 +00:00
|
|
|
{
|
|
|
|
public abstract class SimpleViewModel : MonoBehaviour, INotifyPropertyChanged
|
|
|
|
{
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
|
|
|
|
public virtual void Initialize() { }
|
|
|
|
public virtual void Cleanup() { }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// PropertyChanged 이벤트 발생
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="propertyName">변경된 속성 이름 (자동으로 설정됨)</param>
|
|
|
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
|
|
{
|
2025-08-24 20:12:05 +00:00
|
|
|
if (string.IsNullOrEmpty(propertyName)) return;
|
|
|
|
|
|
|
|
if (_updateDepth > 0)
|
|
|
|
{
|
|
|
|
// 배치 업데이트 중: 나중에 일괄 발행
|
|
|
|
_pendingNotifications.Add(propertyName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-08-20 06:22:08 +00:00
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 필드 값 변경 및 PropertyChanged 이벤트 발생
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">필드 타입</typeparam>
|
|
|
|
/// <param name="field">변경할 필드 참조</param>
|
|
|
|
/// <param name="value">새로운 값</param>
|
|
|
|
/// <param name="propertyName">속성 이름 (자동으로 설정됨)</param>
|
|
|
|
/// <returns>값이 실제로 변경되었는지 여부</returns>
|
|
|
|
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
|
|
|
{
|
|
|
|
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
2025-08-21 07:25:27 +00:00
|
|
|
|
2025-08-20 06:22:08 +00:00
|
|
|
field = value;
|
|
|
|
OnPropertyChanged(propertyName);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2025-08-24 20:12:05 +00:00
|
|
|
private int _updateDepth;
|
2025-08-20 06:22:08 +00:00
|
|
|
private readonly HashSet<string> _pendingNotifications = new();
|
2025-08-24 20:12:05 +00:00
|
|
|
|
|
|
|
protected void BeginUpdate()
|
|
|
|
{
|
|
|
|
_updateDepth++;
|
|
|
|
}
|
2025-08-20 06:22:08 +00:00
|
|
|
|
|
|
|
protected void EndUpdate()
|
|
|
|
{
|
2025-08-24 20:12:05 +00:00
|
|
|
if (_updateDepth == 0)
|
|
|
|
{
|
|
|
|
Debug.LogWarning("EndUpdate called without matching BeginUpdate.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_updateDepth--;
|
|
|
|
|
|
|
|
// 아직 상위 배치가 진행 중이면 플러시하지 않음
|
|
|
|
if (_updateDepth > 0) return;
|
|
|
|
|
2025-08-20 06:22:08 +00:00
|
|
|
if (_pendingNotifications.Count > 0)
|
|
|
|
{
|
2025-08-24 20:12:05 +00:00
|
|
|
// 복사 후 클리어(핸들러 내부에서 BeginUpdate가 호출되어도 안전)
|
|
|
|
var toNotify = new List<string>(_pendingNotifications);
|
|
|
|
_pendingNotifications.Clear();
|
|
|
|
|
|
|
|
foreach (var prop in toNotify)
|
2025-08-21 07:25:27 +00:00
|
|
|
{
|
2025-08-24 20:12:05 +00:00
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
|
2025-08-21 07:25:27 +00:00
|
|
|
}
|
2025-08-20 06:22:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|