using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class RotatingState : SceneMode { private static Vector3 _initialMousePosition; private EventTrigger eventTrigger; Vector3 _initialRotation; Vector3 _finalRotation; Vector3 _initialPosition; Quaternion _intendedRotation; GameObject _objectToRotate; GameObject _lastClicked; public RotatingState(SceneModeManager stateManager) : base(stateManager) { if (MoveHandles.Instance.RotationHandle == null) return; } public override void OnStateEnter() { _G.LockInState = true; MoveHandles.Instance.OnRotationEnter(); Mesure.OnUpdate(); GameObject obj = SceneModeManager.Selected; if(obj == null) { return; } MoveHandles.Instance.ActivateTorus(true, obj.transform); _objectToRotate = obj; // Create an EventTrigger component and add it to the GameObject eventTrigger = _objectToRotate.AddComponent(); _intendedRotation = _objectToRotate.transform.rotation; _initialPosition = _objectToRotate.transform.position; _initialRotation = _objectToRotate.transform.eulerAngles; _initialMousePosition = Input.mousePosition; _lastClicked = MoveHandles.Instance._lastClicked; } public override void OnStateExit() { //MoveHandles.Instance._lastClicked = null; _lastClicked = null; _objectToRotate.GetComponent()?.RepositionIntoRoom(); _finalRotation = _objectToRotate.transform.eulerAngles; MoveHandles.Instance.ActivateTorus(false, null); if (_initialRotation != _finalRotation) { RotationCommand command = new RotationCommand(_objectToRotate, _initialRotation, _initialPosition, _finalRotation, _objectToRotate.transform.position); CommandHandler.Instance.AddToHistory(command); } _G.LockInState = false; Mesure.Hide(); } public override void OnStateUpdate() { if (Input.GetMouseButton(0) || Input.touches.Length > 0) { Vector3 currentMousePosition = Input.mousePosition; float deltaAngle = CalculateDeltaAngle(_initialMousePosition, currentMousePosition); ApplyDeltaRotation(deltaAngle); UpdateFakeHandlePosition(); _initialMousePosition = currentMousePosition; Mesure.OnUpdate(); } else { _manager.SetSceneMode(SceneModes.ReadyMove); } } private void UpdateFakeHandlePosition() { // Assuming _handleGroup is the center of the circle Vector3 position = _objectToRotate.transform.position; int nO = Get.GetObjectIndex(_objectToRotate.name); float height = DOIT.ConvertStringToNumber(_G.OBJs[nO][7]) * 0.5f; position.y -= height; // Get the current mouse position Vector3 currentMousePosition = Input.mousePosition; Plane plane = new Plane(_objectToRotate.transform.up, position); Ray ray = Camera.main.ScreenPointToRay(currentMousePosition); if (plane.Raycast(ray, out float enter)) { Vector3 p = ray.GetPoint(enter); // Calculate the direction from the center to the mouse position, ignoring the z-axis Vector3 direction = position - p; // Normalize the direction vector direction.Normalize(); Vector3 fakeHandlePosition = position - direction * MoveHandles.Instance.Radius; Image image = _lastClicked.GetComponentInChildren(); Vector3 yOffset = MoveHandles.Instance.Torus.transform.up * (image.rectTransform.rect.height * SceneModeManager.Instance.YOffset); fakeHandlePosition += yOffset; Vector3 finalCalculatedPosition = Camera.main.WorldToScreenPoint(fakeHandlePosition); Vector3 offset = MoveHandles.Instance.HandleGroup.transform.position - _lastClicked.transform.position; finalCalculatedPosition += offset; // Assuming _rotationHandleFake is the GameObject you want to move MoveHandles.Instance.HandleGroup.transform.position = finalCalculatedPosition; } } private void ApplyDeltaRotation(float deltaAngle) { // Apply the delta rotation to the GameObject's rotation Quaternion deltaRotation = Quaternion.Euler(0f, deltaAngle, 0f); _intendedRotation = _intendedRotation * deltaRotation; SetRotationWithClamp(_intendedRotation); } void SetRotationWithClamp(Quaternion intendedRotation) { float angleInterval = _G.AngleStep; float angleTolerance = angleInterval * 0.5f; Quaternion clampedRotation = ClampRotation(intendedRotation, angleInterval, angleTolerance); _objectToRotate.transform.rotation = clampedRotation; } Quaternion ClampRotation(Quaternion rotation, float interval, float tolerance) { // Convert the rotation to euler angles for easier manipulation. Vector3 euler = rotation.eulerAngles; // Calculate the closest 90-degree interval. float closestInterval = Mathf.Round(euler.y / interval) * interval; // Check if the current 'y' value is within the tolerance of the closest interval. if (Mathf.Abs(euler.y - closestInterval) <= tolerance) { // If within tolerance, clamp to the closest interval. euler.y = closestInterval; } // Convert back to quaternion. Quaternion clampedRotation = Quaternion.Euler(euler); return clampedRotation; } private float CalculateDeltaAngle(Vector3 previousMousePosition, Vector3 currentMousePosition) { float height = DOIT.ConvertStringToNumber(_G.OBJs[Get.GetObjectIndex(_objectToRotate.name)][7]) * 0.5f; Vector3 origin = _objectToRotate.transform.position; origin.y -= height; Vector3 direction = _objectToRotate.transform.up; Plane plane = new Plane(direction,origin); Ray previousMouseRay = Camera.main.ScreenPointToRay(previousMousePosition); Ray currentMouseRay = Camera.main.ScreenPointToRay(currentMousePosition); plane.Raycast(previousMouseRay, out float previousDistance); plane.Raycast(currentMouseRay, out float currentDistance); // Explicitly convert the Vector3 positions to Vector2 Vector3 previousDir = previousMouseRay.GetPoint(previousDistance) - origin; previousDir.Normalize(); Vector3 currentDir = currentMouseRay.GetPoint(currentDistance) - origin; currentDir.Normalize(); float angle = Vector3.SignedAngle(previousDir, currentDir, direction); return angle; } }