点击选中
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Lean.Pool;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
@@ -7,6 +13,8 @@ namespace Ichni.Editor
|
||||
{
|
||||
[Tooltip("指定用于计算缩放的摄像机(若为空则使用 Camera.main)")]
|
||||
public Camera sceneCamera;
|
||||
|
||||
public float cameraDistance;
|
||||
|
||||
[Tooltip("指定网格所在的平面:0 = XZ (y=0), 1 = XY (z=0), 2 = YZ (x=0)")]
|
||||
public int gridPlane = 0;
|
||||
@@ -21,8 +29,19 @@ namespace Ichni.Editor
|
||||
// 内部缓存材质
|
||||
private Material gridMaterial;
|
||||
|
||||
public float logScale;
|
||||
public float gridScale; // 1, 4, 16, 64...
|
||||
|
||||
[FormerlySerializedAs("showPositionText")] public bool canShowPositionText;
|
||||
public bool isShowingPositionText;
|
||||
public Transform textContainer;
|
||||
public GameObject positionTextPrefab;
|
||||
public Dictionary<GameObject, Vector3> positionTexts;
|
||||
|
||||
void Start()
|
||||
{
|
||||
positionTexts = new Dictionary<GameObject, Vector3>();
|
||||
|
||||
sceneCamera = EditorManager.instance.cameraManager.sceneCamera.sceneCamera;
|
||||
// 实例化材质,避免修改共享材质
|
||||
gridMaterial = GetComponent<MeshRenderer>().material;
|
||||
@@ -35,27 +54,103 @@ namespace Ichni.Editor
|
||||
sceneCamera = EditorManager.instance.cameraManager.currentCamera;
|
||||
|
||||
// 计算摄像机到网格平面的垂直距离
|
||||
float camDistance = 0f;
|
||||
cameraDistance = 0f;
|
||||
Vector3 camPos = sceneCamera.transform.position;
|
||||
Vector3 gridPos = transform.position;
|
||||
switch (gridPlane)
|
||||
{
|
||||
case 0: // XZ 平面:垂直方向为 Y
|
||||
camDistance = Mathf.Abs(camPos.y - gridPos.y);
|
||||
cameraDistance = Mathf.Abs(camPos.y - gridPos.y);
|
||||
break;
|
||||
case 1: // XY 平面:垂直方向为 Z
|
||||
camDistance = Mathf.Abs(camPos.z - gridPos.z);
|
||||
cameraDistance = Mathf.Abs(camPos.z - gridPos.z);
|
||||
break;
|
||||
case 2: // YZ 平面:垂直方向为 X
|
||||
camDistance = Mathf.Abs(camPos.x - gridPos.x);
|
||||
cameraDistance = Mathf.Abs(camPos.x - gridPos.x);
|
||||
break;
|
||||
}
|
||||
|
||||
// 利用对数函数计算缩放等级:距离越远,网格越大
|
||||
float logScale = Mathf.Floor(Mathf.Log(camDistance / distanceFactor + 1, 4));
|
||||
float gridScale = baseScale * Mathf.Pow(4, logScale) * scaleMultiplier;
|
||||
logScale = Mathf.Floor(Mathf.Log(cameraDistance / distanceFactor + 1, 4));
|
||||
gridScale = baseScale * Mathf.Pow(4, logScale) * scaleMultiplier;
|
||||
|
||||
gridMaterial.SetFloat("_GridScale", 1 / gridScale);
|
||||
gridMaterial.SetFloat("_DisappearEndDistance", 100 * gridScale);
|
||||
|
||||
if (canShowPositionText && isShowingPositionText)
|
||||
{
|
||||
GetPoints();
|
||||
|
||||
foreach (KeyValuePair<GameObject,Vector3> positionText in positionTexts)
|
||||
{
|
||||
positionText.Key.transform.position = positionText.Value + new Vector3(gridScale / 6, 0, gridScale / 12);
|
||||
float scaleFactor = gridScale * 1.5f;
|
||||
positionText.Key.transform.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetPoints()
|
||||
{
|
||||
Ray sceneCameraRay = sceneCamera.ScreenPointToRay(new Vector2(Screen.width / 2f, Screen.height / 2f));
|
||||
if (Physics.Raycast(sceneCameraRay, out RaycastHit sceneCameraHit, float.MaxValue, LayerMask.GetMask("Grid")))
|
||||
{
|
||||
if (sceneCameraHit.collider.gameObject == gameObject)
|
||||
{
|
||||
Vector3 point = sceneCameraHit.point;
|
||||
float radius = gridScale * 16f;
|
||||
float step = gridScale * 4f;
|
||||
|
||||
float minX = point.x - radius;
|
||||
float maxX = point.x + radius;
|
||||
float minZ = point.z - radius;
|
||||
float maxZ = point.z + radius;
|
||||
|
||||
// 对于 X 与 Z 方向,根据网格间距取整,确保从整点开始
|
||||
minX = Mathf.Floor(minX / step) * step;
|
||||
maxX = Mathf.Ceil(maxX / step) * step;
|
||||
minZ = Mathf.Floor(minZ / step) * step;
|
||||
maxZ = Mathf.Ceil(maxZ / step) * step;
|
||||
|
||||
List<Vector3> newPositions = new List<Vector3>();
|
||||
|
||||
for (float x = minX; x <= maxX; x += step)
|
||||
{
|
||||
for (float z = minZ; z <= maxZ; z += step)
|
||||
{
|
||||
Vector3 position = new Vector3(x, 0, z);
|
||||
|
||||
if (!positionTexts.ContainsValue(position))
|
||||
{
|
||||
GameObject posText = LeanPool.Spawn(positionTextPrefab);
|
||||
posText.transform.position = position + new Vector3(gridScale / 8, 0, gridScale / 16);
|
||||
posText.transform.forward = -transform.up;
|
||||
posText.GetComponent<TMP_Text>().text = $"({Mathf.RoundToInt(position.x)}, {Mathf.RoundToInt(position.z)})";
|
||||
posText.transform.SetParent(textContainer);
|
||||
positionTexts.Add(posText, position);
|
||||
}
|
||||
|
||||
newPositions.Add(new Vector3(x, 0, z));
|
||||
}
|
||||
}
|
||||
|
||||
List<GameObject> toRemove = new List<GameObject>();
|
||||
// 清除不在新范围内的Text
|
||||
foreach (KeyValuePair<GameObject, Vector3> positionText in positionTexts)
|
||||
{
|
||||
if (!newPositions.Contains(positionText.Value))
|
||||
{
|
||||
LeanPool.Despawn(positionText.Key);
|
||||
toRemove.Add(positionText.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GameObject text in toRemove)
|
||||
{
|
||||
positionTexts.Remove(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
@@ -19,11 +20,14 @@ namespace Ichni.Editor
|
||||
public bool xPlaneEnabled;
|
||||
public bool zPlaneEnabled;
|
||||
|
||||
public bool isYPlaneShowingPositionText;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
yPlaneEnabled = true;
|
||||
xPlaneEnabled = false;
|
||||
zPlaneEnabled = false;
|
||||
isYPlaneShowingPositionText = true;
|
||||
RefreshPlanes();
|
||||
}
|
||||
|
||||
@@ -38,11 +42,15 @@ namespace Ichni.Editor
|
||||
var yPlaneToggle =
|
||||
inspector.GenerateToggle(this, gridSettings, "Y Plane", nameof(yPlaneEnabled))
|
||||
.AddListenerFunction(RefreshPlanes);
|
||||
var xPlaneToggle =
|
||||
inspector.GenerateToggle(this, gridSettings, "X Plane", nameof(xPlaneEnabled))
|
||||
.AddListenerFunction(RefreshPlanes);
|
||||
var zPlaneToggle =
|
||||
inspector.GenerateToggle(this, gridSettings, "Z Plane", nameof(zPlaneEnabled))
|
||||
.AddListenerFunction(RefreshPlanes);
|
||||
var xPlaneToggle =
|
||||
inspector.GenerateToggle(this, gridSettings, "X Plane", nameof(xPlaneEnabled))
|
||||
|
||||
var yPlaneShowPositionToggle =
|
||||
inspector.GenerateToggle(this, gridSettings, "Show Y Plane Position", nameof(isYPlaneShowingPositionText))
|
||||
.AddListenerFunction(RefreshPlanes);
|
||||
}
|
||||
|
||||
@@ -51,6 +59,17 @@ namespace Ichni.Editor
|
||||
yPlaneGrid.gameObject.SetActive(yPlaneEnabled);
|
||||
xPlaneGrid.gameObject.SetActive(xPlaneEnabled);
|
||||
zPlaneGrid.gameObject.SetActive(zPlaneEnabled);
|
||||
yPlaneGrid.isShowingPositionText = isYPlaneShowingPositionText;
|
||||
|
||||
if (!yPlaneGrid.isShowingPositionText)
|
||||
{
|
||||
foreach (KeyValuePair<GameObject, Vector3> positionText in yPlaneGrid.positionTexts)
|
||||
{
|
||||
LeanPool.Despawn(positionText.Key);
|
||||
}
|
||||
|
||||
yPlaneGrid.positionTexts.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user