알람 수정 중

This commit is contained in:
logonkhi
2025-07-02 18:24:00 +09:00
parent b7ad8686f6
commit 08cd464393
21 changed files with 611 additions and 88 deletions

View File

@@ -44,7 +44,8 @@ namespace UVC.Factory.Alarm
//알람 데이터가 AGV와 관련 없는것이 많아서, AGV 이름을 미리 정의합니다.
for (int i = 1; i <= 115; i++)
{
agvNames.Add($"HFF09CNA8{i.ToString("D3")}");
//agvNames.Add($"HFF09CNA8{i.ToString("D3")}");
agvNames.Add($"HFF09CNA8061");
}
}
@@ -186,17 +187,35 @@ namespace UVC.Factory.Alarm
return;
}
// 없으면 새로 생성
FactoryObject? targetObject = dataManager!.FindByName(data.GetString("TRANSPORT_EQP_ID")!);
Debug.Log($"AlarmManager {targetObject==null} {data.Id}, {data.GetString("TRANSPORT_EQP_ID")}");
if (targetObject != null)
string? eqpId = data.GetString("TRANSPORT_EQP_ID");
if (eqpId == null) return;
FactoryObject? targetObject = dataManager!.FindByName(eqpId);
Debug.Log($"AlarmManager {targetObject==null} {data.Id}, {eqpId}");
if (targetObject == null) return;
if (activeAlarmUIs.ContainsKey(eqpId))
{
if(activeAlarmUIs[eqpId].ContainsAlarm(data))
{
activeAlarmUIs[eqpId].UpdateAlarm(data);
}
else
{
activeAlarmUIs[eqpId].AddAlarm(data);
}
}
else
{
// 없으면 새로 생성
GameObject newUIObject = Instantiate(alarmUIPrefab, transform); // 매니저 하위에 생성
AlarmUIController newUiController = newUIObject.GetComponent<AlarmUIController>();
newUiController.Initialize(targetObject, data);
activeAlarmUIs.Add(data.Id!, newUiController);
activeAlarmUIs.Add(eqpId, newUiController);
}
}
@@ -207,11 +226,22 @@ namespace UVC.Factory.Alarm
Debug.LogError($"Modify Alarm Received No data. {data}");
return;
}
string? eqpId = data.GetString("TRANSPORT_EQP_ID");
if (eqpId == null) return;
// 이미 해당 설비에 알람 UI가 떠 있는지 확인
if (activeAlarmUIs.TryGetValue(data.Id!, out AlarmUIController uiController))
if (activeAlarmUIs.TryGetValue(eqpId, out AlarmUIController uiController))
{
// 있으면 기존 UI에 알람 정보만 추가
uiController.UpdateAlarm(data);
// 있으면 기존 UI에 알람 정보 업데이트
if (uiController.ContainsAlarm(data))
{
uiController.UpdateAlarm(data);
}
else
{
// 없으면 새로 추가
uiController.AddAlarm(data);
}
}
}
@@ -222,13 +252,22 @@ namespace UVC.Factory.Alarm
Debug.LogError($"Clear Alarm Received No data. {data}");
return;
}
if (activeAlarmUIs.TryGetValue(data.Id!, out AlarmUIController uiController))
string? eqpId = data.GetString("TRANSPORT_EQP_ID");
if (eqpId == null) return;
if (activeAlarmUIs.TryGetValue(eqpId, out AlarmUIController uiController))
{
uiController.RemoveAlarm(data);
if (uiController.GetAlarmCount() == 0)
// 있으면 기존 UI에 알람 정보 업데이트
if (uiController.ContainsAlarm(data))
{
activeAlarmUIs.Remove(data.Id!);
Destroy(uiController.gameObject);
uiController.RemoveAlarm(data);
if (uiController.GetAlarmCount() == 0)
{
activeAlarmUIs.Remove(data.Id!);
Destroy(uiController.gameObject);
}
}
}
}

View File

