TwinAgentAutoProcessor 가중치 완료조건 및 Entity별 터미널 로그 분리
- CompletionResult enum 추가 (Complete/Warning/Error)로 완료 상태 분류 - WeightedCompletion으로 SubStep별 가중치 기반 랜덤 완료 조건 구현 - Server: OctopusHub 75% / NotFound 25%(Error, 중지) - Protocol: API 75% / MQTT 25% - ServerStatusCheck: Done 85% / Busy 10%(Warning, 중지) / Error 5%(중지) - Speed: 5~120ms 80% / "300ms~" 20% - IsFullPipelineCompleted 속성으로 전체 파이프라인 완료 여부 판별 - MessageHistory 버퍼로 Entity별 터미널 로그 이력 관리 - Entity 전환 시 ClearAllProcessorScopedBindings()로 이전 UI 바인딩 해제 - EntityPropertyAdapter에서 PropertyItem 복원과 터미널 복원 순서 분리 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user