// Amplify Shader Editor - Visual Shader Editing Tool // Copyright (c) Amplify Creations, Lda using System.Collections.Generic; using UnityEngine; using UnityEditor; namespace AmplifyShaderEditor { public class NodeGrid { private bool m_debugGrid = false; private const float GRID_SIZE_X = 100; private const float GRID_SIZE_Y = 100; private const float GRID_AREA_X = 1000; private const float GRID_AREA_Y = 1000; private Dictionary>> m_grid; private int m_xMin = int.MaxValue; private int m_yMin = int.MaxValue; private int m_xMax = int.MinValue; private int m_yMax = int.MinValue; public NodeGrid() { m_grid = new Dictionary>>(); } public void AddNodeToGrid( ParentNode node ) { Rect pos = node.Position; if ( Mathf.Abs( pos.width ) < 0.001f || Mathf.Abs( pos.height ) < 0.001f ) { return; } float initialXf = pos.x / GRID_SIZE_X; float initialYf = pos.y / GRID_SIZE_Y; int endX = Mathf.CeilToInt( initialXf + pos.width / GRID_SIZE_X ); int endY = Mathf.CeilToInt( initialYf + pos.height / GRID_SIZE_Y ); int initialX = Mathf.FloorToInt( initialXf ); int initialY = Mathf.FloorToInt( initialYf ); if ( initialX < m_xMin ) { m_xMin = initialX; } if ( initialY < m_yMin ) { m_yMin = initialY; } if ( endX > m_xMax ) { m_xMax = endX; } if ( endY > m_yMax ) { m_yMax = endY; } for ( int x = initialX; x < endX; x += 1 ) { for ( int y = initialY; y < endY; y += 1 ) { if ( !m_grid.ContainsKey( x ) ) { m_grid.Add( x, new Dictionary>() ); } if ( !m_grid[ x ].ContainsKey( y ) ) { m_grid[ x ].Add( y, new List() ); } m_grid[ x ][ y ].Add( node ); } } node.IsOnGrid = true; //DebugLimits(); } public void RemoveNodeFromGrid( ParentNode node, bool useCachedPos ) { Rect pos = useCachedPos ? node.CachedPos : node.Position; if ( Mathf.Abs( pos.width ) < 0.001f || Mathf.Abs( pos.height ) < 0.001f ) { return; } float initialXf = pos.x / GRID_SIZE_X; float initialYf = pos.y / GRID_SIZE_Y; int endX = Mathf.CeilToInt( initialXf + pos.width / GRID_SIZE_X ); int endY = Mathf.CeilToInt( initialYf + pos.height / GRID_SIZE_Y ); int initialX = Mathf.FloorToInt( initialXf ); int initialY = Mathf.FloorToInt( initialYf ); bool testLimits = false; int xMinCount = 0; int xMaxCount = 0; int yMinCount = 0; int yMaxCount = 0; for ( int x = initialX; x < endX; x += 1 ) { for ( int y = initialY; y < endY; y += 1 ) { if ( m_grid.ContainsKey( x ) ) { if ( m_grid[ x ].ContainsKey( y ) ) { m_grid[ x ][ y ].Remove( node ); node.IsOnGrid = false; if ( initialX == m_xMin && x == initialX ) { testLimits = true; if ( m_grid[ x ][ y ].Count != 0 ) { xMinCount += 1; } } if ( endX == m_xMax && x == endX ) { testLimits = true; if ( m_grid[ x ][ y ].Count != 0 ) { xMaxCount += 1; } } if ( initialY == m_yMin && y == initialY ) { testLimits = true; if ( m_grid[ x ][ y ].Count != 0 ) { yMinCount += 1; } } if ( endY == m_yMax && y == endY ) { testLimits = true; if ( m_grid[ x ][ y ].Count != 0 ) { yMaxCount += 1; } } } } } } if ( testLimits ) { if ( xMinCount == 0 || xMaxCount == 0 || yMinCount == 0 || yMaxCount == 0 ) { m_xMin = int.MaxValue; m_yMin = int.MaxValue; m_xMax = int.MinValue; m_yMax = int.MinValue; foreach ( KeyValuePair>> entryX in m_grid ) { foreach ( KeyValuePair> entryY in entryX.Value ) { if ( entryY.Value.Count > 0 ) { if ( entryX.Key < m_xMin ) { m_xMin = entryX.Key; } if ( entryY.Key < m_yMin ) { m_yMin = entryY.Key; } if ( entryX.Key > m_xMax ) { m_xMax = entryX.Key; } if ( entryY.Key > m_yMax ) { m_yMax = entryY.Key; } } } } // The += 1 is to maintain consistence with AddNodeToGrid() ceil op on max values m_xMax += 1; m_yMax += 1; } } //DebugLimits(); } public void DebugLimits() { Debug.Log( "[ " + m_xMin + " , " + m_yMin + " ] " + "[ " + m_xMax + " , " + m_yMax + " ] " ); } //pos must be the transformed mouse position to local canvas coordinates public List GetNodesOn( Vector2 pos ) { int x = Mathf.FloorToInt( pos.x / GRID_SIZE_X ); int y = Mathf.FloorToInt( pos.y / GRID_SIZE_Y ); if ( m_grid.ContainsKey( x ) ) { if ( m_grid[ x ].ContainsKey( y ) ) { return m_grid[ x ][ y ]; } } return null; } public List GetNodesOn( int x, int y ) { if ( m_grid.ContainsKey( x ) ) { if ( m_grid[ x ].ContainsKey( y ) ) { return m_grid[ x ][ y ]; } } return null; } public void DrawGrid( DrawInfo drawInfo ) { if ( m_debugGrid ) { Handles.CircleHandleCap( 0, drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x, drawInfo.CameraOffset.y, 0f ) ), Quaternion.identity, 5,EventType.Layout ); for ( int x = -( int ) GRID_AREA_X; x < GRID_AREA_X; x += ( int ) GRID_SIZE_X ) { Handles.DrawLine( drawInfo.InvertedZoom * ( new Vector3( x + drawInfo.CameraOffset.x, drawInfo.CameraOffset.y - GRID_AREA_Y, 0 ) ), drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x + x, drawInfo.CameraOffset.y + GRID_AREA_Y, 0 ) ) ); } for ( int y = -( int ) GRID_AREA_Y; y < GRID_AREA_X; y += ( int ) GRID_SIZE_Y ) { Handles.DrawLine( drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x - GRID_AREA_X, drawInfo.CameraOffset.y + y, 0 ) ), drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x + GRID_AREA_X, drawInfo.CameraOffset.y + y, 0 ) ) ); } } } public void Destroy() { foreach ( KeyValuePair>> entryX in m_grid ) { foreach ( KeyValuePair> entryY in entryX.Value ) { entryY.Value.Clear(); } entryX.Value.Clear(); } m_grid.Clear(); } public float MaxNodeDist { get { return Mathf.Max( ( m_xMax - m_xMin )*GRID_SIZE_X, ( m_yMax - m_yMin )*GRID_SIZE_Y ); } } } }