Files
XRLib/Assets/Scripts/Factory/Component/FactoryObjectManager.cs

272 lines
12 KiB
C#
Raw Permalink Normal View History

2025-08-08 18:33:29 +09:00
#nullable enable
2025-06-20 17:37:20 +09:00
using System;
using System.Collections.Generic;
using UVC.Core;
2025-06-23 20:06:15 +09:00
namespace UVC.Factory.Component
2025-06-20 17:37:20 +09:00
{
2025-06-25 18:50:19 +09:00
/// <summary>
/// 씬에 존재하는 모든 FactoryObject 인스턴스를 관리하는 싱글톤 클래스입니다.
/// 이 매니저를 통해 팩토리 객체를 등록, 등록 해제 및 검색할 수 있습니다.
/// </summary>
/// <remarks>
/// SingletonScene을 상속받아 구현되었으므로, `FactoryObjectManager.Instance`를 통해 씬의 어디에서든 쉽게 접근할 수 있습니다.
/// FactoryObject는 Info 속성이 설정될 때 자동으로 이 매니저에 등록되며, 파괴될 때 자동으로 등록 해제됩니다.
/// 따라서 개발자가 직접 Register/Unregister 메서드를 호출할 일은 거의 없습니다.
/// </remarks>
/// <example>
/// 다음은 FactoryObjectManager를 사용하여 씬에 있는 특정 기계를 찾고 제어하는 예제입니다.
/// <code>
/// using UnityEngine;
/// using UVC.Factory.Component;
/// using UVC.Data;
///
/// public class ControlPanel : MonoBehaviour
/// {
/// void Start()
/// {
/// // 가정: 씬 어딘가에 이미 FactoryObject(예: MachineObject)가 생성되어 있고,
/// // Info 속성이 설정되어 FactoryObjectManager에 등록된 상태입니다.
/// //
/// // var machine = new MachineObject();
/// // machine.Info = new FactoryObjectInfo("Drill-01", "MC-1024", ...);
/// }
///
/// // UI 버튼 클릭 시 호출될 함수
/// public void OnFindAndStartMachineButtonClick()
/// {
/// // 1. ID를 사용하여 FactoryObjectManager에서 특정 기계를 찾습니다.
/// FactoryObject machine = FactoryObjectManager.Instance.FindById("MC-1024");
///
/// if (machine != null)
/// {
/// Debug.Log($"기계를 찾았습니다: {machine.Info.Name}");
///
/// // 2. 찾은 기계의 데이터를 업데이트하여 가동시킵니다.
/// var command = new DataObject { { "status", "running" } };
/// machine.UpdateData(command);
/// }
/// else
/// {
/// Debug.LogWarning("ID 'MC-1024'에 해당하는 기계를 찾을 수 없습니다.");
/// }
/// }
///
/// // 특정 구역의 모든 객체를 찾는 예시
/// public void OnFindAllObjectsInArea_A_ButtonClick()
/// {
/// // "Area-A" 구역에 있는 모든 객체를 찾습니다.
/// List<FactoryObject> objectsInArea = FactoryObjectManager.Instance.FindByArea("Area-A");
///
/// Debug.Log($"'Area-A' 구역에서 {objectsInArea.Count}개의 객체를 찾았습니다.");
///
/// foreach (var obj in objectsInArea)
/// {
/// Debug.Log($"- 객체 이름: {obj.Info.Name}, ID: {obj.Info.Id}");
/// }
/// }
/// }
/// </code>
/// </example>
2025-06-20 17:37:20 +09:00
public class FactoryObjectManager : SingletonScene<FactoryObjectManager>
{
2025-06-25 18:50:19 +09:00
/// <summary>
/// 등록된 모든 FactoryObject를 저장하는 딕셔너리입니다.
/// Key는 객체의 식별 정보인 FactoryObjectInfo이고, Value는 FactoryObject 인스턴스입니다.
/// </summary>
2025-06-20 17:37:20 +09:00
public Dictionary<FactoryObjectInfo, FactoryObject> FactoryObjects { get; private set; } = new Dictionary<FactoryObjectInfo, FactoryObject>();
2025-06-25 18:50:19 +09:00
/// <summary>
/// 새로운 FactoryObject를 매니저에 등록합니다.
/// 일반적으로 FactoryObject의 Info 속성이 설정될 때 자동으로 호출됩니다.
/// </summary>
/// <param name="factoryObject">등록할 FactoryObject 인스턴스입니다.</param>
/// <exception cref="ArgumentNullException">factoryObject 또는 factoryObject.Info가 null일 때 발생합니다.</exception>
2025-06-20 17:37:20 +09:00
public void RegisterFactoryObject(FactoryObject factoryObject)
{
if (factoryObject == null || factoryObject.Info == null)
{
throw new ArgumentNullException(nameof(factoryObject), "FactoryObject cannot be null.");
}
if (!FactoryObjects.ContainsKey(factoryObject.Info!))
{
FactoryObjects.Add(factoryObject.Info!, factoryObject);
}
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// 매니저에서 FactoryObject의 등록을 해제합니다.
/// 일반적으로 FactoryObject가 파괴될 때(OnDestroy) 자동으로 호출됩니다.
/// </summary>
/// <param name="factoryObjectInfo">등록 해제할 객체의 FactoryObjectInfo입니다.</param>
2025-06-20 17:37:20 +09:00
public void UnregisterFactoryObject(FactoryObjectInfo factoryObjectInfo)
{
if (factoryObjectInfo == null)
{
2025-06-23 20:06:15 +09:00
//throw new ArgumentNullException(nameof(factoryObjectInfo), "factoryObjectInfo cannot be null.");
return; // Do not throw exception, just return if null
2025-06-20 17:37:20 +09:00
}
FactoryObjects.Remove(factoryObjectInfo);
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// FactoryObjectInfo를 사용하여 등록된 FactoryObject 인스턴스를 가져옵니다.
/// </summary>
/// <param name="factoryObjectInfo">찾고자 하는 객체의 FactoryObjectInfo입니다.</param>
/// <returns>발견된 FactoryObject 인스턴스. 없으면 null을 반환합니다.</returns>
/// <exception cref="ArgumentNullException">factoryObjectInfo가 null일 때 발생합니다.</exception>
2025-06-20 17:37:20 +09:00
public FactoryObject? GetFactoryObject(FactoryObjectInfo factoryObjectInfo)
{
if (factoryObjectInfo == null)
{
throw new ArgumentNullException(nameof(factoryObjectInfo), "factoryObjectInfo cannot be null.");
}
FactoryObjects.TryGetValue(factoryObjectInfo, out var factoryObject);
return factoryObject;
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// 객체의 이름(Name)으로 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다.
/// </summary>
/// <param name="name">찾고자 하는 객체의 이름입니다.</param>
/// <returns>처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다.</returns>
2025-06-20 17:37:20 +09:00
public FactoryObject? FindByName(string name)
{
foreach (var kvp in FactoryObjects)
{
if (kvp.Key.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
return kvp.Value;
}
}
return null;
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// 객체의 고유 ID로 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다.
/// </summary>
/// <param name="id">찾고자 하는 객체의 ID입니다.</param>
/// <returns>처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다.</returns>
2025-06-20 17:37:20 +09:00
public FactoryObject? FindById(string id)
2025-06-27 17:50:23 +09:00
{
2025-06-20 17:37:20 +09:00
foreach (var kvp in FactoryObjects)
{
if (kvp.Key.Id.Equals(id, StringComparison.OrdinalIgnoreCase))
{
return kvp.Value;
}
}
return null;
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// 객체의 위치(Position) 정보로 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다.
/// </summary>
/// <param name="position">찾고자 하는 객체의 위치 정보입니다.</param>
/// <returns>처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다.</returns>
2025-06-20 17:37:20 +09:00
public FactoryObject? FindByPosition(string position)
{
foreach (var kvp in FactoryObjects)
{
if (kvp.Key.Position.Equals(position, StringComparison.OrdinalIgnoreCase))
{
return kvp.Value;
}
}
return null;
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// 특정 구역(Area)에 속한 모든 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다.
/// </summary>
/// <param name="area">찾고자 하는 구역의 이름입니다.</param>
/// <returns>발견된 모든 FactoryObject의 리스트. 없으면 빈 리스트를 반환합니다.</returns>
2025-06-20 17:37:20 +09:00
public List<FactoryObject> FindByArea(string area)
{
List<FactoryObject> foundObjects = new List<FactoryObject>();
foreach (var kvp in FactoryObjects)
{
if (kvp.Key.Area.Equals(area, StringComparison.OrdinalIgnoreCase))
{
foundObjects.Add(kvp.Value);
}
}
return foundObjects;
}
2025-06-25 18:50:19 +09:00
/// <summary>
/// 특정 층(Floor)에 속한 모든 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다.
/// </summary>
/// <param name="floor">찾고자 하는 층의 이름입니다.</param>
/// <returns>발견된 모든 FactoryObject의 리스트. 없으면 빈 리스트를 반환합니다.</returns>
2025-06-20 17:37:20 +09:00
public List<FactoryObject> FindByFloor(string floor)
{
List<FactoryObject> foundObjects = new List<FactoryObject>();
foreach (var kvp in FactoryObjects)
{
if (kvp.Key.Floor.Equals(floor, StringComparison.OrdinalIgnoreCase))
{
foundObjects.Add(kvp.Value);
}
}
return foundObjects;
}
2025-08-08 18:33:29 +09:00
/// <summary>
/// 전체 FactoryObjectInfo를 반환합니다.
/// </summary>
/// <returns></returns>
public List<FactoryObjectInfo> GetAllFactoryObjectInfos()
{
List<FactoryObjectInfo> infos = new List<FactoryObjectInfo>();
foreach (var kvp in FactoryObjects)
{
infos.Add(kvp.Key);
}
return infos;
}
/// <summary>
/// FactoryObject 인스턴스의 리스트를 반환합니다.
/// </summary>
/// <returns></returns>
public List<FactoryObject> GetAllFactoryObjects()
{
List<FactoryObject> objects = new List<FactoryObject>();
foreach (var kvp in FactoryObjects)
{
objects.Add(kvp.Value);
}
return objects;
}
/// <summary>
/// category 이름을 key, FactoryObjectInfo 리스트가 value인 딕셔너리를 반환합니다.
/// </summary>
/// <returns></returns>
2025-09-23 20:40:31 +09:00
public SortedDictionary<string, List<FactoryObjectInfo>> GetFactoryObjectInfosByCategory()
2025-08-08 18:33:29 +09:00
{
2025-09-23 20:40:31 +09:00
SortedDictionary<string, List<FactoryObjectInfo>> categoryDict = new SortedDictionary<string, List<FactoryObjectInfo>>();
2025-08-08 18:33:29 +09:00
foreach (var kvp in FactoryObjects)
{
var info = kvp.Key;
if (!categoryDict.ContainsKey(info.Category))
{
categoryDict[info.Category] = new List<FactoryObjectInfo>();
}
categoryDict[info.Category].Add(info);
}
2025-09-23 20:40:31 +09:00
//key 순 정렬
//name 순 정렬
foreach (var key in categoryDict.Keys)
{
categoryDict[key].Sort((a, b) => a.Name.CompareTo(b.Name));
}
2025-08-08 18:33:29 +09:00
return categoryDict;
}
2025-06-20 17:37:20 +09:00
}
}