#nullable enable using Cysharp.Threading.Tasks; using RTGLite; using TMPro; using UnityEngine; using UVC.Core; using UVC.Studio.Config; using UVC.UI.Tab; namespace UVC.Studio.Modal.Settings { public class SettingGeneralTabContent : MonoBehaviour, ITabContent { [SerializeField] private TMP_InputField? autoSaveValueTxt; [SerializeField] private TMP_InputField? gridValueTxt; [SerializeField] private TMP_InputField? positionSnapValueTxt; [SerializeField] private TMP_InputField? RotationSnapValueTxt; [SerializeField] private TMP_InputField? ScaleSnapValueTxt; private Setting? setting; private bool changedValue = false; // Tab 키 포커스 이동을 위한 InputField 배열 private TMP_InputField?[] inputFields = null!; private int autoSaveInterval = -1; private float gridSize = -1f; private float snapPosition = -1f; private float snapRotation = -1f; private float snapScale = -1f; /// /// 탭 콘텐츠에 데이터를 전달합니다. /// /// 전달할 데이터 객체 public async void SetContentData(object? data) { if (setting == null) { // 동적으로 로드되는 Prefab이므로 [Inject]가 자동으로 동작하지 않음 await InjectorAppContext.Instance.WaitForInitializationAsync(); setting = InjectorAppContext.Instance.Get(); } if (setting != null) { changedValue = false; GeneralSetting general = setting.Data.general; autoSaveInterval = general.autoSaveInterval; gridSize = general.gridSize; snapPosition = general.snapPosition; snapRotation = general.snapRotation; snapScale = general.snapScale; if (autoSaveValueTxt != null) { autoSaveValueTxt.text = general.autoSaveInterval.ToString(); autoSaveValueTxt.onEndEdit.AddListener(onChagedTextAutoSave); } if (gridValueTxt != null) { gridValueTxt.text = general.gridSize.ToString(); gridValueTxt.onEndEdit.AddListener(onChagedTextGrid); } if (positionSnapValueTxt != null) { positionSnapValueTxt.text = general.snapPosition.ToString(); positionSnapValueTxt.onEndEdit.AddListener(onChagedTextSnapPosition); } if (RotationSnapValueTxt != null) { RotationSnapValueTxt.text = general.snapRotation.ToString(); RotationSnapValueTxt.onEndEdit.AddListener(onChagedTextRotationSnap); } if (ScaleSnapValueTxt != null) { ScaleSnapValueTxt.text = general.snapScale.ToString(); ScaleSnapValueTxt.onEndEdit.AddListener(onChagedTextScaleSnap); } // Tab 키 포커스 이동을 위한 배열 초기화 inputFields = new TMP_InputField?[] { autoSaveValueTxt, gridValueTxt, positionSnapValueTxt, RotationSnapValueTxt, ScaleSnapValueTxt }; } } private void Update() { // Tab 키 입력 처리 if (Input.GetKeyDown(KeyCode.Tab) && inputFields != null) { int currentIndex = GetCurrentFocusedIndex(); if (currentIndex >= 0) { int nextIndex = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) ? (currentIndex - 1 + inputFields.Length) % inputFields.Length // Shift+Tab: 이전 : (currentIndex + 1) % inputFields.Length; // Tab: 다음 if (inputFields[nextIndex] != null) { inputFields[nextIndex]!.Select(); } } } } /// /// 현재 포커스된 InputField의 인덱스를 반환합니다. /// private int GetCurrentFocusedIndex() { if (inputFields == null) return -1; for (int i = 0; i < inputFields.Length; i++) { if (inputFields[i] != null && inputFields[i]!.isFocused) { return i; } } return -1; } private void onChagedTextAutoSave(string value) { if (setting != null && int.TryParse(value, out int intValue)) { setting.Data.general.autoSaveInterval = intValue; changedValue = true; } } private void onChagedTextGrid(string value) { if (setting != null && float.TryParse(value, out float floatValue)) { setting.Data.general.gridSize = floatValue; changedValue = true; // Unity에서 1m 단위가 1이므로 RTGrid에 적용할 때도 동일하게 설정 if (setting.Data.general.gridSize != gridSize) { RTGrid.get.settings.cellSize = new Vector3(setting.Data.general.gridSize, setting.Data.general.gridSize, setting.Data.general.gridSize); } } } private void onChagedTextSnapPosition(string value) { if (setting != null && float.TryParse(value, out float floatValue)) { setting.Data.general.snapPosition = floatValue; changedValue = true; // RTGizmos 위치 스냅 설정에 즉시 적용 if (setting.Data.general.snapPosition != snapPosition) { RTGizmos.get.skin.globalGizmoStyle.positionSnap = floatValue; } } } private void onChagedTextRotationSnap(string value) { if (setting != null && float.TryParse(value, out float floatValue)) { setting.Data.general.snapRotation = floatValue; changedValue = true; // RTGizmos 회전 스냅 설정에 즉시 적용 if (setting.Data.general.snapRotation != snapRotation) { RTGizmos.get.skin.globalGizmoStyle.rotationSnap = floatValue; } } } private void onChagedTextScaleSnap(string value) { if (setting != null && float.TryParse(value, out float floatValue)) { setting.Data.general.snapScale = floatValue; changedValue = true; // RTGizmos 스케일 스냅 설정에 즉시 적용 if (setting.Data.general.snapScale != snapScale) { RTGizmos.get.skin.globalGizmoStyle.scaleSnap = floatValue; } } } /// /// 탭 전환 시 데이터가 있는 경우 전달 되는 데이터. SetContentData 이후 호출 됨 /// /// 전달할 데이터 객체 public void UpdateContentData(object? data) { if (data != null && data is string content) { Debug.Log($"UpdateContentData: {content}"); } } /// /// 닫힐 때 실행되는 로직을 처리합니다. /// /// 비동기 닫기 작업을 나타내는 입니다. public async UniTask OnCloseAsync() { if (autoSaveValueTxt != null) autoSaveValueTxt.onEndEdit.RemoveListener(onChagedTextAutoSave); if (gridValueTxt != null) gridValueTxt.onEndEdit.RemoveListener(onChagedTextGrid); if (positionSnapValueTxt != null) positionSnapValueTxt.onEndEdit.RemoveListener(onChagedTextSnapPosition); if (RotationSnapValueTxt != null) RotationSnapValueTxt.onEndEdit.RemoveListener(onChagedTextRotationSnap); if (ScaleSnapValueTxt != null) ScaleSnapValueTxt.onEndEdit.RemoveListener(onChagedTextScaleSnap); Debug.Log($"SettingGeneralTabContent OnCloseAsync: changedValue={changedValue} setting == null:{setting == null}"); // 스냅 활성화 //RTGizmos.get.snapEnabled = true; if (setting != null) { // Grid 크기 설정에 즉시 적용 if (setting.Data.general.gridSize != gridSize) { RTGrid.get.settings.cellSize = new Vector3(setting.Data.general.gridSize, setting.Data.general.gridSize, setting.Data.general.gridSize); } // RTGizmos 위치 스냅 설정에 즉시 적용 if (setting.Data.general.snapPosition != snapPosition) { RTGizmos.get.skin.globalGizmoStyle.positionSnap = setting.Data.general.snapPosition; } // RTGizmos 회전 스냅 설정에 즉시 적용 if (setting.Data.general.snapRotation != snapRotation) { RTGizmos.get.skin.globalGizmoStyle.rotationSnap = setting.Data.general.snapRotation; } // RTGizmos 스케일 스냅 설정에 즉시 적용 if (setting.Data.general.snapScale != snapScale) { RTGizmos.get.skin.globalGizmoStyle.scaleSnap = setting.Data.general.snapScale; } } if(changedValue && setting != null) { await setting.SaveAsync(); changedValue = false; } } } }