Merge pull request 'dd' (#40) from dd into main
Reviewed-on: http://220.90.135.190:3000/UVCXR/OCTOPUS_TWIN-Demo/pulls/40
This commit was merged in pull request #40.
This commit is contained in:
@@ -2,35 +2,68 @@ using UnityEngine;
|
||||
|
||||
namespace OCTOPUS_TWIN
|
||||
{
|
||||
/// <summary>
|
||||
/// 카메라 경유점. CameraRoute의 자식 오브젝트에 추가하여 궤도 파라미터를 설정.
|
||||
/// 없으면 자식 Transform의 position만 사용하고 궤도 파라미터는 현재 카메라 상태 유지.
|
||||
/// </summary>
|
||||
public class CameraRoutePoint : MonoBehaviour
|
||||
{
|
||||
public float elevation = 45f;
|
||||
public float azimuth = 0f;
|
||||
public float distance = 30f;
|
||||
[Tooltip("이 지점까지의 이동 시간(초)")]
|
||||
public float duration = 0.5f;
|
||||
[Tooltip("이 지점에서의 대기 시간(초)")]
|
||||
public float waitTime = 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 카메라 이동 경로. 자식 Transform 순서대로 카메라가 보간 이동.
|
||||
/// 각 자식에 CameraRoutePoint를 추가하면 궤도 파라미터(elevation, azimuth, distance)도 제어 가능.
|
||||
/// </summary>
|
||||
public class CameraRoute : MonoBehaviour
|
||||
{
|
||||
public bool loop;
|
||||
[SerializeField] private int gizmoResolution = 20;
|
||||
[SerializeField] private Color gizmoColor = Color.cyan;
|
||||
|
||||
public int PointCount => transform.childCount;
|
||||
public MovePoint[] movePoints;
|
||||
|
||||
public (Vector3 position, CameraRoutePoint point) GetWaypoint(int index)
|
||||
void Awake()
|
||||
{
|
||||
var child = transform.GetChild(index);
|
||||
return (child.position, child.GetComponent<CameraRoutePoint>());
|
||||
movePoints = GetComponentsInChildren<MovePoint>();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
var points = Application.isPlaying
|
||||
? movePoints
|
||||
: GetComponentsInChildren<MovePoint>();
|
||||
|
||||
if (points == null || points.Length < 2) return;
|
||||
|
||||
Gizmos.color = gizmoColor;
|
||||
|
||||
for (int i = 1; i < points.Length; i++)
|
||||
{
|
||||
Vector3 p0 = (i >= 2) ? points[i - 2].transform.position : points[i - 1].transform.position;
|
||||
Vector3 p1 = points[i - 1].transform.position;
|
||||
Vector3 p2 = points[i].transform.position;
|
||||
Vector3 p3 = (i + 1 < points.Length) ? points[i + 1].transform.position : points[i].transform.position;
|
||||
|
||||
Vector3 prev = p1;
|
||||
for (int s = 1; s <= gizmoResolution; s++)
|
||||
{
|
||||
float t = s / (float)gizmoResolution;
|
||||
Vector3 curr = CatmullRom(p0, p1, p2, p3, t);
|
||||
Gizmos.DrawLine(prev, curr);
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
Gizmos.color = (i == 0) ? Color.green : gizmoColor;
|
||||
Gizmos.DrawWireSphere(points[i].transform.position, 0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
||||
{
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
return 0.5f * (
|
||||
2f * p1 +
|
||||
(-p0 + p2) * t +
|
||||
(2f * p0 - 5f * p1 + 4f * p2 - p3) * t2 +
|
||||
(-p0 + 3f * p1 - 3f * p2 + p3) * t3
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6de7838db2221394597524e5a7722f9f
|
||||
guid: 6de7838db2221394597524e5a7722f9f
|
||||
|
||||
11
Assets/Scripts/Camera/MovePoint.cs
Normal file
11
Assets/Scripts/Camera/MovePoint.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OCTOPUS_TWIN
|
||||
{
|
||||
public class MovePoint : MonoBehaviour
|
||||
{
|
||||
public Ease easeType = Ease.InOutSine;
|
||||
public float speed = -1f;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Camera/MovePoint.cs.meta
Normal file
2
Assets/Scripts/Camera/MovePoint.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98ee8b0a292db7549857af100e90ae1e
|
||||
@@ -65,6 +65,11 @@ namespace OCTOPUS_TWIN
|
||||
public bool IsRouteActive => routeSequence != null && routeSequence.IsActive();
|
||||
private Sequence routeSequence;
|
||||
|
||||
private CameraRoute currentRoute;
|
||||
public bool IsRouteRunning { get; private set; }
|
||||
public Action onRouteComplete;
|
||||
public CameraRoute route;
|
||||
|
||||
public bool IsClickUI
|
||||
{
|
||||
get
|
||||
@@ -150,6 +155,10 @@ namespace OCTOPUS_TWIN
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Q))
|
||||
{
|
||||
SetRoute(route);
|
||||
}
|
||||
//UI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ī<><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
if (IsClickUI || IsOnTheUI)
|
||||
return;
|
||||
@@ -232,11 +241,11 @@ namespace OCTOPUS_TWIN
|
||||
currentAzimuth += input.mouseX * rotateSpeed;
|
||||
currentAzimuth %= 360;
|
||||
|
||||
//if(viewMode == ViewMode.PerspectiveView)
|
||||
//{
|
||||
// currentElevation -= input.mouseY * rotateSpeed;
|
||||
// currentElevation = Mathf.Clamp(currentElevation, minElevation, maxElevation);
|
||||
//}
|
||||
if(viewMode == ViewMode.PerspectiveView)
|
||||
{
|
||||
currentElevation -= input.mouseY * rotateSpeed;
|
||||
currentElevation = Mathf.Clamp(currentElevation, minElevation, maxElevation);
|
||||
}
|
||||
isRotateOperation = true;
|
||||
}
|
||||
|
||||
@@ -354,71 +363,122 @@ namespace OCTOPUS_TWIN
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public void SetRoute(CameraRoute route)
|
||||
{
|
||||
StopRoute();
|
||||
currentRoute = route;
|
||||
|
||||
var points = currentRoute.movePoints;
|
||||
if (points == null || points.Length == 0) return;
|
||||
|
||||
IsRouteRunning = true;
|
||||
Enable = false;
|
||||
|
||||
routeSequence = DOTween.Sequence();
|
||||
camera.transform.position = points[0].transform.position;
|
||||
camera.transform.rotation = points[0].transform.rotation;
|
||||
|
||||
for (int i = 0; i < route.PointCount; i++)
|
||||
if (points.Length == 1)
|
||||
{
|
||||
var (position, point) = route.GetWaypoint(i);
|
||||
|
||||
float elev = point != null ? point.elevation : currentElevation;
|
||||
float azi = point != null ? point.azimuth : currentAzimuth;
|
||||
float dist = point != null ? point.distance : currentDistance;
|
||||
float dur = point != null ? point.duration : 0.5f;
|
||||
float wait = point != null ? point.waitTime : 0f;
|
||||
|
||||
routeSequence.Append(
|
||||
DOTween.To(() => nextPosition, x => nextPosition = x, position, dur));
|
||||
routeSequence.Join(
|
||||
DOTween.To(() => currentElevation, x => currentElevation = x, elev, dur));
|
||||
routeSequence.Join(
|
||||
DOTween.To(() => currentAzimuth, x => currentAzimuth = x, azi, dur));
|
||||
routeSequence.Join(
|
||||
DOTween.To(() => currentDistance, x => currentDistance = x, dist, dur));
|
||||
|
||||
if (wait > 0f)
|
||||
routeSequence.AppendInterval(wait);
|
||||
CompleteRoute();
|
||||
return;
|
||||
}
|
||||
|
||||
if (route.loop)
|
||||
routeSequence.SetLoops(-1, LoopType.Restart);
|
||||
int segCount = points.Length - 1;
|
||||
float[] segDurations = new float[segCount];
|
||||
float totalDuration = 0f;
|
||||
for (int i = 0; i < segCount; i++)
|
||||
{
|
||||
float dist = Vector3.Distance(points[i].transform.position, points[i + 1].transform.position);
|
||||
float spd = points[i + 1].speed > 0f ? points[i + 1].speed : moveSpeed;
|
||||
segDurations[i] = spd > 0f ? dist / spd : 1f;
|
||||
totalDuration += segDurations[i];
|
||||
}
|
||||
|
||||
routeSequence.OnUpdate(LastPositioning);
|
||||
routeSequence.OnKill(() => Enable = true);
|
||||
float[] segEnd = new float[segCount];
|
||||
float acc = 0f;
|
||||
for (int i = 0; i < segCount; i++)
|
||||
{
|
||||
acc += segDurations[i];
|
||||
segEnd[i] = acc / totalDuration;
|
||||
}
|
||||
|
||||
Vector3[] pos = new Vector3[points.Length];
|
||||
Quaternion[] rot = new Quaternion[points.Length];
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
pos[i] = points[i].transform.position;
|
||||
rot[i] = points[i].transform.rotation;
|
||||
}
|
||||
|
||||
routeSequence = DOTween.Sequence();
|
||||
routeSequence.Append(
|
||||
DOVirtual.Float(0f, 1f, totalDuration, t =>
|
||||
{
|
||||
int seg = segCount - 1;
|
||||
for (int i = 0; i < segEnd.Length; i++)
|
||||
{
|
||||
if (t <= segEnd[i]) { seg = i; break; }
|
||||
}
|
||||
|
||||
float start = seg > 0 ? segEnd[seg - 1] : 0f;
|
||||
float localT = Mathf.InverseLerp(start, segEnd[seg], t);
|
||||
|
||||
int idx = seg + 1;
|
||||
Vector3 p0 = (idx >= 2) ? pos[idx - 2] : pos[idx - 1];
|
||||
Vector3 p1 = pos[idx - 1];
|
||||
Vector3 p2 = pos[idx];
|
||||
Vector3 p3 = (idx + 1 < pos.Length) ? pos[idx + 1] : pos[idx];
|
||||
|
||||
camera.transform.position = CatmullRom(p0, p1, p2, p3, localT);
|
||||
camera.transform.rotation = Quaternion.Slerp(rot[idx - 1], rot[idx], localT);
|
||||
}).SetEase(Ease.Linear));
|
||||
|
||||
routeSequence.OnComplete(CompleteRoute);
|
||||
}
|
||||
|
||||
private static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
||||
{
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
return 0.5f * (
|
||||
2f * p1 +
|
||||
(-p0 + p2) * t +
|
||||
(2f * p0 - 5f * p1 + 4f * p2 - p3) * t2 +
|
||||
(-p0 + 3f * p1 - 3f * p2 + p3) * t3
|
||||
);
|
||||
}
|
||||
|
||||
public void StopRoute()
|
||||
{
|
||||
if (routeSequence != null && routeSequence.IsActive())
|
||||
{
|
||||
routeSequence.Kill();
|
||||
routeSequence = null;
|
||||
}
|
||||
if (!IsRouteRunning) return;
|
||||
routeSequence?.Kill();
|
||||
routeSequence = null;
|
||||
currentRoute = null;
|
||||
IsRouteRunning = false;
|
||||
SyncFromCamera();
|
||||
Enable = true;
|
||||
}
|
||||
|
||||
public void AnimateToState(Vector3 pivotPosition, Vector3 eulerAngles, float distance, float duration = 0.4f)
|
||||
private void CompleteRoute()
|
||||
{
|
||||
// <20>ִϸ<D6B4><CFB8>̼<EFBFBD> <20>߿<EFBFBD><DFBF><EFBFBD> <20><><EFBFBD>콺 <20>Է<EFBFBD> <20><>Ȱ<EFBFBD><C8B0>ȭ
|
||||
Enable = false;
|
||||
|
||||
// DoTween<65><6E> <20><><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20><>Ʈ<EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε巴<CEB5><E5B7B4> <20><><EFBFBD><EFBFBD>
|
||||
DOTween.To(() => nextPosition, x => nextPosition = x, pivotPosition, duration);
|
||||
DOTween.To(() => currentElevation, x => currentElevation = x, eulerAngles.x, duration);
|
||||
DOTween.To(() => currentAzimuth, x => currentAzimuth = x, eulerAngles.y, duration);
|
||||
DOTween.To(() => currentDistance, x => currentDistance = x, distance, duration)
|
||||
.OnComplete(() => {
|
||||
// <20>ִϸ<D6B4><CFB8>̼<EFBFBD><CCBC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>콺 <20>Է<EFBFBD><D4B7><EFBFBD> <20>ٽ<EFBFBD> Ȱ<><C8B0>ȭ
|
||||
Enable = true;
|
||||
});
|
||||
routeSequence = null;
|
||||
currentRoute = null;
|
||||
IsRouteRunning = false;
|
||||
SyncFromCamera();
|
||||
Enable = true;
|
||||
onRouteComplete?.Invoke();
|
||||
}
|
||||
|
||||
//public bool IsOperation()
|
||||
//{
|
||||
// if(is)
|
||||
//}
|
||||
private void SyncFromCamera()
|
||||
{
|
||||
var euler = camera.transform.eulerAngles;
|
||||
currentElevation = euler.x;
|
||||
currentAzimuth = euler.y;
|
||||
|
||||
var offset = Quaternion.Euler(euler.x, euler.y, 0f) * new Vector3(0, 0, -currentDistance);
|
||||
nextPosition = camera.transform.position - offset;
|
||||
cameraPivot.transform.position = nextPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,15 @@ using Cysharp.Threading.Tasks;
|
||||
using OCTOPUS_TWIN;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UVC.Config;
|
||||
using UVC.Entity;
|
||||
using UVC.Entity.Processors;
|
||||
using UVC.Management;
|
||||
using UVC.Object3d.Manager;
|
||||
using OCTOPUS_TWIN.Command;
|
||||
using UVC.Core;
|
||||
using UVC.UI.Window.PropertyWindow;
|
||||
|
||||
namespace ChunilENG.Management
|
||||
@@ -22,6 +28,9 @@ namespace ChunilENG.Management
|
||||
private List<Machine> machines;
|
||||
private Dictionary<string, MachineInfoItem> machineKPIs = new();
|
||||
private Dictionary<MachineInfoItem, Machine> itemToMachines = new();
|
||||
private Dictionary<MachineInfoItem, StageObjectManager.StageObject> itemToStageObjects = new();
|
||||
|
||||
private StageObjectManager stageObjectManager;
|
||||
|
||||
public Action<Machine> onClickKPIToMachine;
|
||||
|
||||
@@ -39,24 +48,43 @@ namespace ChunilENG.Management
|
||||
cam = OctopusTwinAppMain.Instance.cameraController; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: Start<72><74><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD>Ͽ<EFBFBD> ij<><C4B3>
|
||||
|
||||
machineInfoItem = Resources.Load<MachineInfoItem>($"{ResourceURL.chunilENGUIPrefabFolderPath}{nameof(MachineInfoItem)}");
|
||||
stageObjectManager = InjectorAppContext.Instance.Get<StageObjectManager>();
|
||||
machines = ChunilENGSceneMain.Instance.building.GetMachines();
|
||||
if (machines != null)
|
||||
{
|
||||
foreach (var machine in machines)
|
||||
{
|
||||
var infoItem = Instantiate(machineInfoItem, transform);
|
||||
infoItem.Init();
|
||||
machine.machineKPI = infoItem;
|
||||
infoItem.onClickItem += OnClickMachineInfoItem;
|
||||
itemToMachines.Add(infoItem, machine);
|
||||
Regist(machine);
|
||||
}
|
||||
}
|
||||
|
||||
// StageObject 감시
|
||||
if (stageObjectManager != null)
|
||||
{
|
||||
stageObjectManager.OnObjectAdded += OnStageObjectAdded;
|
||||
stageObjectManager.OnObjectRemoved += OnStageObjectRemoved;
|
||||
|
||||
foreach (var kvp in stageObjectManager.Objects)
|
||||
{
|
||||
OnStageObjectAdded(kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
await UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public void Regist(Machine machine)
|
||||
{
|
||||
var infoItem = Instantiate(machineInfoItem, transform);
|
||||
infoItem.Init();
|
||||
machine.machineKPI = infoItem;
|
||||
infoItem.onClickItem += OnClickMachineInfoItem;
|
||||
itemToMachines.Add(infoItem, machine);
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
{
|
||||
if (machines == null || machines.Count == 0)
|
||||
if ((machines == null || machines.Count == 0) && itemToStageObjects.Count == 0)
|
||||
return;
|
||||
|
||||
IconPositionSetting();
|
||||
@@ -64,18 +92,35 @@ namespace ChunilENG.Management
|
||||
}
|
||||
private void IconPositionSetting()
|
||||
{
|
||||
foreach (var machine in machines)
|
||||
if (machines != null)
|
||||
{
|
||||
var worldPos = machine.centerPos + Vector3.up * defaultNameHeight;
|
||||
foreach (var machine in machines)
|
||||
{
|
||||
var worldPos = machine.centerPos + Vector3.up * defaultNameHeight;
|
||||
var screenPos = Camera.main.WorldToScreenPoint(worldPos);
|
||||
|
||||
if (screenPos.z < 0.3f)
|
||||
{
|
||||
machine.machineKPI.Deactive();
|
||||
continue;
|
||||
}
|
||||
|
||||
machine.machineKPI.transform.position = screenPos;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kvp in itemToStageObjects)
|
||||
{
|
||||
var worldPos = kvp.Value.gameObject.transform.position + Vector3.up * defaultNameHeight;
|
||||
var screenPos = Camera.main.WorldToScreenPoint(worldPos);
|
||||
|
||||
if (screenPos.z < 0.3f)
|
||||
{
|
||||
machine.machineKPI.Deactive();
|
||||
kvp.Key.Deactive();
|
||||
continue;
|
||||
}
|
||||
|
||||
machine.machineKPI.transform.position = screenPos;
|
||||
kvp.Key.transform.position = screenPos;
|
||||
}
|
||||
}
|
||||
void RangeDetection()
|
||||
@@ -84,11 +129,20 @@ namespace ChunilENG.Management
|
||||
float scale = Mathf.Lerp(minScale, maxScale, t);
|
||||
var newScale = new Vector3(scale, scale, scale);
|
||||
|
||||
foreach (var machine in machines)
|
||||
if (machines != null)
|
||||
{
|
||||
MachineIconsActive(machine);
|
||||
var machineInfoItem = machine.machineKPI;
|
||||
machineInfoItem.transform.localScale = newScale;
|
||||
foreach (var machine in machines)
|
||||
{
|
||||
MachineIconsActive(machine);
|
||||
var machineInfoItem = machine.machineKPI;
|
||||
machineInfoItem.transform.localScale = newScale;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kvp in itemToStageObjects)
|
||||
{
|
||||
kvp.Key.Active();
|
||||
kvp.Key.transform.localScale = newScale;
|
||||
}
|
||||
}
|
||||
void MachineIconsActive(Machine machine)
|
||||
@@ -158,5 +212,137 @@ namespace ChunilENG.Management
|
||||
icon.gameObject.SetActive(isActive);
|
||||
}
|
||||
}
|
||||
|
||||
#region StageObject
|
||||
|
||||
private void OnStageObjectAdded(StageObjectManager.StageObject stageObject)
|
||||
{
|
||||
if (stageObject.TryGetProcessor<TwinAgentAutoProcessor>(out var processor))
|
||||
{
|
||||
if (processor.IsCompleted)
|
||||
{
|
||||
RegistStageObject(stageObject);
|
||||
return;
|
||||
}
|
||||
processor.onComplete += () => OnProcessorCompleted(stageObject);
|
||||
return;
|
||||
}
|
||||
|
||||
// 프로세서가 아직 없으면 등록 시점에 구독
|
||||
stageObject.OnProcessorRegistered += registeredProcessor =>
|
||||
{
|
||||
if (registeredProcessor is TwinAgentAutoProcessor)
|
||||
{
|
||||
registeredProcessor.onComplete += () => OnProcessorCompleted(stageObject);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void OnProcessorCompleted(StageObjectManager.StageObject stageObject)
|
||||
{
|
||||
if (itemToStageObjects.ContainsValue(stageObject)) return;
|
||||
RegistStageObject(stageObject);
|
||||
}
|
||||
|
||||
public void RegistStageObject(StageObjectManager.StageObject stageObject)
|
||||
{
|
||||
var infoItem = Instantiate(machineInfoItem, transform);
|
||||
infoItem.Init();
|
||||
|
||||
var mockData = CreateMockCompleteInfo(stageObject.Equipment);
|
||||
infoItem.SetData(mockData, stageObject.Equipment.label);
|
||||
infoItem.onClickItem += OnClickStageObjectInfoItem;
|
||||
|
||||
itemToStageObjects.Add(infoItem, stageObject);
|
||||
}
|
||||
|
||||
private void OnStageObjectRemoved(StageObjectManager.StageObject stageObject)
|
||||
{
|
||||
var item = itemToStageObjects.FirstOrDefault(kvp => kvp.Value == stageObject).Key;
|
||||
if (item != null)
|
||||
{
|
||||
itemToStageObjects.Remove(item);
|
||||
Destroy(item.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClickStageObjectInfoItem(MachineInfoItem item)
|
||||
{
|
||||
item.transform.SetAsLastSibling();
|
||||
CommandManager.Instance.Execute(
|
||||
new OpenMachineDashBoardCommand(propertyWindow, null, item.data));
|
||||
}
|
||||
|
||||
private CompleteInfo CreateMockCompleteInfo(EquipmentItem equipment)
|
||||
{
|
||||
int plan = UnityEngine.Random.Range(300, 600);
|
||||
int goal = (int)(plan * UnityEngine.Random.Range(0.85f, 0.95f));
|
||||
int work = UnityEngine.Random.Range((int)(plan * 0.6f), plan);
|
||||
int good = (int)(work * UnityEngine.Random.Range(0.93f, 0.99f));
|
||||
int bad = work - good;
|
||||
float badRate = work > 0 ? (float)bad / work * 100f : 0f;
|
||||
float efficiency = UnityEngine.Random.Range(80f, 99f);
|
||||
float progressRate = plan > 0 ? (float)work / plan * 100f : 0f;
|
||||
float eoRate = UnityEngine.Random.Range(85f, 99f);
|
||||
float poRate = UnityEngine.Random.Range(80f, 98f);
|
||||
float goodQtyRate = work > 0 ? (float)good / work * 100f : 0f;
|
||||
|
||||
int startHour = UnityEngine.Random.Range(6, 10);
|
||||
int startMin = UnityEngine.Random.Range(0, 59);
|
||||
int endHour = UnityEngine.Random.Range(17, 22);
|
||||
int endMin = UnityEngine.Random.Range(0, 59);
|
||||
|
||||
return new CompleteInfo
|
||||
{
|
||||
datagbn = "P",
|
||||
wordno = $"W{UnityEngine.Random.Range(1000, 9999)}",
|
||||
workdt = DateTime.Now.ToString("yyyyMMdd"),
|
||||
daynight = "1",
|
||||
sitecd = "S01",
|
||||
wccd = "WC01",
|
||||
workcd = equipment.id,
|
||||
worknm = equipment.label,
|
||||
workseq = UnityEngine.Random.Range(1, 5).ToString(),
|
||||
status = "30",
|
||||
statusnm = "가동중",
|
||||
itemcd = $"ITM-{UnityEngine.Random.Range(10000, 99999)}",
|
||||
itemdesc = $"{equipment.label} 부품",
|
||||
pjtcd = $"PJT-{UnityEngine.Random.Range(100, 999)}",
|
||||
matcd = $"MAT-{UnityEngine.Random.Range(1000, 9999)}",
|
||||
cycletime = UnityEngine.Random.Range(10, 60).ToString(),
|
||||
cavity = UnityEngine.Random.Range(1, 8).ToString(),
|
||||
planqty = plan.ToString(),
|
||||
goalqty = goal.ToString(),
|
||||
workqty = work.ToString(),
|
||||
goodqty = good.ToString(),
|
||||
badqty = bad.ToString(),
|
||||
badrate = badRate.ToString("F1"),
|
||||
efficiency = efficiency.ToString("F1"),
|
||||
progressrate = progressRate.ToString("F1"),
|
||||
sttm = $"{startHour:D2}{startMin:D2}",
|
||||
totm = $"{endHour:D2}{endMin:D2}",
|
||||
goaltime = "",
|
||||
ptotm = "",
|
||||
psttm = "",
|
||||
moldcd = "",
|
||||
moldseq = "",
|
||||
eorate = eoRate.ToString("F1"),
|
||||
porate = poRate.ToString("F1"),
|
||||
goodqtyrate = goodQtyRate.ToString("F1"),
|
||||
lct = "",
|
||||
wct = "",
|
||||
};
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (stageObjectManager != null)
|
||||
{
|
||||
stageObjectManager.OnObjectAdded -= OnStageObjectAdded;
|
||||
stageObjectManager.OnObjectRemoved -= OnStageObjectRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ namespace ChunilENG.UI
|
||||
}
|
||||
private void SetTextData(CompleteInfo data, Machine machine)
|
||||
{
|
||||
MachineName.SetText(SetNameData(data.worknm, machine.machineName));
|
||||
MachineName.SetText(SetNameData(data.worknm, machine?.machineName ?? ""));
|
||||
wordno.SetText(SetTextData(data.wordno));
|
||||
sttm.SetText(CorrectionTime(data.sttm, "hh:mm"));
|
||||
totm.SetText(CorrectionTime(data.totm, "hh:mm"));
|
||||
@@ -179,6 +179,14 @@ namespace ChunilENG.UI
|
||||
}
|
||||
private void SetMoldData(Machine machine, CompleteInfo data)
|
||||
{
|
||||
if (machine == null)
|
||||
{
|
||||
Circle_10.gameObject.SetActive(false);
|
||||
AttributeName_10.SetText("");
|
||||
moldData.SetText("");
|
||||
return;
|
||||
}
|
||||
|
||||
var moldDataTitle = "";
|
||||
var moldDataValue = "";
|
||||
|
||||
@@ -186,14 +194,14 @@ namespace ChunilENG.UI
|
||||
{
|
||||
Circle_10.gameObject.SetActive(true);
|
||||
|
||||
if (machine.typeOptions[1].Contains("엔겔") || machine.typeOptions[1].Contains("스미토모"))
|
||||
if (machine.typeOptions[1].Contains("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>") || machine.typeOptions[1].Contains("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"))
|
||||
{
|
||||
moldDataTitle = "금형 차수";
|
||||
moldDataTitle = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>";
|
||||
moldDataValue = data.moldseq;
|
||||
}
|
||||
else if (machine.typeOptions[1].Contains("우진"))
|
||||
else if (machine.typeOptions[1].Contains("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"))
|
||||
{
|
||||
moldDataTitle = "금형 코드";
|
||||
moldDataTitle = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڵ<EFBFBD>";
|
||||
moldDataValue = data.moldcd;
|
||||
}
|
||||
}
|
||||
|
||||
41
Assets/Scripts/Object/ForkLift.cs
Normal file
41
Assets/Scripts/Object/ForkLift.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
public class ForkLift : MonoBehaviour
|
||||
{
|
||||
public float speed;
|
||||
public Transform route;
|
||||
Vector3 curr;
|
||||
Vector3 next;
|
||||
void Start()
|
||||
{
|
||||
curr = transform.position;
|
||||
//Run().Forget();
|
||||
}
|
||||
|
||||
async UniTask Run()
|
||||
{
|
||||
for(int i= 0; i < route.childCount; ++i)
|
||||
{
|
||||
var point = route.GetChild(i);
|
||||
next = point.transform.position;
|
||||
var dist = Vector3.Distance(curr, next);
|
||||
var dir = next - curr;
|
||||
var startRot = transform.rotation;
|
||||
var targetRot = dir.sqrMagnitude > 0.001f
|
||||
? Quaternion.LookRotation(dir)
|
||||
: startRot;
|
||||
float p = 0;
|
||||
|
||||
while (p < 1f)
|
||||
{
|
||||
p += speed * Time.deltaTime / Mathf.Max(dist, 0.001f);
|
||||
transform.position = Vector3.Lerp(curr, next, p);
|
||||
transform.rotation = Quaternion.Slerp(startRot, targetRot, Mathf.Clamp01(p));
|
||||
await UniTask.Yield();
|
||||
}
|
||||
curr= next;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Object/ForkLift.cs.meta
Normal file
2
Assets/Scripts/Object/ForkLift.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5305ef3eef137614a99f6d91581d32db
|
||||
@@ -59,17 +59,17 @@ namespace UVC.Studio.Command
|
||||
|
||||
foreach (var stageObject in selectedObjects)
|
||||
{
|
||||
if (stageObject.GameObject == null) continue;
|
||||
if (stageObject.gameObject == null) continue;
|
||||
|
||||
// Undo용 데이터 저장
|
||||
_deletedObjects.Add(new DeletedObjectData
|
||||
{
|
||||
OriginalId = stageObject.Id,
|
||||
ObjectName = stageObject.GameObject.name,
|
||||
ObjectName = stageObject.gameObject.name,
|
||||
Equipment = stageObject.Equipment,
|
||||
Position = stageObject.GameObject.transform.position,
|
||||
Rotation = stageObject.GameObject.transform.rotation,
|
||||
Scale = stageObject.GameObject.transform.localScale
|
||||
Position = stageObject.gameObject.transform.position,
|
||||
Rotation = stageObject.gameObject.transform.rotation,
|
||||
Scale = stageObject.gameObject.transform.localScale
|
||||
});
|
||||
|
||||
// 객체 제거 (Unregister가 Destroy도 수행)
|
||||
@@ -90,9 +90,9 @@ namespace UVC.Studio.Command
|
||||
GameObject? templateObject = null;
|
||||
foreach (var kvp in _stageObjectManager.Objects)
|
||||
{
|
||||
if (kvp.Value.Equipment?.id == data.Equipment.id && kvp.Value.GameObject != null)
|
||||
if (kvp.Value.Equipment?.id == data.Equipment.id && kvp.Value.gameObject != null)
|
||||
{
|
||||
templateObject = kvp.Value.GameObject;
|
||||
templateObject = kvp.Value.gameObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user