EnergyEfficiencyManagement/Assets/Zion/Scripts/EnhancedModelViewerOrbitCam...

1023 lines
32 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 UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class EnhancedModelViewerOrbitCamera : MonoBehaviour
{
[Header("观察目标")]
[SerializeField] private Transform target; // 要观察的模型
public Transform GetTarget()
{
return target;
}
[Header("基础控制开关")]
[SerializeField] private bool enableClickToFocus = true; // 是否启用点击子物体聚焦功能
[SerializeField] private bool enableRotation = true; // 是否启用旋转功能
[SerializeField] private bool enablePan = true; // 是否启用平移功能
[SerializeField] private bool enableZoom = true; // 是否启用缩放功能
[SerializeField] private bool enableAutoRotation = false; // 是否启用自动旋转
[Header("旋转设置")]
[SerializeField] private float rotationSpeed = 5.0f;
[SerializeField] private float autoRotationSpeed = 0.5f;
[SerializeField] private float rotationSmoothness = 5.0f;
[Header("缩放设置")]
[SerializeField] private float zoomSpeed = 5.0f;
[SerializeField] private float minZoomDistance = 1.0f;
[SerializeField] private float maxZoomDistance = 20.0f;
[SerializeField] private float defaultZoomDistance = 5.0f;
[Header("平移设置")]
[SerializeField] private float panSpeed = 0.5f;
[Header("平移距离限制")]
[SerializeField] private float maxPanDistanceX = 5.0f; // X轴最大平移距离
[SerializeField] private float maxPanDistanceZ = 5.0f; // Z轴最大平移距离
[SerializeField] private bool showPanBoundary = true; // 是否显示平移边界
[Header("子物体复制体父级")]
[SerializeField] private Transform childInstanceParent; // 子物体复制体的父级
[Header("子物体观察模式 - 层级设置")]
[SerializeField] private LayerMask selectableLayers = -1; // 可选择图层
[SerializeField] private LayerMask excludedLayers = 0; // 要排除的图层
[Header("子物体观察模式 - 物体类型排除")]
[SerializeField] private bool excludeCameras = true; // 是否排除摄像机
[SerializeField] private bool excludeLights = true; // 是否排除灯光
[SerializeField] private bool excludeUI = true; // 是否排除UI元素
[SerializeField] private string[] excludeTags = { "MainCamera", "Light", "UI" }; // 要排除的标签
[SerializeField] private float childMinZoomDistance = 0.5f; // 观察子物体时的最小缩放距离
[SerializeField] private float childMaxZoomDistance = 10.0f; // 观察子物体时的最大缩放距离
[SerializeField] private Color highlightColor = new Color(1f, 0.5f, 0f, 0.3f); // 高亮颜色
[SerializeField] private float highlightFadeSpeed = 5.0f; // 高亮淡出速度
[Header("鼠标控制")]
[SerializeField] private MouseButton rotateButton = MouseButton.Left;
[SerializeField] private MouseButton panButton = MouseButton.Middle;
[SerializeField] private float mouseSensitivity = 1.0f;
[Header("触摸屏控制")]
[SerializeField] private float touchSensitivity = 0.5f;
[Header("边界限制")]
[SerializeField] private Vector2 verticalAngleLimit = new Vector2(10f, 80f);
private Vector3 currentRotation = Vector3.zero;
private Vector3 targetRotation = Vector3.zero;
private float currentDistance = 5.0f;
private float targetDistance = 5.0f;
private Vector3 targetPositionOffset = Vector3.zero;
private Vector3 currentTargetPositionOffset = Vector3.zero;
private Vector3 lastMousePosition = Vector3.zero;
private Vector3 lastPanPosition = Vector3.zero;
// 子物体观察模式相关变量
private bool isObservingChild = false;
private GameObject currentObservedChild = null;
private GameObject childInstance = null;
// 子物体观察模式下的缩放距离
private float childCurrentDistance = 3.0f;
private float childTargetDistance = 3.0f;
// 高亮相关
private Renderer[] highlightedRenderers = null;
private List<Material[]> originalMaterials = new List<Material[]>();
private List<Material[]> highlightMaterials = new List<Material[]>();
private float highlightTimer = 0f;
// 保存原始状态
private Vector3 savedTargetPositionOffset = Vector3.zero;
private Vector3 savedTargetRotation = Vector3.zero;
private float savedTargetDistance = 5.0f;
private float savedCurrentDistance = 5.0f;
private bool savedEnableAutoRotation = false;
public bool isOpenOnGUI = false;
/// <summary>
/// 当开始观察子物体时触发。参数1: 克隆体, 参数2: 原始物体
/// </summary>
public System.Action<GameObject, GameObject> OnChildObservationStarted;
/// <summary>
/// 当结束观察子物体时触发。参数1: 克隆体 (可能为null) 参数2: 原始物体
/// </summary>
public System.Action<GameObject, GameObject> OnChildObservationEnded;
private enum MouseButton
{
Left = 0,
Right = 1,
Middle = 2
}
void LateUpdate()
{
if (target == null) return;
if (EventSystem.current.IsPointerOverGameObject()) return;
HandleInput();
UpdateCameraPosition();
// 更新高亮效果
UpdateHighlight();
}
private void HandleInput()
{
HandleDesktopInput();
HandleTouchInput();
// 处理子物体观察模式切换
HandleChildObservationMode();
}
private void HandleChildObservationMode()
{
// 按左Shift键退出子物体观察模式
if (Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKeyDown(KeyCode.RightShift))
{
ExitChildObservationMode();
}
}
private void HandleDesktopInput()
{
// 点击选择子物体
if (enableClickToFocus && Input.GetMouseButtonDown(0) && !isObservingChild)
{
HandleObjectClick();
}
// 在子物体观察模式下,允许旋转和缩放
if (isObservingChild)
{
if (enableRotation) HandleRotationInput();
if (enableZoom) HandleZoomInput();
}
else
{
// 正常模式下的所有输入
if (enableRotation) HandleRotationInput();
if (enablePan) HandlePanInput();
if (enableZoom) HandleZoomInput();
}
// 重置按钮
if (Input.GetKeyDown(KeyCode.R))
{
ResetView();
}
/*
// 自动旋转切换
if (Input.GetKeyDown(KeyCode.A))
{
ToggleAutoRotation(!enableAutoRotation);
}*/
// 聚焦到模型
if (Input.GetKeyDown(KeyCode.F))
{
FocusOnModel();
}
}
private void HandleObjectClick()
{
if (!enableClickToFocus) return;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
// 执行射线检测,使用可选择图层
if (Physics.Raycast(ray, out hit, Mathf.Infinity, selectableLayers))
{
GameObject hitObject = hit.collider.gameObject;
// 检查是否在排除的图层中
if (IsInExcludedLayers(hitObject))
{
Debug.Log($"跳过:物体 {hitObject.name} 在排除的图层中");
return;
}
// 检查是否是要排除的物体类型
if (ShouldExcludeObject(hitObject))
{
Debug.Log($"跳过:物体 {hitObject.name} 是需要排除的类型");
return;
}
// 检查是否点击了目标或目标的子物体
if (hit.collider.transform == target || IsChildOfTarget(hit.collider.transform))
{
StartObservingChild(hitObject);
}
}
}
private bool IsInExcludedLayers(GameObject obj)
{
// 检查物体是否在排除的图层中
int layerMask = 1 << obj.layer;
return (excludedLayers.value & layerMask) != 0;
}
private bool ShouldExcludeObject(GameObject obj)
{
// 检查是否需要排除摄像机
if (excludeCameras && obj.GetComponent<Camera>() != null)
{
return true;
}
// 检查是否需要排除灯光
if (excludeLights && obj.GetComponent<Light>() != null)
{
return true;
}
// 检查是否需要排除UI元素
if (excludeUI && (obj.GetComponent<UnityEngine.UI.Graphic>() != null ||
obj.GetComponent<UnityEngine.UI.Selectable>() != null))
{
return true;
}
// 检查是否有要排除的标签
foreach (string tag in excludeTags)
{
if (obj.CompareTag(tag))
{
return true;
}
}
return false;
}
private bool IsChildOfTarget(Transform child)
{
Transform parent = child.parent;
while (parent != null)
{
if (parent == target)
{
return true;
}
parent = parent.parent;
}
return false;
}
private void HandleRotationInput()
{
if (!enableRotation) return;
if (Input.GetMouseButton((int)rotateButton))
{
float horizontal = Input.GetAxis("Mouse X") * rotationSpeed * mouseSensitivity;
float vertical = -Input.GetAxis("Mouse Y") * rotationSpeed * mouseSensitivity;
if (isObservingChild)
{
// 子物体观察模式:旋转相机
targetRotation.x += horizontal;
targetRotation.y += vertical;
}
else
{
// 正常模式:旋转相机
targetRotation.x += horizontal;
targetRotation.y += vertical;
}
targetRotation.y = Mathf.Clamp(targetRotation.y, verticalAngleLimit.x, verticalAngleLimit.y);
enableAutoRotation = false;
}
}
private void HandlePanInput()
{
if (!enablePan) return;
if (!isObservingChild && Input.GetMouseButton((int)panButton))
{
if (Input.GetMouseButtonDown((int)panButton))
{
lastPanPosition = Input.mousePosition;
}
Vector3 delta = Input.mousePosition - lastPanPosition;
Vector3 right = transform.right;
Vector3 up = transform.up;
right.y = 0;
up.y = 0;
Vector3 panDelta = (right * delta.x + up * delta.y) * panSpeed * 0.01f;
ApplyPanWithLimits(panDelta);
lastPanPosition = Input.mousePosition;
}
}
private void HandleZoomInput()
{
if (!enableZoom) return;
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (Mathf.Abs(scroll) > 0.01f)
{
if (isObservingChild)
{
// 子物体观察模式:调整子物体观察距离
childTargetDistance -= scroll * zoomSpeed;
childTargetDistance = Mathf.Clamp(childTargetDistance, childMinZoomDistance, childMaxZoomDistance);
}
else
{
// 正常模式:调整模型观察距离
targetDistance -= scroll * zoomSpeed;
targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance);
}
}
}
private void ApplyPanWithLimits(Vector3 panDelta)
{
Vector3 newOffset = targetPositionOffset - panDelta;
newOffset.x = Mathf.Clamp(newOffset.x, -maxPanDistanceX, maxPanDistanceZ);
newOffset.z = Mathf.Clamp(newOffset.z, -maxPanDistanceZ, maxPanDistanceZ);
targetPositionOffset = newOffset;
}
private void HandleTouchInput()
{
#if UNITY_IOS || UNITY_ANDROID || UNITY_WEBGL
if (Input.touchCount == 1)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
Vector2 delta = touch.deltaPosition;
targetRotation.x += delta.x * rotationSpeed * touchSensitivity * 0.1f;
targetRotation.y -= delta.y * rotationSpeed * touchSensitivity * 0.1f;
targetRotation.y = Mathf.Clamp(targetRotation.y, verticalAngleLimit.x, verticalAngleLimit.y);
}
}
else if (Input.touchCount == 2)
{
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
if (isObservingChild)
{
childTargetDistance += deltaMagnitudeDiff * zoomSpeed * 0.01f;
childTargetDistance = Mathf.Clamp(childTargetDistance, childMinZoomDistance, childMaxZoomDistance);
}
else
{
targetDistance += deltaMagnitudeDiff * zoomSpeed * 0.01f;
targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance);
}
}
#endif
}
private void StartObservingChild(GameObject child)
{
if (isObservingChild || !enableClickToFocus) return;
/* target.gameObject.SetActive(false);
// 保存当前状态
savedTargetPositionOffset = targetPositionOffset;
savedTargetRotation = targetRotation;
savedTargetDistance = targetDistance;
savedCurrentDistance = currentDistance;
savedEnableAutoRotation = enableAutoRotation;
currentObservedChild = child;
originalTargetPosition = target.position;
originalChildPosition = child.transform.position;
originalChildRotation = child.transform.rotation;
originalParent = child.transform.parent;
// 计算子物体的包围盒
Bounds bounds = CalculateBounds(child);
Vector3 childCenter = bounds.center;
// 复制子物体
childInstance = Instantiate(child, childCenter, child.transform.rotation);
//childInstance.transform.SetLocalPositionAndRotation(default, default);
// 删除所有子物体上的脚本,避免干扰
MonoBehaviour[] scripts = childInstance.GetComponentsInChildren<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
Destroy(script);
}
// 隐藏原来的子物体
//child.SetActive(false);
// 高亮显示复制出的物体
HighlightObject(childInstance);
// 计算适合观察的距离
float objectSize = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z);
childTargetDistance = objectSize * 1.5f;
childTargetDistance = Mathf.Clamp(childTargetDistance, childMinZoomDistance, childMaxZoomDistance);
childCurrentDistance = childTargetDistance;
// 设置子物体观察模式参数
isObservingChild = true;
targetDistance = childTargetDistance;
currentDistance = childTargetDistance;
targetPositionOffset = Vector3.zero;
enableAutoRotation = false;
// 将相机对准子物体中心
Vector3 toCamera = (transform.position - childCenter).normalized;
targetRotation.x = Mathf.Atan2(toCamera.x, toCamera.z) * Mathf.Rad2Deg;
targetRotation.y = Mathf.Asin(toCamera.y) * Mathf.Rad2Deg;
Debug.Log($"开始观察子物体: {child.name}");
// --- 新增:触发开始观察事件 ---
if (OnChildObservationStarted != null)
{
OnChildObservationStarted(childInstance, child);
}
*/
if (SK.Framework.UIView.Get<EquipmentChildStructureView>())
{
SK.Framework.UIView.Show<EquipmentChildStructureView>().ShowDeviceInformation(child);
}
else
{
SK.Framework.UIView.Load<EquipmentChildStructureView>(SK.Framework.ViewLevel.POP).ShowDeviceInformation(child);
}
}
private Bounds CalculateBounds(GameObject obj)
{
Renderer[] renderers = obj.GetComponentsInChildren<Renderer>();
if (renderers.Length == 0)
{
return new Bounds(obj.transform.position, Vector3.one);
}
Bounds bounds = renderers[0].bounds;
foreach (Renderer renderer in renderers)
{
bounds.Encapsulate(renderer.bounds);
}
return bounds;
}
private void HighlightObject(GameObject obj)
{
// 获取所有渲染器
highlightedRenderers = obj.GetComponentsInChildren<Renderer>();
// 保存原始材质并创建高亮材质
originalMaterials.Clear();
highlightMaterials.Clear();
foreach (Renderer renderer in highlightedRenderers)
{
Material[] originalMats = renderer.materials;
originalMaterials.Add(originalMats);
Material[] highlightMats = new Material[originalMats.Length];
for (int i = 0; i < originalMats.Length; i++)
{
Material highlightMat = new Material(originalMats[i]);
highlightMat.EnableKeyword("_EMISSION");
highlightMat.SetColor("_EmissionColor", highlightColor);
highlightMats[i] = highlightMat;
}
highlightMaterials.Add(highlightMats);
renderer.materials = highlightMats;
}
highlightTimer = 0f;
}
private void UpdateHighlight()
{
if (highlightedRenderers == null || highlightTimer >= 1f) return;
highlightTimer += Time.deltaTime * highlightFadeSpeed;
// 渐变高亮效果
for (int i = 0; i < highlightedRenderers.Length; i++)
{
Renderer renderer = highlightedRenderers[i];
Material[] highlightMats = highlightMaterials[i];
for (int j = 0; j < highlightMats.Length; j++)
{
if (highlightMats[j] != null)
{
Color emissionColor = Color.Lerp(highlightColor, Color.black, highlightTimer);
highlightMats[j].SetColor("_EmissionColor", emissionColor);
}
}
renderer.materials = highlightMats;
}
// 高亮结束后清理
if (highlightTimer >= 1f)
{
RestoreOriginalMaterials();
}
}
private void RestoreOriginalMaterials()
{
if (highlightedRenderers != null)
{
for (int i = 0; i < highlightedRenderers.Length; i++)
{
if (highlightedRenderers[i] != null && i < originalMaterials.Count)
{
highlightedRenderers[i].materials = originalMaterials[i];
}
}
}
highlightedRenderers = null;
originalMaterials.Clear();
highlightMaterials.Clear();
}
private void ExitChildObservationMode()
{
if (!isObservingChild) return;
// 删除复制的物体
if (childInstance != null)
{
Destroy(childInstance);
childInstance = null;
}
// 恢复原子物体的显示
if (currentObservedChild != null)
{
currentObservedChild.SetActive(true);
}
// 恢复原始状态
targetPositionOffset = savedTargetPositionOffset;
targetRotation = savedTargetRotation;
targetDistance = savedTargetDistance;
currentDistance = savedCurrentDistance;
enableAutoRotation = savedEnableAutoRotation;
// 触发结束观察事件 (在清理引用前)
if (OnChildObservationEnded != null)
{
OnChildObservationEnded(childInstance, currentObservedChild);
}
// 重置状态
isObservingChild = false;
currentObservedChild = null;
// 恢复原始高亮材质
RestoreOriginalMaterials();
target.gameObject.SetActive(true);
Debug.Log("退出子物体观察模式");
}
private void UpdateCameraPosition()
{
if (enableAutoRotation && !isObservingChild)
{
targetRotation.x += autoRotationSpeed;
}
// 平滑旋转
currentRotation = Vector3.Lerp(currentRotation, targetRotation, rotationSmoothness * Time.deltaTime);
if (isObservingChild)
{
// 子物体观察模式:平滑子物体观察距离
childCurrentDistance = Mathf.Lerp(childCurrentDistance, childTargetDistance, rotationSmoothness * Time.deltaTime);
currentDistance = childCurrentDistance;
}
else
{
// 正常模式:平滑模型观察距离
currentDistance = Mathf.Lerp(currentDistance, targetDistance, rotationSmoothness * Time.deltaTime);
}
// 在子物体观察模式下,不更新平移偏移
if (!isObservingChild)
{
currentTargetPositionOffset = Vector3.Lerp(currentTargetPositionOffset, targetPositionOffset, rotationSmoothness * Time.deltaTime);
}
Quaternion rotation = Quaternion.Euler(currentRotation.y, currentRotation.x, 0);
// 计算观察中心
Vector3 lookAtPoint = target.position;
if (isObservingChild && childInstance != null)
{
lookAtPoint = childInstance.transform.position;
}
else
{
lookAtPoint += currentTargetPositionOffset;
}
Vector3 position = rotation * new Vector3(0, 0, -currentDistance) + lookAtPoint;
transform.position = position;
transform.LookAt(lookAtPoint);
}
public void ResetView()
{
if (isObservingChild)
{
ExitChildObservationMode();
}
targetRotation = new Vector3(0, 45f, 0);
targetDistance = defaultZoomDistance;
targetPositionOffset = Vector3.zero;
enableAutoRotation = false;
}
public void FocusOnModel()
{
if (target != null)
{
targetPositionOffset = Vector3.zero;
}
}
public void SetTarget(Transform newTarget)
{
target = newTarget;
ResetView();
}
public void SetTarget(GameObject newTarget)
{
if (newTarget != null)
{
target = newTarget.transform;
ResetView();
}
}
public void SetTargetOffset(Vector3 offset)
{
targetPositionOffset = new Vector3(
Mathf.Clamp(offset.x, -maxPanDistanceX, maxPanDistanceZ),
offset.y,
Mathf.Clamp(offset.z, -maxPanDistanceZ, maxPanDistanceZ)
);
}
public void SetZoomDistance(float distance)
{
if (isObservingChild)
{
childTargetDistance = Mathf.Clamp(distance, childMinZoomDistance, childMaxZoomDistance);
}
else
{
targetDistance = Mathf.Clamp(distance, minZoomDistance, maxZoomDistance);
}
}
public void SetRotation(float horizontal, float vertical)
{
targetRotation = new Vector3(horizontal, Mathf.Clamp(vertical, verticalAngleLimit.x, verticalAngleLimit.y), 0);
}
public void ToggleAutoRotation(bool enable)
{
enableAutoRotation = enable;
}
public void SetAutoRotationSpeed(float speed)
{
autoRotationSpeed = speed;
}
public void SetPanLimits(float maxX, float maxZ)
{
maxPanDistanceX = Mathf.Max(0, maxX);
maxPanDistanceZ = Mathf.Max(0, maxZ);
}
public float GetCurrentZoomDistance()
{
return isObservingChild ? childCurrentDistance : currentDistance;
}
public Vector3 GetCurrentPanOffset()
{
return currentTargetPositionOffset;
}
public bool IsObservingChild()
{
return isObservingChild;
}
public GameObject GetCurrentObservedChild()
{
return currentObservedChild;
}
public void AddExcludedTag(string tag)
{
if (!System.Array.Exists(excludeTags, t => t == tag))
{
System.Array.Resize(ref excludeTags, excludeTags.Length + 1);
excludeTags[excludeTags.Length - 1] = tag;
}
}
public void RemoveExcludedTag(string tag)
{
int index = System.Array.IndexOf(excludeTags, tag);
if (index >= 0)
{
for (int i = index; i < excludeTags.Length - 1; i++)
{
excludeTags[i] = excludeTags[i + 1];
}
System.Array.Resize(ref excludeTags, excludeTags.Length - 1);
}
}
// 新增的公共方法,用于外部控制功能开关
public void SetEnableClickToFocus(bool enable)
{
enableClickToFocus = enable;
if (!enable && isObservingChild)
{
ExitChildObservationMode();
}
}
public bool GetEnableClickToFocus()
{
return enableClickToFocus;
}
public void SetEnableRotation(bool enable)
{
enableRotation = enable;
}
public bool GetEnableRotation()
{
return enableRotation;
}
public void SetEnablePan(bool enable)
{
enablePan = enable;
}
public bool GetEnablePan()
{
return enablePan;
}
public void SetEnableZoom(bool enable)
{
enableZoom = enable;
}
public bool GetEnableZoom()
{
return enableZoom;
}
void OnGUI()
{
if (Application.isEditor && isOpenOnGUI)
{
int yOffset = 10;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"上帝视角观察器 - 模型查看器");
yOffset += 20;
if (target != null)
{
GUI.Label(new Rect(10, yOffset, 300, 20),
$"目标: {target.name}");
}
else
{
GUI.Label(new Rect(10, yOffset, 300, 20),
"目标: 未设置 (请在Inspector中指定)");
}
yOffset += 20;
if (isObservingChild && currentObservedChild != null)
{
GUI.Label(new Rect(10, yOffset, 300, 20),
$"正在观察: {currentObservedChild.name} (子物体模式)");
yOffset += 20;
}
GUI.Label(new Rect(10, yOffset, 300, 20),
$"旋转: ({currentRotation.x:F1}, {currentRotation.y:F1})");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"距离: {GetCurrentZoomDistance():F1} (范围: {minZoomDistance:F1}-{maxZoomDistance:F1})");
yOffset += 20;
if (!isObservingChild)
{
GUI.Label(new Rect(10, yOffset, 300, 20),
$"平移偏移: X={currentTargetPositionOffset.x:F2}, Z={currentTargetPositionOffset.z:F2}");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"平移限制: X=±{maxPanDistanceX:F1}, Z=±{maxPanDistanceZ:F1}");
yOffset += 20;
}
GUI.Label(new Rect(10, yOffset, 300, 20),
$"自动旋转: {(enableAutoRotation ? "" : "")}");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"点击聚焦: {(enableClickToFocus ? "" : "")}");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"旋转功能: {(enableRotation ? "" : "")}");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"平移功能: {(enablePan ? "" : "")}");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 300, 20),
$"缩放功能: {(enableZoom ? "" : "")}");
yOffset += 20;
yOffset += 10;
GUI.Label(new Rect(10, yOffset, 400, 20),
"控制说明:");
yOffset += 20;
if (enableClickToFocus)
{
GUI.Label(new Rect(10, yOffset, 400, 20),
"左键点击: 选择子物体观察 (已排除UI/摄像机/灯光)");
yOffset += 20;
}
if (isObservingChild)
{
if (enableRotation)
{
GUI.Label(new Rect(10, yOffset, 400, 20),
"左键拖拽: 旋转子物体");
yOffset += 20;
}
if (enableZoom)
{
GUI.Label(new Rect(10, yOffset, 400, 20),
"滚轮: 缩小子物体观察距离");
yOffset += 20;
}
GUI.Label(new Rect(10, yOffset, 400, 20),
"Shift键: 退出子物体观察模式");
yOffset += 20;
}
else
{
if (enableRotation)
{
GUI.Label(new Rect(10, yOffset, 400, 20),
"左键拖拽: 旋转视角");
yOffset += 20;
}
if (enablePan)
{
GUI.Label(new Rect(10, yOffset, 400, 20),
"中键拖拽: 平移视角 (有距离限制)");
yOffset += 20;
}
if (enableZoom)
{
GUI.Label(new Rect(10, yOffset, 400, 20),
"滚轮: 缩放 (有距离限制)");
yOffset += 20;
}
}
GUI.Label(new Rect(10, yOffset, 400, 20),
"R键: 重置视角");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 400, 20),
"A键: 切换自动旋转");
yOffset += 20;
GUI.Label(new Rect(10, yOffset, 400, 20),
"F键: 聚焦到模型中心");
yOffset += 20;
}
}
void OnDrawGizmosSelected()
{
if (target != null && showPanBoundary && !isObservingChild)
{
Vector3 center = target.position;
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(center, 0.5f);
Gizmos.color = new Color(1f, 0.5f, 0f, 0.3f);
Vector3 size = new Vector3(maxPanDistanceX * 2, 0.1f, maxPanDistanceZ * 2);
Gizmos.DrawWireCube(center, size);
Gizmos.color = new Color(0f, 1f, 0f, 0.5f);
Vector3 currentOffset = target.position + currentTargetPositionOffset;
Gizmos.DrawWireSphere(currentOffset, 0.3f);
Gizmos.DrawLine(center, currentOffset);
Gizmos.color = Color.red;
Vector3 cameraPos = transform.position;
Gizmos.DrawLine(currentOffset, cameraPos);
DrawBoundaryCorners(center);
}
}
private void DrawBoundaryCorners(Vector3 center)
{
Gizmos.color = Color.cyan;
Vector3[] corners = new Vector3[4];
corners[0] = center + new Vector3(-maxPanDistanceX, 0, -maxPanDistanceZ);
corners[1] = center + new Vector3(maxPanDistanceX, 0, -maxPanDistanceZ);
corners[2] = center + new Vector3(maxPanDistanceX, 0, maxPanDistanceZ);
corners[3] = center + new Vector3(-maxPanDistanceX, 0, maxPanDistanceZ);
for (int i = 0; i < 4; i++)
{
Gizmos.DrawSphere(corners[i], 0.2f);
Gizmos.DrawLine(corners[i], corners[(i + 1) % 4]);
}
}
void OnDestroy()
{
// 清理高亮材质
RestoreOriginalMaterials();
}
}