diff --git a/Assets/Resources/Studio/Prefabs/Modal/Setting/SettingShortcutTabContent.prefab b/Assets/Resources/Studio/Prefabs/Modal/Setting/SettingShortcutTabContent.prefab
index c9fa3167..d059f82f 100644
--- a/Assets/Resources/Studio/Prefabs/Modal/Setting/SettingShortcutTabContent.prefab
+++ b/Assets/Resources/Studio/Prefabs/Modal/Setting/SettingShortcutTabContent.prefab
@@ -71,7 +71,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 5, y: 0}
+ m_AnchoredPosition: {x: 1, y: -2}
m_SizeDelta: {x: 280, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!114 &1439525333927440954
@@ -173,6 +173,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 0cd2a999fb90a1842bc1b34fc30f49c4, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::UVC.Studio.Modal.Settings.SettingShortcutTabContent
+ scrollRect: {fileID: 1767596478105099482}
labelGroup: {fileID: 1439525333927440954}
valueGroup: {fileID: 4763940519200166932}
firstLabelTxt: {fileID: 6899382311698274704}
@@ -303,7 +304,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 285, y: 0}
+ m_AnchoredPosition: {x: 281, y: -2}
m_SizeDelta: {x: 300, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!114 &4763940519200166932
@@ -1307,9 +1308,9 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup
m_Padding:
- m_Left: 5
+ m_Left: 1
m_Right: 0
- m_Top: 0
+ m_Top: 2
m_Bottom: 0
m_ChildAlignment: 0
m_Spacing: 0
diff --git a/Assets/Runtime Transform Gizmos (Lite)/Lite/Resources/Gizmos/Skins/DefaultGizmosSkin.asset b/Assets/Runtime Transform Gizmos (Lite)/Lite/Resources/Gizmos/Skins/DefaultGizmosSkin.asset
index f2bb6768..5dcd9844 100644
--- a/Assets/Runtime Transform Gizmos (Lite)/Lite/Resources/Gizmos/Skins/DefaultGizmosSkin.asset
+++ b/Assets/Runtime Transform Gizmos (Lite)/Lite/Resources/Gizmos/Skins/DefaultGizmosSkin.asset
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 6eec73d24eb5fde4695987a5dceedb12, type: 3}
m_Name: DefaultGizmosSkin
m_EditorClassIdentifier:
- mGizmoType: 1
+ mGizmoType: 0
mInitialized: 1
mGlobalGizmoStyle:
mVisible: 1
diff --git a/Assets/Scenes/Studio.unity b/Assets/Scenes/Studio.unity
index a74d21a1..6de54e62 100644
--- a/Assets/Scenes/Studio.unity
+++ b/Assets/Scenes/Studio.unity
@@ -649,7 +649,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 23e3c568776ffe042b2f38278a66f548, type: 3}
m_Name:
m_EditorClassIdentifier:
- mSkin: {fileID: 0}
+ mSkin: {fileID: 11400000, guid: 5a1d6f55a1eee8943831d025fbb2a974, type: 2}
mSortGizmos: 1
--- !u!1 &177094387
GameObject:
diff --git a/Assets/Scripts/Studio/Modal/Settings/SettingDatabaseTabContent.cs b/Assets/Scripts/Studio/Modal/Settings/SettingDatabaseTabContent.cs
index fa6bee11..850a9d19 100644
--- a/Assets/Scripts/Studio/Modal/Settings/SettingDatabaseTabContent.cs
+++ b/Assets/Scripts/Studio/Modal/Settings/SettingDatabaseTabContent.cs
@@ -30,22 +30,22 @@ namespace UVC.Studio.Modal.Settings
private bool changedValue = false;
+ // Tab 키 포커스 이동을 위한 InputField 배열
+ private TMP_InputField?[] inputFields = null!;
+
///
/// 탭 콘텐츠에 데이터를 전달합니다.
///
/// 전달할 데이터 객체
public async void SetContentData(object? data)
{
- Debug.Log($"SettingDatabaseTabContent SetContentData: {data} {setting == null}");
-
if (setting == null)
{
+ // Start 전에 호출 되서 Injection 완료 대기 후 Setting 인스턴스 획득
await InjectorAppContext.Instance.WaitForInitializationAsync();
setting = InjectorAppContext.Instance.Get();
}
- Debug.Log($"SettingDatabaseTabContent SetContentData: {data} {setting == null}");
-
if (setting != null)
{
changedValue = false;
@@ -91,9 +91,45 @@ namespace UVC.Studio.Modal.Settings
});
}
+ // Tab 키 포커스 이동을 위한 배열 초기화
+ inputFields = new TMP_InputField?[] { ipTxt, portTxt, idTxt, pwTxt };
}
}
+ 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();
+ }
+ }
+ }
+ }
+
+ 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;
+ }
+
///
/// 탭 전환 시 데이터가 있는 경우 전달 되는 데이터. SetContentData 이후 호출 됨
///
diff --git a/Assets/Scripts/Studio/Modal/Settings/SettingGeneralTabContent.cs b/Assets/Scripts/Studio/Modal/Settings/SettingGeneralTabContent.cs
index b15e5845..c543d020 100644
--- a/Assets/Scripts/Studio/Modal/Settings/SettingGeneralTabContent.cs
+++ b/Assets/Scripts/Studio/Modal/Settings/SettingGeneralTabContent.cs
@@ -1,5 +1,6 @@
#nullable enable
using Cysharp.Threading.Tasks;
+using RTGLite;
using TMPro;
using UnityEngine;
using UVC.Core;
@@ -31,16 +32,25 @@ namespace UVC.Studio.Modal.Settings
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)
{
- Debug.Log($"SettingGeneralTabContent SetContentData: {data}");
if (setting == null)
{
+ // Start 전에 호출 되서 Injection 완료 대기 후 Setting 인스턴스 획득
await InjectorAppContext.Instance.WaitForInitializationAsync();
setting = InjectorAppContext.Instance.Get();
}
@@ -50,6 +60,12 @@ namespace UVC.Studio.Modal.Settings
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();
@@ -75,9 +91,55 @@ namespace UVC.Studio.Modal.Settings
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))
@@ -93,6 +155,11 @@ namespace UVC.Studio.Modal.Settings
{
setting.Data.general.gridSize = floatValue;
changedValue = true;
+
+ if (setting.Data.general.gridSize != gridSize)
+ {
+ RTGrid.get.settings.cellSize = new Vector3(setting.Data.general.gridSize, setting.Data.general.gridSize, setting.Data.general.gridSize);
+ }
}
}
@@ -149,6 +216,11 @@ namespace UVC.Studio.Modal.Settings
Debug.Log($"SettingGeneralTabContent OnCloseAsync: changedValue={changedValue} setting == null:{setting == null}");
+ if (setting != null && setting.Data.general.gridSize != gridSize)
+ {
+ RTGrid.get.settings.cellSize = new Vector3(setting.Data.general.gridSize, setting.Data.general.gridSize, setting.Data.general.gridSize);
+ }
+
if(changedValue && setting != null)
{
await setting.SaveAsync();
diff --git a/Assets/Scripts/Studio/Modal/Settings/SettingModal.cs b/Assets/Scripts/Studio/Modal/Settings/SettingModal.cs
index 7ab3fc9f..3f0a4563 100644
--- a/Assets/Scripts/Studio/Modal/Settings/SettingModal.cs
+++ b/Assets/Scripts/Studio/Modal/Settings/SettingModal.cs
@@ -65,11 +65,11 @@ namespace UVC.Studio.Modal.Settings
if (parts.Length > 0)
{
//시간차를 계산해 0.5초 후에 탭을 활성화
- UniTask.Delay(500).ContinueWith(() => {
+ //UniTask.Delay(500).ContinueWith(() => {
Debug.Log($"ActivateTab: {parts[0]}");
string tabKey = parts;
tabController.ActivateTab(tabKey, content.Message);
- });
+ //});
}
}
}
diff --git a/Assets/Scripts/Studio/Modal/Settings/SettingShortcutTabContent.cs b/Assets/Scripts/Studio/Modal/Settings/SettingShortcutTabContent.cs
index 3c24bc3c..fc68692c 100644
--- a/Assets/Scripts/Studio/Modal/Settings/SettingShortcutTabContent.cs
+++ b/Assets/Scripts/Studio/Modal/Settings/SettingShortcutTabContent.cs
@@ -12,6 +12,8 @@ namespace UVC.Studio.Modal.Settings
{
public class SettingShortcutTabContent : MonoBehaviour, ITabContent
{
+ [SerializeField]
+ private ScrollRect? scrollRect;
[SerializeField]
private LayoutGroup? labelGroup;
@@ -40,10 +42,10 @@ namespace UVC.Studio.Modal.Settings
/// 전달할 데이터 객체
public async void SetContentData(object? data)
{
- Debug.Log($"SettingShortcutTabContent SetContentData: {data}");
if (setting == null)
{
+ // Start 전에 호출 되서 Injection 완료 대기 후 Setting 인스턴스 획득
await InjectorAppContext.Instance.WaitForInitializationAsync();
setting = InjectorAppContext.Instance.Get();
}
@@ -71,7 +73,7 @@ namespace UVC.Studio.Modal.Settings
{
var shortcut = (ShortcutItem?)field.GetValue(group);
if (shortcut == null) continue;
- if (i == 0)
+ if (i == 0 && group == shortcuts.menu)
{
firstLabelTxt!.text = shortcut.label;
firstValueTxt!.text = shortcut.key;
@@ -128,6 +130,78 @@ namespace UVC.Studio.Modal.Settings
}
}
+ private void Update()
+ {
+ // Tab 키 입력 처리
+ if (Input.GetKeyDown(KeyCode.Tab) && valueTxts.Count > 0)
+ {
+ int currentIndex = GetCurrentFocusedIndex();
+ if (currentIndex >= 0)
+ {
+ int nextIndex = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)
+ ? (currentIndex - 1 + valueTxts.Count) % valueTxts.Count // Shift+Tab: 이전
+ : (currentIndex + 1) % valueTxts.Count; // Tab: 다음
+
+ valueTxts[nextIndex].Select();
+ ScrollToItem(nextIndex);
+ }
+ }
+ }
+
+ private int GetCurrentFocusedIndex()
+ {
+ for (int i = 0; i < valueTxts.Count; i++)
+ {
+ if (valueTxts[i] != null && valueTxts[i].isFocused)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ ///
+ /// 해당 인덱스의 항목이 보이도록 스크롤합니다.
+ ///
+ private void ScrollToItem(int index)
+ {
+ if (scrollRect == null || scrollRect.content == null || index < 0 || index >= valueTxts.Count)
+ return;
+
+ RectTransform targetRect = valueTxts[index].GetComponent();
+ RectTransform contentRect = scrollRect.content;
+ RectTransform viewportRect = scrollRect.viewport != null ? scrollRect.viewport : scrollRect.GetComponent();
+
+ // 타겟 항목의 위치 계산
+ float contentHeight = contentRect.rect.height;
+ float viewportHeight = viewportRect.rect.height;
+
+ if (contentHeight <= viewportHeight) return; // 스크롤 필요 없음
+
+ // 타겟의 로컬 위치 (content 기준)
+ float targetY = -targetRect.anchoredPosition.y;
+ float itemHeight = targetRect.rect.height;
+
+ // 현재 스크롤 위치에서 보이는 영역
+ float scrollY = contentRect.anchoredPosition.y;
+ float visibleTop = scrollY;
+ float visibleBottom = scrollY + viewportHeight;
+
+ // 항목이 보이지 않으면 스크롤
+ if (targetY < visibleTop)
+ {
+ // 위로 스크롤
+ float normalizedPos = targetY / (contentHeight - viewportHeight);
+ scrollRect.verticalNormalizedPosition = 1f - Mathf.Clamp01(normalizedPos);
+ }
+ else if (targetY + itemHeight > visibleBottom)
+ {
+ // 아래로 스크롤
+ float normalizedPos = (targetY + itemHeight - viewportHeight) / (contentHeight - viewportHeight);
+ scrollRect.verticalNormalizedPosition = 1f - Mathf.Clamp01(normalizedPos);
+ }
+ }
+
///
/// 탭 전환 시 데이터가 있는 경우 전달 되는 데이터. SetContentData 이후 호출 됨
///
diff --git a/Assets/Scripts/Studio/StudioSceneMain.cs b/Assets/Scripts/Studio/StudioSceneMain.cs
index c98acdc7..133ed569 100644
--- a/Assets/Scripts/Studio/StudioSceneMain.cs
+++ b/Assets/Scripts/Studio/StudioSceneMain.cs
@@ -57,6 +57,7 @@ namespace UVC.Studio
var sceneCtx = FindAnyObjectByType();
if (sceneCtx != null)
{
+ // Injection이 완료될 때까지 대기
await sceneCtx.WaitForInitializationAsync();
Initialize();
}
diff --git a/Assets/StreamingAssets/Settings.json b/Assets/StreamingAssets/Settings.json
index fc872682..0e050b34 100644
--- a/Assets/StreamingAssets/Settings.json
+++ b/Assets/StreamingAssets/Settings.json
@@ -7,7 +7,7 @@
},
"general": {
"autoSaveInterval": 5,
- "gridSize": 5.0,
+ "gridSize": 1.0,
"snapPosition": 0.5,
"snapRotation": 10.0,
"snapScale": 0.5