QuickMove!

Signed-off-by: TRAfoer <lhf190@outlook.com>
This commit is contained in:
2025-08-10 16:00:46 +08:00
parent 7b152a2ecd
commit 19ff2f4862
55 changed files with 343288 additions and 364537 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bd71e53392300e547bd7aae27850df3a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,191 @@
using System.Collections;
using UnityEngine;
using Ichni.RhythmGame;
using UnityEngine.InputSystem;
using DG.Tweening;
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));
}
void Update()
{
if (isMoving) return;
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;
Vector3 newPositionFormatted = new Vector3(
Mathf.Round(newPosition.x * 100f) / 100f,
Mathf.Round(newPosition.y * 100f) / 100f,
Mathf.Round(newPosition.z * 100f) / 100f
);
targetGameElement.transform.position = newPositionFormatted;
transform.position = newPositionFormatted;
}
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cde63278924ce8944b8accfbf000a7e5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -232,7 +232,7 @@ public class SampleWindow : MovableWindow//该window高度为300横的要XWid
far += 1f / Xdevide;
}
far -= 1f / Xdevide;
float time = far * timePerBeat;
float time = Mathf.Round(far * timePerBeat * 1000f) / 1000f;
switch (NoteCode)