Files
XRLib/Assets/Scripts/Simulator/Components/ComponentPoolManager.cs

271 lines
12 KiB
C#
Raw Permalink Normal View History

2026-02-25 16:30:12 +09:00
using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using UnityEngine;
using UVC.Data;
using UVC.Data.Core;
using UVC.Data.Mqtt;
using UVC.Pool;
2026-02-26 17:09:39 +09:00
using UVC.UI.Loading;
2026-02-25 16:30:12 +09:00
namespace Simulator.Data
{
public class ComponentPoolManager
{
private readonly Transform _parentTransform;
private readonly Dictionary<string, string> _prefabPaths = new Dictionary<string, string>()
{
{"source","prefabs/pallet"},
{"queue","prefabs/queue"},
{"rack","prefabs/rack"},
{"sink","prefabs/Sink_Container"},
{"asrs","prefabs/ASRS"},
{"robotArm","prefabs/RobotArm"},
{"processor","prefabs/Processor"},
{"worker","prefabs/Worker"}
};
private GameObjectPool<SourceComponent> _sourcePool;
private GameObjectPool<SinkComponent> _sinkPool;
private GameObjectPool<QueueComponent> _queuePool;
private GameObjectPool<RackComponent> _rackPool;
private GameObjectPool<ASRSComponent> _asrsPool;
private GameObjectPool<RobotArmComponent> _robotArmPool;
private GameObjectPool<ProcessorComponent> _processorPool;
private GameObjectPool<WorkerComponent> _workerPool;
private readonly Dictionary<ComponentType, DataMapper> _dataMapperDict = new Dictionary<ComponentType, DataMapper>();
public IReadOnlyDictionary<ComponentType, DataMapper> DataMappers => _dataMapperDict;
2026-02-26 14:04:33 +09:00
private ComponentUIBinder _uiBinder;
public ComponentUIBinder UIBinder => _uiBinder;
2026-02-25 16:30:12 +09:00
public ComponentPoolManager(Transform parentTransform)
{
_parentTransform = parentTransform;
}
2026-02-26 14:04:33 +09:00
public void InitializeUIBinder()
2026-02-25 16:30:12 +09:00
{
2026-02-26 14:04:33 +09:00
_uiBinder = new ComponentUIBinder();
_uiBinder.Initialize();
}
2026-02-25 16:30:12 +09:00
2026-02-26 14:04:33 +09:00
public void InitializeAllPools()
{
2026-03-17 10:52:33 +09:00
InitializePoolAsync<SourceComponent>(_sourcePool, "source").ContinueWith(pool => { _sourcePool = pool; _dataMapperDict.Add(ComponentType.Source, CreateDataMapper(ComponentType.Source)); });
InitializePoolAsync<SinkComponent>(_sinkPool, "sink").ContinueWith(pool => { _sinkPool = pool; _dataMapperDict.Add(ComponentType.Sink, CreateDataMapper(ComponentType.Sink)); });
InitializePoolAsync<QueueComponent>(_queuePool, "queue").ContinueWith(pool => { _queuePool = pool; _dataMapperDict.Add(ComponentType.Queue, null); });
InitializePoolAsync<RackComponent>(_rackPool, "rack").ContinueWith(pool => { _rackPool = pool; _dataMapperDict.Add(ComponentType.Rack, CreateDataMapper(ComponentType.Rack)); });
InitializePoolAsync<ASRSComponent>(_asrsPool, "asrs").ContinueWith(pool => { _asrsPool = pool; _dataMapperDict.Add(ComponentType.ASRS, CreateDataMapper(ComponentType.ASRS)); });
InitializePoolAsync<RobotArmComponent>(_robotArmPool, "robotArm").ContinueWith(pool => { _robotArmPool = pool; _dataMapperDict.Add(ComponentType.RobotArm, CreateDataMapper(ComponentType.RobotArm)); });
InitializePoolAsync<ProcessorComponent>(_processorPool, "processor").ContinueWith(pool => { _processorPool = pool; _dataMapperDict.Add(ComponentType.Processor, CreateDataMapper(ComponentType.Processor)); });
InitializePoolAsync<WorkerComponent>(_workerPool, "worker").ContinueWith(pool => { _workerPool = pool; _dataMapperDict.Add(ComponentType.Worker, CreateDataMapper(ComponentType.Worker)); });
2026-02-26 14:04:33 +09:00
}
2026-02-25 16:30:12 +09:00
2026-02-26 14:04:33 +09:00
private DataMapper CreateDataMapper(ComponentType type)
{
switch (type)
2026-02-25 16:30:12 +09:00
{
2026-02-26 14:04:33 +09:00
case ComponentType.Source:
return new DataMapper(CreateEventMask("Source", new DataMask
{
["entity_ids"] = new List<string>(),
["total_entity"] = 0
}));
case ComponentType.Sink:
return new DataMapper(CreateEventMask("Sink", new DataMask
{
["entity_ids"] = new List<string>()
}));
case ComponentType.RobotArm:
return new DataMapper(CreateEventMask("RobotArm", new DataMask
{
["entity_id"] = "",
["processing_time"] = 0.0f,
["from"] = "",
["to"] = ""
}));
case ComponentType.Rack:
return new DataMapper(new DataMask { ObjectName = "rack", ObjectIdKey = "component_id" });
case ComponentType.ASRS:
return new DataMapper(new DataMask { ObjectName = "asrs", ObjectIdKey = "component_id" });
default:
return new DataMapper(new DataMask());
}
}
2026-02-25 16:30:12 +09:00
2026-02-26 14:04:33 +09:00
private DataMask CreateEventMask(string objectName, DataMask dataMask)
{
var mask = new DataMask
2026-02-25 16:30:12 +09:00
{
2026-02-26 14:04:33 +09:00
ObjectName = objectName,
ObjectIdKey = "component_id",
["component_id"] = "",
["event_name"] = "",
["timestamp"] = new DateTime(),
["data"] = dataMask
};
return mask;
2026-02-25 16:30:12 +09:00
}
#region Pool Initialization
2026-03-17 10:52:33 +09:00
private async UniTask<GameObjectPool<T>> InitializePoolAsync<T>(GameObjectPool<T> existingPool, string key) where T : MonoBehaviour
2026-02-25 16:30:12 +09:00
{
2026-03-17 10:52:33 +09:00
if (existingPool != null) return existingPool;
var prefab = await Resources.LoadAsync<GameObject>(_prefabPaths[key]) as GameObject;
if (prefab == null) { Debug.LogError($"Prefab not found at path: {_prefabPaths[key]}"); return null; }
return new GameObjectPool<T>(prefab, _parentTransform);
2026-02-25 16:30:12 +09:00
}
#endregion
public Dictionary<string, ComponentBase> SpawnComponents(LogicDetailData data)
{
var registry = new Dictionary<string, ComponentBase>();
2026-02-26 14:04:33 +09:00
var ps = data.production_system;
if (ps != null)
2026-02-25 16:30:12 +09:00
{
2026-02-26 14:04:33 +09:00
SpawnGroup(ps.sources, _sourcePool, ComponentType.Source, (c, d) => c.SetComponent(d), registry);
SpawnGroup(ps.sinks, _sinkPool, ComponentType.Sink, (c, d) => c.SetComponent(d), registry);
SpawnGroup(ps.racks, _rackPool, ComponentType.Rack, (c, d) => c.SetComponent(d), registry);
SpawnGroup(ps.asrs, _asrsPool, ComponentType.ASRS, (c, d) => c.SetComponent(d), registry);
SpawnGroup(ps.robot_arms, _robotArmPool, ComponentType.RobotArm, (c, d) => c.SetComponent(d), registry);
SpawnGroup(ps.processors, _processorPool, ComponentType.Processor, (c, d) => c.SetComponent(d), registry);
2026-02-25 16:30:12 +09:00
}
2026-02-26 14:04:33 +09:00
var infra = data.infrastructure;
if (infra != null)
2026-02-25 16:30:12 +09:00
{
2026-02-26 14:04:33 +09:00
SpawnGroup(infra.queues, _queuePool, ComponentType.Queue, (c, d) => c.SetComponent(d), registry);
SpawnGroup(infra.resources, _workerPool, ComponentType.Worker, (c, d) => c.SetComponent(d), registry);
2026-02-25 16:30:12 +09:00
}
return registry;
}
2026-02-26 14:04:33 +09:00
private void SpawnGroup<TComp, TData>(
List<TData> items,
GameObjectPool<TComp> pool,
ComponentType type,
Action<TComp, TData> setup,
Dictionary<string, ComponentBase> registry)
where TComp : ComponentBase
where TData : ComponentDataBase
{
if (items == null) return;
foreach (var item in items)
{
var comp = pool.GetItem(item.name);
comp.componentType = type;
setup(comp, item);
_uiBinder.BindStandardComponent(comp);
2026-02-26 17:09:39 +09:00
registry[item.name] = comp;
2026-02-26 14:04:33 +09:00
}
}
2026-02-26 17:09:39 +09:00
public async UniTask<Dictionary<string, ComponentBase>> SpawnComponentsAsync(LogicDetailData data)
{
var registry = new Dictionary<string, ComponentBase>();
int totalCount = CountAllItems(data);
int spawnedCount = 0;
int batchSize = 5;
var ps = data.production_system;
if (ps != null)
{
spawnedCount = await SpawnGroupAsync(ps.sources, _sourcePool, ComponentType.Source, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
spawnedCount = await SpawnGroupAsync(ps.sinks, _sinkPool, ComponentType.Sink, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
spawnedCount = await SpawnGroupAsync(ps.racks, _rackPool, ComponentType.Rack, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
spawnedCount = await SpawnGroupAsync(ps.asrs, _asrsPool, ComponentType.ASRS, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
spawnedCount = await SpawnGroupAsync(ps.robot_arms, _robotArmPool, ComponentType.RobotArm, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
spawnedCount = await SpawnGroupAsync(ps.processors, _processorPool, ComponentType.Processor, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
}
var infra = data.infrastructure;
if (infra != null)
{
spawnedCount = await SpawnGroupAsync(infra.queues, _queuePool, ComponentType.Queue, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
spawnedCount = await SpawnGroupAsync(infra.resources, _workerPool, ComponentType.Worker, (c, d) => c.SetComponent(d), registry, spawnedCount, totalCount, batchSize);
}
return registry;
}
private async UniTask<int> SpawnGroupAsync<TComp, TData>(
List<TData> items,
GameObjectPool<TComp> pool,
ComponentType type,
Action<TComp, TData> setup,
Dictionary<string, ComponentBase> registry,
int spawnedCount,
int totalCount,
int batchSize)
where TComp : ComponentBase
where TData : ComponentDataBase
{
if (items == null) return spawnedCount;
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
var comp = pool.GetItem(item.name);
comp.componentType = type;
setup(comp, item);
_uiBinder.BindStandardComponent(comp);
registry[item.name] = comp;
spawnedCount++;
if (totalCount > 0)
UILoadingBar.Percent = 0.7f * spawnedCount / totalCount;
if (spawnedCount % batchSize == 0)
await UniTask.Yield();
}
return spawnedCount;
}
private int CountAllItems(LogicDetailData data)
{
int count = 0;
var ps = data.production_system;
if (ps != null)
{
if (ps.sources != null) count += ps.sources.Count;
if (ps.sinks != null) count += ps.sinks.Count;
if (ps.racks != null) count += ps.racks.Count;
if (ps.asrs != null) count += ps.asrs.Count;
if (ps.robot_arms != null) count += ps.robot_arms.Count;
if (ps.processors != null) count += ps.processors.Count;
}
var infra = data.infrastructure;
if (infra != null)
{
if (infra.queues != null) count += infra.queues.Count;
if (infra.resources != null) count += infra.resources.Count;
}
return count;
}
2026-02-25 16:30:12 +09:00
public ComponentBase FindActiveItem(ComponentType type, string componentId)
{
switch (type)
{
case ComponentType.Source: return _sourcePool?.FindActiveItem(componentId);
case ComponentType.Sink: return _sinkPool?.FindActiveItem(componentId);
case ComponentType.Queue: return _queuePool?.FindActiveItem(componentId);
case ComponentType.Rack: return _rackPool?.FindActiveItem(componentId);
case ComponentType.ASRS: return _asrsPool?.FindActiveItem(componentId);
case ComponentType.RobotArm: return _robotArmPool?.FindActiveItem(componentId);
case ComponentType.Processor:return _processorPool?.FindActiveItem(componentId);
case ComponentType.Worker: return _workerPool?.FindActiveItem(componentId);
default: return null;
}
}
}
}