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(); if (!rectTransform) rectTransform = gameObject.AddComponent(); 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().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(); 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 onEndEditCallback) { var rectConfig = RectTransformConfig.Default; var pack = ControlUtilities.CreateRect(parent, "向量组", rectConfig); var hLayout = pack.gameObject.AddComponent(); 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 onEndEditCallback) { var rectConfig = RectTransformConfig.Default; var pack = ControlUtilities.CreateRect(parent, "向量组", rectConfig); var hLayout = pack.gameObject.AddComponent(); 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; } } }