shenjianxing e3bc40bf8b 完善3D解剖功能
增加TextTip标题功能
2025-02-13 17:21:18 +08:00

218 lines
5.8 KiB
C#

using GCSeries.Core;
using System;
using Unity.Burst.CompilerServices;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityEngine.UIElements;
public class Show3DCamera : MonoBehaviour
{
public Vector3 targetPos; // 围绕旋转的目标点
public float rotateSpeed = 10f; // 旋转速度
public float moveSpeed = 10f; // 移动速度
public float distance = 10f; // 相机与目标的距离
public float distanceMin = 0.2f;
public float distanceMax = 20f;
public Vector2 pitchMinMax = new Vector2(-20, 80); // 相机俯仰角范围
private Vector3 offset; // 相机与目标的偏移量
private float yaw = 0f; // 偏航角(左右旋转)
private float pitch = 0f; // 俯仰角(上下旋转)
public static Show3DCamera instance;
RectTransform inputRect;
Camera self;
private GameObject lastHitObject = null;
public RenderTexture texture;
public bool lockMove = false;
private void Awake()
{
instance = this;
self = transform.GetComponent<Camera>();
DontDestroyOnLoad(this);
gameObject.SetActive(false);
}
public void Set(Transform target, float rotateSpeed = 10, float moveSpeed = 0.1f, float distance = 0.1f, float pitchMin = -20, float pitchMax = 80, float distanceMin = 0.2f, float distanceMax = 20f, RectTransform inputRect = null, bool isRenderTexture = true)
{
if (target == null)
{
Debug.LogError("Target is not assigned!");
return;
}
yaw = 0;
pitch = 0;
this.inputRect = inputRect;
this.targetPos = target.transform.position;
this.rotateSpeed = rotateSpeed;
this.moveSpeed = moveSpeed;
this.distance = distance;
this.distanceMin = distanceMin;
this.distanceMax = distanceMax;
this.pitchMinMax = new Vector2(pitchMin, pitchMax);
// 初始化相机位置
offset = new Vector3(0, 0, -distance);
if (isRenderTexture)
{
self.targetTexture = texture;
}
else
{
self.targetTexture = null;
}
UpdateCameraPosition();
}
void Update()
{
if (targetPos != null && lockMove == false)
{
// 按住鼠标左键时旋转相机
if (Input.GetMouseButton(0))
{
RotateCamera();
}
// 鼠标滚轮缩放
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll != 0)
{
ZoomCamera(scroll);
}
// 按住鼠标右键时移动目标点
if (Input.GetMouseButton(1))
{
MoveTarget();
}
DetectHoveredObject();
}
}
// 检测鼠标悬停的物体
public void DetectHoveredObject()
{
GameObject obj = null;
Vector2 mousePosition = Input.mousePosition;
if (inputRect != null)
{
var pos = (mousePosition - (Vector2)inputRect.position) / inputRect.lossyScale - inputRect.rect.position;
mousePosition = pos / inputRect.rect.size;
}
var ray = self.ViewportPointToRay(mousePosition);
RaycastHit raycastHit;
if (Physics.Raycast(ray, out raycastHit))
{
//Debug.Log(raycastHit.transform.name);
obj = raycastHit.transform.gameObject;
// 如果击中的物体与上一次击中的物体不同,表示射线进入了新物体
if (obj != lastHitObject)
{
// 触发进入事件
OnMouseEnterObj(obj);
// 如果上一次击中的物体不为空,触发离开事件
if (lastHitObject != null && lastHitObject != obj)
{
OnMouseExitObj(lastHitObject);
// 更新上一次击中的物体
lastHitObject = obj;
}
}
}
else
{
// 如果射线没有击中任何物体,且上一次击中的物体不为空,触发离开事件
if (lastHitObject != null)
{
OnMouseExitObj(lastHitObject);
lastHitObject = null;
}
}
Debug.DrawLine(ray.origin, raycastHit.point, Color.red);
}
public void OnMouseEnterObj(GameObject obj)
{
TipItem tip = obj.GetComponent<TipItem>();
if (tip != null)
{
tip.OnEnter();
}
}
public void OnMouseExitObj(GameObject obj)
{
TipItem tip = obj.GetComponent<TipItem>();
if (tip != null)
{
tip.OnExit();
}
}
// 移动目标点
private void MoveTarget()
{
float mouseX = Input.GetAxis("Mouse X") * moveSpeed;
float mouseY = Input.GetAxis("Mouse Y") * moveSpeed;
transform.Translate(new Vector3(-mouseX, -mouseY, 0));
}
// 缩放相机
private void ZoomCamera(float scroll)
{
distance -= scroll * 5f; // 调整缩放速度
distance = Mathf.Clamp(distance, distanceMin, distanceMax); // 限制距离范围
offset = new Vector3(0, 0, -distance);
UpdateCameraPosition();
}
// 旋转相机
private void RotateCamera()
{
// 获取鼠标移动量
float mouseX = Input.GetAxis("Mouse X") * rotateSpeed;
float mouseY = Input.GetAxis("Mouse Y") * rotateSpeed;
// 更新偏航角和俯仰角
yaw += mouseX;
pitch -= mouseY; // 注意:鼠标 Y 轴移动方向与俯仰角相反
pitch = Mathf.Clamp(pitch, pitchMinMax.x, pitchMinMax.y); // 限制俯仰角范围
// 更新相机位置
UpdateCameraPosition();
}
// 更新相机位置和朝向
private void UpdateCameraPosition()
{
// 计算旋转后的偏移量
Quaternion rotation = Quaternion.Euler(pitch, yaw, 0);
Vector3 rotatedOffset = rotation * offset;
// 更新相机位置
transform.position = targetPos + rotatedOffset;
// 相机始终朝向目标点
transform.LookAt(targetPos);
}
}