306 lines
10 KiB
C#
306 lines
10 KiB
C#
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;
|
|
private IProgramView view;
|
|
private TCPView tcpView;
|
|
private RobotController controlledRobot;
|
|
private string _programId;
|
|
private bool lastKnownMotorState = false;
|
|
|
|
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;
|
|
this.tcpView = tcpView;
|
|
|
|
this.view.OnCreateProgramClicked += async (id) => await HandleCreateProgram(id);
|
|
this.view.OnLoadProgramListRequested += HandleLoadProgramList;
|
|
this.view.OnProgramSelectedToLoad += HandleProgramSelected;
|
|
this.view.OnOpenProgramClicked += async () => await HandleOpenProgram();
|
|
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()
|
|
{
|
|
try
|
|
{
|
|
bool currentState = await model.GetRobotMotorStateAsync();
|
|
|
|
if (currentState != lastKnownMotorState)
|
|
{
|
|
controlledRobot.SetMotorState(currentState);
|
|
lastKnownMotorState = currentState;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogWarning($"모터 상태 업데이트 실패: {e.Message}");
|
|
}
|
|
}
|
|
|
|
public void OnApplicationStart()
|
|
{
|
|
if (controlledRobot != null)
|
|
{
|
|
Debug.Log("제어할 로봇이 등록되었습니다.");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("제어할 로봇이 등록되지 않았습니다");
|
|
}
|
|
}
|
|
|
|
private async Task HandleCreateProgram(string programId)
|
|
{
|
|
if (await model.CreateNewProgram(programId))
|
|
{
|
|
view.DisplayProgram(programId);
|
|
view.HideProgramSelectPanel();
|
|
OnApplicationStart();
|
|
}
|
|
else
|
|
{
|
|
view.ShowMessage($"Error: Program ID '{programId}.job' already exists or is invalid.");
|
|
}
|
|
}
|
|
|
|
private void HandleLoadProgramList()
|
|
{
|
|
var programIds = model.GetAllProgramIds();
|
|
view.ShowProgramList(programIds);
|
|
}
|
|
|
|
private void HandleProgramSelected(string programId)
|
|
{
|
|
_programId = programId;
|
|
}
|
|
|
|
private async Task HandleOpenProgram()
|
|
{
|
|
if(_programId != null && await model.LoadProgram(_programId))
|
|
{
|
|
view.DisplayProgram(_programId);
|
|
view.HideProgramSelectPanel();
|
|
view.HideProgramList();
|
|
|
|
OnApplicationStart();
|
|
|
|
_programId = null;
|
|
}
|
|
}
|
|
|
|
private void HandleSaveProgram()
|
|
{
|
|
//model.SaveCurrentProgram();
|
|
}
|
|
|
|
private void HandleAddPoint()
|
|
{
|
|
//// 실제로는 UI상의 좌표나 로봇 엔드포인트 좌표를 받아와야 함
|
|
//// 여기서는 예시로 랜덤 좌표를 사용
|
|
//Vector3 newPoint = new Vector3(Random.Range(-1f, 1f), Random.Range(0f, 1f), Random.Range(-1f, 1f));
|
|
|
|
//model.AddPointToCurrentProgram(newPoint);
|
|
//view.DisplayProgram(model.CurrentProgram);
|
|
}
|
|
|
|
private void HandleTCPViewUpdate()
|
|
{
|
|
if (model.IsNewDataAvailable())
|
|
{
|
|
RobotData data = model.GetLatestRobotData();
|
|
|
|
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);
|
|
this.view.OnLoadProgramListRequested -= HandleLoadProgramList;
|
|
this.view.OnProgramSelectedToLoad -= HandleProgramSelected;
|
|
this.view.OnOpenProgramClicked -= async () => await HandleOpenProgram();
|
|
this.view.OnSaveClicked -= HandleSaveProgram;
|
|
this.view.OnAddPointClicked -= HandleAddPoint;
|
|
this.tcpView.OnTCPupdateRequested -= HandleTCPViewUpdate;
|
|
}
|
|
} |