<feat> 로봇 TCP 동기화

This commit is contained in:
SOOBEEN HAN
2025-10-30 09:31:05 +09:00
parent 437f273595
commit 6d62309b68
17 changed files with 1173 additions and 31 deletions

View File

@@ -1,8 +1,18 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.XR.ARSubsystems;
public enum PopupState
{
None,
ConfirmAddPoint,
ConfirmModifyPoint,
MoveOrDelete,
ConfirmDelete
}
public class ProgramPresenter
{
private ProgramModel model;
@@ -12,7 +22,19 @@ public class ProgramPresenter
private string _programId;
private bool lastKnownMotorState = false;
public ProgramPresenter(ProgramModel model, IProgramView view, TCPView tcpView)
private IInteractionView interactionView;
private IPointManagerView pointManagerView;
private IPathLineView pathLineView;
private IPopupView popupView;
private PopupState currentPopupState = PopupState.None;
private RobotData pendingPointData; // 팝업창에 대한 응답을 기다리는 임시 데이터
private int activePointIndex = -1; // 현재 수정/삭제 중인 포인트의 인덱스
private bool IsDragging = false;
public ProgramPresenter(ProgramModel model, IProgramView view, TCPView tcpView,
IInteractionView interactionView, IPointManagerView pmView, IPopupView popView, IPathLineView pathLineView)
{
this.model = model;
this.view = view;
@@ -25,11 +47,20 @@ public class ProgramPresenter
this.view.OnSaveClicked += HandleSaveProgram;
this.view.OnAddPointClicked += HandleAddPoint;
this.tcpView.OnTCPupdateRequested += HandleTCPViewUpdate;
//this.interactionView.OnRobotReleased += HandleRobotReleased;
//this.interactionView.OnPointClicked += HandlePointClicked;
//this.interactionView.OnPointDragStart += HandlePointDragStart;
//this.interactionView.OnPointDragUpdate += HandlePointDragUpdate;
//this.interactionView.OnPointDragEnd += HandlePointDragEnd;
//this.popupView.OnPopupResponse += HandlePopupResponse;
}
public void RegisterControlledRobot(RobotController robot)
{
this.controlledRobot = robot;
this.controlledRobot.OnPoseUpdateRequest += HandlePoseViewUpdate;
}
public async Task UpdateMotorStateAsync()
@@ -62,7 +93,6 @@ public class ProgramPresenter
}
}
private async Task HandleCreateProgram(string programId)
{
if (await model.CreateNewProgram(programId))
@@ -126,6 +156,143 @@ public class ProgramPresenter
tcpView.SetCoordinates(data);
}
}
// --- 실시간 동기화 ---
private void HandlePoseViewUpdate()
{
RobotData data = model.GetLatestRobotData();
controlledRobot.SetRobotPosition(data); // 3D 가상 로봇 모델 위치 업데이트
}
// --- 새 포인트 추가 ---
private void HandleRobotReleased(RobotData pose)
{
pendingPointData = pose; // 1. 임시 저장
currentPopupState = PopupState.ConfirmAddPoint; // 2. 상태 설정
popupView.ShowConfirmPopup("위치 확정", "이 위치를 새 포인트로 저장하시겠습니까?"); // 3. 팝업 요청
}
// --- 포인트 클릭 ---
private void HandlePointClicked(int index)
{
activePointIndex = index; // 인덱스 저장
currentPopupState = PopupState.MoveOrDelete; // 상태 설정
popupView.ShowOptionPopup("포인트 작업", "무엇을 하시겠습니까?", "여기로 이동", "삭제"); // 팝업 요청
}
// --- 포인트 드래그 ---
private RobotData originalDragPose; // 취소 시 돌아갈 원본 위치
private void HandlePointDragStart(int index)
{
IsDragging = true;
activePointIndex = index;
originalDragPose = model.CurrentProgram.GetStepPose(index);
//interactionView.ShowDragArrow(GetPositionFromPose(originalDragPose));
interactionView.ShowGhostRobot(originalDragPose);
}
private async void HandlePointDragUpdate(int index, Vector3 newWorldPos)
{
if (!IsDragging) return;
//RobotData newPose = ConvertVectorToRobotData(newWorldPos);
// 고스트 로봇, 포인트, 경로 실시간 이동
//interactionView.ShowGhostRobot(newPose);
//pointManagerView.UpdatePointPosition(index, newPose);
//pathLineView.DrawPath(GetFullPathOfProgramWithTempChange(index, newPose)); // 임시 경로 그리기
//await model.StreamPoseToRobotUdpAsync(newPose);
}
private void HandlePointDragEnd(int index)
{
//IsDragging = false;
//interactionView.HideDragArrow();
//interactionView.HideGhostRobot();
//// (가상 로봇 위치 이동 로직 - 5단계)
//// robotController.SetRobotPosition(newPose);
//pendingPointData = ConvertVectorToRobotData(GetLastDragPosition()); // 임시 저장
//currentPopupState = PopupState.ConfirmModifyPoint; // 상태 설정
//popupView.ShowConfirmPopup("위치 수정", "이 위치로 포인트를 수정하시겠습니까?"); // 팝업 요청
}
// --- 팝업 응답 통합 핸들러 ---
private async void HandlePopupResponse(PopupResponse response)
{
popupView.HidePopup();
switch (currentPopupState)
{
case PopupState.ConfirmAddPoint:
if (response == PopupResponse.Confirm) // 확정
{
await model.SavePointToProgramAsync(pendingPointData);
RedrawSceneFromModel(); // 뷰 갱신
}
break;
// 드래그 확정/취소
case PopupState.ConfirmModifyPoint:
if (response == PopupResponse.Confirm) // 확정
{
// 최종 위치를 서버에 저장
// 드래그가 끝났으니 이 위치를 프로그램에 저장
await model.SavePointToProgramAsync(pendingPointData, activePointIndex);
RedrawSceneFromModel();
}
else // 취소
{
pointManagerView.UpdatePointPosition(activePointIndex, originalDragPose); // 원위치
RedrawSceneFromModel(); // 경로 원위치
}
break;
// 이동/삭제
case PopupState.MoveOrDelete:
if (response == PopupResponse.Option1) // 여기로 이동
{
RobotData targetPose = model.CurrentProgram.GetStepPose(activePointIndex);
//await model.StartMovement(targetPose);
}
else if (response == PopupResponse.Option2) // 삭제
{
currentPopupState = PopupState.ConfirmDelete;
popupView.ShowConfirmPopup("삭제 확인", "정말로 이 포인트를 삭제하시겠습니까?");
}
break;
// 최종 삭제
case PopupState.ConfirmDelete:
if (response == PopupResponse.Confirm)
{
await model.DeletePointFromProgramAsync(activePointIndex);
RedrawSceneFromModel();
}
break;
}
// 모든 작업 후 상태 초기화
currentPopupState = PopupState.None;
activePointIndex = -1;
}
// Model의 현재 상태를 읽어 모든 View(포인트, 경로)를 새로 고침
private void RedrawSceneFromModel()
{
//if (model.CurrentProgram == null) return;
//// (RobotProgram.Steps (List<RobotMoveStep>)를 List<RobotData>로 변환하는 로직)
//List<RobotData> poses = model.CurrentProgram.GetAllStepPoses();
//pointManagerView.RedrawPoints(poses); // 포인트 다시 그림
//pathLineView.DrawPath(poses); // 경로 다시 그림
}
private void Destroy()
{
this.view.OnCreateProgramClicked -= async (id) => await HandleCreateProgram(id);