using System; using System.Collections.Generic; using System.Linq; using Core; using Interface; using Gameplay.Player; using Script.Gameplay.Facility; using UnityEngine; using Script.Gameplay.Input; namespace UI { // 用于显示和编辑 Facility 上的各个 IEditComponent 组件的 UI 面板 public class PlayerEditViewer : UIBase { private PlayerEditController controller; private PlayerWatchModeController watchModeController; private IEditable editable; private List components = new List(); private List componentViewers = new List(); [SerializeField] private GameObject componentEditViewerPrefab; [SerializeField] private GameObject noEditableTargetPanel; [SerializeField] private float panelRadius = 100f; private InputManager inputManager; private void Awake() { inputManager = InputManager.Instance; ControllerLocator.Instance.TryGetWait(GetPlayerEditControllerHandle); ControllerLocator.Instance.TryGetWait(GetPlayerWatchModeControllerHandle); } private void Start() { } public void OnEnterInsideWatchMode() { this.gameObject.SetActive(true); if (GetEditableFromController() != null) { GetEditableComponentsFromEditable(); ClearComponentUI(); GenerateComponentUI(); } else { if (noEditableTargetPanel != null) { noEditableTargetPanel.SetActive(true); } } } public void OnExitInsideWatchMode() { this.gameObject.SetActive(false); ClearComponentUI(); if (noEditableTargetPanel != null) { noEditableTargetPanel.SetActive(false); } } // 获取 PlayerEditController 的回调 private void GetPlayerEditControllerHandle(PlayerEditController editController) { controller = editController; //Debug.Log("PlayerEditViewer obtained PlayerEditController."); } // 获取 PlayerWatchModeController 的回调 private void GetPlayerWatchModeControllerHandle(PlayerWatchModeController watchModeCtrl) { watchModeController = watchModeCtrl; watchModeController.OnEnterWatchMode += (WatchMode mode) => { if (mode == WatchMode.Inside) OnEnterInsideWatchMode(); }; watchModeController.OnExitWatchMode += (WatchMode mode) => { if (mode == WatchMode.Inside) OnExitInsideWatchMode(); }; //Debug.Log("PlayerEditViewer subscribed to WatchMode events."); } private IEditable GetEditableFromController() { if (controller == null) { Debug.Log($"controller is null in {nameof(PlayerEditViewer)}"); return null; } return editable = controller.GetCurrentTarget(); } private void GetEditableComponentsFromEditable() { if (editable == null) { Debug.Log($"editable is null in {nameof(PlayerEditViewer)}"); return; } components = editable.GetEditableComponents() .Where(c => c != null) .ToList(); } private void ClearComponentUI() { foreach (var viewer in componentViewers) { if (viewer != null) { if (Application.isPlaying) Destroy(viewer.gameObject); else DestroyImmediate(viewer.gameObject); } } componentViewers.Clear(); } // 根据 components 生成 UI, 根据拥有的 IEditComponent 的数量动态生成 UI 元素。布局为环绕着面板中心排列(自适应间隔)。 private void GenerateComponentUI() { if (components == null || components.Count == 0 || componentEditViewerPrefab == null) return; // 计算半径:如果有 RectTransform 就根据面板大小自适应,否则使用默认值 float radius = panelRadius; var rect = GetComponent(); if (rect != null) { radius = Mathf.Min(rect.rect.width, rect.rect.height) * 0.4f; } int n = components.Count; float angleStep = 360f / n; for (int i = 0; i < n; i++) { float angleDeg = angleStep * i; float angleRad = Mathf.Deg2Rad * angleDeg; Vector2 localPos = new Vector2(Mathf.Cos(angleRad), Mathf.Sin(angleRad)) * radius; var go = Instantiate(componentEditViewerPrefab, transform); go.name = $"{componentEditViewerPrefab.name}_{i}"; var viewer = go.GetComponent(); if (viewer != null) { viewer.SetComponent(components[i]); // 注入此UI需要的组件数据 componentViewers.Add(viewer); } // 如果是 UI 元素,优先设置 RectTransform.anchoredPosition var childRect = go.GetComponent(); if (childRect != null) { childRect.anchoredPosition = localPos; childRect.localRotation = Quaternion.identity; childRect.localScale = Vector3.one; } else { go.transform.localPosition = new Vector3(localPos.x, localPos.y, 0f); go.transform.localRotation = Quaternion.identity; go.transform.localScale = Vector3.one; } // 如果预制件包含接收组件的方法(例如 SetComponent),通过 SendMessage 传递。若无则忽略。 //go.SendMessage("SetComponent", components[i], SendMessageOptions.DontRequireReceiver); } } } }