From 0a372cb88db67b3bc9b13da84be9d40ab437ccb9 Mon Sep 17 00:00:00 2001 From: jklee Date: Sun, 14 Jun 2026 20:08:17 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9E=85=EA=B3=A0=20PDA=20UI=20(UI=20T?= =?UTF-8?q?oolkit)=20=E2=80=94=20=EB=B3=B4=EB=A5=98=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EB=AC=BC=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 캐릭터-first 전환 전에 만든 PDA/창고 UI 작업물을 히스토리에 보존. - InboundPda.uxml/.uss/.tss + InboundPanelSettings - InboundUIController: 단계별 렌더링 + 입력 위임 - InboundSceneSetup: UIDocument/PanelSettings 자동 와이어링 씬에는 비활성 상태로 존재. 추후 입고 로직 재연결 시 재사용 가능. Co-Authored-By: Claude Opus 4.8 (1M context) --- Assets/Scripts/Editor/InboundSceneSetup.cs | 78 ++++ .../Scripts/Editor/InboundSceneSetup.cs.meta | 2 + Assets/Scripts/UI.meta | 8 + Assets/Scripts/UI/InboundUIController.cs | 419 ++++++++++++++++++ Assets/Scripts/UI/InboundUIController.cs.meta | 2 + Assets/UI.meta | 8 + Assets/UI/InboundPanelSettings.asset | 52 +++ Assets/UI/InboundPanelSettings.asset.meta | 8 + Assets/UI/InboundPda.uss | 245 ++++++++++ Assets/UI/InboundPda.uss.meta | 12 + Assets/UI/InboundPda.uxml | 40 ++ Assets/UI/InboundPda.uxml.meta | 10 + Assets/UI/InboundRuntimeTheme.tss | 1 + Assets/UI/InboundRuntimeTheme.tss.meta | 12 + CHANGELOG.md | 9 +- 15 files changed, 902 insertions(+), 4 deletions(-) create mode 100644 Assets/Scripts/Editor/InboundSceneSetup.cs create mode 100644 Assets/Scripts/Editor/InboundSceneSetup.cs.meta create mode 100644 Assets/Scripts/UI.meta create mode 100644 Assets/Scripts/UI/InboundUIController.cs create mode 100644 Assets/Scripts/UI/InboundUIController.cs.meta create mode 100644 Assets/UI.meta create mode 100644 Assets/UI/InboundPanelSettings.asset create mode 100644 Assets/UI/InboundPanelSettings.asset.meta create mode 100644 Assets/UI/InboundPda.uss create mode 100644 Assets/UI/InboundPda.uss.meta create mode 100644 Assets/UI/InboundPda.uxml create mode 100644 Assets/UI/InboundPda.uxml.meta create mode 100644 Assets/UI/InboundRuntimeTheme.tss create mode 100644 Assets/UI/InboundRuntimeTheme.tss.meta diff --git a/Assets/Scripts/Editor/InboundSceneSetup.cs b/Assets/Scripts/Editor/InboundSceneSetup.cs new file mode 100644 index 0000000..817a585 --- /dev/null +++ b/Assets/Scripts/Editor/InboundSceneSetup.cs @@ -0,0 +1,78 @@ +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.UIElements; +using SinoWms.Inbound; +using SinoWms.UI; + +namespace SinoWms.EditorTools +{ + /// + /// 입고 UI 씬을 한 번에 구성한다(런타임 UI Toolkit 와이어링 자동화). + /// 메뉴 SinoWMS/Setup Inbound Scene 실행 후 Play 하면 PDA 미션이 뜬다. + /// + public static class InboundSceneSetup + { + private const string UiDir = "Assets/UI"; + private const string ThemePath = UiDir + "/InboundRuntimeTheme.tss"; + private const string UxmlPath = UiDir + "/InboundPda.uxml"; + private const string UssPath = UiDir + "/InboundPda.uss"; + private const string PanelSettingsPath = UiDir + "/InboundPanelSettings.asset"; + + [MenuItem("SinoWMS/Setup Inbound Scene")] + public static void Setup() + { + var panelSettings = EnsurePanelSettings(); + if (panelSettings == null) return; + + var uxml = AssetDatabase.LoadAssetAtPath(UxmlPath); + if (uxml == null) + { + Debug.LogError($"[InboundSceneSetup] UXML을 찾을 수 없습니다: {UxmlPath}"); + return; + } + + var go = GameObject.Find("InboundUI") ?? new GameObject("InboundUI"); + + var manager = go.GetComponent() ?? go.AddComponent(); + + var doc = go.GetComponent() ?? go.AddComponent(); + doc.panelSettings = panelSettings; + doc.visualTreeAsset = uxml; + + // 컨트롤러는 UIDocument 이후에 추가(RequireComponent 충족) + manager 연결 + var controller = go.GetComponent() ?? go.AddComponent(); + var styleSheet = AssetDatabase.LoadAssetAtPath(UssPath); + if (styleSheet == null) + Debug.LogWarning($"[InboundSceneSetup] USS를 찾을 수 없습니다: {UssPath}"); + var so = new SerializedObject(controller); + so.FindProperty("manager").objectReferenceValue = manager; + so.FindProperty("styleSheet").objectReferenceValue = styleSheet; + so.ApplyModifiedProperties(); + + Selection.activeGameObject = go; + EditorSceneManager.MarkSceneDirty(go.scene); + Debug.Log("[InboundSceneSetup] 완료. 'InboundUI' 오브젝트 생성 → Play 하면 미션이 시작됩니다."); + } + + private static PanelSettings EnsurePanelSettings() + { + var existing = AssetDatabase.LoadAssetAtPath(PanelSettingsPath); + if (existing != null) return existing; + + var theme = AssetDatabase.LoadAssetAtPath(ThemePath); + if (theme == null) + { + Debug.LogError($"[InboundSceneSetup] 런타임 테마를 찾을 수 없습니다: {ThemePath}"); + return null; + } + + var ps = ScriptableObject.CreateInstance(); + ps.themeStyleSheet = theme; + AssetDatabase.CreateAsset(ps, PanelSettingsPath); + AssetDatabase.SaveAssets(); + Debug.Log($"[InboundSceneSetup] PanelSettings 생성: {PanelSettingsPath}"); + return ps; + } + } +} diff --git a/Assets/Scripts/Editor/InboundSceneSetup.cs.meta b/Assets/Scripts/Editor/InboundSceneSetup.cs.meta new file mode 100644 index 0000000..65fd382 --- /dev/null +++ b/Assets/Scripts/Editor/InboundSceneSetup.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4a169582dd1dc4035b39ac7c0635fadb \ No newline at end of file diff --git a/Assets/Scripts/UI.meta b/Assets/Scripts/UI.meta new file mode 100644 index 0000000..3b7301c --- /dev/null +++ b/Assets/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 09512757295aa4e849a36067192a5348 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/InboundUIController.cs b/Assets/Scripts/UI/InboundUIController.cs new file mode 100644 index 0000000..30ccaa6 --- /dev/null +++ b/Assets/Scripts/UI/InboundUIController.cs @@ -0,0 +1,419 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; +using SinoWms.Core; +using SinoWms.Data; +using SinoWms.Inbound; + +namespace SinoWms.UI +{ + /// + /// 입고 미션 PDA + 탑다운 창고 UI (UI Toolkit). + /// InboundManager의 이벤트를 구독해 단계별 화면을 다시 그리고, 입력을 매니저로 위임한다. + /// mockup/inbound_pda.html 의 화면 흐름을 그대로 옮긴 구현. + /// + [RequireComponent(typeof(UIDocument))] + public class InboundUIController : MonoBehaviour + { + [SerializeField] private InboundManager manager; + [SerializeField] private StyleSheet styleSheet; // UXML