Files
ChunilENG/Assets/WorkSpace/Personal/JYM/MachineKPIManager.cs

258 lines
9.0 KiB
C#
Raw Normal View History

using System;
2025-02-20 09:59:37 +09:00
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using WI;
namespace CHN
{
public class MachineKPIManager : MonoBehaviour, ISingle
{
public UI_MachineKPI prefab_MachineKPI;
private OrbitalController cam;
private Machine[] machines;
private List<Machine> matchingMachines = new();
private SDictionary<string, UI_MachineKPI> machineKPIs = new();
2025-04-01 13:47:45 +09:00
private List<UI_MachineKPI> kpis = new List<UI_MachineKPI>();
2025-02-20 09:59:37 +09:00
2025-02-25 10:23:33 +09:00
private UI_MachineKPI current_MachineKPI;
2025-02-20 09:59:37 +09:00
public float defaultNameHeight;
public float radius;
public Vector3 originScale;
2025-04-01 13:47:45 +09:00
public float verticalSpacing = 100f;
2025-02-20 09:59:37 +09:00
public Action<UI_MachineKPI> onClickKPI;
2025-04-01 13:47:45 +09:00
[Range(0.1f, 0.8f)]
2025-03-12 14:57:35 +09:00
public float minScale;
2025-04-01 13:47:45 +09:00
[Range(0.5f, 1.5f)]
2025-03-12 14:57:35 +09:00
public float maxScale;
[Range(0.1f, 2f)]
public float scaleClamp;
2025-02-20 09:59:37 +09:00
public void SetMachineKPI(MachineKPIData machineKPIData)
{
foreach (var item in machineKPIs)
{
Destroy(item.Value.gameObject);
}
2025-04-07 13:37:31 +09:00
uiElements.Clear();
2025-02-20 09:59:37 +09:00
machineKPIs.Clear();
matchingMachines.Clear();
cam = FindSingle<OrbitalController>();
prefab_MachineKPI = Resources.Load<UI_MachineKPI>("Prefabs/UI/PRF_UI_MachineKPI");
foreach (var data in machineKPIData.data.rows)
{
if (machineKPIs.ContainsKey(data.workcd))
continue;
var machineKPI = Instantiate(prefab_MachineKPI, transform);
machineKPI.SetData(data);
2025-02-25 10:23:33 +09:00
machineKPI.onClickKPI += OnClickMachineKPI;
2025-02-20 09:59:37 +09:00
machineKPI.name = data.workcd;
2025-03-12 15:02:16 +09:00
machineKPI.SetActive(false);
2025-04-01 13:47:45 +09:00
uiElements.Add(machineKPI.rectTransform);
2025-02-20 09:59:37 +09:00
2025-04-01 13:47:45 +09:00
kpis.Add(machineKPI);
2025-02-20 09:59:37 +09:00
machineKPIs.Add(data.workcd, machineKPI);
}
var building = FindSingle<Building>();
machines = building.floors.SelectMany(f => f.machines).ToArray();
foreach (var machine in machines)
{
if (machineKPIs.ContainsKey(machine.code))
{
machine.machineKPI = machineKPIs[machine.code];
var machinePos = machine.centerPos;
machine.machineKPI.transform.position = new Vector3(machinePos.x, machinePos.y + defaultNameHeight, machinePos.z);
matchingMachines.Add(machine);
machine.SetAnimationSpeed();
2025-02-20 09:59:37 +09:00
}
}
}
2025-02-25 10:23:33 +09:00
private void OnClickMachineKPI(UI_MachineKPI machineKPI)
{
foreach(var machine in machines)
2025-02-25 10:23:33 +09:00
{
if (machine.machineKPI != null)
{
machine.machineKPI.Shrink();
}
2025-02-25 10:23:33 +09:00
}
current_MachineKPI = machineKPI;
current_MachineKPI.Expand();
2025-03-12 14:57:35 +09:00
current_MachineKPI.transform.SetAsLastSibling();
onClickKPI?.Invoke(current_MachineKPI);
2025-02-25 10:23:33 +09:00
}
2025-02-20 09:59:37 +09:00
private void Update()
{
2025-04-01 13:47:45 +09:00
GroupOverlappingUIElements();
2025-02-20 09:59:37 +09:00
RangeDetection();
2025-02-25 10:23:33 +09:00
RectangleContainsPoint();
}
private void RectangleContainsPoint()
{
if (Input.GetMouseButton(0))
{
if (current_MachineKPI == null)
return;
if(!RectTransformUtility.RectangleContainsScreenPoint(current_MachineKPI.DetailsKPI, Input.mousePosition))
{
current_MachineKPI.Shrink();
current_MachineKPI = null;
}
}
2025-02-20 09:59:37 +09:00
}
2025-04-01 13:47:45 +09:00
public List<RectTransform> uiElements = new List<RectTransform>();
public List<List<RectTransform>> groupedElements = new List<List<RectTransform>>();
void GroupOverlappingUIElements()
2025-02-20 09:59:37 +09:00
{
2025-04-01 13:47:45 +09:00
foreach(var matchingMachine in matchingMachines)
{
var machinePos = matchingMachine.centerPos;
var screenPos = cam.camera.WorldToScreenPoint(new Vector3(machinePos.x, machinePos.y + defaultNameHeight, machinePos.z));
matchingMachine.machineKPI.transform.position = screenPos;
}
// <20>׷<EFBFBD>ȭ<EFBFBD><C8AD> UI <20><><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD> <20>ʱ<EFBFBD>ȭ
groupedElements.Clear();
// UI <20><><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD> <20><>ħ <20><><EFBFBD>ο<EFBFBD> <20><><EFBFBD><EFBFBD> <20>׷<EFBFBD>ȭ
var uncheckedElements = new HashSet<RectTransform>(uiElements); // <20><>ħ <20><><EFBFBD><EFBFBD> üũ <20>ȵ<EFBFBD> UI <20><><EFBFBD>ҵ<EFBFBD>
// <20><>ħ<EFBFBD><C4A7> Ȯ<><C8AE><EFBFBD><EFBFBD> UI <20><><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׷<EFBFBD>ȭ
while (uncheckedElements.Count > 0)
{
var currentElement = uncheckedElements.First();
uncheckedElements.Remove(currentElement);
var group = new List<RectTransform> { currentElement };
// <20>׷<EFBFBD>ȭ<EFBFBD><C8AD> UI <20><><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD> <20>߰<EFBFBD>
var overlappingElements = uncheckedElements.Where(element => AreRectanglesOverlapping(currentElement, element)).ToList();
foreach (var overlappingElement in overlappingElements)
{
uncheckedElements.Remove(overlappingElement);
group.Add(overlappingElement);
}
groupedElements.Add(group);
}
foreach (var group in groupedElements)
2025-02-20 09:59:37 +09:00
{
2025-04-01 13:47:45 +09:00
var centerPos = GroupCenterCalculate(group);
2025-02-20 09:59:37 +09:00
2025-04-01 13:47:45 +09:00
for (int i = 0; i < group.Count; i++)
2025-02-20 09:59:37 +09:00
{
2025-04-01 13:47:45 +09:00
var kpi = group[i];
var newPos = new Vector3(centerPos.x, centerPos.y + kpi.rect.height * i * kpi.transform.localScale.y, centerPos.z);
kpi.transform.localPosition = newPos;
2025-02-20 09:59:37 +09:00
}
}
}
2025-04-01 13:47:45 +09:00
private bool AreRectanglesOverlapping(RectTransform rectA, RectTransform rectB)
{
Rect rectAWorld = GetWorldRect(rectA);
Rect rectBWorld = GetWorldRect(rectB);
return rectAWorld.Overlaps(rectBWorld);
}
private Rect GetWorldRect(RectTransform rectTransform)
{
Vector3[] worldCorners = new Vector3[4];
rectTransform.GetWorldCorners(worldCorners);
Vector2 min = new Vector2(worldCorners[0].x, worldCorners[0].y);
Vector2 max = new Vector2(worldCorners[2].x, worldCorners[2].y);
return new Rect(min, max - min);
}
private Vector3 GroupCenterCalculate(List<RectTransform> group)
{
var centerPos = Vector3.zero;
group.Sort((a, b) => a.transform.localPosition.y.CompareTo(b.transform.localPosition.y));
foreach (var kpi in group)
{
centerPos += kpi.transform.localPosition;
}
centerPos /= group.Count;
return centerPos;
}
2025-02-20 09:59:37 +09:00
void RangeDetection()
{
var layerMask = LayerMask.GetMask("Camera", "Floor Wall");
2025-02-20 09:59:37 +09:00
var currentFloor = FindSingle<Building>().currentFloor;
2025-03-12 14:57:35 +09:00
var max = cam.option.maxDistance - cam.option.minDistance;
var distance = cam.option.currentDistance;
var distanceScale = (max - distance) / max;
distanceScale *= scaleClamp;
distanceScale = Mathf.Clamp(distanceScale, minScale, maxScale);
2025-02-20 09:59:37 +09:00
foreach (var machine in matchingMachines)
{
2025-03-12 14:57:35 +09:00
if (machine.GetComponentInParent<Floor>() != currentFloor)
{
2025-04-01 13:47:45 +09:00
machine.machineKPI.Deactive();
2025-03-12 14:57:35 +09:00
continue;
}
2025-03-12 14:57:35 +09:00
MachineKPIsActive(machine, layerMask);
var machineKPI = machine.machineKPI;
machineKPI.transform.localScale = originScale * distanceScale;
2025-02-20 09:59:37 +09:00
}
}
bool IsScreenRange(Machine machine)
{
Vector3 viewPos = cam.camera.WorldToViewportPoint(machine.centerPos);
if (viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1 && viewPos.z > 0)
{
return true;
}
return false;
}
2025-02-20 09:59:37 +09:00
void MachineKPIsActive(Machine machine, LayerMask layerMask)
{
var dir = cam.camera.transform.position - machine.centerPos;
2025-02-20 09:59:37 +09:00
var hit = new RaycastHit();
if (Physics.Raycast(machine.centerPos, dir, out hit, Mathf.Infinity, layerMask))
{
var hitCameraLayer = hit.collider.gameObject.layer.Equals(LayerMask.NameToLayer("Camera"));
if (hitCameraLayer)
{
if (!IsScreenRange(machine))
{
machine.machineKPI.Deactive();
}
else
{
machine.machineKPI.Active();
}
2025-02-20 09:59:37 +09:00
}
else
{
machine.machineKPI.Deactive();
}
}
}
}
}