@@ -5,7 +5,7 @@ using UVC.Util;
namespace UVC.Factory.Alarm
{
public class SingleAlarmIcon : MonoBehaviour
public class AlarmSingleIcon : MonoBehaviour
{
[Tooltip("알람 내용을 표시하는 텍스트입니다.")]

View File

@@ -18,12 +18,12 @@ namespace UVC.Factory.Alarm
[Tooltip("확장된 알람 뷰입니다. 개별 알람 아이콘을 표시합니다.")]
[SerializeField] private GameObject expandedView;
[Tooltip("개별 알람 아이콘 프리팹입니다. 이 프리팹은 개별 알람 정보를 표시하는 UI 요소를 포함해야 합니다.")]
[SerializeField] private GameObject singleAlarmIconPrefab; // 개별 알람 아이콘
[SerializeField] private GameObject alarmSingleIconPrefab; // 개별 알람 아이콘
private Transform targetObject;
private List<DataObject> alarms = new List<DataObject>();
private bool isExpanded = false;
private SingleAlarmIcon singleAlarmIcon1 = null;
private AlarmSingleIcon singleAlarmIcon1 = null;
private RectTransform rectTransform;
private Canvas mainCanvas;
@@ -99,6 +99,11 @@ namespace UVC.Factory.Alarm
}
}
public bool ContainsAlarm(DataObject alarm)
{
return alarms.Exists(a => a.Id == alarm.Id);
}
public void AddAlarm(DataObject alarm)
{
alarms.Add(alarm);
@@ -156,7 +161,7 @@ namespace UVC.Factory.Alarm
// 여기에 단일 알람 아이콘을 보여주는 로직 추가
if (singleAlarmIcon1 == null)
{
singleAlarmIcon1 = Instantiate(singleAlarmIconPrefab, transform).GetComponent<SingleAlarmIcon>();
singleAlarmIcon1 = Instantiate(alarmSingleIconPrefab, transform).GetComponent<AlarmSingleIcon>();
}
singleAlarmIcon1.gameObject.SetActive(true);
singleAlarmIcon1.SetData(alarms[0], targetObject);
@@ -205,16 +210,17 @@ namespace UVC.Factory.Alarm
}
// 원형으로 아이콘 배치
float radius = 100.0f; // Canvas 좌표계에 맞는 반지름 값
float radius = (alarms.Count - 1) * 20.0f; // Canvas 좌표계에 맞는 반지름 값
for (int i = 0; i < alarms.Count; i++)
{
float angle = i * Mathf.PI * 2f / alarms.Count;
Vector3 pos = new Vector3(Mathf.Cos(angle), Mathf.Sin(angle), 0) * radius;
GameObject iconObj = Instantiate(singleAlarmIconPrefab, expandedView.transform);
GameObject iconObj = Instantiate(alarmSingleIconPrefab, expandedView.transform);
iconObj.transform.localPosition = pos;
// iconObj의 SingleAlarmIcon 스크립트에 알람 데이터 전달
iconObj.GetComponent<SingleAlarmIcon>().SetData(alarms[i], targetObject);
// iconObj의 AlarmSingleIcon 스크립트에 알람 데이터 전달
iconObj.GetComponent<AlarmSingleIcon>().SetData(alarms[i], targetObject);
}
//AnimateUISpace(0f); // 간격을 0으로 애니메이션

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 8822a5b71db85f64483ede945af84867
guid: ef255ae14c2a7a647ab9e652029763b2
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,10 +1,9 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.Core;
namespace UVC.Util
namespace UVC.Factory
{
/// <summary>
/// 마우스 입력에 따라 카메라를 이동, 회전, 줌하는 컨트롤러입니다.
@@ -116,15 +115,15 @@ namespace UVC.Util
if (prevTransform != null && (prevTransform.position != transform.position || prevTransform.rotation != transform.rotation))
{
OnCameraChanged?.Invoke(transform);
if(prevTransform.position != transform.position)
if (prevTransform.position != transform.position)
{
OnCameraPositionChanged?.Invoke(transform.position);
}
if(prevTransform.rotation != transform.rotation)
if (prevTransform.rotation != transform.rotation)
{
OnCameraRotionChanged?.Invoke(transform.rotation);
}
}
}
prevTransform = transform; // 현재 카메라 위치 저장
}
@@ -312,7 +311,7 @@ namespace UVC.Util
float currentPitch = transform.eulerAngles.x;
if (currentPitch > 180f) currentPitch -= 360f;
if (currentPitch < minPitch || currentPitch > maxPitch) return;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 zoomTarget;
@@ -364,7 +363,7 @@ namespace UVC.Util
{
position.y = maxCameraY; // 최대 높이 제한
}
// 카메라가 바라볼 대상의 중심점
Vector3 targetPosition = equipmentPosition;
@@ -400,11 +399,11 @@ namespace UVC.Util
StopFocusCoroutine();
Vector3 position = equipmentPosition;
if(position.y < minCameraY)
if (position.y < minCameraY)
{
position.y = minCameraY; // 최소 높이 제한
}
else if(position.y > maxCameraY)
else if (position.y > maxCameraY)
{
position.y = maxCameraY; // 최대 높이 제한
}
@@ -442,30 +441,30 @@ namespace UVC.Util
{
// 카메라가 바라볼 대상의 중심점
Vector3 targetPosition = targetTransform;
// 시작 위치와 회전 저장
Vector3 startPosition = transform.position;
Quaternion startRotation = transform.rotation;
// 타겟을 보는 최종 위치와 회전 계산
Vector3 directionToTarget = (targetPosition - startPosition).normalized;
Vector3 endPosition = targetPosition - directionToTarget * distance;
// 최종 회전값 계산
Quaternion endRotation = Quaternion.LookRotation(targetPosition - endPosition);
endRotation = ValidateRotation(endRotation); // 회전값 검증 및 수정
// 이동 시간 계산을 위한 변수
float elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
float t = Mathf.Clamp01(elapsedTime / duration);
// 부드러운 이동을 위한 Easing 함수 적용
float smoothT = EaseInOutCubic(t);
// 위치와 회전 보간
transform.position = Vector3.Lerp(startPosition, endPosition, smoothT);
transform.rotation = Quaternion.Slerp(startRotation, endRotation, smoothT);
@@ -474,11 +473,11 @@ namespace UVC.Util
yield return null;
}
// 정확한 최종 위치와 회전 설정
transform.position = endPosition;
transform.LookAt(targetPosition);
// 회전 피봇 포인트 업데이트
rotationPivot = targetPosition;
@@ -487,7 +486,7 @@ namespace UVC.Util
DispatchEvnet();
focusCoroutine = null; // 코루틴 완료 후 참조를 null로 설정
}
/// <summary>
/// Cubic ease-in/out 함수로 부드러운 이동 효과를 줍니다.
/// </summary>
@@ -497,7 +496,7 @@ namespace UVC.Util
}
}
}

