Signed-off-by: TRAfoer <lhf190@outlook.com>
This commit is contained in:
2025-09-13 21:33:54 +08:00
parent 27b3cf58d0
commit 305c45655a
16 changed files with 219117 additions and 325430 deletions

View File

@@ -224,7 +224,7 @@ namespace Ichni.Editor
processedArgs.Add(a);
}
// 数字
else if (Regex.IsMatch(a, @"^-?\d+(\.\d+)?$"))
else if (Regex.IsMatch(a, @"^-?\d+(\.\d+)?([eE][+-]?\d+)?$"))
{
processedArgs.Add(a);
}

View File

@@ -593,7 +593,30 @@ namespace Ichni.Editor
GUIUtility.systemCopyBuffer = result;
LogWindow.Log("Colped Done!", Color.green);
}
public static void AdjustPathnodeZ(float OriginZpoint, float scale)
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
{
LogWindow.Log("Please select a Track first!");
return;
}
Track track = (Track)inspector.connectedGameElement;
var pathnodes = track.trackPathSubmodule.pathNodeList;
foreach (var pathnode in pathnodes)
{
if (pathnode.childElementList.OfType<Displacement>().Count() > 0)
{
LogWindow.Log($"PathNode {pathnode.elementName} has Displacement, which may cause issues", Color.yellow);
}
float worldZ = pathnode.transform.position.z;
float deltaZ = worldZ - OriginZpoint;
float newZ = OriginZpoint + deltaZ * scale;
pathnode.transform.position = new Vector3(pathnode.transform.position.x, pathnode.transform.position.y, newZ);
pathnode.transformSubmodule.originalPosition = pathnode.transform.localPosition;
pathnode.transformSubmodule.Refresh();
pathnode.Refresh();
}
}
}
}

View File

