using Fusion; using UnityEngine; using System.Collections; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; using UnityEngine.XR; using BNG; public class MarkerNetwork : NetworkBehaviour { public NetworkObject box; private Color GetJoystickColor(float x, float y) { // ترکیب رنگ‌ها بر اساس حرکت جوی‌استیک float red = Mathf.Abs(y); // جهت بالا و پایین باعث تغییر رنگ قرمز float blue = Mathf.Abs(x); // جهت چپ و راست باعث تغییر رنگ آبی float green = Mathf.Abs(x * y); // جهت مورب (چپ و بالا / راست و پایین) باعث تغییر رنگ سبز // به‌روزرسانی رنگ بر اساس مقادیر ورودی return new Color(red, green, blue); // استفاده از مقادیر قرمز، سبز و آبی برای ساخت رنگ } [Range(-1f, 1f)] // محدود کردن مقدار بین -1 تا 1 public float joystickX = 0f; [Range(-1f, 1f)] public float joystickY = 0f; private Vector2 lastValidJoystickInput = Vector2.zero; Vector2 joystickInputValue; bool isTouching = false; private void Update() { Vector2 joystickInputValue = Vector2.zero; // particle.SetActive((Physics.Raycast(RaycastStart.position, RaycastStart.up, out RaycastHit hit, RaycastLength, DrawingLayers) || (rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.trigger, out float isPressed) && isPressed > 0.5f) || Input.GetKey(KeyCode.Z)) && HasStateAuthority); bool isActive = ( Physics.Raycast(RaycastStart.position, RaycastStart.up, out RaycastHit hit, RaycastLength, DrawingLayers) || (rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.trigger, out float isPressed) && isPressed > 0.5f) || Input.GetKey(KeyCode.Z)) && GetComponent().BeingHeld&&HasStateAuthority; particle.SetActive(isActive); // اگر فعال شد، ویبره بده if (isActive) { rightController.SendHapticImpulse(0, 0.1f, 0.1f); // (کانال, شدت, مدت‌زمان) } if (rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.primary2DAxisTouch, out isTouching)) { if (isTouching && rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.primary2DAxis, out joystickInputValue)) { joystickX = joystickInputValue.x; joystickY = joystickInputValue.y; if (Mathf.Abs(joystickX) > 0.05f || Mathf.Abs(joystickY) > 0.05f) // یه آستانه بذار که نویز صفرهای ریز رد شه { DrawColor = GetJoystickColor(joystickX, joystickY); lastValidJoystickInput = joystickInputValue; } } else { // درحال لمس هست ولی مقدار معنادار نیست یا مرکزیه // کاری نکن } } else { // لمس نکرده، پس مقدار قبلی رو نگه دار joystickInputValue = lastValidJoystickInput; } // if (rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.primary2DAxis, out joystickInputValue)) //{ // joystickX = joystickInputValue.x; // محور x (چپ و راست) // joystickY = joystickInputValue.y; // محور y (بالا و پایین) // if(Mathf.Abs(joystickX) ==1&& Mathf.Abs(joystickY) == 1) // DrawColor = GetJoystickColor(joystickX, joystickY); // } // else{ // // joystickX+=Input.GetKey(KeyCode.K)?.1f:-.1f; //} if (rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.trigger, out float triggerValue)) { if (previousTriggerValue > 0.5f && triggerValue <= 0.5f) // اگر تریگر از فشرده بودن به رها شدن تغییر کرد { CreateBoxForLine(); // ایجاد باکس و قرار دادن خط داخل آن } previousTriggerValue = triggerValue; // ذخیره مقدار فعلی برای بررسی فریم بعدی }else if (Input.GetKeyUp(KeyCode.Z)) { CreateBoxForLine(); // ایجاد باکس و قرار دادن خط داخل آن } // تغییر رنگ بر اساس ورودی جوی‌استیک transform.Find("GFX").GetChild(1).GetComponent().material.color = DrawColor; transform.Find("GFX").GetChild(3).GetComponent().material.color = DrawColor; } private float previousTriggerValue = 0f; // ذخیره مقدار قبلی تریگر public Vector3[] localOffsets; private Vector3 GetLineCenterPoint(LineRenderer line) { Vector3 sum = Vector3.zero; int count = line.positionCount; if (count == 0) return lastDrawPoint; for (int i = 0; i < count; i++) { sum += line.GetPosition(i); } return sum / count; } private void CreateBoxForLine() { if (currentLineRenderer == null || !Object.HasInputAuthority) return; // اطمینان از وجود خط و مجوز کنترل // ایجاد باکس در آخرین نقطه ترسیم‌شده // NetworkObject newBox = Runner.Spawn(box, lastDrawPoint, Quaternion.identity, Runner.LocalPlayer); Vector3 centerPoint = GetLineCenterPoint(currentLineRenderer); NetworkObject newBox = Runner.Spawn(box, centerPoint, Quaternion.identity, Runner.LocalPlayer); // تنظیم خط به عنوان زیرمجموعه‌ی باکس // ارسال درخواست به همه‌ی کلاینت‌ها برای افزودن اسکریپت Draws RPC_SetLineParent(newBox); } // این متد را به عنوان یک RPC تعریف کنید تا در کل شبکه اجرا شود [Rpc(RpcSources.InputAuthority, RpcTargets.All)] private void RPC_SetLineParent(NetworkObject newBox) { if (currentLineRenderer == null) return; Draws drawComponent = currentLineRenderer.gameObject.GetComponent(); if (drawComponent == null) { drawComponent = currentLineRenderer.gameObject.AddComponent(); } drawComponent.parent = newBox.transform; } public Material DrawMaterial; public Color DrawColor = Color.red; public float LineWidth = 0.015f; public void Start(){ rightController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand ); } private UnityEngine.XR.InputDevice rightController; public Transform RaycastStart; public LayerMask DrawingLayers; public float RaycastLength = 0.01f; public float MinDrawDistance = 0.002f; private Vector3 lastDrawPoint; private LineRenderer currentLineRenderer; private bool isDrawing = false; private bool wasDrawingLastFrame = false; // برای تشخیص قطع و وصل اتصال public void StartDrawing() { isDrawing = true; StartCoroutine(DrawRoutine()); } public void StopDrawing() { isDrawing = false; } public Transform tip; public GameObject particle; IEnumerator DrawRoutine() { while (isDrawing) { bool isCurrentlyDrawing = false; if (Physics.Raycast(RaycastStart.position, RaycastStart.up, out RaycastHit hit, RaycastLength, DrawingLayers)|| ( rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.trigger, out float isPressed) && isPressed>0.5f)||Input.GetKey(KeyCode.Z)) // if ( ( rightController.TryGetFeatureValue(UnityEngine.XR.CommonUsages.trigger, out float isPressed) && isPressed>0.5f)||Input.GetKey(KeyCode.Z)) { isCurrentlyDrawing = true; Vector3 drawPosition =tip.position; Quaternion drawRotation =tip.rotation; if(!hit.transform){ }else{ drawPosition = hit.point + (-RaycastStart.up * 0.0005f); drawRotation = Quaternion.FromToRotation(Vector3.back, hit.normal); } float lineWidth = LineWidth; // اگر قبلاً رسم نمی‌کردیم اما الان اتصال برقرار شده، خط جدید ایجاد کن و برای همه بفرست if (!wasDrawingLastFrame) { RPC_CreateNewLineRenderer(DrawColor); } if (Vector3.Distance(lastDrawPoint, drawPosition) > MinDrawDistance) { lastDrawPoint = drawPosition; RPC_DrawPoint(drawPosition, DrawColor); } } // به‌روزرسانی وضعیت اتصال برای فریم بعدی wasDrawingLastFrame = isCurrentlyDrawing; yield return null; } } [Rpc(RpcSources.All, RpcTargets.All)] private void RPC_DrawPoint(Vector3 position, Color lineColor) { if (currentLineRenderer == null) { CreateNewLineRenderer(lineColor); } DrawColor = lineColor; currentLineRenderer.positionCount += 1; currentLineRenderer.SetPosition(currentLineRenderer.positionCount - 1, position); } [Rpc(RpcSources.StateAuthority, RpcTargets.All)] private void RPC_CreateNewLineRenderer(Color draw) { DrawColor = draw; CreateNewLineRenderer(DrawColor); } private void CreateNewLineRenderer(Color drawColor) { GameObject drawObj = new GameObject("DrawLine"); currentLineRenderer = drawObj.AddComponent(); currentLineRenderer.tag = "draw"; currentLineRenderer.material = DrawMaterial; currentLineRenderer.startColor = drawColor; currentLineRenderer.endColor = drawColor; currentLineRenderer.startWidth = LineWidth; currentLineRenderer.endWidth = LineWidth; currentLineRenderer.useWorldSpace = true; currentLineRenderer.positionCount = 0; // drawObj.gameObject.layer = LayerMask.NameToLayer("draw"); // MarkerEraser.instance.allLines.Add(currentLineRenderer); // NetworkMarkerEraser.instance.allLines.Add(currentLineRenderer); } }