完善device的3D展示功能

This commit is contained in:
shenjianxing 2025-02-10 10:54:47 +08:00
parent 3ac082043d
commit b58b34c80a
7 changed files with 135 additions and 56 deletions

View File

@ -309,13 +309,13 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 826586917723392204}
m_Father: {fileID: 8188781184013275445}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: -0}
m_AnchoredPosition: {x: -640, y: -360}
m_SizeDelta: {x: 1280, y: 720}
m_Pivot: {x: 0.5, y: 0.5}
m_Pivot: {x: 0, y: 0}
--- !u!222 &3370089183326341287
CanvasRenderer:
m_ObjectHideFlags: 0
@ -364,7 +364,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
MarkType: 0
CustomComponentName:
CustomComponentName: DeviceRawImage
CustomComment:
mComponentName: UnityEngine.UI.RawImage
--- !u!1 &1587529206278800681
@ -379,7 +379,7 @@ GameObject:
- component: {fileID: 7277770534815806214}
- component: {fileID: 5964642934946449171}
m_Layer: 0
m_Name: bg
m_Name: Right
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -744,7 +744,7 @@ GameObject:
- component: {fileID: 1954549762747143972}
- component: {fileID: 2228057524689582266}
m_Layer: 0
m_Name: Show
m_Name: Bg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -761,8 +761,7 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1614371002034144690}
m_Children: []
m_Father: {fileID: 8188781184013275445}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@ -947,6 +946,7 @@ RectTransform:
m_Children:
- {fileID: 1915876869541640623}
- {fileID: 826586917723392204}
- {fileID: 1614371002034144690}
- {fileID: 2836954293480787745}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

View File

@ -192,7 +192,7 @@ MonoBehaviour:
m_Spacing: 15
m_ChildForceExpandWidth: 0
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 1

View File

@ -1,13 +1,19 @@
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 Transform target; // 围绕旋转的目标点
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; // 相机与目标的偏移量
@ -16,10 +22,11 @@ public class Show3DCamera : MonoBehaviour
public static Show3DCamera instance;
int rawWidth;
int rawHeight;
RectTransform inputRect;
Camera self;
private GameObject lastHitObject = null;
private void Awake()
{
instance = this;
@ -27,35 +34,34 @@ public class Show3DCamera : MonoBehaviour
DontDestroyOnLoad(this);
gameObject.SetActive(false);
}
public void Set(int width,int height, Transform target, float rotateSpeed = 10, float moveSpeed = 0.1f, float distance = 0.1f, float pitchMin = -20, float pitchMax = 80)
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)
{
if (target == null)
{
Debug.LogError("Target is not assigned!");
return;
}
this.rawWidth = width;
this.rawHeight = height;
yaw = 0;
pitch = 0;
this.target = target.transform;
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);
UpdateCameraPosition();
}
public void Clear()
{
target = null;
}
void Update()
{
if (target != null)
if (targetPos != null)
{
// 按住鼠标左键时旋转相机
if (Input.GetMouseButton(0))
@ -76,45 +82,76 @@ public class Show3DCamera : MonoBehaviour
{
MoveTarget();
}
DetectHoveredObject();
}
}
// 检测鼠标悬停的物体
private void DetectHoveredObject()
public void DetectHoveredObject()
{
// 从相机发射射线
Ray ray = self.ScreenPointToRay(ConvertScreenToRenderTextureCoordinates(Input.mousePosition));
if (Physics.Raycast(ray, out RaycastHit hit))
GameObject obj = null;
Vector2 mousePosition = Input.mousePosition;
if (inputRect != null)
{
// 打印物体名称
Debug.LogError("Hovered Object: " + hit.collider.gameObject.name);
}
Debug.DrawLine(ray.origin, hit.point, Color.red);
var pos = (mousePosition - (Vector2)inputRect.position) / inputRect.lossyScale - inputRect.rect.position;
mousePosition = pos / inputRect.rect.size;
}
private Vector3 ConvertScreenToRenderTextureCoordinates(Vector3 screenPosition)
var ray = self.ViewportPointToRay(mousePosition);
RaycastHit raycastHit;
if (Physics.Raycast(ray, out raycastHit))
{
// 获取屏幕分辨率
int screenWidth = Screen.width;
int screenHeight = Screen.height;
//Debug.Log(raycastHit.transform.name);
obj = raycastHit.transform.gameObject;
// 计算比例
float scaleX = (float)rawWidth / screenWidth;
float scaleY = (float)rawHeight / screenHeight;
// 如果击中的物体与上一次击中的物体不同,表示射线进入了新物体
if (obj != lastHitObject)
{
// 触发进入事件
OnMouseEnterObj(obj);
// 转换鼠标位置
Vector3 renderTexturePosition = new Vector3(
screenPosition.x * scaleX,
screenPosition.y * scaleY,
screenPosition.z
);
return renderTexturePosition;
// 如果上一次击中的物体不为空,触发离开事件
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()
@ -128,7 +165,7 @@ public class Show3DCamera : MonoBehaviour
private void ZoomCamera(float scroll)
{
distance -= scroll * 5f; // 调整缩放速度
distance = Mathf.Clamp(distance, 0.2f, 20f); // 限制距离范围
distance = Mathf.Clamp(distance, distanceMin, distanceMax); // 限制距离范围
offset = new Vector3(0, 0, -distance);
UpdateCameraPosition();
}
@ -157,10 +194,10 @@ public class Show3DCamera : MonoBehaviour
Vector3 rotatedOffset = rotation * offset;
// 更新相机位置
transform.position = target.position + rotatedOffset;
transform.position = targetPos + rotatedOffset;
// 相机始终朝向目标点
transform.LookAt(target);
transform.LookAt(targetPos);
}
}

