using SC.XR.Unity.Module_InputSystem; using SC.XR.Unity.Module_InputSystem.InputDeviceHand; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; public class SafetyPlaneMono : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler { private bool isFreeze = false; private bool isHover = false; private bool canFill = false; private int lastPaintIndex = -1; private PointerEventData currentPointerEventData; private PointerEventData hoverPointerEventData; private Mesh mesh; private MeshRenderer meshRenderer; //private Mesh hoverMesh; private MeshRenderer hoverMeshRenderer; //private Mesh largerMesh; //private MeshRenderer largerMeshRenderer; private Color[] colors; //private Color[] hoverColors; //private Color[] largerColors; private GroundHeightStep groundHeightStep; private float animationTime; private bool isPlayAnimation = false; private Action OnPointerClickDown { get; set; } private Action OnPointerClickUp { get; set; } private void Awake() { DontDestroyOnLoad(this.gameObject); } public void Init() { if (groundHeightStep == null) { groundHeightStep = SafetyAreaManager.Instance.GetStep(SafetyAreaStepEnum.GroundHeight); } MeshFilter meshFilter = this.gameObject.AddComponent(); meshFilter.mesh = SafetyAreaVertexHelper.GeneratePlaneMesh(); mesh = meshFilter.mesh; meshRenderer = this.gameObject.AddComponent(); meshRenderer.material = Resources.Load("Material/SafetyPlaneMat"); BoxCollider boxCollider = this.gameObject.AddComponent(); //boxCollider.size = new Vector3(); //MeshCollider meshCollider = this.gameObject.AddComponent(); //meshCollider.sharedMesh = mesh; GameObject hoverObject = GameObject.Instantiate(this.gameObject); hoverMeshRenderer = hoverObject.GetComponent(); GameObject.Destroy(hoverObject.GetComponent()); //GameObject.Destroy(hoverObject.GetComponent()); GameObject.Destroy(hoverObject.GetComponent()); //hoverMesh = hoverObject.GetComponent().mesh; hoverObject.transform.SetParent(this.gameObject.transform); ClearAllMeshColor(); } public void DisableRenderer() { meshRenderer.enabled = false; hoverMeshRenderer.enabled = false; } public void EnableRenderer() { meshRenderer.enabled = true; hoverMeshRenderer.enabled = true; } float bias = -6.3f; // Update is called once per frame void Update() { if (!isFreeze) { ContinueSetPlaneHeight(); meshRenderer.sharedMaterial.SetVector("_MainTex_ST", new Vector4(30f, 30f, Camera.main.transform.position.x * PlayAreaConstant.CELL_SIZE * (PlayAreaConstant.GRID_SIZE + bias) / 2f, Camera.main.transform.position.z * PlayAreaConstant.CELL_SIZE * (PlayAreaConstant.GRID_SIZE + bias) / 2f)); } else { if (canFill) { FillNearest(currentPointerEventData); } //ClearHoverMesh(); if (isHover) { FillHoverNearest(hoverPointerEventData); } } if (isPlayAnimation) { animationTime += Time.deltaTime; meshRenderer.sharedMaterial.SetFloat("_Mtime", animationTime / 15f); } } public void FreezePlaneHeight() { Transform headTransform = GetHeadTransform(); this.gameObject.transform.position = new Vector3(headTransform.position.x, 0, headTransform.position.z); isFreeze = true; } public void UnFreezePlaneHeight() { ContinueSetPlaneHeight(); isFreeze = false; } public void ContinueSetPlaneHeight() { GameObject interactiveObject = GetInteractiveGameObject(); if (interactiveObject != null) { groundHeightStep.SetPlaneHeight(interactiveObject.transform.position.y - 0.1f); } Transform headTransform = GetHeadTransform(); groundHeightStep.SetHeadPosition(headTransform.position); this.gameObject.transform.position = new Vector3(headTransform.position.x, groundHeightStep.GetPlaneHeight(), headTransform.position.z); Vector3 localHeadPosition = this.transform.InverseTransformPoint(Camera.main.transform.position); meshRenderer.sharedMaterial.SetVector("headPosition", new Vector4(localHeadPosition.x, localHeadPosition.y, localHeadPosition.z, 1)); } private void EnableFill(PointerEventData eventData) { canFill = true; } private void DisableFill(PointerEventData eventData) { canFill = false; } private GameObject GetInteractiveGameObject() { if (Module_InputSystem.instance == null) return null; if (Module_InputSystem.instance.IsSomeDeviceActiveWithoutHead) { if (Module_InputSystem.instance.GetInputDeviceStatus(InputDeviceType.GGT26Dof)) { InputDeviceBase inputDevice = Module_InputSystem.instance.GetInputDevice(InputDeviceType.GGT26Dof); GameObject handModel = null; foreach (var part in inputDevice.inputDevicePartList) { if (part.inputDataBase.isVaild == true) { GameObject handModlePart = (part as InputDeviceHandPart).inputDeviceHandPartUI.modelHand.ActiveHandModel.GetJointTransform(FINGER.forefinger, JOINT.One).gameObject; if (handModel == null || handModel.transform.position.y > handModlePart.transform.position.y) { handModel = handModlePart; } } } //Debug.Log(handModel.name); return handModel; } else if (Module_InputSystem.instance.GetInputDeviceStatus(InputDeviceType.KS)) { InputDeviceBase inputDevice = Module_InputSystem.instance.GetInputDevice(InputDeviceType.KS); GameObject KSModel = null; foreach (var part in inputDevice.inputDevicePartList) { if (part.inputDataBase.isVaild == true) { GameObject KSPart = part.inputDevicePartUIBase.gameObject; if (KSModel == null || KSModel.transform.position.y > KSPart.transform.position.y) { KSModel = KSPart; } } } return KSModel; } else if (Module_InputSystem.instance.GetInputDeviceStatus(InputDeviceType.BT3Dof)) { InputDeviceBase inputDevice = Module_InputSystem.instance.GetInputDevice(InputDeviceType.BT3Dof); GameObject BT3DofModel = null; foreach (var part in inputDevice.inputDevicePartList) { if (part.inputDataBase.isVaild == true) { GameObject BT3DofPart = part.inputDevicePartUIBase.gameObject; if (BT3DofModel == null || BT3DofModel.transform.position.y > BT3DofPart.transform.position.y) { BT3DofModel = BT3DofPart; } } } return BT3DofModel; } } else { return Camera.main.transform.gameObject; } return null; } private Transform GetHeadTransform() { return Camera.main.transform.transform; } public void OnPointerDown(PointerEventData eventData) { currentPointerEventData = eventData; OnPointerClickDown?.Invoke(eventData); } public void OnPointerUp(PointerEventData eventData) { currentPointerEventData = null; OnPointerClickUp?.Invoke(eventData); } public void OnPointerEnter(PointerEventData eventData) { hoverPointerEventData = eventData; isHover = true; } public void OnPointerExit(PointerEventData eventData) { hoverPointerEventData = null; isHover = false; } public void RegistPointerDownFillEvent() { OnPointerClickDown += EnableFill; } public void UnRegistPointerDownFillEvent() { OnPointerClickDown -= EnableFill; } public void RegistPointerUpFillEvent() { OnPointerClickUp += DisableFill; } public void UnRegistPointerUpFillEvent() { OnPointerClickUp -= DisableFill; } public void RegistPointerUpEvent(Action callback) { OnPointerClickUp += callback; } public void UnRegistPointerUpEvent(Action callback) { OnPointerClickUp -= callback; } public void FillNearest(PointerEventData pointerEventData) { if (pointerEventData == null) { Debug.LogError("currentPointerEventData == null"); return; } Vector3 raycastPosition = pointerEventData.pointerCurrentRaycast.worldPosition; Vector3 pointerLocalPosition = transform.InverseTransformPoint(raycastPosition); List effectIndices = SafetyAreaVertexHelper.CaculateEffectVerticeIndices(pointerLocalPosition, PlayAreaConstant.BRUSH_SIZE); for (int i = 0; i < effectIndices.Count; i++) { int index = effectIndices[i]; colors[index] = Color.white; lastPaintIndex = index; } mesh.colors = colors; } public void FillHoverNearest(PointerEventData pointerEventData) { if (pointerEventData == null) { //Debug.LogError("hoverPointerEventData == null"); return; } Vector3 raycastPosition = pointerEventData.pointerCurrentRaycast.worldPosition; Vector3 pointerLocalPosition = transform.InverseTransformPoint(raycastPosition); hoverMeshRenderer.sharedMaterial.SetFloat("brushSize", PlayAreaConstant.BRUSH_SIZE); hoverMeshRenderer.sharedMaterial.SetVector("pointerLocalPosition", new Vector4(pointerLocalPosition.x, pointerLocalPosition.y, pointerLocalPosition.z, 1.0f)); //List effectHoverIndices = SafetyAreaVertexHelper.CaculateEffectVerticeIndices(pointerLocalPosition, PlayAreaConstant.BRUSH_SIZE); //for (int i = 0; i < effectHoverIndices.Count; i++) //{ // int index = effectHoverIndices[i]; // hoverColors[index] = new Color(1f, 1f, 1f, 1f); // //lastPaintIndex = index; //} //hoverMesh.colors = hoverColors; } public void GenerateEdgeMesh(Action onGenerateMesh) { if (lastPaintIndex == -1) { Debug.LogError("lastPaintIndex == -1"); return; } SafetyAreaEightNeighbourHelper.EightNeighbours(lastPaintIndex, (index) => { return colors[index] == Color.white; }, (edgeIndices) => { float planeHeight = 0f;//groundHeightStep.GetPlaneHeight(); float perimeter = 0f; Mesh edgeMesh = SafetyAreaVertexHelper.GenerateEdgeMesh(mesh, edgeIndices, planeHeight + PlayAreaConstant.SAFETY_AREA_HEIGHT, planeHeight, ref perimeter); onGenerateMesh?.Invoke(edgeMesh, perimeter); }); } //填充中间 public void FillIndices() { if (lastPaintIndex == -1) { Debug.LogError("lastPaintIndex == -1"); return; } SafetyAreaEightNeighbourHelper.EightNeighbours(lastPaintIndex, (index) => { return colors[index] == Color.white; }, (edgeIndices) => { List fillIndices = ScanLineFillHelper.ScaneLine((index) => { return colors[index] == Color.white; }, edgeIndices); for (int i = 0; i < fillIndices.Count; i++) { colors[fillIndices[i]] = Color.white; } mesh.colors = colors; }); } public bool CheckIndicesEnough() { int count = 0; for (int i = 0; i < (PlayAreaConstant.GRID_SIZE + 1); i++) { for (int j = 0; j < (PlayAreaConstant.GRID_SIZE + 1); j++) { int index = i * (PlayAreaConstant.GRID_SIZE + 1) + j; if (colors[index] == Color.white) { count++; } } } Debug.Log("fillCount=" + count); int oneSquareMeterIndexCount = (int)Mathf.Pow(Mathf.CeilToInt(1f / PlayAreaConstant.CELL_SIZE), 2); Debug.Log("oneSquareMeterIndexCount:" + oneSquareMeterIndexCount); return count > oneSquareMeterIndexCount; } public void ClearAllMeshColor() { ClearMeshColor(); //ClearHoverMesh(); } private void ClearMeshColor() { colors = Enumerable.Repeat(Color.clear, mesh.vertexCount).ToArray(); mesh.colors = colors; } //private void ClearHoverMesh() //{ // hoverColors = Enumerable.Repeat(Color.clear, hoverMesh.vertexCount).ToArray(); // hoverMesh.colors = hoverColors; //} public void SetPlaneMat(Material mat) { meshRenderer.sharedMaterial = mat; } public void SetHoverPlaneMat(Material mat) { hoverMeshRenderer.sharedMaterial = mat; } public void StartPlaneAnimation() { animationTime = 0.3f; meshRenderer.sharedMaterial.SetFloat("_AniUVScale", 1f); isPlayAnimation = true; } public void StopPlaneAnimation() { meshRenderer.sharedMaterial.SetFloat("_AniUVScale", 0f); isPlayAnimation = false; } public Color[] GetColorArray() { return colors; } }