ParameterFiddler.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /*
  2. This script plays with a renderer's material parameters.
  3. Included is both an automatic mode as well as a mode that lets
  4. users change parameters.
  5. Email :: thomas.ir.rasor@gmail.com
  6. */
  7. using UnityEngine;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using gui = UnityEngine.GUILayout;
  11. [System.Serializable]
  12. public class MaterialParameter
  13. {
  14. public string parameterName = "_Parameter";
  15. public string displayName = "Parameter Value";
  16. public int repeat = 2;
  17. public enum MaterialParamType { number, color, texture, vector }
  18. public MaterialParamType type = MaterialParamType.number;
  19. public float min = 0f;
  20. public float max = 1f;
  21. public string label_x = "X", label_y = "Y", label_z = "Z", label_w = "W";
  22. public Vector4 min4 = Vector4.zero;
  23. public Vector4 max4 = Vector4.one;
  24. public List<Texture> textures = new List<Texture>();
  25. [System.NonSerialized]
  26. public float value;
  27. [System.NonSerialized]
  28. public Color valueC;
  29. [System.NonSerialized]
  30. public Vector4 value4;
  31. public int texID { get { return Mathf.FloorToInt( Mathf.Repeat( value * textures.Count , textures.Count ) ); } }
  32. public MaterialParameter()
  33. {
  34. parameterName = "_Parameter";
  35. displayName = "Parameter Value";
  36. repeat = 1;
  37. type = MaterialParamType.number;
  38. min = 0f;
  39. max = 1f;
  40. min4 = Vector4.zero;
  41. max4 = Vector4.one;
  42. textures = new List<Texture>();
  43. }
  44. public MaterialParameter( MaterialParameter other )
  45. {
  46. parameterName = other.parameterName;
  47. displayName = other.displayName;
  48. repeat = other.repeat;
  49. type = other.type;
  50. min = other.min;
  51. max = other.max;
  52. min4 = other.min4;
  53. max4 = other.max4;
  54. textures = new List<Texture>( other.textures );
  55. }
  56. }
  57. public class ParameterFiddler : MonoBehaviour
  58. {
  59. public Material sourceMaterial;
  60. Material material;
  61. public bool automatic = true;
  62. public bool showMenu = false;
  63. public float menuVis = 0f;
  64. [Range(0.25f,5f)]
  65. public float fiddleTime = 3f;
  66. public List<MaterialParameter> parameters = new List<MaterialParameter>();
  67. public Texture sliderBar , sliderThumb;
  68. GUIStyle sliderStyle , sliderThumbStyle;
  69. int currentParameterIndex = 0;
  70. float t = 0f;
  71. float tf { get { return t / fiddleTime; } }
  72. bool fiddling;
  73. void Start ()
  74. {
  75. material = new Material( sourceMaterial );
  76. GetComponent<Renderer>().material = material;
  77. if ( parameters.Count > 0 && automatic )
  78. StartCoroutine( Unfiddle() );
  79. ManualRead();
  80. }
  81. void Update ()
  82. {
  83. if ( automatic )
  84. {
  85. if ( fiddling )
  86. t += Time.deltaTime;
  87. if ( parameters[ currentParameterIndex ].parameterName != "_Phase" )
  88. material.SetFloat( "_Phase" , 0.5f );
  89. }
  90. else
  91. {
  92. if (showMenu)
  93. menuVis = Mathf.Lerp( menuVis , ( Input.mousePosition.x > Screen.width - Screen.width * 0.2f ) ? 1f : 0f , Time.deltaTime * 10f );
  94. int lastId = currentParameterIndex;
  95. if ( Input.GetKeyDown( KeyCode.A ) )
  96. currentParameterIndex = ( int )Mathf.Repeat( currentParameterIndex - 1 , parameters.Count - 1 );
  97. if ( Input.GetKeyDown( KeyCode.D ) )
  98. currentParameterIndex = ( int )Mathf.Repeat( currentParameterIndex + 1 , parameters.Count - 1 );
  99. if ( lastId != currentParameterIndex )
  100. ManualRead();
  101. ManualFiddle();
  102. }
  103. }
  104. public void ManualRead ()
  105. {
  106. if ( currentParameterIndex < 0 ) return;
  107. MaterialParameter param = parameters[ currentParameterIndex ];
  108. if ( material.HasProperty( param.parameterName ) )
  109. {
  110. switch ( param.type )
  111. {
  112. case MaterialParameter.MaterialParamType.number:
  113. param.value = material.GetFloat( param.parameterName );
  114. break;
  115. case MaterialParameter.MaterialParamType.color:
  116. param.valueC = material.GetColor( param.parameterName );
  117. break;
  118. case MaterialParameter.MaterialParamType.vector:
  119. param.value4 = material.GetVector( param.parameterName );
  120. break;
  121. case MaterialParameter.MaterialParamType.texture:
  122. break;
  123. default:break;
  124. }
  125. }
  126. }
  127. public void ManualFiddle()
  128. {
  129. if ( currentParameterIndex < 0 ) return;
  130. MaterialParameter param = parameters[ currentParameterIndex ];
  131. if ( material.HasProperty( param.parameterName ) )
  132. {
  133. switch ( param.type )
  134. {
  135. case MaterialParameter.MaterialParamType.number:
  136. material.SetFloat( param.parameterName , param.value );
  137. break;
  138. case MaterialParameter.MaterialParamType.color:
  139. material.SetColor( param.parameterName , param.valueC );
  140. break;
  141. case MaterialParameter.MaterialParamType.vector:
  142. material.SetVector( param.parameterName , param.value4 );
  143. break;
  144. case MaterialParameter.MaterialParamType.texture:
  145. if ( param.textures.Count > 0 )
  146. material.SetTexture( param.parameterName , param.textures[ param.texID ] );
  147. break;
  148. default: break;
  149. }
  150. }
  151. }
  152. public void FiddleParameter()
  153. {
  154. MaterialParameter p = parameters[ currentParameterIndex ];
  155. if ( material.HasProperty( p.parameterName ) )
  156. {
  157. switch ( p.type )
  158. {
  159. case MaterialParameter.MaterialParamType.number: StartCoroutine( FiddleFloat( p ) ); break;
  160. case MaterialParameter.MaterialParamType.color: StartCoroutine( FiddleColor( p ) ); break;
  161. case MaterialParameter.MaterialParamType.texture: StartCoroutine( FiddleTexture( p ) ); break;
  162. case MaterialParameter.MaterialParamType.vector: StartCoroutine( FiddleVector( p ) ); break;
  163. }
  164. }
  165. else
  166. {
  167. Debug.Log( "Material Parameter Not Found: " + p.parameterName );
  168. }
  169. }
  170. public IEnumerator FiddleFloat( MaterialParameter p )
  171. {
  172. float o = material.GetFloat( p.parameterName );
  173. p.value = o;
  174. float i = 0f;
  175. while ( i < 1f )
  176. {
  177. i += Time.deltaTime * 6f;
  178. p.value = Mathf.Lerp( p.value , 0f , i );
  179. material.SetFloat( p.parameterName , p.value );
  180. yield return new WaitForEndOfFrame();
  181. }
  182. while ( t < fiddleTime )
  183. {
  184. float v = -Mathf.Cos( tf * Mathf.PI * 1.5f * p.repeat ) * 0.5f + 0.5f;
  185. p.value = Mathf.Lerp( p.min , p.max , v );
  186. material.SetFloat( p.parameterName , p.value );
  187. yield return new WaitForEndOfFrame();
  188. }
  189. i = 0f;
  190. while (i < 1f)
  191. {
  192. i += Time.deltaTime * 6f;
  193. p.value = Mathf.Lerp( p.value , o , i );
  194. material.SetFloat( p.parameterName , p.value );
  195. yield return new WaitForEndOfFrame();
  196. }
  197. currentParameterIndex = currentParameterIndex + 1;
  198. StartCoroutine( Unfiddle() );
  199. }
  200. public IEnumerator FiddleColor( MaterialParameter param )
  201. {
  202. Color o = material.GetColor( param.parameterName );
  203. Color c = o;
  204. float i = 0f;
  205. while ( i < 1f )
  206. {
  207. i += Time.deltaTime * 6f;
  208. material.SetColor( param.parameterName , Color.HSVToRGB( 0f , 0.9f , 0.9f ) );
  209. yield return new WaitForEndOfFrame();
  210. }
  211. while ( t < fiddleTime )
  212. {
  213. param.valueC = Color.HSVToRGB( Mathf.Repeat( tf * param.repeat , 1f ) , 0.9f , 0.9f );
  214. material.SetColor( param.parameterName , param.valueC );
  215. yield return new WaitForEndOfFrame();
  216. }
  217. i = 0f;
  218. while ( i < 1f )
  219. {
  220. i += Time.deltaTime * 6f;
  221. material.SetColor( param.parameterName , Color.Lerp( c , o , i ) );
  222. yield return new WaitForEndOfFrame();
  223. }
  224. material.SetColor( param.parameterName , o );
  225. currentParameterIndex = currentParameterIndex + 1;
  226. StartCoroutine( Unfiddle() );
  227. }
  228. public IEnumerator FiddleTexture( MaterialParameter param )
  229. {
  230. Texture o = material.GetTexture( param.parameterName );
  231. while ( t < fiddleTime )
  232. {
  233. int id = ( int )Mathf.Floor( tf * param.textures.Count );
  234. param.value = Mathf.Clamp01( (float)id / (float)param.textures.Count );
  235. material.SetTexture( param.parameterName , param.textures[ id ] );
  236. yield return new WaitForEndOfFrame();
  237. }
  238. material.SetTexture( param.parameterName , o );
  239. currentParameterIndex = currentParameterIndex + 1;
  240. StartCoroutine( Unfiddle() );
  241. }
  242. public IEnumerator FiddleVector( MaterialParameter param )
  243. {
  244. Vector4 o = material.GetVector( param.parameterName );
  245. while ( t < fiddleTime )
  246. {
  247. float v = -Mathf.Cos( tf * Mathf.PI * 1.5f * param.repeat ) * 0.5f + 0.5f;
  248. param.value4 = Vector4.Lerp( param.min4 , param.max4 , v );
  249. material.SetVector( param.parameterName , param.value4 );
  250. yield return new WaitForEndOfFrame();
  251. }
  252. material.SetVector( param.parameterName , o );
  253. currentParameterIndex = currentParameterIndex + 1;
  254. StartCoroutine( Unfiddle() );
  255. }
  256. IEnumerator Unfiddle ()
  257. {
  258. fiddling = false;
  259. yield return new WaitForSeconds( 1f );
  260. t = 0f;
  261. fiddling = true;
  262. FiddleParameter();
  263. }
  264. GUIStyle nameStyle, nameStyle2;
  265. GUIStyle buttonStyle;
  266. GUIStyle scrollStyle;
  267. GUIStyle boxStyle;
  268. public void SetupGUIStyles()
  269. {
  270. nameStyle = new GUIStyle( GUI.skin.box );
  271. if ( sliderBar != null ) nameStyle.normal.background = (Texture2D)sliderBar;
  272. nameStyle.normal.textColor = Color.black;
  273. nameStyle.stretchWidth = true;
  274. nameStyle.margin = new RectOffset( 0 , 0 , 0 , 0 );
  275. nameStyle.padding = new RectOffset( 4 , 4 , 3 , 3 );
  276. nameStyle.overflow.bottom = 1;
  277. nameStyle.overflow.right = 1;
  278. nameStyle.wordWrap = false;
  279. nameStyle.alignment = TextAnchor.LowerLeft;
  280. nameStyle2 = new GUIStyle( nameStyle );
  281. nameStyle2.alignment = TextAnchor.LowerCenter;
  282. boxStyle = new GUIStyle( GUI.skin.box );
  283. if ( sliderBar != null ) boxStyle.normal.background = ( Texture2D )sliderBar;
  284. boxStyle.margin = new RectOffset( 0 , 0 , 0 , 0 );
  285. boxStyle.padding = new RectOffset( 0 , 0 , 0 , 0 );
  286. boxStyle.overflow.top = 1;
  287. boxStyle.overflow.right = 1;
  288. boxStyle.overflow.bottom = 1;
  289. scrollStyle = new GUIStyle( GUI.skin.scrollView );
  290. scrollStyle.normal.background = GUI.skin.box.normal.background;
  291. scrollStyle.border = GUI.skin.box.border;
  292. scrollStyle.margin = new RectOffset( 0 , 0 , 0 , 0 );
  293. scrollStyle.padding = new RectOffset( 8 , 8 , 8 , 8 );
  294. scrollStyle.stretchWidth = true;
  295. buttonStyle = new GUIStyle( GUI.skin.button );
  296. buttonStyle.normal.background = GUI.skin.box.normal.background;
  297. buttonStyle.normal.textColor = Color.black;
  298. buttonStyle.hover.background = GUI.skin.box.normal.background;
  299. buttonStyle.hover.textColor = Color.black;
  300. buttonStyle.active.background = GUI.skin.box.normal.background;
  301. buttonStyle.active.textColor = Color.black;
  302. }
  303. Color baseGUIColor = Color.white;
  304. void OnGUI()
  305. {
  306. baseGUIColor = GUI.color;
  307. SetupGUIStyles();
  308. if ( parameters.Count > 0 && currentParameterIndex < parameters.Count && currentParameterIndex > -1 )
  309. {
  310. GUIStyle labelStyle = new GUIStyle( GUI.skin.label );
  311. labelStyle.alignment = TextAnchor.LowerCenter;
  312. labelStyle.fontStyle = FontStyle.Bold;
  313. labelStyle.fontSize = 24;
  314. labelStyle.clipping = TextClipping.Overflow;
  315. labelStyle.wordWrap = false;
  316. sliderStyle = new GUIStyle( GUI.skin.horizontalSlider );
  317. sliderThumbStyle = new GUIStyle( GUI.skin.horizontalSliderThumb );
  318. if ( sliderBar != null ) sliderStyle.normal.background = ( Texture2D )sliderBar;
  319. if ( sliderThumb != null )
  320. {
  321. sliderThumbStyle.normal.background = ( Texture2D )sliderThumb;
  322. sliderThumbStyle.hover.background = ( Texture2D )sliderThumb;
  323. sliderThumbStyle.active.background = ( Texture2D )sliderThumb;
  324. }
  325. MaterialParameter p = parameters[ currentParameterIndex ];
  326. gui.BeginArea( new Rect( 0f , 0f , Screen.width , Screen.height ) );
  327. gui.Space( 30f );
  328. gui.BeginHorizontal();
  329. gui.FlexibleSpace();
  330. gui.Label( fiddling || !automatic ? p.displayName : "" , labelStyle , gui.Height( 40f ) );
  331. gui.FlexibleSpace();
  332. gui.EndHorizontal();
  333. gui.FlexibleSpace();
  334. gui.BeginHorizontal();
  335. gui.Space( Screen.width * 0.25f );
  336. gui.BeginVertical();
  337. labelStyle.fontSize = 14;
  338. if ( automatic )
  339. {
  340. switch (p.type)
  341. {
  342. case MaterialParameter.MaterialParamType.number:
  343. Slider( "" , p.value );
  344. break;
  345. case MaterialParameter.MaterialParamType.texture:
  346. Slider( "" , p.value );
  347. break;
  348. case MaterialParameter.MaterialParamType.vector:
  349. Slider( p.value4 , p.min4 , p.max4 );
  350. break;
  351. case MaterialParameter.MaterialParamType.color:
  352. Slider( p.valueC );
  353. break;
  354. }
  355. }
  356. else
  357. {
  358. switch ( p.type )
  359. {
  360. case MaterialParameter.MaterialParamType.number:
  361. Slider( "" , ref p.value , p.min , p.max );
  362. break;
  363. case MaterialParameter.MaterialParamType.texture:
  364. Slider( p.textures[ p.texID ].name , ref p.value );
  365. break;
  366. case MaterialParameter.MaterialParamType.vector:
  367. Slider( ref p.value4 , p.min4 , p.max4 , p.label_x , p.label_y , p.label_z , p.label_w );
  368. break;
  369. case MaterialParameter.MaterialParamType.color:
  370. Slider( ref p.valueC );
  371. break;
  372. }
  373. }
  374. gui.EndVertical();
  375. gui.Space( Screen.width * 0.25f );
  376. gui.EndHorizontal();
  377. gui.Space( 30f );
  378. gui.EndArea();
  379. }
  380. if ( parameters.Count > 0 )
  381. {
  382. float w = 150f;
  383. float w2 = 8f;
  384. float w3 = (parameters.Count + 1) * 21f + 1f;
  385. gui.BeginArea( new Rect( Screen.width - w * menuVis - w2 , Screen.height * 0.5f - w3 * 0.5f , w + w2 , w3 ) );
  386. gui.BeginHorizontal();
  387. gui.Label( "" , boxStyle , gui.Width( w2 ) , gui.ExpandHeight( true ) );
  388. gui.BeginVertical();
  389. gui.Label( "Parameters" , nameStyle2 );
  390. for ( int i = 0 ; i < parameters.Count ; i++ )
  391. {
  392. GUI.color = currentParameterIndex == i ? new Color( 1f , 1f , 1f , 1f ) : new Color( 1f , 1f , 1f , 0.6f );
  393. MaterialParameter p2 = parameters[ i ];
  394. if ( gui.Button( p2.displayName , nameStyle ) )
  395. {
  396. currentParameterIndex = currentParameterIndex == i ? -1 : i;
  397. ManualRead();
  398. }
  399. GUI.color = baseGUIColor;
  400. }
  401. gui.EndVertical();
  402. gui.EndHorizontal();
  403. gui.EndArea();
  404. }
  405. }
  406. public void Slider( Color color )
  407. {
  408. GUI.color = color * 0.5f + Color.white * 0.5f;
  409. Slider( "R" , color.r );
  410. Slider( "G" , color.g );
  411. Slider( "B" , color.b );
  412. Slider( "A" , color.a );
  413. GUI.color = baseGUIColor;
  414. }
  415. public void Slider( ref Color color )
  416. {
  417. GUI.color = color * 0.8f + Color.white * 0.2f;
  418. Slider( "R" , ref color.r );
  419. Slider( "G" , ref color.g );
  420. Slider( "B" , ref color.b );
  421. Slider( "A" , ref color.a );
  422. GUI.color = baseGUIColor;
  423. }
  424. public void Slider( Vector4 v , Vector4 min4 , Vector4 max4 )
  425. {
  426. Slider( "X" , v.x , min4.x , max4.x );
  427. Slider( "Y" , v.y , min4.y , max4.y );
  428. Slider( "Z" , v.z , min4.z , max4.z );
  429. Slider( "W" , v.w , min4.w , max4.w );
  430. }
  431. public void Slider( ref Vector4 v , Vector4 min4 , Vector4 max4 , string xLabel = "X" , string yLabel = "Y" , string zLabel = "Z" , string wLabel = "W" )
  432. {
  433. if ( !string.IsNullOrEmpty( xLabel ) )
  434. Slider( xLabel , ref v.x , min4.x , max4.x );
  435. if ( !string.IsNullOrEmpty( yLabel ) )
  436. Slider( yLabel , ref v.y , min4.y , max4.y );
  437. if ( !string.IsNullOrEmpty( zLabel ) )
  438. Slider( zLabel , ref v.z , min4.z , max4.z );
  439. if ( !string.IsNullOrEmpty( wLabel ) )
  440. Slider( wLabel , ref v.w , min4.w , max4.w );
  441. }
  442. public void Slider( string label , float v , float min = 0f , float max = 1f )
  443. {
  444. gui.BeginHorizontal();
  445. gui.FlexibleSpace();
  446. if(label.Length > 0)
  447. gui.Label( label , gui.Width( Screen.width * 0.3f ) );
  448. gui.HorizontalSlider( v , min , max , sliderStyle , sliderThumbStyle , gui.Width( Screen.width*0.3f ) );
  449. gui.FlexibleSpace();
  450. gui.EndHorizontal();
  451. }
  452. public void Slider( string label , ref float v , float min = 0f , float max = 1f )
  453. {
  454. gui.BeginHorizontal();
  455. gui.FlexibleSpace();
  456. if(label.Length > 0)
  457. gui.Label( label , gui.Width( Screen.width * 0.3f ) );
  458. v = gui.HorizontalSlider( v , min , max , sliderStyle , sliderThumbStyle , gui.Width( Screen.width * 0.3f ) );
  459. gui.FlexibleSpace();
  460. gui.EndHorizontal();
  461. }
  462. }