View File

@@ -3,8 +3,8 @@ using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UVC.Data;
using UVC.Factory.Modal;
using UVC.Object3d;
using UVC.UI.Info;
namespace UVC.Factory.Component
{

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 331531bab0bc0974c89e2eb1560a5043
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,13 +1,13 @@
#nullable enable
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UVC.Core;
using UVC.UI.Modal;
namespace UVC.UI.Info
namespace UVC.Factory.Modal
{
/// <summary>
/// 3D 객체를 따라다니며 정보를 표시하는 UI 창입니다.
@@ -64,7 +64,7 @@ namespace UVC.UI.Info
{
copyButton.onClick.AddListener(CopyToClipboard);
}
// 처음에는 정보 창을 숨깁니다.
if (gameObject.activeSelf)
@@ -79,6 +79,7 @@ namespace UVC.UI.Info
if (!string.IsNullOrEmpty(message))
{
GUIUtility.systemCopyBuffer = message;
Toast.Show("정보가 클립보드에 복사되었습니다.", 2f, 0.5f);
}
}
@@ -137,7 +138,7 @@ namespace UVC.UI.Info
rectTransform.localPosition = new Vector3(localPoint.x, localPoint.y, rectTransform.localPosition.z);
}
}
// UI가 항상 보이도록 카메라를 향하게 설정 (World Space Canvas인 경우에만 필요)
Canvas parentCanvas = GetComponentInParent<Canvas>();
@@ -171,15 +172,17 @@ namespace UVC.UI.Info
if (target == null) return;
if (text != null)
{
message = string.Empty;
string combinedString = string.Empty;
foreach (var kvp in information)
{
// <indent> 태그를 사용하여 줄바꿈 시에도 정렬이 유지되도록 합니다.
combinedString += $"{kvp.Key}<pos=40%><indent=40%>{kvp.Value ?? "null"}</indent>\n";
message += $"{kvp.Key}: {kvp.Value ?? "null"}\n"; // 메시지에 추가
}
combinedString = combinedString.TrimEnd('\n'); // 마지막 줄바꿈 제거
message = message.TrimEnd('\n'); // 마지막 줄바꿈 제거
text.text = combinedString;
message = combinedString;
}
// size를 text에 맞게 조정합니다.
RectTransform? rect = GetComponent<RectTransform>();

