235 lines
8.4 KiB
C#
235 lines
8.4 KiB
C#
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace UnityEditor.Tilemaps
|
||
|
{
|
||
|
/// <summary> This class is in charge of handling Grid component based grid in the scene view (rendering, snapping).
|
||
|
/// It will hide global scene view grid when it has something to render</summary>
|
||
|
internal class SceneViewGridManager : ScriptableSingleton<SceneViewGridManager>
|
||
|
{
|
||
|
internal static readonly PrefColor sceneViewGridComponentGizmo = new PrefColor("Scene/Grid Component", 255.0f / 255.0f, 255.0f / 255.0f, 255.0f / 255.0f, 25.5f / 255.0f);
|
||
|
|
||
|
private static Mesh s_GridProxyMesh;
|
||
|
private static Material s_GridProxyMaterial;
|
||
|
private static int s_LastGridProxyHash;
|
||
|
|
||
|
[SerializeField]
|
||
|
private GridLayout m_ActiveGridProxy;
|
||
|
|
||
|
private Dictionary<SceneView, bool> m_SceneViewShowGridMap;
|
||
|
|
||
|
private bool m_RegisteredEventHandlers;
|
||
|
|
||
|
private bool active { get { return m_ActiveGridProxy != null; } }
|
||
|
internal GridLayout activeGridProxy { get { return m_ActiveGridProxy; } }
|
||
|
|
||
|
private UnityType m_GridType;
|
||
|
|
||
|
[InitializeOnLoadMethod]
|
||
|
private static void Initialize()
|
||
|
{
|
||
|
instance.RegisterEventHandlers();
|
||
|
}
|
||
|
|
||
|
private void OnEnable()
|
||
|
{
|
||
|
m_SceneViewShowGridMap = new Dictionary<SceneView, bool>();
|
||
|
RegisterEventHandlers();
|
||
|
}
|
||
|
|
||
|
private void RegisterEventHandlers()
|
||
|
{
|
||
|
if (m_RegisteredEventHandlers)
|
||
|
return;
|
||
|
|
||
|
SceneView.duringSceneGui += OnSceneGuiDelegate;
|
||
|
Selection.selectionChanged += UpdateCache;
|
||
|
EditorApplication.hierarchyChanged += UpdateCache;
|
||
|
UnityEditor.EditorTools.ToolManager.activeToolChanged += ActiveToolChanged;
|
||
|
EditorApplication.quitting += EditorQuitting;
|
||
|
GridPaintingState.brushChanged += OnBrushChanged;
|
||
|
GridPaintingState.scenePaintTargetChanged += OnScenePaintTargetChanged;
|
||
|
GridSnapping.snapPosition = OnSnapPosition;
|
||
|
GridSnapping.activeFunc = GetActive;
|
||
|
|
||
|
m_GridType = UnityType.FindTypeByName("Grid");
|
||
|
|
||
|
m_RegisteredEventHandlers = true;
|
||
|
}
|
||
|
|
||
|
private void OnBrushChanged(GridBrushBase brush)
|
||
|
{
|
||
|
UpdateCache();
|
||
|
}
|
||
|
|
||
|
private void ActiveToolChanged()
|
||
|
{
|
||
|
UpdateCache();
|
||
|
}
|
||
|
|
||
|
private void OnScenePaintTargetChanged(GameObject scenePaintTarget)
|
||
|
{
|
||
|
UpdateCache();
|
||
|
}
|
||
|
|
||
|
private void OnDisable()
|
||
|
{
|
||
|
FlushCachedGridProxy();
|
||
|
RestoreSceneViewShowGrid();
|
||
|
SceneView.duringSceneGui -= OnSceneGuiDelegate;
|
||
|
Selection.selectionChanged -= UpdateCache;
|
||
|
EditorApplication.hierarchyChanged -= UpdateCache;
|
||
|
EditorApplication.quitting -= EditorQuitting;
|
||
|
UnityEditor.EditorTools.ToolManager.activeToolChanged -= ActiveToolChanged;
|
||
|
GridPaintingState.brushChanged -= OnBrushChanged;
|
||
|
GridPaintingState.scenePaintTargetChanged -= OnScenePaintTargetChanged;
|
||
|
GridSnapping.snapPosition = null;
|
||
|
GridSnapping.activeFunc = null;
|
||
|
m_RegisteredEventHandlers = false;
|
||
|
}
|
||
|
|
||
|
private void UpdateCache()
|
||
|
{
|
||
|
GridLayout gridProxy;
|
||
|
if (PaintableGrid.InGridEditMode())
|
||
|
gridProxy = GridPaintingState.scenePaintTarget != null ? GridPaintingState.scenePaintTarget.GetComponentInParent<GridLayout>() : null;
|
||
|
else
|
||
|
gridProxy = Selection.activeGameObject != null ? Selection.activeGameObject.GetComponentInParent<GridLayout>() : null;
|
||
|
|
||
|
if (gridProxy != m_ActiveGridProxy)
|
||
|
{
|
||
|
if (m_ActiveGridProxy == null)
|
||
|
{
|
||
|
// Disable SceneView grid if there is now a GridProxy. Store user settings to be restored.
|
||
|
StoreSceneViewShowGrid(false);
|
||
|
}
|
||
|
else if (gridProxy == null)
|
||
|
{
|
||
|
RestoreSceneViewShowGrid();
|
||
|
}
|
||
|
m_ActiveGridProxy = gridProxy;
|
||
|
FlushCachedGridProxy();
|
||
|
SceneView.RepaintAll();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void EditorQuitting()
|
||
|
{
|
||
|
if (NeedsRestoreSceneViewShowGrid())
|
||
|
{
|
||
|
RestoreSceneViewShowGrid();
|
||
|
// SceneView.showGrid is part of default window preferences
|
||
|
WindowLayout.SaveDefaultWindowPreferences();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool IsGridAnnotationEnabled()
|
||
|
{
|
||
|
var annotations = AnnotationUtility.GetAnnotations();
|
||
|
foreach (var annotation in annotations)
|
||
|
{
|
||
|
if (annotation.classID == m_GridType.persistentTypeID)
|
||
|
{
|
||
|
return annotation.gizmoEnabled > 0;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private void OnSceneGuiDelegate(SceneView sceneView)
|
||
|
{
|
||
|
if (active && sceneView.drawGizmos && IsGridAnnotationEnabled())
|
||
|
DrawGrid(activeGridProxy);
|
||
|
}
|
||
|
|
||
|
private static int GenerateHash(GridLayout layout, Color color)
|
||
|
{
|
||
|
int hash = 0x7ed55d16;
|
||
|
hash ^= layout.cellSize.GetHashCode();
|
||
|
hash ^= layout.cellLayout.GetHashCode() << 23;
|
||
|
hash ^= (layout.cellGap.GetHashCode() << 4) + 0x165667b1;
|
||
|
hash ^= layout.cellSwizzle.GetHashCode() << 7;
|
||
|
hash ^= color.GetHashCode();
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
private static void DrawGrid(GridLayout gridLayout)
|
||
|
{
|
||
|
int gridHash = GenerateHash(gridLayout, sceneViewGridComponentGizmo.Color);
|
||
|
if (s_LastGridProxyHash != gridHash)
|
||
|
{
|
||
|
FlushCachedGridProxy();
|
||
|
s_LastGridProxyHash = gridHash;
|
||
|
}
|
||
|
GridEditorUtility.DrawGridGizmo(gridLayout, gridLayout.transform, sceneViewGridComponentGizmo.Color, ref s_GridProxyMesh, ref s_GridProxyMaterial);
|
||
|
}
|
||
|
|
||
|
private bool NeedsRestoreSceneViewShowGrid()
|
||
|
{
|
||
|
return m_SceneViewShowGridMap.Count > 0;
|
||
|
}
|
||
|
|
||
|
private void StoreSceneViewShowGrid(bool value)
|
||
|
{
|
||
|
m_SceneViewShowGridMap.Clear();
|
||
|
foreach (SceneView sceneView in SceneView.sceneViews)
|
||
|
{
|
||
|
m_SceneViewShowGridMap.Add(sceneView, sceneView.showGrid);
|
||
|
sceneView.showGrid = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void RestoreSceneViewShowGrid()
|
||
|
{
|
||
|
foreach (var item in m_SceneViewShowGridMap)
|
||
|
{
|
||
|
var sceneView = item.Key;
|
||
|
if (sceneView != null)
|
||
|
sceneView.showGrid = item.Value;
|
||
|
}
|
||
|
m_SceneViewShowGridMap.Clear();
|
||
|
}
|
||
|
|
||
|
private bool GetActive()
|
||
|
{
|
||
|
return active;
|
||
|
}
|
||
|
|
||
|
internal Vector3 OnSnapPosition(Vector3 position)
|
||
|
{
|
||
|
Vector3 result = position;
|
||
|
if (active && (EditorSnapSettings.hotkeyActive || EditorSnapSettings.gridSnapActive))
|
||
|
{
|
||
|
// This will automatically prefer the Grid
|
||
|
Vector3 local = activeGridProxy.WorldToLocal(position);
|
||
|
Vector3 interpolatedCell = activeGridProxy.LocalToCellInterpolated(local);
|
||
|
|
||
|
Vector3 inverse = Vector3.one;
|
||
|
inverse.x = Mathf.Approximately(EditorSnapSettings.move.x, 0.0f) ? 1.0f : 1.0f / EditorSnapSettings.move.x;
|
||
|
inverse.y = Mathf.Approximately(EditorSnapSettings.move.y, 0.0f) ? 1.0f : 1.0f / EditorSnapSettings.move.y;
|
||
|
inverse.z = Mathf.Approximately(EditorSnapSettings.move.z, 0.0f) ? 1.0f : 1.0f / EditorSnapSettings.move.z;
|
||
|
|
||
|
Vector3 roundedCell = new Vector3(
|
||
|
Mathf.Round(inverse.x * interpolatedCell.x) / inverse.x,
|
||
|
Mathf.Round(inverse.y * interpolatedCell.y) / inverse.y,
|
||
|
Mathf.Round(inverse.z * interpolatedCell.z) / inverse.z
|
||
|
);
|
||
|
|
||
|
local = activeGridProxy.CellToLocalInterpolated(roundedCell);
|
||
|
result = activeGridProxy.LocalToWorld(local);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
internal static void FlushCachedGridProxy()
|
||
|
{
|
||
|
if (s_GridProxyMesh == null)
|
||
|
return;
|
||
|
|
||
|
DestroyImmediate(s_GridProxyMesh);
|
||
|
s_GridProxyMesh = null;
|
||
|
s_GridProxyMaterial = null;
|
||
|
}
|
||
|
}
|
||
|
}
|