View File

@ -16,6 +16,11 @@ public class TipItem : MonoBehaviour
}
private void OnMouseEnter()
{
OnEnter();
}
public void OnEnter()
{
tip = UIKit.GetPanel<UIDeviceTip>();
if (tip == null)
@ -33,8 +38,7 @@ public class TipItem : MonoBehaviour
tip.Active(true);
}
}
private void OnMouseExit()
public void OnExit()
{
if (tip != null)
{
@ -42,6 +46,11 @@ public class TipItem : MonoBehaviour
}
}
private void OnMouseExit()
{
OnExit();
}
private void OnMouseUpAsButton()
{
if (tip != null)

View File

@ -3,8 +3,9 @@ using UnityEngine.UI;
using QFramework;
using XMLTool;
using System.Collections.Generic;
using static UnityEditor.Progress;
using TMPro;
using GCSeries.Core;
using UnityEngine.EventSystems;
namespace QFramework.Example
{
@ -18,6 +19,8 @@ namespace QFramework.Example
public float rotateSpeed = 10;
public float moveSpeed = 0.1f;
public float distance = 0.2f;
public float distanceMin = 0.2f;
public float distanceMax = 20f;
public float pitchMin = -30f;
public float pitchMax = 80;
public string deviceName;
@ -28,15 +31,18 @@ namespace QFramework.Example
{
ResLoader loader;
GameObject curObj;
RectTransform rawImg;
protected override void OnInit(IUIData uiData = null)
{
loader = ResLoader.Allocate();
rawImg = DeviceRawImage.GetComponent<RectTransform>();
}
protected override void OnOpen(IUIData uiData = null)
{
mData = uiData as UI3DObjShowData ?? new UI3DObjShowData();
FreeCameraController.instance.SetLock(false, false);
Show3DCamera.instance.gameObject.SetActive(true);
Content.RemoveAllChildren();
foreach (var data in mData.datas)
{
@ -63,13 +69,12 @@ namespace QFramework.Example
curObj.transform.localScale = data.scale;
curObj.transform.eulerAngles = data.rotate;
curObj.gameObject.SetActive(true);
Show3DCamera.instance.Set(DeviceRawImage.texture.width, DeviceRawImage.texture.height, curObj.transform, data.rotateSpeed, data.moveSpeed, data.distance, data.pitchMin, data.pitchMax);
Show3DCamera.instance.Set(curObj.transform, data.rotateSpeed, data.moveSpeed, data.distance, data.pitchMin, data.pitchMax, distanceMin: data.distanceMin, distanceMax: data.distanceMax, inputRect: rawImg);
}
else
{
if (curObj)
{
Show3DCamera.instance.Clear();
GameObject.Destroy(curObj);
curObj = null;
}
@ -79,7 +84,6 @@ namespace QFramework.Example
}
loader.LoadAsync();
}
protected override void OnShow()
{
}
@ -87,11 +91,13 @@ namespace QFramework.Example
protected override void OnHide()
{
FreeCameraController.instance.SetLock(true, true);
Show3DCamera.instance.gameObject.SetActive(false);
loader.Recycle2Cache();
}
protected override void OnClose()
{
}
}
}

View File

@ -1325,6 +1325,16 @@ namespace XMLTool
{
float.TryParse(distance.Value, out objData.distance);
}
XAttribute distanceMin = item.Attribute("distanceMin");
if (distanceMin != null)
{
float.TryParse(distanceMin.Value, out objData.distanceMin);
}
XAttribute distanceMax = item.Attribute("distanceMax");
if (distanceMax != null)
{
float.TryParse(distanceMax.Value, out objData.distanceMax);
}
XAttribute pitchMin = item.Attribute("pitchMin");
if (pitchMin != null)
{

View File

@ -208,6 +208,23 @@
<Action type="Mat" value="Models/zhudao/nan_shoushufu.012" matName="yiyongshoutao_yellow1" index="1" mainTexture="贴图名字"></Action>
<!--3D展示
3D展示的UI界面 是自动启动 但需要使用UIShow手动关闭
关闭的监听可以使用Btns与UIClick配合
属性解释:
Object 是要展示的物体 与 Device配合使用
postion rotate scale是物体初始位置和旋转
rotateSpeed 按住鼠标左键的旋转速度
moveSpeed 按住鼠标右键的移动速度
distance 是相机默认距离物体的距离
distanceMin 和 distanceMax 是相机远近的最小和最大值
pitchMin和pitchMax 是相机俯仰角范围
-->
<Action type="3DObjShow">
<Object deviceName="器械盒" position="10000,10000,10000" rotate="0,90,0" rotateSpeed="11" moveSpeed="0.12" distance="0.25" pitchMin="-31" pitchMax="81" distanceMin="0.3" distanceMax="10"></Object>
<Object deviceName="创巾钳"></Object>
</Action>
<!--预加载模块 要在app.xml的Data标签内-->
<PreLoad>
<Action type="Parallel">