TemplateOptionsUI.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using System;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEditor;
  7. namespace AmplifyShaderEditor
  8. {
  9. // UI STRUCTURES
  10. [Serializable]
  11. public class TemplateOptionUIItem
  12. {
  13. public delegate void OnActionPerformed( bool actionFromUser, bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, int recursionLevel = 0, params TemplateActionItem[] validActions );
  14. public event OnActionPerformed OnActionPerformedEvt;
  15. [SerializeField]
  16. private bool m_isVisible = true;
  17. [SerializeField]
  18. private bool m_wasVisible = true;
  19. [SerializeField]
  20. private int m_currentOption = 0;
  21. [SerializeField]
  22. private TemplateOptionsItem m_options;
  23. [SerializeField]
  24. private bool m_checkOnExecute = false;
  25. [SerializeField]
  26. private bool m_invertActionOnDeselection = false;
  27. [SerializeField]
  28. private Int64 m_lastClickedTimestamp = 0;
  29. public TemplateOptionUIItem( TemplateOptionsItem options )
  30. {
  31. m_options = options;
  32. if( m_options.Type == AseOptionsType.Field )
  33. {
  34. m_options.FieldValue.FloatValue = m_options.DefaultFieldValue;
  35. }
  36. else
  37. {
  38. m_currentOption = m_options.DefaultOptionIndex;
  39. }
  40. m_invertActionOnDeselection = options.Setup == AseOptionItemSetup.InvertActionOnDeselection;
  41. }
  42. public void CopyValuesFrom( TemplateOptionUIItem origin )
  43. {
  44. m_isVisible = origin.IsVisible;
  45. m_wasVisible = origin.WasVisible;
  46. m_currentOption = origin.CurrentOption;
  47. m_options.FieldValue.FloatValue = origin.CurrentFieldValue;
  48. m_checkOnExecute = origin.CheckOnExecute;
  49. m_invertActionOnDeselection = origin.InvertActionOnDeselection;
  50. }
  51. public void Draw( UndoParentNode owner )
  52. {
  53. if( m_isVisible )
  54. {
  55. int lastOption = m_currentOption;
  56. EditorGUI.BeginChangeCheck();
  57. switch( m_options.UIWidget )
  58. {
  59. case AseOptionsUIWidget.Dropdown:
  60. {
  61. m_currentOption = owner.EditorGUILayoutPopup( m_options.Name, m_currentOption, m_options.DisplayOptions );
  62. }
  63. break;
  64. case AseOptionsUIWidget.Toggle:
  65. {
  66. m_currentOption = owner.EditorGUILayoutToggle( m_options.Name, m_currentOption == 1 ) ? 1 : 0;
  67. }
  68. break;
  69. case AseOptionsUIWidget.Float:
  70. {
  71. if( m_options.FieldInline )
  72. {
  73. m_options.FieldValue.FloatField( ref owner, m_options.Name );
  74. if( m_options.FieldValue.Active )
  75. m_currentOption = 1;
  76. else
  77. m_currentOption = 0;
  78. }
  79. else
  80. {
  81. m_options.FieldValue.FloatValue = owner.EditorGUILayoutFloatField( m_options.Name, m_options.FieldValue.FloatValue );
  82. }
  83. }
  84. break;
  85. case AseOptionsUIWidget.Int:
  86. {
  87. if( m_options.FieldInline )
  88. {
  89. m_options.FieldValue.IntField( ref owner, m_options.Name );
  90. if( m_options.FieldValue.Active )
  91. m_currentOption = 1;
  92. else
  93. m_currentOption = 0;
  94. }
  95. else
  96. m_options.FieldValue.FloatValue = owner.EditorGUILayoutIntField( m_options.Name, (int)m_options.FieldValue.FloatValue );
  97. }
  98. break;
  99. case AseOptionsUIWidget.FloatRange:
  100. {
  101. if( m_options.FieldInline )
  102. {
  103. m_options.FieldValue.SliderField( ref owner, m_options.Name, m_options.FieldMin, m_options.FieldMax );
  104. if( m_options.FieldValue.Active )
  105. m_currentOption = 1;
  106. else
  107. m_currentOption = 0;
  108. }
  109. else
  110. m_options.FieldValue.FloatValue = owner.EditorGUILayoutSlider( m_options.Name, m_options.FieldValue.FloatValue, m_options.FieldMin, m_options.FieldMax );
  111. }
  112. break;
  113. case AseOptionsUIWidget.IntRange:
  114. {
  115. if( m_options.FieldInline )
  116. {
  117. m_options.FieldValue.IntSlider( ref owner, m_options.Name, (int)m_options.FieldMin, (int)m_options.FieldMax );
  118. if( m_options.FieldValue.Active )
  119. m_currentOption = 1;
  120. else
  121. m_currentOption = 0;
  122. }
  123. else
  124. m_options.FieldValue.FloatValue = owner.EditorGUILayoutIntSlider( m_options.Name, (int)m_options.FieldValue.FloatValue, (int)m_options.FieldMin, (int)m_options.FieldMax );
  125. }
  126. break;
  127. }
  128. if( EditorGUI.EndChangeCheck() )
  129. {
  130. m_lastClickedTimestamp = DateTime.UtcNow.Ticks;
  131. if( OnActionPerformedEvt != null )
  132. {
  133. if( m_invertActionOnDeselection )
  134. OnActionPerformedEvt( true, false, lastOption != m_options.DisableIdx, this, 0, m_options.ActionsPerOption[ lastOption ] );
  135. OnActionPerformedEvt( true, false, false, this, 0, m_options.ActionsPerOption[ m_currentOption ] );
  136. }
  137. }
  138. }
  139. }
  140. public void CheckEnDisable( bool actionFromUser )
  141. {
  142. //string deb = string.Empty;// "-- Checked --" + m_options.Name+" "+ m_isVisible + " "+ m_wasVisible;
  143. if( m_isVisible )
  144. {
  145. if( !m_wasVisible )
  146. {
  147. //deb = "-- Enable --" + m_options.Name;
  148. //Debug.Log( deb );
  149. if( OnActionPerformedEvt != null )
  150. {
  151. if( m_invertActionOnDeselection )
  152. {
  153. for( int i = 0; i < m_options.Count; i++ )
  154. {
  155. if( i != m_currentOption && i != m_options.DisableIdx )
  156. {
  157. OnActionPerformedEvt( actionFromUser, false, true, this, 0, m_options.ActionsPerOption[ i ] );
  158. }
  159. }
  160. }
  161. OnActionPerformedEvt( actionFromUser, false, false, this, 0, m_options.ActionsPerOption[ m_currentOption ] );
  162. //if( !m_isVisible )
  163. //OnActionPerformedEvt( isRefreshing, false, this, 0, m_options.ActionsPerOption[ m_options.DisableIdx ] );
  164. }
  165. }
  166. m_wasVisible = true;
  167. }
  168. else if( m_wasVisible )
  169. {
  170. //deb = "-- Disable --" + m_options.Name;
  171. //Debug.Log( deb );
  172. m_wasVisible = false;
  173. if( OnActionPerformedEvt != null )
  174. {
  175. OnActionPerformedEvt( actionFromUser, false, false, this, 0, m_options.ActionsPerOption[ m_options.DisableIdx ] );
  176. }
  177. }
  178. }
  179. public void FillDataCollector( ref MasterNodeDataCollector dataCollector )
  180. {
  181. if( m_isVisible && m_checkOnExecute )
  182. {
  183. for( int i = 0; i < m_options.ActionsPerOption[ m_currentOption ].Length; i++ )
  184. {
  185. switch( m_options.ActionsPerOption[ m_currentOption ][ i ].ActionType )
  186. {
  187. case AseOptionsActionType.SetDefine:
  188. {
  189. dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ m_currentOption ][ i ].ActionData );
  190. }
  191. break;
  192. case AseOptionsActionType.SetUndefine:
  193. {
  194. dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ m_currentOption ][ i ].ActionData, false );
  195. }
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. public void Update( int recursionLevel = 0, bool isRefreshing = true )
  202. {
  203. if( OnActionPerformedEvt != null )
  204. {
  205. if( m_invertActionOnDeselection )
  206. {
  207. for( int i = 0; i < m_options.Count; i++ )
  208. {
  209. if( i != m_currentOption && i != m_options.DisableIdx )
  210. {
  211. OnActionPerformedEvt( false, isRefreshing, true, this, recursionLevel, m_options.ActionsPerOption[ i ] );
  212. }
  213. }
  214. }
  215. OnActionPerformedEvt( false, isRefreshing, false, this, recursionLevel, m_options.ActionsPerOption[ m_currentOption ] );
  216. }
  217. }
  218. public TemplateOptionsItem Options { get { return m_options; } }
  219. public void Destroy()
  220. {
  221. OnActionPerformedEvt = null;
  222. }
  223. public bool IsVisible
  224. {
  225. get { return m_isVisible; }
  226. set { m_isVisible = value; }
  227. }
  228. public bool WasVisible
  229. {
  230. get { return m_wasVisible; }
  231. set { m_wasVisible = value; }
  232. }
  233. public bool CheckOnExecute
  234. {
  235. get { return m_checkOnExecute; }
  236. set { m_checkOnExecute = value; }
  237. }
  238. public InlineProperty FieldValue
  239. {
  240. get { return m_options.FieldValue; }
  241. set { m_options.FieldValue = value; }
  242. }
  243. public float CurrentFieldValue
  244. {
  245. get { return m_options.FieldValue.FloatValue; }
  246. set { m_options.FieldValue.FloatValue = value; }
  247. }
  248. public int CurrentOption
  249. {
  250. get { return m_currentOption; }
  251. set
  252. {
  253. m_currentOption = Mathf.Clamp( value, 0, m_options.Options.Length - 1 );
  254. // why refreshing here?
  255. //Refresh();
  256. }
  257. }
  258. public int CurrentOptionIdx
  259. {
  260. set
  261. {
  262. m_currentOption = Mathf.Clamp( value, 0, m_options.Options.Length - 1 );
  263. }
  264. }
  265. public bool EmptyEvent { get { return OnActionPerformedEvt == null; } }
  266. public TemplateActionItemGrid.TemplateActionItemRow CurrentOptionActions
  267. {
  268. get
  269. {
  270. if( m_options.Type == AseOptionsType.Field &&
  271. m_currentOption == 1 )
  272. {
  273. if( m_options.FieldValue.NodeId < -1 )
  274. {
  275. //This is quite the hack. The bug is related to if a user chooses an inline property on the field option, then the behavior is to comment the original property set on the template
  276. // The problem is that, if the user sets an inline property and select its own internal property from there, then the behavior that will prevail without this hack is to call the actions associated with setting a new inline property
  277. // Which is on all templates to comment the original template internal property leaving the property commented on the final code (This was detected on URP PBR)
  278. PropertyNode node = UIUtils.CurrentWindow.OutsideGraph.GetInternalTemplateNode( m_options.FieldValue.NodeId ) as PropertyNode;
  279. if( node != null )
  280. {
  281. if( node.PropertyName.Equals( m_options.FieldInlineName ) )
  282. {
  283. return m_options.ActionsPerOption.Rows[ 0 ];
  284. }
  285. }
  286. }
  287. else if( m_options.FieldValue.NodeId == -1 )
  288. {
  289. // If node id is -1 then no node is selected on the inline dropdown then we should also fallback to using its internal property
  290. return m_options.ActionsPerOption.Rows[ 0 ];
  291. }
  292. }
  293. return m_options.ActionsPerOption.Rows[m_currentOption];
  294. }
  295. }
  296. public bool InvertActionOnDeselection { get { return m_invertActionOnDeselection; } }
  297. public Int64 LastClickedTimestamp { get { return m_lastClickedTimestamp; } set { m_lastClickedTimestamp = value; } }
  298. }
  299. }