Files
DuckovMods/SceneView/ParametersPanel.cs

341 lines
15 KiB
C#
Raw Normal View History

using System;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace SceneView
{
public class ParametersPanel : MonoBehaviour, IDragHandler, IBeginDragHandler
{
public RectTransform rectTransform;
public const float wide = 400;
public (TMP_InputField x, TMP_InputField y, TMP_InputField z)
position, localPosition, localScale; // 删除了 'scale',因为它在 Awake 中被注释掉了
public (TMP_InputField x, TMP_InputField y, TMP_InputField z, TMP_InputField w)
rotation, localRotation;
private Vector2 shift;
private int timer = 0;
private int refreshTime = 10; // 每10帧刷新一次
// 新增:标志位,表示是否有输入框正在被编辑
private bool isEditingInputField = false;
private void Awake()
{
if (!rectTransform) rectTransform = GetComponent<RectTransform>();
if (!rectTransform) rectTransform = gameObject.AddComponent<RectTransform>();
rectTransform.sizeDelta = new Vector2(wide, 500);
rectTransform.anchoredPosition = new Vector2(wide / 2 + 10, 0);
CanvasControl.OnChangeFocusObject += OnChangeFocusObject;
var title = RectTransformConfig.Default;
title.AnchorMin = Vector2.up;
title.AnchorMax = Vector2.one;
title.Pivot = new Vector2(0.5f, 0);
title.SizeDelta = new Vector2(0, 50);
title.AnchoredPosition = new Vector2(0, 0);
var titleObj = ControlUtilities.CreateRect(transform, "标题", title);
titleObj.gameObject.AddComponent<Image>().color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
var titleText = TextConfig.Default;
titleText.RectConfig = RectTransformConfig.FillParent;
titleText.Text = "焦点参数";
ControlUtilities.CreateText(titleObj, titleText);
var contentConfig = RectTransformConfig.FillParent;
var content = ControlUtilities.CreateRect(transform, "内容", contentConfig);
var vLayout = content.gameObject.AddComponent<VerticalLayoutGroup>();
vLayout.padding = new RectOffset(2, 2, 2, 2);
vLayout.childAlignment = TextAnchor.UpperCenter;
vLayout.childControlWidth = true;
vLayout.childControlHeight = true;
vLayout.spacing = 2;
var labelConfig = TextConfig.Default;
// 全局位置
labelConfig.Text = "全局位置";
ControlUtilities.CreateText(content, labelConfig);
position = CreateVector3InputField(content, ApplyWorldPositionChange);
// 全局旋转 (使用Quaternion)
labelConfig.Text = "全局旋转";
ControlUtilities.CreateText(content, labelConfig);
rotation = CreateVector4InputField(content, ApplyWorldRotationChange);
// 局部位置
labelConfig.Text = "局部位置";
ControlUtilities.CreateText(content, labelConfig);
localPosition = CreateVector3InputField(content, ApplyLocalPositionChange);
// 局部缩放
labelConfig.Text = "局部缩放";
ControlUtilities.CreateText(content, labelConfig);
localScale = CreateVector3InputField(content, ApplyLocalScaleChange);
// 局部旋转 (使用Quaternion)
labelConfig.Text = "局部旋转";
ControlUtilities.CreateText(content, labelConfig);
localRotation = CreateVector4InputField(content, ApplyLocalRotationChange);
}
private void OnDestroy()
{
CanvasControl.OnChangeFocusObject -= OnChangeFocusObject;
}
private void Update()
{
timer++;
// 只有当没有输入框被编辑时才刷新
if (timer >= refreshTime && !isEditingInputField)
{
timer = 0;
Refresh();
}
}
public void OnChangeFocusObject(GameObject obj)
{
// 焦点对象改变时,立即刷新
Refresh();
}
private void Refresh()
{
if (!CanvasControl.FocusGameObject)
{
ClearAllInputFields();
return;
}
var targetTransform = CanvasControl.FocusGameObject.transform;
// --- 全局位置 (World Position) ---
var currentPosition = targetTransform.position;
position.x.text = currentPosition.x.ToString("F3"); // "F3" 表示保留3位小数
position.y.text = currentPosition.y.ToString("F3");
position.z.text = currentPosition.z.ToString("F3");
// --- 局部位置 (Local Position) ---
var currentLocalPosition = targetTransform.localPosition;
localPosition.x.text = currentLocalPosition.x.ToString("F3");
localPosition.y.text = currentLocalPosition.y.ToString("F3");
localPosition.z.text = currentLocalPosition.z.ToString("F3");
// --- 局部缩放 (Local Scale) ---
var currentLocalScale = targetTransform.localScale;
localScale.x.text = currentLocalScale.x.ToString("F3");
localScale.y.text = currentLocalScale.y.ToString("F3");
localScale.z.text = currentLocalScale.z.ToString("F3");
// --- 全局旋转 (World Rotation) - Quaternion ---
var currentRotation = targetTransform.rotation;
rotation.x.text = currentRotation.x.ToString("F3");
rotation.y.text = currentRotation.y.ToString("F3");
rotation.z.text = currentRotation.z.ToString("F3");
rotation.w.text = currentRotation.w.ToString("F3");
// --- 局部旋转 (Local Rotation) - Quaternion ---
var currentLocalRotation = targetTransform.localRotation;
localRotation.x.text = currentLocalRotation.x.ToString("F3");
localRotation.y.text = currentLocalRotation.y.ToString("F3");
localRotation.z.text = currentLocalRotation.z.ToString("F3");
localRotation.w.text = currentLocalRotation.w.ToString("F3");
}
private void ClearAllInputFields()
{
position.x.text = ""; position.y.text = ""; position.z.text = "";
localPosition.x.text = ""; localPosition.y.text = ""; localPosition.z.text = "";
localScale.x.text = ""; localScale.y.text = ""; localScale.z.text = "";
rotation.x.text = ""; rotation.y.text = ""; rotation.z.text = ""; rotation.w.text = "";
localRotation.x.text = ""; localRotation.y.text = ""; localRotation.z.text = ""; localRotation.w.text = "";
}
// Helper method to add common input field event listeners
private void AddInputFieldListeners(TMP_InputField inputField)
{
inputField.onSelect.AddListener((_) => isEditingInputField = true);
inputField.onDeselect.AddListener((_) =>
{
isEditingInputField = false;
// 在失去焦点后立即刷新,以更新可能的非用户输入引起的改变或重新格式化用户输入
Refresh();
});
}
// 修改 CreateVector3InputField接受一个Action用于处理onEndEdit
public (TMP_InputField x, TMP_InputField y, TMP_InputField z) CreateVector3InputField(Transform parent, Action<string, int> onEndEditCallback)
{
var rectConfig = RectTransformConfig.Default;
var pack = ControlUtilities.CreateRect(parent, "向量组", rectConfig);
var hLayout = pack.gameObject.AddComponent<HorizontalLayoutGroup>();
hLayout.childForceExpandHeight = true;
hLayout.childForceExpandWidth = true;
hLayout.childControlWidth = true;
hLayout.childControlHeight = true;
hLayout.spacing = 2;
hLayout.padding = new RectOffset(2, 2, 2, 2);
var inputConfig = LabeledInputFieldConfig.Default;
inputConfig.InputFieldConfig.BackgroundColor = new Color(0.7f, 0.7f, 0.7f, 0.7f);
inputConfig.LabelWidth = 15;
inputConfig.LabelFontSize = 14;
inputConfig.Spacing = 0;
inputConfig.LabelText = "X";
var inputX = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputX.inputField);
inputX.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 0));
inputConfig.LabelText = "Y";
var inputY = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputY.inputField);
inputY.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 1));
inputConfig.LabelText = "Z";
var inputZ = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputZ.inputField);
inputZ.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 2));
return (inputX.inputField, inputY.inputField, inputZ.inputField);
}
// 修改 CreateVector4InputField接受一个Action用于处理onEndEdit
public (TMP_InputField x, TMP_InputField y, TMP_InputField z, TMP_InputField w) CreateVector4InputField(
Transform parent, Action<string, int> onEndEditCallback)
{
var rectConfig = RectTransformConfig.Default;
var pack = ControlUtilities.CreateRect(parent, "向量组", rectConfig);
var hLayout = pack.gameObject.AddComponent<HorizontalLayoutGroup>();
hLayout.childForceExpandHeight = true;
hLayout.childForceExpandWidth = true;
hLayout.childControlWidth = true;
hLayout.childControlHeight = true;
hLayout.spacing = 2;
hLayout.padding = new RectOffset(2, 2, 2, 2);
var inputConfig = LabeledInputFieldConfig.Default;
inputConfig.InputFieldConfig.BackgroundColor = new Color(0.7f, 0.7f, 0.7f, 0.7f);
inputConfig.LabelWidth = 15;
inputConfig.LabelFontSize = 14;
inputConfig.Spacing = 0;
inputConfig.LabelText = "X";
var inputX = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputX.inputField);
inputX.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 0));
inputConfig.LabelText = "Y";
var inputY = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputY.inputField);
inputY.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 1));
inputConfig.LabelText = "Z";
var inputZ = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputZ.inputField);
inputZ.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 2));
inputConfig.LabelText = "W";
var inputW = ControlUtilities.CreateLabeledInputField(pack, inputConfig);
AddInputFieldListeners(inputW.inputField);
inputW.inputField.onEndEdit.AddListener(text => onEndEditCallback?.Invoke(text, 3));
return (inputX.inputField, inputY.inputField, inputZ.inputField, inputW.inputField);
}
private void ApplyWorldPositionChange(string text, int axisIndex)
{
if (CanvasControl.FocusGameObject == null) return;
var targetTransform = CanvasControl.FocusGameObject.transform;
if (float.TryParse(text, out var newValue))
{
var pos = targetTransform.position;
if (axisIndex == 0) pos.x = newValue;
else if (axisIndex == 1) pos.y = newValue;
else if (axisIndex == 2) pos.z = newValue;
targetTransform.position = pos;
}
Refresh(); // 刷新以确保所有相关字段如localPosition都已更新
}
private void ApplyLocalPositionChange(string text, int axisIndex)
{
if (CanvasControl.FocusGameObject == null) return;
var targetTransform = CanvasControl.FocusGameObject.transform;
if (float.TryParse(text, out var newValue))
{
var localPos = targetTransform.localPosition;
if (axisIndex == 0) localPos.x = newValue;
else if (axisIndex == 1) localPos.y = newValue;
else if (axisIndex == 2) localPos.z = newValue;
targetTransform.localPosition = localPos;
}
Refresh();
}
private void ApplyLocalScaleChange(string text, int axisIndex)
{
if (CanvasControl.FocusGameObject == null) return;
var targetTransform = CanvasControl.FocusGameObject.transform;
if (float.TryParse(text, out var newValue))
{
var localScale = targetTransform.localScale;
if (axisIndex == 0) localScale.x = newValue;
else if (axisIndex == 1) localScale.y = newValue;
else if (axisIndex == 2) localScale.z = newValue;
targetTransform.localScale = localScale;
}
Refresh();
}
private void ApplyWorldRotationChange(string text, int axisIndex)
{
if (CanvasControl.FocusGameObject == null) return;
var targetTransform = CanvasControl.FocusGameObject.transform;
if (float.TryParse(text, out var newValue))
{
var rot = targetTransform.rotation;
if (axisIndex == 0) rot.x = newValue;
else if (axisIndex == 1) rot.y = newValue;
else if (axisIndex == 2) rot.z = newValue;
else if (axisIndex == 3) rot.w = newValue;
targetTransform.rotation = rot; // Quaternion需要整体重新赋值
}
Refresh();
}
private void ApplyLocalRotationChange(string text, int axisIndex)
{
if (CanvasControl.FocusGameObject == null) return;
var targetTransform = CanvasControl.FocusGameObject.transform;
if (float.TryParse(text, out var newValue))
{
var localRot = targetTransform.localRotation;
if (axisIndex == 0) localRot.x = newValue;
else if (axisIndex == 1) localRot.y = newValue;
else if (axisIndex == 2) localRot.z = newValue;
else if (axisIndex == 3) localRot.w = newValue;
targetTransform.localRotation = localRot; // Quaternion需要整体重新赋值
}
Refresh();
}
public void OnBeginDrag(PointerEventData eventData)
{
shift = transform.position - new Vector3(eventData.position.x, eventData.position.y);
}
public void OnDrag(PointerEventData eventData)
{
transform.position = eventData.position + shift;
}
}
}