Files
DuckovMods/SceneView/ParametersPanel.cs

341 lines
15 KiB
C#
Raw Permalink 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 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;
}
}
}