EditableIf.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. //
  4. // Donated by BinaryCats
  5. // https://forum.unity.com/threads/best-tool-asset-store-award-amplify-shader-editor-node-based-shader-creation-tool.430959/page-60#post-3414465
  6. //////////////////////
  7. // README / HOW TO USE
  8. //////////////////////
  9. // Examples:
  10. //
  11. // Floats:
  12. //
  13. // x Equals value
  14. // EditableIf( _float1, Equalto, 1)
  15. // This will allow the value to be edited, if the property _float1 is equal to 1. (_float1==1)
  16. // Note: NotEqualTo is also a valid argument which will do the opposite of this example.EditableIf(_float1, NotEqualTo, 1) (NotEqualTo != 1)
  17. //
  18. // x Greater than value
  19. // EditableIf(_Float1,GreaterThan,1)
  20. // This will allow the value to be edited if the property _float1 is Greater than 1. (_float1>1)
  21. //
  22. // x Greater Than Or Equal to value
  23. // EditableIf(_Float1,GreaterThanOrEqualTo,1)
  24. // This will allow the value to be edited if the property _float1 is Greater than or equal to 1. (_float1>=1)
  25. //
  26. //
  27. // x Less Than value
  28. // EditableIf(_Float1,LessThan,1)
  29. // This will allow the value to be edited if the property _float1 is Less than 1. (_float1<1)
  30. //
  31. // x Less Than Or Equal to value
  32. // EditableIf(_Float1,LessThanOrEqualTo,1)
  33. // This will allow the value to be edited if the property _float1 is Less than or equal to 1. (_float1<=1)
  34. //
  35. //
  36. // Colour:
  37. //
  38. // x Equals r,g,b,a
  39. // EditableIf(_Color0,EqualTo,255,255,255,255)
  40. // This will allow the value to be edited, if the property _Color0 R,G,B and A value all Equal 255. (_Color0.R==255 && _Color0.G==255 & _Color0.B == 255 && _Color0.A == 255)
  41. //
  42. // x Equals alpha
  43. // EditableIf(_Color0,EqualTo,null,null,null,255)
  44. // This will allow the value to be edited, if the property _Color0 Alpha value is Equal to 255. (_Color0.A == 255)
  45. //
  46. // a Greater than blue
  47. // EditableIf(_Color0,GreaterThan,null,null,125)
  48. // This will allow the value to be edited, if the property _Color0 Blue value is Greater Than 125. (_Color0.B > 125)
  49. // Note: as I do not want to check the Red or Green Values, i have entered "null" for the parameter
  50. // Note: I have not inputted a value to check for Alpha, as i do not want to check it. Simularly, if I wanted to Only check the Red Value I could have used EditableIf(_Color0,GreaterThan,125)
  51. //
  52. // Like wise with floats GreaterThanOrEqualTo, LessThan, LessThanOrEqualTo
  53. //
  54. // Vector:
  55. // Vector Checks work the same as colour checks
  56. //
  57. // Texture:
  58. // x Does Not have a Texture
  59. // EditableIf(_TextureSample0,Equals,null)
  60. // This will allow the value to be edited, if the property _TextureSample0 does NOT have a texture
  61. //
  62. // x Does have a Texture
  63. // EditableIf(_TextureSample0,NotEqualTo,null)
  64. // This will allow the value to be edited, if the property _TextureSample0 does have a texture
  65. using UnityEngine;
  66. using UnityEditor;
  67. using System;
  68. namespace AmplifyShaderEditor
  69. {
  70. public enum ComparisonOperators
  71. {
  72. EqualTo, NotEqualTo, GreaterThan, LessThan, EqualsOrGreaterThan, EqualsOrLessThan, ContainsFlags,
  73. DoesNotContainsFlags
  74. }
  75. public class EditableIf : MaterialPropertyDrawer
  76. {
  77. ComparisonOperators op;
  78. string FieldName = "";
  79. object ExpectedValue;
  80. bool InputError;
  81. public EditableIf()
  82. {
  83. InputError = true;
  84. }
  85. public EditableIf( object fieldname, object comparison, object expectedvalue )
  86. {
  87. if ( expectedvalue.ToString().ToLower() == "true" )
  88. {
  89. expectedvalue = ( System.Single )1;
  90. }
  91. else if ( expectedvalue.ToString().ToLower() == "false" )
  92. {
  93. expectedvalue = ( System.Single )0;
  94. }
  95. Init( fieldname, comparison, expectedvalue );
  96. }
  97. public EditableIf( object fieldname, object comparison, object expectedvaluex, object expectedvaluey )
  98. {
  99. float? x = expectedvaluex as float?;
  100. float? y = expectedvaluey as float?;
  101. float? z = float.NegativeInfinity;
  102. float? w = float.NegativeInfinity;
  103. x = GetVectorValue( x );
  104. y = GetVectorValue( y );
  105. Init( fieldname, comparison, new Vector4( x.Value, y.Value, z.Value, w.Value ) );
  106. }
  107. public EditableIf( object fieldname, object comparison, object expectedvaluex, object expectedvaluey, object expectedvaluez )
  108. {
  109. float? x = expectedvaluex as float?;
  110. float? y = expectedvaluey as float?;
  111. float? z = expectedvaluez as float?;
  112. float? w = float.NegativeInfinity;
  113. x = GetVectorValue( x );
  114. y = GetVectorValue( y );
  115. z = GetVectorValue( z );
  116. Init( fieldname, comparison, new Vector4( x.Value, y.Value, z.Value, w.Value ) );
  117. }
  118. public EditableIf( object fieldname, object comparison, object expectedvaluex, object expectedvaluey, object expectedvaluez, object expectedvaluew )
  119. {
  120. var x = expectedvaluex as float?;
  121. var y = expectedvaluey as float?;
  122. var z = expectedvaluez as float?;
  123. var w = expectedvaluew as float?;
  124. x = GetVectorValue( x );
  125. y = GetVectorValue( y );
  126. z = GetVectorValue( z );
  127. w = GetVectorValue( w );
  128. Init( fieldname, comparison, new Vector4( x.Value, y.Value, z.Value, w.Value ) );
  129. }
  130. private void Init( object fieldname, object comparison, object expectedvalue )
  131. {
  132. FieldName = fieldname.ToString();
  133. var names = Enum.GetNames( typeof( ComparisonOperators ) );
  134. var name = comparison.ToString().ToLower().Replace( " ", "" );
  135. for ( int i = 0; i < names.Length; i++ )
  136. {
  137. if ( names[ i ].ToLower() == name )
  138. {
  139. op = ( ComparisonOperators )i;
  140. break;
  141. }
  142. }
  143. ExpectedValue = expectedvalue;
  144. }
  145. private static float? GetVectorValue( float? x )
  146. {
  147. if ( x.HasValue == false )
  148. {
  149. x = float.NegativeInfinity;
  150. }
  151. return x;
  152. }
  153. // Draw the property inside the given rect
  154. public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor )
  155. {
  156. if ( InputError )
  157. {
  158. EditorGUI.LabelField( position, "EditableIf Attribute Error: Input parameters are invalid!" );
  159. return;
  160. }
  161. var LHSprop = MaterialEditor.GetMaterialProperty( prop.targets, FieldName );
  162. if ( string.IsNullOrEmpty( LHSprop.name ) )
  163. {
  164. LHSprop = MaterialEditor.GetMaterialProperty( prop.targets, "_" + FieldName.Replace( " ", "" ) );
  165. if ( string.IsNullOrEmpty( LHSprop.name ) )
  166. {
  167. EditorGUI.LabelField( position, "EditableIf Attribute Error: " + FieldName + " Does not exist!" );
  168. return;
  169. }
  170. }
  171. object LHSVal = null;
  172. bool test = false;
  173. switch ( LHSprop.type )
  174. {
  175. case MaterialProperty.PropType.Color:
  176. case MaterialProperty.PropType.Vector:
  177. LHSVal = LHSprop.type == MaterialProperty.PropType.Color ? ( Vector4 )LHSprop.colorValue : LHSprop.vectorValue;
  178. var v4 = ExpectedValue as Vector4?;
  179. v4 = v4.HasValue ? v4 : new Vector4( ( System.Single )ExpectedValue, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity );
  180. if ( LHSprop.type == MaterialProperty.PropType.Color )
  181. {
  182. test = VectorCheck( ( Vector4 )LHSVal, op, v4 / 255 );
  183. }
  184. else
  185. test = VectorCheck( ( Vector4 )LHSVal, op, v4 );
  186. break;
  187. case MaterialProperty.PropType.Range:
  188. case MaterialProperty.PropType.Float:
  189. LHSVal = LHSprop.floatValue;
  190. test = ( Check( LHSVal, op, ExpectedValue ) );
  191. break;
  192. case MaterialProperty.PropType.Texture:
  193. LHSVal = LHSprop.textureValue;
  194. test = ( CheckObject( LHSVal, op, ExpectedValue ) );
  195. break;
  196. }
  197. GUI.enabled = test;
  198. editor.DefaultShaderProperty( position, prop, label );
  199. GUI.enabled = true;
  200. }
  201. private bool VectorCheck( Vector4 LHS, ComparisonOperators op, object expectedValue )
  202. {
  203. var RHS = ( Vector4 )expectedValue;
  204. if ( RHS.x != float.NegativeInfinity )
  205. {
  206. if ( !Check( LHS.x, op, RHS.x ) )
  207. return false;
  208. }
  209. if ( RHS.y != float.NegativeInfinity )
  210. {
  211. if ( !Check( LHS.y, op, RHS.y ) )
  212. return false;
  213. }
  214. if ( RHS.z != float.NegativeInfinity )
  215. {
  216. if ( !Check( LHS.z, op, RHS.z ) )
  217. return false;
  218. }
  219. if ( RHS.w != float.NegativeInfinity )
  220. {
  221. if ( !Check( LHS.w, op, RHS.w ) )
  222. return false;
  223. }
  224. return true;
  225. }
  226. protected bool Check( object LHS, ComparisonOperators op, object RHS )
  227. {
  228. if ( !( LHS is IComparable ) || !( RHS is IComparable ) )
  229. throw new Exception( "Check using non basic type" );
  230. switch ( op )
  231. {
  232. case ComparisonOperators.EqualTo:
  233. return ( ( IComparable )LHS ).CompareTo( RHS ) == 0;
  234. case ComparisonOperators.NotEqualTo:
  235. return ( ( IComparable )LHS ).CompareTo( RHS ) != 0;
  236. case ComparisonOperators.EqualsOrGreaterThan:
  237. return ( ( IComparable )LHS ).CompareTo( RHS ) >= 0;
  238. case ComparisonOperators.EqualsOrLessThan:
  239. return ( ( IComparable )LHS ).CompareTo( RHS ) <= 0;
  240. case ComparisonOperators.GreaterThan:
  241. return ( ( IComparable )LHS ).CompareTo( RHS ) > 0;
  242. case ComparisonOperators.LessThan:
  243. return ( ( IComparable )LHS ).CompareTo( RHS ) < 0;
  244. case ComparisonOperators.ContainsFlags:
  245. return ( ( int )LHS & ( int )RHS ) != 0; // Dont trust LHS values, it has been casted to a char and then to an int again, first bit will be the sign
  246. case ComparisonOperators.DoesNotContainsFlags:
  247. return ( ( ( int )LHS & ( int )RHS ) == ( int )LHS ); // Dont trust LHS values, it has been casted to a char and then to an int again, first bit will be the sign
  248. default:
  249. break;
  250. }
  251. return false;
  252. }
  253. private bool CheckObject( object LHS, ComparisonOperators comparasonOperator, object RHS )
  254. {
  255. switch ( comparasonOperator )
  256. {
  257. case ComparisonOperators.EqualTo:
  258. return ( LHS == null );
  259. case ComparisonOperators.NotEqualTo:
  260. return ( LHS != null );
  261. }
  262. return true;
  263. }
  264. }
  265. }