@@ -1,7 +1,10 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DG.Tweening;
using Ichni;
using Ichni.RhythmGame;
using TMPro;
using UnityEngine;
@@ -62,51 +65,113 @@ public class EventPoint : MonoBehaviour
UpdateValue();
ReDraw(value);
}
public void ReDraw(float value)
public IEnumerator GenerateTextureCoroutine(int width, int height, float value)
{
Texture2D Texture = new Texture2D((int)CurveCanvas.rectTransform.sizeDelta.x / 5, (int)CurveCanvas.rectTransform.sizeDelta.y / 5);
for (int i = 0; i < Texture.width; i++)
Task<Color[]> task = Task.Run(() => GenerateTextureColors(width, height, value));
while (!task.IsCompleted)
{
for (int j = 0; j < Texture.height; j++)
{
Texture.SetPixel(i, j, new Color(0, 0, 0, 0));
}
}
Texture.Apply();
int LastEventPointY = 0;
for (int i = 0; i < Texture.width; i++)
{
float t = (float)i / Texture.width;
int f = (int)(
(Texture.height / 2) + (animatedFloat.startValue * value + ((animatedFloat.endValue - animatedFloat.startValue)
* AnimationCurveEvaluator.Evaluate(animatedFloat.animationCurveType, t) * value))
);
//不是哥们
for (int j = LastEventPointY; j < f; j++)
{
if (j < Texture.height) Texture.SetPixel(i, j, Color.green);
else Texture.SetPixel(i, j, Color.red);
}
for (int j = LastEventPointY; j > f; j--)
{
if (j > 0) Texture.SetPixel(i, j, Color.green);
else Texture.SetPixel(i, j, Color.red);
}
if (f < Texture.height && f > 0) Texture.SetPixel(i, f, Color.green);//丑陋
else Texture.SetPixel(i, f, Color.red);
LastEventPointY = f;
yield return null; // 等待下一帧
}
Color[] textureColors = task.Result;
Texture2D Texture = new Texture2D(width, height);
Texture.SetPixels(textureColors);
Texture.Apply();
CurveCanvas.texture = Texture;
// CurveCanvas.color = new Color(1, 1, 1, 0);
// CurveCanvas.DOColor(new Color(1, 1, 1, 1), 0.2f).SetEase(Ease.InOutSine);
}
public Color[] GenerateTextureColors(int width, int height, float value)
{
Color[] pixels = new Color[width * height];
// 初始化所有像素为透明
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = new Color(0, 0, 0, 0);
}
int LastEventPointY = 0;
for (int i = 0; i < width; i++)
{
float t = (float)i / width;
int f = (int)(
(height / 2) + (animatedFloat.startValue * value + ((animatedFloat.endValue - animatedFloat.startValue)
* AnimationCurveEvaluator.Evaluate(animatedFloat.animationCurveType, t) * value))
);
// 绘制垂直线段 - 保留超出边界的红色标记
if (LastEventPointY < f)
{
for (int j = LastEventPointY; j < f; j++)
{
// 检查是否超出边界
bool isOutOfBounds = j < 0 || j >= height;
// 计算实际坐标(循环调整)
int actualY = j;
while (actualY < 0) actualY += height;
while (actualY >= height) actualY -= height;
int index = actualY * width + i;
if (index >= 0 && index < pixels.Length)
{
// 根据是否超出边界设置颜色
pixels[index] = isOutOfBounds ? Color.red : Color.green;
}
}
}
else
{
for (int j = LastEventPointY; j > f; j--)
{
// 检查是否超出边界
bool isOutOfBounds = j < 0 || j >= height;
// 计算实际坐标(循环调整)
int actualY = j;
while (actualY < 0) actualY += height;
while (actualY >= height) actualY -= height;
int index = actualY * width + i;
if (index >= 0 && index < pixels.Length)
{
// 根据是否超出边界设置颜色
pixels[index] = isOutOfBounds ? Color.red : Color.green;
}
}
}
// 绘制当前点 - 保留超出边界的红色标记
bool isFOutOfBounds = f < 0 || f >= height;
int actualF = f;
while (actualF < 0) actualF += height;
while (actualF >= height) actualF -= height;
int currentIndex = actualF * width + i;
if (currentIndex >= 0 && currentIndex < pixels.Length)
{
// 根据是否超出边界设置颜色
pixels[currentIndex] = isFOutOfBounds ? Color.red : Color.green;
}
LastEventPointY = f;
}
return pixels;
}
public void ReDraw(float value)
{
int width = (int)CurveCanvas.rectTransform.sizeDelta.x / 5;
int height = (int)CurveCanvas.rectTransform.sizeDelta.y / 5;
// 获取颜色数组(可在多线程环境中调用)
// 在主线程中创建和设置纹理Unity对象操作必须在主线程
StartCoroutine(GenerateTextureCoroutine(width, height, value));
// 其余的非纹理相关代码保持不变
if (NextEventPoint != null)
{
OvDrawimage.transform.localPosition = new Vector3(RightSide.transform.localPosition.x,
@@ -128,8 +193,7 @@ public class EventPoint : MonoBehaviour
}
else
{
OvDrawimage.rectTransform.sizeDelta = new Vector2(0, OvDrawimage.rectTransform.sizeDelta.y
);
OvDrawimage.rectTransform.sizeDelta = new Vector2(0, OvDrawimage.rectTransform.sizeDelta.y);
}
selectButton.transform.localPosition = EvDrawimage.transform.localPosition;
@@ -141,7 +205,6 @@ public class EventPoint : MonoBehaviour
}
public void SelectButtonClick()//unity内当按钮按下时
{
if (Locked) return;

View File

@@ -23,6 +23,12 @@ namespace Ichni.Editor
private List<SelectionConnector> lastHitConnectors = new List<SelectionConnector>();
private int currentSelectIndex = 0;
private Vector2 lastMousePosition;
private bool cachedIsPointerOverUI;
private GameObject cachedHoveredUI;
private int uiCheckFrameInterval = 3; // 每3帧检查一次
private int frameCount;
private void Awake()
{
instance = this;
@@ -34,7 +40,22 @@ namespace Ichni.Editor
private void Update()
{
isPointerOverUI = IsPointerOverUI(out hoveredUI);
frameCount++;
// 只有当鼠标移动或每隔几帧时才更新UI检测
Vector2 currentMousePosition = Mouse.current.position.ReadValue();
if (currentMousePosition != lastMousePosition || frameCount % uiCheckFrameInterval == 0)
{
isPointerOverUI = IsPointerOverUI(out hoveredUI);
lastMousePosition = currentMousePosition;
cachedIsPointerOverUI = isPointerOverUI;
cachedHoveredUI = hoveredUI;
}
else
{
isPointerOverUI = cachedIsPointerOverUI;
hoveredUI = cachedHoveredUI;
}
SceneCameraOperation();
MusicPlayerOperation();
@@ -296,6 +317,12 @@ namespace Ichni.Editor
public bool IsPointerOverUI(out GameObject hoveredUI)
{
hoveredUI = null;
// 快速检查 - 使用Unity内置方法
if (!EventSystem.current.IsPointerOverGameObject())
return false;
// 详细检查 - 只有当快速检查通过时才执行
if (eventSystem == null || graphicRaycasters.Count == 0)
return false;
@@ -306,20 +333,19 @@ namespace Ichni.Editor
List<RaycastResult> allResults = new List<RaycastResult>();
// 遍历所有 Canvas 上的 GraphicRaycaster
foreach (var raycaster in graphicRaycasters)
// 只对最上层的Canvas进行检测
foreach (var raycaster in graphicRaycasters.Where(r => r.gameObject.activeInHierarchy))
{
List<RaycastResult> results = new List<RaycastResult>();
raycaster.Raycast(pointerEventData, results);
allResults.AddRange(results);
}
if (allResults.Count > 0)
{
// 按照 sortingOrder 获取最前面的 UI 物体
allResults.Sort((a, b) => b.sortingOrder.CompareTo(a.sortingOrder));
hoveredUI = allResults[0].gameObject;
return true;
if (results.Count > 0)
{
// 找到最前面的结果后立即返回
results.Sort((a, b) => b.sortingOrder.CompareTo(a.sortingOrder));
hoveredUI = results[0].gameObject;
return true;
}
}
return false;