RangedFloatNode.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System;
  6. namespace AmplifyShaderEditor
  7. {
  8. [Serializable]
  9. [NodeAttributes( "Float", "Constants And Properties", "Float property", null, KeyCode.Alpha1 )]
  10. public sealed class RangedFloatNode : PropertyNode
  11. {
  12. private const int OriginalFontSize = 11;
  13. private const string MinValueStr = "Min";
  14. private const string MaxValueStr = "Max";
  15. private const float LabelWidth = 8;
  16. [SerializeField]
  17. private float m_defaultValue = 0;
  18. [SerializeField]
  19. private float m_materialValue = 0;
  20. [SerializeField]
  21. private float m_min = 0;
  22. [SerializeField]
  23. private float m_max = 0;
  24. [SerializeField]
  25. private bool m_floatMode = true;
  26. private int m_cachedPropertyId = -1;
  27. private bool m_isEditingFields;
  28. private Vector3 m_previousValue = Vector3.zero;
  29. private string[] m_fieldText = new string[] { "0", "0", "0" };
  30. public RangedFloatNode() : base() { }
  31. public RangedFloatNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { }
  32. protected override void CommonInit( int uniqueId )
  33. {
  34. base.CommonInit( uniqueId );
  35. GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Float" );
  36. AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue );
  37. m_insideSize.Set( 50, 0 );
  38. m_showPreview = false;
  39. m_showHybridInstancedUI = true;
  40. m_selectedLocation = PreviewLocation.BottomCenter;
  41. m_availableAttribs.Add( new PropertyAttributes( "Toggle", "[Toggle]" ) );
  42. m_availableAttribs.Add( new PropertyAttributes( "No Keyword Toggle", "[ToggleUI]","[NoKeywordToggle]" ) );
  43. m_availableAttribs.Add( new PropertyAttributes( "Int Range", "[IntRange]" ) );
  44. m_availableAttribs.Add( new PropertyAttributes( "Enum", "[Enum]" ) );
  45. m_previewShaderGUID = "d9ca47581ac157145bff6f72ac5dd73e";
  46. m_srpBatcherCompatible = true;
  47. }
  48. protected override void OnUniqueIDAssigned()
  49. {
  50. base.OnUniqueIDAssigned();
  51. UIUtils.RegisterFloatIntNode( this );
  52. }
  53. public override void Destroy()
  54. {
  55. base.Destroy();
  56. UIUtils.UnregisterFloatIntNode( this );
  57. }
  58. public override void OnDirtyProperty()
  59. {
  60. UIUtils.UpdateFloatIntDataNode( UniqueId, PropertyInspectorName );
  61. }
  62. public override void RefreshExternalReferences()
  63. {
  64. base.RefreshExternalReferences();
  65. OnPropertyNameChanged();
  66. OnDirtyProperty();
  67. }
  68. public void SetFloatMode( bool value )
  69. {
  70. if ( m_floatMode == value )
  71. return;
  72. m_floatMode = value;
  73. if ( value )
  74. {
  75. m_insideSize.x = 50;// + ( m_showPreview ? 50 : 0 );
  76. //m_firstPreviewDraw = true;
  77. }
  78. else
  79. {
  80. m_insideSize.x = 200;// + ( m_showPreview ? 0 : 0 );
  81. //m_firstPreviewDraw = true;
  82. }
  83. m_sizeIsDirty = true;
  84. }
  85. public override void CopyDefaultsToMaterial()
  86. {
  87. m_materialValue = m_defaultValue;
  88. }
  89. void DrawMinMaxUI()
  90. {
  91. EditorGUI.BeginChangeCheck();
  92. m_min = EditorGUILayoutFloatField( MinValueStr, m_min );
  93. m_max = EditorGUILayoutFloatField( MaxValueStr, m_max );
  94. if ( m_min > m_max )
  95. m_min = m_max;
  96. if ( m_max < m_min )
  97. m_max = m_min;
  98. if ( EditorGUI.EndChangeCheck() )
  99. {
  100. SetFloatMode( m_min == m_max );
  101. }
  102. }
  103. public override void DrawSubProperties()
  104. {
  105. DrawMinMaxUI();
  106. if ( m_floatMode )
  107. {
  108. m_defaultValue = EditorGUILayoutFloatField( Constants.DefaultValueLabel, m_defaultValue );
  109. }
  110. else
  111. {
  112. m_defaultValue = EditorGUILayoutSlider( Constants.DefaultValueLabel, m_defaultValue, m_min, m_max );
  113. }
  114. }
  115. public override void DrawMaterialProperties()
  116. {
  117. DrawMinMaxUI();
  118. EditorGUI.BeginChangeCheck();
  119. if ( m_floatMode )
  120. {
  121. m_materialValue = EditorGUILayoutFloatField( Constants.MaterialValueLabel, m_materialValue );
  122. }
  123. else
  124. {
  125. m_materialValue = EditorGUILayoutSlider( Constants.MaterialValueLabel, m_materialValue, m_min, m_max );
  126. }
  127. if ( EditorGUI.EndChangeCheck() )
  128. {
  129. //MarkForPreviewUpdate();
  130. if ( m_materialMode )
  131. m_requireMaterialUpdate = true;
  132. }
  133. }
  134. public override void SetPreviewInputs()
  135. {
  136. base.SetPreviewInputs();
  137. if ( m_cachedPropertyId == -1 )
  138. m_cachedPropertyId = Shader.PropertyToID( "_InputFloat" );
  139. if ( m_materialMode && m_currentParameterType != PropertyType.Constant )
  140. PreviewMaterial.SetFloat( m_cachedPropertyId, m_materialValue );
  141. else
  142. PreviewMaterial.SetFloat( m_cachedPropertyId, m_defaultValue );
  143. }
  144. public override void OnNodeLayout( DrawInfo drawInfo )
  145. {
  146. base.OnNodeLayout( drawInfo );
  147. if ( m_floatMode )
  148. {
  149. m_propertyDrawPos = m_remainingBox;
  150. m_propertyDrawPos.x = m_remainingBox.x - LabelWidth * drawInfo.InvertedZoom;
  151. m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE;
  152. m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE;
  153. }
  154. else
  155. {
  156. m_propertyDrawPos = m_remainingBox;
  157. m_propertyDrawPos.width = m_outputPorts[ 0 ].Position.x - m_propertyDrawPos.x - (m_outputPorts[ 0 ].LabelSize.x + (Constants.PORT_TO_LABEL_SPACE_X + 3) * drawInfo.InvertedZoom + 2);
  158. m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE;
  159. }
  160. }
  161. public override void DrawGUIControls( DrawInfo drawInfo )
  162. {
  163. base.DrawGUIControls( drawInfo );
  164. if ( drawInfo.CurrentEventType != EventType.MouseDown )
  165. return;
  166. Rect hitBox = m_remainingBox;
  167. hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom;
  168. bool insideBox = hitBox.Contains( drawInfo.MousePosition );
  169. if ( insideBox )
  170. {
  171. GUI.FocusControl( null );
  172. m_isEditingFields = true;
  173. }
  174. else if ( m_isEditingFields && !insideBox )
  175. {
  176. GUI.FocusControl( null );
  177. m_isEditingFields = false;
  178. }
  179. }
  180. void DrawFakeFloatMaterial( DrawInfo drawInfo )
  181. {
  182. if( m_floatMode )
  183. {
  184. //UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_materialValue, LabelWidth * drawInfo.InvertedZoom );
  185. Rect fakeField = m_propertyDrawPos;
  186. fakeField.xMin += LabelWidth * drawInfo.InvertedZoom;
  187. if( GUI.enabled )
  188. {
  189. Rect fakeLabel = m_propertyDrawPos;
  190. fakeLabel.xMax = fakeField.xMin;
  191. EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow );
  192. EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text );
  193. }
  194. if( m_previousValue[ 0 ] != m_materialValue )
  195. {
  196. m_previousValue[ 0 ] = m_materialValue;
  197. m_fieldText[ 0 ] = m_materialValue.ToString();
  198. }
  199. GUI.Label( fakeField, m_fieldText[ 0 ], UIUtils.MainSkin.textField );
  200. }
  201. else
  202. {
  203. DrawFakeSlider( ref m_materialValue, drawInfo );
  204. }
  205. }
  206. public override void Draw( DrawInfo drawInfo )
  207. {
  208. base.Draw( drawInfo );
  209. if ( !m_isVisible )
  210. return;
  211. if ( m_isEditingFields && m_currentParameterType != PropertyType.Global )
  212. {
  213. if ( m_materialMode && m_currentParameterType != PropertyType.Constant )
  214. {
  215. EditorGUI.BeginChangeCheck();
  216. if ( m_floatMode )
  217. {
  218. UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_materialValue, LabelWidth * drawInfo.InvertedZoom );
  219. }
  220. else
  221. {
  222. DrawSlider( ref m_materialValue, drawInfo );
  223. }
  224. if ( EditorGUI.EndChangeCheck() )
  225. {
  226. PreviewIsDirty = true;
  227. m_requireMaterialUpdate = true;
  228. if ( m_currentParameterType != PropertyType.Constant )
  229. {
  230. BeginDelayedDirtyProperty();
  231. }
  232. }
  233. }
  234. else
  235. {
  236. EditorGUI.BeginChangeCheck();
  237. if ( m_floatMode )
  238. {
  239. UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_defaultValue, LabelWidth * drawInfo.InvertedZoom );
  240. }
  241. else
  242. {
  243. DrawSlider( ref m_defaultValue, drawInfo );
  244. }
  245. if ( EditorGUI.EndChangeCheck() )
  246. {
  247. PreviewIsDirty = true;
  248. BeginDelayedDirtyProperty();
  249. }
  250. }
  251. }
  252. else if ( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
  253. {
  254. if( m_currentParameterType == PropertyType.Global )
  255. {
  256. bool guiEnabled = GUI.enabled;
  257. GUI.enabled = false;
  258. DrawFakeFloatMaterial( drawInfo );
  259. GUI.enabled = guiEnabled;
  260. }
  261. else if ( m_materialMode && m_currentParameterType != PropertyType.Constant )
  262. {
  263. DrawFakeFloatMaterial( drawInfo );
  264. }
  265. else
  266. {
  267. if ( m_floatMode )
  268. {
  269. //UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_defaultValue, LabelWidth * drawInfo.InvertedZoom );
  270. Rect fakeField = m_propertyDrawPos;
  271. fakeField.xMin += LabelWidth * drawInfo.InvertedZoom;
  272. Rect fakeLabel = m_propertyDrawPos;
  273. fakeLabel.xMax = fakeField.xMin;
  274. EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow );
  275. EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text );
  276. if ( m_previousValue[ 0 ] != m_defaultValue )
  277. {
  278. m_previousValue[ 0 ] = m_defaultValue;
  279. m_fieldText[ 0 ] = m_defaultValue.ToString();
  280. }
  281. GUI.Label( fakeField, m_fieldText[ 0 ], UIUtils.MainSkin.textField );
  282. }
  283. else
  284. {
  285. DrawFakeSlider( ref m_defaultValue, drawInfo );
  286. }
  287. }
  288. }
  289. }
  290. void DrawFakeSlider( ref float value, DrawInfo drawInfo )
  291. {
  292. float rangeWidth = 30 * drawInfo.InvertedZoom;
  293. float rangeSpacing = 5 * drawInfo.InvertedZoom;
  294. //Min
  295. Rect minRect = m_propertyDrawPos;
  296. minRect.width = rangeWidth;
  297. EditorGUIUtility.AddCursorRect( minRect, MouseCursor.Text );
  298. if ( m_previousValue[ 1 ] != m_min )
  299. {
  300. m_previousValue[ 1 ] = m_min;
  301. m_fieldText[ 1 ] = m_min.ToString();
  302. }
  303. GUI.Label( minRect, m_fieldText[ 1 ], UIUtils.MainSkin.textField );
  304. //Value Area
  305. Rect valRect = m_propertyDrawPos;
  306. valRect.width = rangeWidth;
  307. valRect.x = m_propertyDrawPos.xMax - rangeWidth - rangeWidth - rangeSpacing;
  308. EditorGUIUtility.AddCursorRect( valRect, MouseCursor.Text );
  309. if ( m_previousValue[ 0 ] != value )
  310. {
  311. m_previousValue[ 0 ] = value;
  312. m_fieldText[ 0 ] = value.ToString();
  313. }
  314. GUI.Label( valRect, m_fieldText[ 0 ], UIUtils.MainSkin.textField );
  315. //Max
  316. Rect maxRect = m_propertyDrawPos;
  317. maxRect.width = rangeWidth;
  318. maxRect.x = m_propertyDrawPos.xMax - rangeWidth;
  319. EditorGUIUtility.AddCursorRect( maxRect, MouseCursor.Text );
  320. if ( m_previousValue[ 2 ] != m_max )
  321. {
  322. m_previousValue[ 2 ] = m_max;
  323. m_fieldText[ 2 ] = m_max.ToString();
  324. }
  325. GUI.Label( maxRect, m_fieldText[ 2 ], UIUtils.MainSkin.textField );
  326. Rect sliderValRect = m_propertyDrawPos;
  327. sliderValRect.x = minRect.xMax + rangeSpacing;
  328. sliderValRect.xMax = valRect.xMin - rangeSpacing;
  329. Rect sliderBackRect = sliderValRect;
  330. sliderBackRect.height = 5 * drawInfo.InvertedZoom;
  331. sliderBackRect.center = new Vector2( sliderValRect.center.x, Mathf.Round( sliderValRect.center.y ) );
  332. GUI.Label( sliderBackRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SliderStyle ) );
  333. sliderValRect.width = 10;
  334. float percent = ( value - m_min) / ( m_max-m_min );
  335. percent = Mathf.Clamp01( percent );
  336. sliderValRect.x += percent * (sliderBackRect.width - 10 * drawInfo.InvertedZoom );
  337. GUI.Label( sliderValRect, string.Empty, UIUtils.RangedFloatSliderThumbStyle );
  338. }
  339. void DrawSlider( ref float value, DrawInfo drawInfo )
  340. {
  341. float rangeWidth = 30 * drawInfo.InvertedZoom;
  342. float rangeSpacing = 5 * drawInfo.InvertedZoom;
  343. //Min
  344. Rect minRect = m_propertyDrawPos;
  345. minRect.width = rangeWidth;
  346. m_min = EditorGUIFloatField( minRect, m_min, UIUtils.MainSkin.textField );
  347. //Value Area
  348. Rect valRect = m_propertyDrawPos;
  349. valRect.width = rangeWidth;
  350. valRect.x = m_propertyDrawPos.xMax - rangeWidth - rangeWidth - rangeSpacing;
  351. value = EditorGUIFloatField( valRect, value, UIUtils.MainSkin.textField );
  352. //Max
  353. Rect maxRect = m_propertyDrawPos;
  354. maxRect.width = rangeWidth;
  355. maxRect.x = m_propertyDrawPos.xMax - rangeWidth;
  356. m_max = EditorGUIFloatField( maxRect, m_max, UIUtils.MainSkin.textField );
  357. //Value Slider
  358. Rect sliderValRect = m_propertyDrawPos;
  359. sliderValRect.x = minRect.xMax + rangeSpacing;
  360. sliderValRect.xMax = valRect.xMin - rangeSpacing;
  361. Rect sliderBackRect = sliderValRect;
  362. sliderBackRect.height = 5 * drawInfo.InvertedZoom;
  363. sliderBackRect.center = new Vector2( sliderValRect.center.x, Mathf.Round( sliderValRect.center.y ));
  364. GUI.Label( sliderBackRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SliderStyle ) );
  365. value = GUIHorizontalSlider( sliderValRect, value, m_min, m_max, GUIStyle.none, UIUtils.RangedFloatSliderThumbStyle );
  366. }
  367. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  368. {
  369. base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
  370. m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType );
  371. if ( m_currentParameterType != PropertyType.Constant )
  372. return PropertyData( dataCollector.PortCategory );
  373. return IOUtils.Floatify( m_defaultValue );
  374. }
  375. public override string GetPropertyValue()
  376. {
  377. string value = UIUtils.PropertyFloatToString( m_defaultValue );
  378. if ( m_floatMode )
  379. {
  380. return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + value;
  381. }
  382. else
  383. {
  384. string min = UIUtils.PropertyFloatToString( m_min );
  385. string max = UIUtils.PropertyFloatToString( m_max );
  386. return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Range( " + min + " , " + max + ")) = " + value;
  387. }
  388. }
  389. public override void UpdateMaterial( Material mat )
  390. {
  391. base.UpdateMaterial( mat );
  392. if ( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction )
  393. {
  394. mat.SetFloat( m_propertyName, m_materialValue );
  395. }
  396. }
  397. public override void SetMaterialMode( Material mat , bool fetchMaterialValues )
  398. {
  399. base.SetMaterialMode( mat , fetchMaterialValues );
  400. if ( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) )
  401. {
  402. m_materialValue = mat.GetFloat( m_propertyName );
  403. }
  404. }
  405. public override void ForceUpdateFromMaterial( Material material )
  406. {
  407. if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) )
  408. {
  409. m_materialValue = material.GetFloat( m_propertyName );
  410. PreviewIsDirty = true;
  411. }
  412. }
  413. public override void ReadFromString( ref string[] nodeParams )
  414. {
  415. base.ReadFromString( ref nodeParams );
  416. m_defaultValue = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  417. if( UIUtils.CurrentShaderVersion() > 14101 )
  418. {
  419. m_materialValue = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  420. }
  421. m_min = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  422. m_max = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  423. SetFloatMode( m_min == m_max );
  424. }
  425. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  426. {
  427. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  428. IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultValue );
  429. IOUtils.AddFieldValueToString( ref nodeInfo, m_materialValue );
  430. IOUtils.AddFieldValueToString( ref nodeInfo, m_min );
  431. IOUtils.AddFieldValueToString( ref nodeInfo, m_max );
  432. }
  433. public override string GetPropertyValStr()
  434. {
  435. return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ?
  436. m_materialValue.ToString( Mathf.Abs( m_materialValue ) > 1000 ? Constants.PropertyBigFloatFormatLabel : Constants.PropertyFloatFormatLabel ) :
  437. m_defaultValue.ToString( Mathf.Abs( m_defaultValue ) > 1000 ? Constants.PropertyBigFloatFormatLabel : Constants.PropertyFloatFormatLabel );
  438. }
  439. public override void SetGlobalValue() { Shader.SetGlobalFloat( m_propertyName, m_defaultValue ); }
  440. public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalFloat( m_propertyName ); }
  441. public float Value
  442. {
  443. get { return m_defaultValue; }
  444. set { m_defaultValue = value; }
  445. }
  446. public void SetMaterialValueFromInline( float val )
  447. {
  448. m_materialValue = val;
  449. m_requireMaterialUpdate = true;
  450. }
  451. public override void GeneratePPSInfo( ref string propertyDeclaration, ref string propertySet )
  452. {
  453. string additionalHeaders = string.Empty;
  454. if( !m_floatMode )
  455. {
  456. additionalHeaders = string.Format( "Range( {0}, {1} ),", m_min, m_max );
  457. }
  458. propertyDeclaration += string.Format( ASEPPSHelperTool.PPSPropertyDecFormat, additionalHeaders, PropertyInspectorName,
  459. ASEPPSHelperTool.WireToPPSType[ WirePortDataType.FLOAT ], PropertyName, m_defaultValue );
  460. propertySet += string.Format( ASEPPSHelperTool.PPSPropertySetFormat, "Float", PropertyName );
  461. }
  462. }
  463. }