View File

@@ -0,0 +1,115 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UVC.Core;
namespace UVC.UI.Modal
{
public class Toast : SingletonApp<Toast>
{
protected static string prefabPath = "Prefabs/UI/Modal/Toast";
protected static GameObject prefab;
protected static Toast toast;
public static void Show(string message, float duration = 3f, float fadeInOutTime = 0.25f)
{
if (prefab == null) prefab = Resources.Load(prefabPath, typeof(GameObject)) as GameObject;
if (prefab != null && toast == null)
{
GameObject go = UnityEngine.Object.Instantiate(prefab);
toast = go.GetComponent<Toast>();
toast.change(0);
}
if (toast != null)
{
toast.gameObject.SetActive(true);
var canvass = GameObject.FindObjectsByType<Canvas>(FindObjectsSortMode.None);
Canvas canvas = null;
foreach (var c in canvass)
{
if (c.tag == "ModalCanvas")
{
canvas = c;
toast.transform.SetParent(canvas.transform);
toast.show(message, duration, fadeInOutTime);
break;
}
}
}
}
protected CanvasGroup canvasGroup;
protected TextMeshProUGUI txt;
protected void show(string message, float duration = 3, float fadeInOutTime = 0.25f)
{
StopAllCoroutines();
StartCoroutine(showCoroutine(message, duration, fadeInOutTime));
}
protected IEnumerator showCoroutine(string message, float duration = 3, float fadeInOutTime = 0.25f)
{
if (txt == null) txt = GetComponentInChildren<TextMeshProUGUI>();
fitTextWidth(GetComponent<RectTransform>(), txt, message);
yield return fadeInOut(fadeInOutTime, true);
change(1);
float elapsedTime = 0.0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
yield return null;
}
yield return fadeInOut(fadeInOutTime, false);
change(0);
transform.SetParent(null);
gameObject.SetActive(true);
}
protected IEnumerator fadeInOut(float durationTime, bool inOut)
{
float start = 0.0f;
float end = 1.0f;
if (!inOut)
{
start = 1.0f;
end = 0.0f;
}
float elapsedTime = 0.0f;
while (elapsedTime < durationTime)
{
float alpha = Mathf.Lerp(start, end, elapsedTime / durationTime);
change(alpha);
elapsedTime += Time.deltaTime;
yield return null;
}
}
protected void change(float alpha)
{
if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>();
canvasGroup.alpha = alpha;
}
private void fitTextWidth(RectTransform rect, TextMeshProUGUI text, string textValue)
{
text.text = textValue;
Vector2 rectSize = rect.sizeDelta;
rectSize.x = text.preferredWidth + 20;
rect.sizeDelta = rectSize;
rect.anchoredPosition = new Vector2(0, rectSize.y + 10);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d007f3f774d241a44a69d7349dd7c464