EnergyEfficiencyManagement/Assets/Zion/Scripts/RawImageModelController.cs

372 lines
11 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 UnityEngine.UI;
using System.Collections;
/// <summary>
/// RawImage模型控制器
/// 功能在RawImage上显示3D模型并支持旋转和缩放操作
/// </summary>
public class RawImageModelController : MonoBehaviour
{
[Header("【模型设置】")]
[Tooltip("要显示的3D模型")]
[SerializeField] private GameObject model;
[Header("【UI组件】")]
[Tooltip("显示模型的RawImage组件")]
[SerializeField] private RawImage displayImage;
[Tooltip("渲染模型的相机")]
[SerializeField] private Camera renderCamera;
[Tooltip("渲染纹理相机将画面渲染到此再由RawImage显示")]
[SerializeField] private RenderTexture renderTexture;
[Header("【控制设置】")]
[Tooltip("旋转速度")]
[SerializeField] private float rotationSpeed = 2.0f;
[Tooltip("缩放速度")]
[SerializeField] private float zoomSpeed = 0.5f;
[Tooltip("最小缩放值")]
[SerializeField] private float minZoom = 0.5f;
[Tooltip("最大缩放值")]
[SerializeField] private float maxZoom = 3.0f;
[Tooltip("默认缩放值")]
[SerializeField] private float defaultZoom = 1.0f;
[Header("【相机设置】")]
[Tooltip("相机相对于模型的初始偏移")]
[SerializeField] private Vector3 cameraOffset = new Vector3(0, 0, 5);
[Tooltip("相机视野")]
[SerializeField] private float fieldOfView = 60f;
[Header("【初始变换】")]
[Tooltip("模型的初始旋转")]
[SerializeField] private Vector3 initialRotation = Vector3.zero;
[Tooltip("模型的初始缩放")]
[SerializeField] private Vector3 initialScale = Vector3.one;
// 内部状态变量
private Vector2 currentRotation = Vector2.zero;
private float currentZoom = 1.0f;
private float targetZoom = 1.0f;
private Vector2 lastMousePosition;
private bool isDragging = false;
private bool isInitialized = false;
/// <summary>
/// 设置要显示的模型
/// </summary>
/// <param name="modelObj">要显示的模型对象</param>
public void SetModel(GameObject modelObj)
{
model = modelObj;
if (model != null)
{
InitializeModel();
}
}
/// <summary>
/// 获取当前显示的模型
/// </summary>
/// <returns>当前模型对象</returns>
public GameObject GetModel()
{
return model;
}
/// <summary>
/// 初始化组件
/// </summary>
void Start()
{
Initialize();
}
/// <summary>
/// 初始化所有组件
/// </summary>
private void Initialize()
{
if (isInitialized) return;
// 验证必要组件
if (displayImage == null)
{
Debug.LogError("RawImageModelController: 未设置Display Image组件", this);
return;
}
if (renderCamera == null)
{
Debug.LogError("RawImageModelController: 未设置Render Camera", this);
return;
}
if (renderTexture == null)
{
Debug.LogError("RawImageModelController: 未设置Render Texture", this);
return;
}
// 配置渲染相机
ConfigureRenderCamera();
// 设置RawImage的纹理
displayImage.texture = renderTexture;
// 如果已有模型,则初始化
if (model != null)
{
InitializeModel();
}
// 设置初始状态
currentZoom = defaultZoom;
targetZoom = defaultZoom;
currentRotation = new Vector2(initialRotation.y, -initialRotation.x);
isInitialized = true;
}
/// <summary>
/// 配置渲染相机
/// </summary>
private void ConfigureRenderCamera()
{
renderCamera.targetTexture = renderTexture;
renderCamera.fieldOfView = fieldOfView;
renderCamera.enabled = true; // 默认启用相机
// 设置相机的初始位置
if (model != null)
{
renderCamera.transform.position = model.transform.position + cameraOffset;
renderCamera.transform.LookAt(model.transform);
}
else
{
renderCamera.transform.position = cameraOffset;
renderCamera.transform.LookAt(Vector3.zero);
}
}
/// <summary>
/// 初始化模型
/// </summary>
private void InitializeModel()
{
if (model == null) return;
// 设置模型的初始状态
model.transform.localRotation = Quaternion.Euler(initialRotation);
model.transform.localScale = initialScale;
// 将相机定位到模型前方
renderCamera.transform.position = model.transform.position + cameraOffset;
renderCamera.transform.LookAt(model.transform);
}
/// <summary>
/// 每帧更新
/// </summary>
void Update()
{
if (!isInitialized || model == null) return;
HandleInput();
UpdateModelTransform();
}
/// <summary>
/// 处理用户输入
/// </summary>
private void HandleInput()
{
// 检查鼠标是否在RawImage区域内
if (IsMouseOverDisplayImage())
{
// 旋转控制(鼠标左键拖拽)
if (Input.GetMouseButtonDown(0))
{
isDragging = true;
lastMousePosition = Input.mousePosition;
}
if (Input.GetMouseButton(0) && isDragging)
{
Vector2 currentMousePos = Input.mousePosition;
Vector2 delta = currentMousePos - lastMousePosition;
// 根据鼠标移动增量更新旋转角度
currentRotation.x += delta.y * rotationSpeed * 0.1f; // 绕X轴旋转
currentRotation.y -= delta.x * rotationSpeed * 0.1f; // 绕Y轴旋转
// 限制垂直旋转角度,避免过度翻转
currentRotation.x = Mathf.Clamp(currentRotation.x, -85f, 85f);
lastMousePosition = currentMousePos;
}
if (Input.GetMouseButtonUp(0))
{
isDragging = false;
}
// 缩放控制(鼠标滚轮)
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (Mathf.Abs(scroll) > 0.01f)
{
// 根据滚轮方向调整目标缩放值
targetZoom -= scroll * zoomSpeed;
targetZoom = Mathf.Clamp(targetZoom, minZoom, maxZoom);
}
}
// 重置视图R键
if (Input.GetKeyDown(KeyCode.R))
{
ResetView();
}
}
/// <summary>
/// 检测鼠标是否在显示图像的区域内
/// </summary>
/// <returns>如果鼠标在区域内返回true否则返回false</returns>
private bool IsMouseOverDisplayImage()
{
if (displayImage == null) return false;
RectTransform rect = displayImage.rectTransform;
Vector2 localPoint;
// 将屏幕鼠标坐标转换为UI矩形内的本地坐标
return RectTransformUtility.ScreenPointToLocalPointInRectangle(
rect, Input.mousePosition, null, out localPoint)
&& rect.rect.Contains(localPoint);
}
/// <summary>
/// 更新模型的变换
/// </summary>
private void UpdateModelTransform()
{
if (model == null) return;
// 平滑插值缩放
currentZoom = Mathf.Lerp(currentZoom, targetZoom, 5f * Time.deltaTime);
// 应用旋转
Quaternion targetRotation = Quaternion.Euler(currentRotation.x, currentRotation.y, 0);
model.transform.rotation = targetRotation;
// 应用缩放
model.transform.localScale = initialScale * currentZoom;
// 更新相机位置以保持相对距离
Vector3 cameraDirection = (renderCamera.transform.position - model.transform.position).normalized;
Vector3 targetCameraPosition = model.transform.position + cameraDirection * (cameraOffset.magnitude * currentZoom);
renderCamera.transform.position = targetCameraPosition;
renderCamera.transform.LookAt(model.transform);
}
/// <summary>
/// 重置视图到初始状态
/// </summary>
public void ResetView()
{
currentRotation = new Vector2(initialRotation.y, -initialRotation.x);
currentZoom = defaultZoom;
targetZoom = defaultZoom;
if (model != null)
{
model.transform.localRotation = Quaternion.Euler(initialRotation);
model.transform.localScale = initialScale;
}
// 重置相机位置
if (model != null)
{
renderCamera.transform.position = model.transform.position + cameraOffset;
renderCamera.transform.LookAt(model.transform);
}
else
{
renderCamera.transform.position = cameraOffset;
renderCamera.transform.LookAt(Vector3.zero);
}
}
/// <summary>
/// 设置旋转速度
/// </summary>
/// <param name="speed">新的旋转速度</param>
public void SetRotationSpeed(float speed)
{
rotationSpeed = speed;
}
/// <summary>
/// 设置缩放速度
/// </summary>
/// <param name="speed">新的缩放速度</param>
public void SetZoomSpeed(float speed)
{
zoomSpeed = speed;
}
/// <summary>
/// 设置缩放限制
/// </summary>
/// <param name="min">最小缩放值</param>
/// <param name="max">最大缩放值</param>
public void SetZoomLimits(float min, float max)
{
minZoom = min;
maxZoom = max;
targetZoom = Mathf.Clamp(targetZoom, minZoom, maxZoom);
}
/// <summary>
/// 获取当前缩放值
/// </summary>
/// <returns>当前缩放值</returns>
public float GetCurrentZoom()
{
return currentZoom;
}
/// <summary>
/// 设置当前缩放值
/// </summary>
/// <param name="zoom">目标缩放值</param>
public void SetZoom(float zoom)
{
targetZoom = Mathf.Clamp(zoom, minZoom, maxZoom);
}
/// <summary>
/// 启用/禁用控制器
/// </summary>
/// <param name="enabled">是否启用</param>
public void SetEnabled(bool enabled)
{
gameObject.SetActive(enabled);
}
/// <summary>
/// 在编辑器中绘制调试信息
/// </summary>
void OnValidate()
{
if (renderCamera != null)
{
// 确保相机设置正确
if (fieldOfView > 0)
{
renderCamera.fieldOfView = fieldOfView;
}
}
}
}