Files
ichni_Creator_Studio/Assets/Scripts/Graphical Tools/QuickMover/QuickMover.cs
TRAfoer 66ec7fb4a9 改了点材质
Signed-off-by: TRAfoer <lhf190@outlook.com>
2025-08-15 14:29:58 +08:00

201 lines
7.6 KiB
C#

using System.Collections;
using UnityEngine;
using Ichni.RhythmGame;
using UnityEngine.InputSystem;
using DG.Tweening;
using UniRx;
using UniRx.Triggers;
namespace Ichni.Editor
{
public class QuickMover : MonoBehaviour
{
public static QuickMover instance;
[Header("Settings")]
public float moveSensitivity = 0.5f; // 移动灵敏度
[Header("References")]
public GameObject prefab;
public BoxCollider colliderX;
public BoxCollider colliderY;
public BoxCollider colliderZ;
// 运行时状态
private IHaveTransformSubmodule targetElement;
private Camera editorCamera => EditorManager.instance.cameraManager.currentCamera;
private bool isMoving;
private int activeMoveCode = -1;
private Vector3 initialTargetPosition;
private Vector3 initialMouseScreenPos;
public GameElement targetGameElement =>
targetElement?.transformSubmodule?.attachedGameElement;
public void Initialize(IHaveTransformSubmodule targetElement)
{
this.targetElement = targetElement;
if (instance != null)
{
Destroy(instance.gameObject);
}
instance = this;
if (targetGameElement != null)
transform.position = targetGameElement.transform.position;
transform.localScale = Vector3.zero;
StartCoroutine(WindowAnim.ShowPanelOnScale(gameObject));
targetGameElement.OnDestroyAsObservable()
.Subscribe(_ =>
{
if (gameObject != null) Destroy(gameObject);
instance = null;
}).AddTo(this);
}
void Update()
{
if (isMoving) return;
transform.eulerAngles = targetGameElement.parentElement?.transform.eulerAngles ?? Vector3.zero;
transform.position = targetGameElement.transform.position;
if (Mouse.current.leftButton.wasPressedThisFrame)
{
Vector2 mousePosition = Mouse.current.position.ReadValue();
Ray ray = editorCamera.ScreenPointToRay(mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, LayerMask.GetMask("Default")))
{
if (hit.collider == colliderX)
{
colliderX.gameObject.transform.DOScale(colliderX.gameObject.transform.localScale * 1.2f, 0.2f);
StartMovement(0);
}
else if (hit.collider == colliderY)
{
colliderY.gameObject.transform.DOScale(colliderY.gameObject.transform.localScale * 1.2f, 0.2f);
StartMovement(1);
}
else if (hit.collider == colliderZ)
{
colliderZ.gameObject.transform.DOScale(colliderZ.gameObject.transform.localScale * 1.2f, 0.2f);
StartMovement(2);
}
}
}
}
private Vector3 objPosOffset;
private void StartMovement(int moveCode)
{
Debug.Log($"StartMovement: {moveCode}");
if (targetGameElement == null) return;
activeMoveCode = moveCode;
initialTargetPosition = targetGameElement.transform.position;
initialMouseScreenPos = Mouse.current.position.ReadValue();
objPosOffset = targetElement.transformSubmodule.currentPosition - targetElement.transformSubmodule.originalPosition;
StartCoroutine(MovementRoutine());
}
private IEnumerator MovementRoutine()
{
isMoving = true;
while (Mouse.current.leftButton.isPressed)
{
UpdateTargetPosition();
targetElement.transformSubmodule.originalPosition = targetElement.transformSubmodule.currentPosition - objPosOffset;
yield return null;
}
// 当鼠标释放时,结束移动
EndMovement();
isMoving = false;
activeMoveCode = -1;
}
private void EndMovement()
{
targetGameElement.transform.position = transform.position;
targetElement.transformSubmodule.currentPosition = targetGameElement.transform.localPosition;
targetElement.transformSubmodule.originalPosition = targetElement.transformSubmodule.currentPosition - objPosOffset;
targetGameElement.Refresh();
if (activeMoveCode == 0)
{
colliderX.gameObject.transform.DOScale(colliderX.gameObject.transform.localScale / 1.2f, 0.2f);
// Do something specific for X axis
}
else if (activeMoveCode == 1)
{
colliderY.gameObject.transform.DOScale(colliderY.gameObject.transform.localScale / 1.2f, 0.2f);
// Do something specific for Y axis
}
else if (activeMoveCode == 2)
{
colliderZ.gameObject.transform.DOScale(colliderZ.gameObject.transform.localScale / 1.2f, 0.2f);
// Do something specific for Z axis
}
}
private void UpdateTargetPosition()
{
if (targetGameElement == null) return;
// 获取当前鼠标位置
Vector3 currentMousePos = Mouse.current.position.ReadValue();
Vector3 mouseDelta = currentMousePos - initialMouseScreenPos;
// 计算移动轴的世界方向
Vector3 worldAxis = GetWorldAxis(activeMoveCode);
// 计算屏幕移动向量对应的世界移动量
float worldDelta = CalculateWorldDelta(worldAxis, mouseDelta);
// 应用新位置
Vector3 newPosition = initialTargetPosition + worldAxis * worldDelta;
targetGameElement.transform.position = newPosition;
targetGameElement.transform.localPosition = new Vector3(
Mathf.Round(targetGameElement.transform.localPosition.x * 100f) / 100f,
Mathf.Round(targetGameElement.transform.localPosition.y * 100f) / 100f,
Mathf.Round(targetGameElement.transform.localPosition.z * 100f) / 100f
);
transform.position = newPosition;
}
private Vector3 GetWorldAxis(int moveCode)
{
return moveCode switch
{
0 => transform.right, // X轴
1 => transform.up, // Y轴
2 => transform.forward, // Z轴
_ => Vector3.zero
};
}
private float CalculateWorldDelta(Vector3 worldAxis, Vector3 mouseDelta)
{
// 将世界轴转换为屏幕方向
Vector3 screenRefPoint = editorCamera.WorldToScreenPoint(initialTargetPosition);
Vector3 screenAxisEnd = editorCamera.WorldToScreenPoint(initialTargetPosition + worldAxis);
// 计算屏幕方向向量
Vector3 screenAxis = (screenAxisEnd - screenRefPoint).normalized;
// 防止摄像机与轴平行时出现零向量
if (screenAxis.sqrMagnitude < 0.01f) return 0;
// 计算鼠标移动在轴方向上的投影
Vector2 screenAxis2D = new Vector2(screenAxis.x, screenAxis.y);
Vector2 mouseDelta2D = new Vector2(mouseDelta.x, mouseDelta.y);
float projection = Vector2.Dot(mouseDelta2D, screenAxis2D.normalized);
// 应用灵敏度并返回
return projection * moveSensitivity * 0.01f;
}
}
}