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

View File

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

View File

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

View File

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

View File

@ -1325,6 +1325,16 @@ namespace XMLTool
{ {
float.TryParse(distance.Value, out objData.distance); 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"); XAttribute pitchMin = item.Attribute("pitchMin");
if (pitchMin != null) 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> <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标签内--> <!--预加载模块 要在app.xml的Data标签内-->
<PreLoad> <PreLoad>
<Action type="Parallel"> <Action type="Parallel">