111111111111

Signed-off-by: TRAfoer <lhf190@outlook.com>
This commit is contained in:
2026-01-18 13:11:38 +08:00
parent a31269c632
commit de4e399d78
76 changed files with 3199823 additions and 10619 deletions

View File

@@ -12,6 +12,10 @@ using Ichni.Editor;
using Ichni.RhythmGame;
using Ichni.RhythmGame.Beatmap;
using TMPro;
using UniRx;
using Unity.VisualScripting;
@@ -74,7 +78,6 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
line.startColor = line.endColor = color;
}
// 工具方法:刷新两个线条之间的 MeshCollider
private void RefreshMeshCollider(LineRenderer lineA, LineRenderer lineB)
{
MeshCollider col = lineA.GetComponent<MeshCollider>();
@@ -150,7 +153,7 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
GameObject obj = Instantiate(EditorManager.instance.basePrefabs.emptyObject, this.transform);
LineRenderer lr = obj.AddComponent<LineRenderer>();
Color color = (b % 1f <= 0.01f) ? Color.green : Color.cyan;
Color color = (Mathf.Abs(b - Mathf.Round(b)) <= 0.01f) ? Color.green : Color.cyan;
SetupLineRenderer(lr, p0, p1, color);
float bi = (trackPercent >= 1f) ? EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackEndTime) : b;
@@ -201,54 +204,29 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
BeatLines.Add(lr);
}
Color color = (b % 1f <= 0.01f) ? Color.green : Color.cyan;
Color color = (Mathf.Abs(b - Mathf.Round(b)) <= 0.01f) ? Color.green : Color.cyan;
SetupLineRenderer(lr, p0, p1, color, false);
// 同步 Beats 数组,这对 AddNote 很重要
float bi = (trackPercent >= 1f) ? EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackEndTime) : b;
Beats.Add(bi < 0 ? 0f : bi);
index++;
}
// 隐藏多余
for (int i = index; i < BeatLines.Count; i++) BeatLines[i].gameObject.SetActive(false);
// 刷新 Collider
for (int i = 0; i < index - 1; i++) RefreshMeshCollider(BeatLines[i], BeatLines[i + 1]);
}
// void OnDrawGizmos()
// {
// // 调试用,保持原样
// if (BeatLines.Count > 0)
// {
// foreach (var line in BeatLines)
// {
// if (line != null)
// {
// MeshCollider collider = line.GetComponent<MeshCollider>();
// if (collider != null && collider.sharedMesh != null)
// {
// Gizmos.color = new Color(0, 1, 0, 0.3f);
// // DrawMesh 需要传入位置和旋转,因为 Mesh 数据是局部的
// Gizmos.DrawWireMesh(collider.sharedMesh, line.transform.position, line.transform.rotation);
// }
// }
// }
// }
// }
public bool ForceRefresh = false;
void Update()
{
if (ForceRefresh)
{
AdjustBeatLine();
}
if (InputListener.instance.isPointerOverUI) return;
CastRay();
if (IsEnabled && selectedLine != null)
{
DetectNote();
}
if (ForceRefresh)
{
AdjustBeatLine();
}
}
public void CastRay()
@@ -262,44 +240,30 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
if (Physics.RaycastAll(ray).FirstOrDefault(h => h.collider.CompareTag("LineRenderer")).collider != null)
{
hit = Physics.RaycastAll(ray).First(h => h.collider.CompareTag("LineRenderer"));
if (hit.collider.CompareTag("LineRenderer"))
LineRenderer hoveredLine = hit.collider.GetComponent<LineRenderer>();
if (BeatLines.Contains(hoveredLine))
{
LineRenderer hoveredLine = hit.collider.GetComponent<LineRenderer>();
// [修复] DOTween 逻辑
if (BeatLines.Contains(hoveredLine))
if (Mouse.current.leftButton.wasPressedThisFrame)
{
if (Mouse.current.leftButton.wasPressedThisFrame)
Debug.Log($"Clicked on line area: {hoveredLine.gameObject.name} at {hit.point}");
}
if (selectedLine != hoveredLine)
{
if (selectedLine != null)
{
Debug.Log($"Clicked on line area: {hoveredLine.gameObject.name} at {hit.point}");
}
// 如果悬停到了新的线
if (selectedLine != hoveredLine)
{
// 1. 还原上一条选中的线
if (selectedLine != null)
{
// 杀掉旧的动画
selectedLine.startWidth = 0.05f;
selectedLine.endWidth = 0.05f;
}
// 2. 更新当前选中的线
selectedLine = hoveredLine;
// 3. 对新线开启宽度的 PingPong 动画
selectedLine.startWidth = 0.15f;
selectedLine.endWidth = 0.15f;
selectedLine.startWidth = 0.05f;
selectedLine.endWidth = 0.05f;
}
selectedLine = hoveredLine;
selectedLine.startWidth = 0.15f;
selectedLine.endWidth = 0.15f;
}
}
}
else
{
// [优化] 如果鼠标移到了空白处,应该停止所有高亮
if (selectedLine != null)
{
selectedLine.startWidth = 0.05f;
@@ -335,53 +299,86 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
float time = EditorManager.instance.songInformation.beatManager.GetTimeFromBeat(
Beats[BeatLines.IndexOf(selectedLine)]
);
Vector3 pos = new Vector3();
NoteBase a = null;
switch (NoteCode)
{
case 0:
Tap a = Tap.GenerateElement("New Tap", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time);
//a.noteVisual.transformSubmodule.originalPosition = new Vector3(isExpand ? (localMousePosition.x / XWidth) : 0f, 0f, 0f);
case 0:
a = Tap.GenerateElement("New Tap", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time);
a.noteVisual.transformSubmodule.Refresh();
pos = a.noteVisual.transform.position;
break;
case 3:
Hold b = Hold.GenerateElement("New Hold", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time, time + 0.5f);
a = Hold.GenerateElement("New Hold", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time, time + 0.5f);
a.noteVisual.transformSubmodule.Refresh();
Observable.NextFrame().Subscribe(_ =>
{
StartCoroutine(DraggingHold((Hold)a));
});
//b.noteVisual.transformSubmodule.originalPosition = new Vector3(isExpand ? (localMousePosition.x / XWidth) : 0f, 0f, 0f);
b.noteVisual.transformSubmodule.Refresh();
pos = b.noteVisual.transform.position;
break;
case 1:
Stay c = Stay.GenerateElement("New Stay", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time);
//c.noteVisual.transformSubmodule.originalPosition = new Vector3(isExpand ? (localMousePosition.x / XWidth) : 0f, 0f, 0f);
c.noteVisual.transformSubmodule.Refresh();
pos = c.noteVisual.transform.position;
a = Stay.GenerateElement("New Stay", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time);
a.noteVisual.transformSubmodule.Refresh();
break;
case 2:
Flick d = Flick.GenerateElement("New Flick", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time, new List<Vector2>());
//d.noteVisual.transformSubmodule.originalPosition = new Vector3(isExpand ? (localMousePosition.x / XWidth) : 0f, 0f, 0f);
d.noteVisual.transformSubmodule.Refresh();
pos = d.noteVisual.transform.position;
a = Flick.GenerateElement("New Flick", Guid.NewGuid(), new List<string>(), true, TrackedTrack, time, new List<Vector2>());
a.noteVisual.transformSubmodule.Refresh();
break;
default:
break;
}
CreateTextHint(pos, $"A Note Added");
Observable.NextFrame().Subscribe(_ =>
{
CreateTextHint(a);
});
}
private void CreateTextHint(Vector3 worldPos, string content)
private IEnumerator DraggingHold(Hold hold)
{
GameObject obj = Instantiate(EditorManager.instance.basePrefabs.emptyObject, this.transform);
LineRenderer lr = obj.AddComponent<LineRenderer>();
lr.startWidth = lr.endWidth = 0.05f;
lr.positionCount = 2;
lr.material = EditorManager.instance.basePrefabs.defaultTrailMaterial;
lr.startColor = lr.endColor = Color.yellow;
lr.SetPosition(0, hold.noteVisual.transform.position);
lr.SetPosition(1, hold.noteVisual.transform.position);
while (Keyboard.current.digit4Key.isPressed && selectedLine != null)
{
yield return null;
try
{
float time = EditorManager.instance.songInformation.beatManager.GetTimeFromBeat(
Beats[BeatLines.IndexOf(selectedLine)]
);
hold.holdEndTime = time < hold.exactJudgeTime ? hold.exactJudgeTime + 0.1f : time;
hold.noteVisual.transformSubmodule.Refresh();
lr.SetPosition(1, (selectedLine.GetPosition(0) + selectedLine.GetPosition(1)) / 2);
}
catch (Exception e)
{
Debug.LogWarning(e);
break;
}
}
yield return null;
Destroy(lr.gameObject);
CreateTextHint(hold);
}
private void CreateTextHint(NoteBase noteBase)
{
// 1. 创建一个新的 GameObject
string content = noteBase.elementName;
Vector3 worldPos = noteBase.noteVisual.transform.position;
GameObject hintObj = new GameObject("NoteHint_" + content);
hintObj.transform.position = worldPos;
// 2. 添加 TextMeshPro 组件 (注意是 TextMeshPro不是 TextMeshProUGUI)
// 因为我们在 3D 空间生成,所以使用非 UI 版本
TextMeshPro text = hintObj.AddComponent<TextMeshPro>();
// 3. 配置文字属性
text.text = content;
text.fontSize = 6; // 根据你的缩放调整大小
@@ -393,6 +390,7 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
// 5. 动画效果:向上移动 1 个单位,并同时淡出
// 1 秒后执行
hintObj.transform.DOScale(Vector3.one * 1.2f, 1f).SetEase(Ease.OutBack).From(Vector3.zero);
hintObj.transform.DOMoveY(worldPos.y + 1f, 1f);
text.DOFade(0, 1f).OnComplete(() => Destroy(hintObj));
// 7. 让文字始终面向相机 (Billboard 效果)