using System.Collections.Generic; using UnityEngine; using UnityEngine.Experimental.Rendering; namespace UnityEditor.Experimental.TerrainAPI { /// /// Collection class for mapping string and integer values to RTHandles /// public class RTHandleCollection : System.IDisposable { private bool m_Disposed; private Dictionary< int, RTHandle > m_Handles; private Dictionary< int, GraphicsFormat > m_Formats; private Dictionary< string, int > m_NameToHash; private Dictionary< int, string > m_HashToName; private List< int > m_Hashes; /// /// Access a RTHandle using an integer hash /// public RTHandle this[ int hash ] { get { if( m_Handles.ContainsKey( hash ) ) { return m_Handles[ hash ]; } return null; } set { m_Handles[ hash ] = value; } } /// /// Access a RTHandle using a string value /// public RTHandle this[ string name ] { get { if( m_NameToHash.ContainsKey( name ) ) { return m_Handles[ m_NameToHash[ name ] ]; } return null; } set { m_Handles[ m_NameToHash[ name ] ] = value; } } /// /// RTHandleCollection constructor /// public RTHandleCollection() { m_Handles = new Dictionary< int, RTHandle >(); m_Formats = new Dictionary< int, GraphicsFormat >(); m_NameToHash = new Dictionary< string, int >(); m_HashToName = new Dictionary< int, string >(); m_Hashes = new List< int >(); } /// /// Add a RTHandle description to the RTHandleCollection for later use when calling GatherRTHandles /// The hash or integer value used to identify the RTHandle /// The name used to identify the RTHandle /// The GraphicsFormat to use for the RTHandle description /// public void AddRTHandle( int hash, string name, GraphicsFormat format ) { if( !m_Handles.ContainsKey( hash ) ) { m_NameToHash.Add( name, hash ); m_HashToName.Add( hash, name ); m_Handles.Add( hash, null ); m_Formats.Add( hash, format ); m_Hashes.Add( hash ); } else { // if the RTHandle already exists, assume they are changing the descriptor m_Formats[ hash ] = format; m_NameToHash[ name ] = hash; m_HashToName[ hash ] = name; } } /// /// Check to see if a RTHandle with the provided name exists already /// The name used to identify a RTHandle in this RTHandleCollection /// public bool ContainsRTHandle( string name ) { return m_NameToHash.ContainsKey( name ); } /// /// Check to see if a RTHandle with the provided hash value exists already /// The hash or integer value used to identify a RTHandle in this RTHandleCollection /// The RTHandle reference associated with the provided hash or integer value. NULL if the key is not found /// public RTHandle GetRTHandle( int hash ) { if(m_Handles.ContainsKey( hash )) { return m_Handles[ hash ]; } return null; } /// /// Gather/Create all added RTHandles using the provided width, height, and depth value, if provided /// The width of the RTHandles to gather /// The height of the RTHandles to gather /// The optional depth of the RTHandles to gather /// /// public void GatherRTHandles( int width, int height, int depth = 0 ) { foreach( int key in m_Hashes ) { var desc = new RenderTextureDescriptor( width, height, m_Formats[ key ], depth ); m_Handles[ key ] = RTUtils.GetNewHandle( desc ); m_Handles[ key ].RT.Create(); } } /// /// Release the RTHandle resources that have been gathered /// public void ReleaseRTHandles() { foreach( int key in m_Hashes ) { if( m_Handles[ key ] != null ) { var handle = m_Handles[ key ]; RTUtils.Release( handle ); m_Handles[ key ] = null; } } } /// /// Render debug GUI in the SceneView that displays all the RTHandles in this RTHandleCollection /// The size that is used to draw the textures /// public void OnSceneGUI( float size ) { const float padding = 10; Handles.BeginGUI(); { Color prev = GUI.color; Rect rect = new Rect( padding, padding, size, size ); foreach( KeyValuePair p in m_Handles ) { GUI.color = new Color( 1, 0, 1, 1 ); GUI.DrawTexture( rect, Texture2D.whiteTexture, ScaleMode.ScaleToFit ); GUI.color = Color.white; if(p.Value != null) { GUI.DrawTexture( rect, p.Value, ScaleMode.ScaleToFit, false ); } else { GUI.Label( rect, "NULL" ); } Rect labelRect = rect; labelRect.y = rect.yMax; labelRect.height = EditorGUIUtility.singleLineHeight; GUI.Box( labelRect, m_HashToName[ p.Key ], Styles.box ); rect.y += padding + size + EditorGUIUtility.singleLineHeight; if( rect.yMax + EditorGUIUtility.singleLineHeight > Screen.height - EditorGUIUtility.singleLineHeight * 2 ) { rect.y = padding; rect.x = rect.xMax + padding; } } GUI.color = prev; } Handles.EndGUI(); } /// /// Dispose method for this class /// public void Dispose() { Dispose(true); } /// /// Overridable Dispose method for this class. Override this if you create a class that derives from RTHandleCollection /// Whether or not resources should be disposed /// public virtual void Dispose(bool dispose) { if(m_Disposed) return; if(!dispose) return; ReleaseRTHandles(); m_Handles.Clear(); m_Disposed = true; } private static class Styles { public static GUIStyle box; static Styles() { box = new GUIStyle(EditorStyles.helpBox); box.normal.textColor = Color.white; } } } }