Files
2025TapTapGameJam/Assets/Script/Gameplay/UI/PlayerEditViewer.cs

181 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<IEditableComponent> components = new List<IEditableComponent>();
private List<EditableComponentViewer> componentViewers = new List<EditableComponentViewer>();
[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<PlayerEditController>(GetPlayerEditControllerHandle);
ControllerLocator.Instance.TryGetWait<PlayerWatchModeController>(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<RectTransform>();
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<EditableComponentViewer>();
if (viewer != null)
{
viewer.SetComponent(components[i]); // 注入此UI需要的组件数据
componentViewers.Add(viewer);
}
// 如果是 UI 元素,优先设置 RectTransform.anchoredPosition
var childRect = go.GetComponent<RectTransform>();
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);
}
}
}
}