TFHCFlipBookUVAnimation.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. //
  4. // Custom Node Flipbook UV Animation
  5. // Donated by The Four Headed Cat - @fourheadedcat
  6. using UnityEngine;
  7. using UnityEditor;
  8. using System;
  9. namespace AmplifyShaderEditor
  10. {
  11. [Serializable]
  12. [NodeAttributes( "Flipbook UV Animation", "UV Coordinates", "Animate a Flipbook Texture Modifying UV Coordinates.", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat" )]
  13. public sealed class TFHCFlipBookUVAnimation : ParentNode
  14. {
  15. private const string TextureVerticalDirectionStr = "Texture Direction";
  16. private const string NegativeSpeedBehaviorStr = "If Negative Speed";
  17. [SerializeField]
  18. private int m_selectedTextureVerticalDirection = 0;
  19. [SerializeField]
  20. private int m_negativeSpeedBehavior = 0;
  21. [SerializeField]
  22. private readonly string[] m_textureVerticalDirectionValues = { "Top To Bottom", "Bottom To Top" };
  23. [SerializeField]
  24. private readonly string[] m_negativeSpeedBehaviorValues = { "Switch to Positive", "Reverse Animation" };
  25. protected override void CommonInit( int uniqueId )
  26. {
  27. base.CommonInit( uniqueId );
  28. AddInputPort( WirePortDataType.FLOAT2, false, "UV" );
  29. AddInputPort( WirePortDataType.FLOAT, false, "Columns" );
  30. AddInputPort( WirePortDataType.FLOAT, false, "Rows" );
  31. AddInputPort( WirePortDataType.FLOAT, false, "Speed" );
  32. AddInputPort( WirePortDataType.FLOAT, false, "Start Frame" );
  33. AddInputPort( WirePortDataType.FLOAT, false, "Time" );
  34. AddInputPort( WirePortDataType.FLOAT, false, "Max Frame" );
  35. m_inputPorts[ 6 ].FloatInternalData = -1;
  36. AddOutputVectorPorts( WirePortDataType.FLOAT2, "UV" );
  37. m_outputPorts[ 1 ].Name = "U";
  38. m_outputPorts[ 2 ].Name = "V";
  39. AddOutputPort( WirePortDataType.INT, "Frame" );
  40. m_textLabelWidth = 125;
  41. m_useInternalPortData = true;
  42. m_autoWrapProperties = true;
  43. m_previewShaderGUID = "04fe24be792bfd5428b92132d7cf0f7d";
  44. }
  45. public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
  46. {
  47. base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
  48. if( portId == 5 )
  49. {
  50. m_previewMaterialPassId = 1;
  51. }
  52. }
  53. public override void OnInputPortDisconnected( int portId )
  54. {
  55. base.OnInputPortDisconnected( portId );
  56. if( portId == 5 )
  57. {
  58. m_previewMaterialPassId = 0;
  59. }
  60. }
  61. public override void DrawProperties()
  62. {
  63. base.DrawProperties();
  64. EditorGUILayout.BeginVertical();
  65. m_selectedTextureVerticalDirection = EditorGUILayoutPopup( TextureVerticalDirectionStr, m_selectedTextureVerticalDirection, m_textureVerticalDirectionValues );
  66. m_negativeSpeedBehavior = EditorGUILayoutPopup( NegativeSpeedBehaviorStr, m_negativeSpeedBehavior, m_negativeSpeedBehaviorValues );
  67. EditorGUILayout.EndVertical();
  68. EditorGUILayout.HelpBox( "Flipbook UV Animation:\n\n - UV: Texture Coordinates to Flipbook.\n - Columns: number of Columns (X) of the Flipbook Texture.\n - Rows: number of Rows (Y) of the Flipbook Textures.\n - Speed: speed of the animation.\n - Texture Direction: set the vertical order of the texture tiles.\n - If Negative Speed: set the behavior when speed is negative.\n\n - Out: UV Coordinates.", MessageType.None );
  69. }
  70. public override void ReadFromString( ref string[] nodeParams )
  71. {
  72. base.ReadFromString( ref nodeParams );
  73. m_selectedTextureVerticalDirection = ( int ) int.Parse( GetCurrentParam( ref nodeParams ) );
  74. m_negativeSpeedBehavior = ( int ) int.Parse( GetCurrentParam( ref nodeParams ) );
  75. }
  76. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  77. {
  78. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  79. IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedTextureVerticalDirection );
  80. IOUtils.AddFieldValueToString( ref nodeInfo, m_negativeSpeedBehavior );
  81. }
  82. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  83. {
  84. // OPTIMIZATION NOTES
  85. //
  86. // round( fmod( x, y ) ) can be replaced with a faster
  87. // floor( frac( x / y ) * y + 0.5 ) => div can be muls with 1/y, almost always static/constant
  88. //
  89. if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) )
  90. return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) );
  91. string uv = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector );
  92. string columns = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector );
  93. if ( !m_inputPorts[ 1 ].IsConnected )
  94. columns = ( float.Parse( columns ) == 0f ? "1" : columns );
  95. string rows = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector );
  96. if ( !m_inputPorts[ 2 ].IsConnected )
  97. rows = ( float.Parse( rows ) == 0f ? "1" : rows );
  98. string speed = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector );
  99. string startframe = m_inputPorts[ 4 ].GeneratePortInstructions( ref dataCollector );
  100. string timer = m_inputPorts[ 5 ].IsConnected ? m_inputPorts[ 5 ].GeneratePortInstructions( ref dataCollector ) : "_Time[ 1 ]";
  101. string vcomment1 = "// *** BEGIN Flipbook UV Animation vars ***";
  102. string vcomment2 = "// Total tiles of Flipbook Texture";
  103. string vtotaltiles;
  104. if ( m_inputPorts[ 6 ].IsConnected || m_inputPorts[ 6 ].FloatInternalData >= 0 ) // MaxFrame
  105. {
  106. string maxframe = m_inputPorts[ 6 ].GeneratePortInstructions( ref dataCollector );
  107. vtotaltiles = "float fbtotaltiles" + OutputId + " = min( " + columns + " * " + rows + ", " + maxframe + " + 1 );";
  108. }
  109. else
  110. {
  111. vtotaltiles = "float fbtotaltiles" + OutputId + " = " + columns + " * " + rows + ";";
  112. }
  113. string vcomment3 = "// Offsets for cols and rows of Flipbook Texture";
  114. string vcolsoffset = "float fbcolsoffset" + OutputId + " = 1.0f / " + columns + ";";
  115. string vrowssoffset = "float fbrowsoffset" + OutputId + " = 1.0f / " + rows + ";";
  116. string vcomment4 = "// Speed of animation";
  117. string vspeed = string.Format( "float fbspeed{0} = {1} * {2};", OutputId,timer,speed);
  118. string vcomment5 = "// UV Tiling (col and row offset)";
  119. string vtiling = "float2 fbtiling" + OutputId + " = float2(fbcolsoffset" + OutputId + ", fbrowsoffset" + OutputId + ");";
  120. string vcomment6 = "// UV Offset - calculate current tile linear index, and convert it to (X * coloffset, Y * rowoffset)";
  121. string vcomment7 = "// Calculate current tile linear index";
  122. //float fbcurrenttileindex1 = round( fmod( fbspeed1 + _Float0, fbtotaltiles1 ) );
  123. string vcurrenttileindex = "float fbcurrenttileindex" + OutputId + " = floor( fmod( fbspeed" + OutputId + " + " + startframe + ", fbtotaltiles" + OutputId + ") );";
  124. string vcurrenttileindex1 = "fbcurrenttileindex" + OutputId + " += ( fbcurrenttileindex" + OutputId + " < 0) ? fbtotaltiles" + OutputId + " : 0;";
  125. //fbcurrenttileindex1 += ( fbcurrenttileindex1 < 0 ) ? fbtotaltiles1 : 0;
  126. //string vcurrenttileindex = "int fbcurrenttileindex" + m_uniqueId + " = (int)fmod( fbspeed" + m_uniqueId + ", fbtotaltiles" + m_uniqueId + ") + " + startframe + ";";
  127. string vcomment8 = "// Obtain Offset X coordinate from current tile linear index";
  128. //float fblinearindextox1 = round( fmod( fbcurrenttileindex1, 5.0 ) );
  129. //string voffsetx1 = "int fblinearindextox" + m_uniqueId + " = fbcurrenttileindex" + m_uniqueId + " % (int)" + columns + ";";
  130. string voffsetx1 = "float fblinearindextox" + OutputId + " = round ( fmod ( fbcurrenttileindex" + OutputId + ", " + columns + " ) );";
  131. string vcomment9 = String.Empty;
  132. string voffsetx2 = String.Empty;
  133. if ( m_negativeSpeedBehavior != 0 )
  134. {
  135. vcomment9 = "// Reverse X animation if speed is negative";
  136. voffsetx2 = "fblinearindextox" + OutputId + " = (" + speed + " > 0 ? fblinearindextox" + OutputId + " : (int)" + columns + " - fblinearindextox" + OutputId + ");";
  137. }
  138. string vcomment10 = "// Multiply Offset X by coloffset";
  139. string voffsetx3 = "float fboffsetx" + OutputId + " = fblinearindextox" + OutputId + " * fbcolsoffset" + OutputId + ";";
  140. string vcomment11 = "// Obtain Offset Y coordinate from current tile linear index";
  141. //float fblinearindextoy1 = round( fmod( ( fbcurrenttileindex1 - fblinearindextox1 ) / 5.0, 5.0 ) );
  142. string voffsety1 = "float fblinearindextoy" + OutputId + " = round( fmod( ( fbcurrenttileindex" + OutputId + " - fblinearindextox" + OutputId + " ) / " + columns + ", " + rows + " ) );";
  143. //string voffsety1 = "int fblinearindextoy" + m_uniqueId + " = (int)( ( fbcurrenttileindex" + m_uniqueId + " - fblinearindextox" + m_uniqueId + " ) / " + columns + " ) % (int)" + rows + ";";
  144. //string vcomment10 = "// Reverse Y to get from Top to Bottom";
  145. //string voffsety2 = "fblinearindextoy" + m_uniqueId + " = (int)" + rows + " - fblinearindextoy" + m_uniqueId + ";";
  146. string vcomment12 = String.Empty;
  147. string voffsety2 = String.Empty;
  148. if ( m_negativeSpeedBehavior == 0 )
  149. {
  150. if ( m_selectedTextureVerticalDirection == 0 )
  151. {
  152. vcomment12 = "// Reverse Y to get tiles from Top to Bottom";
  153. voffsety2 = "fblinearindextoy" + OutputId + " = (int)(" + rows + "-1) - fblinearindextoy" + OutputId + ";";
  154. }
  155. }
  156. else
  157. {
  158. string reverseanimationoperator = String.Empty;
  159. if ( m_selectedTextureVerticalDirection == 0 )
  160. {
  161. vcomment12 = "// Reverse Y to get tiles from Top to Bottom and Reverse Y animation if speed is negative";
  162. reverseanimationoperator = " < ";
  163. }
  164. else
  165. {
  166. vcomment12 = "// Reverse Y animation if speed is negative";
  167. reverseanimationoperator = " > ";
  168. }
  169. voffsety2 = "fblinearindextoy" + OutputId + " = (" + speed + reverseanimationoperator + " 0 ? fblinearindextoy" + OutputId + " : (int)" + rows + " - fblinearindextoy" + OutputId + ");";
  170. }
  171. string vcomment13 = "// Multiply Offset Y by rowoffset";
  172. string voffsety3 = "float fboffsety" + OutputId + " = fblinearindextoy" + OutputId + " * fbrowsoffset" + OutputId + ";";
  173. string vcomment14 = "// UV Offset";
  174. string voffset = "float2 fboffset" + OutputId + " = float2(fboffsetx" + OutputId + ", fboffsety" + OutputId + ");";
  175. //string voffset = "float2 fboffset" + m_uniqueId + " = float2( ( ( (int)fmod( fbspeed" + m_uniqueId + " , fbtotaltiles" + m_uniqueId + ") % (int)" + columns + " ) * fbcolsoffset" + m_OutputId + " ) , ( ( (int)" + rows + " - ( (int)( ( (int)fmod( fbspeed" + m_uniqueId + " , fbtotaltiles" + m_uniqueId + " ) - ( (int)fmod( fbspeed" + m_uniqueId + " , fbtotaltiles" + m_uniqueId + " ) % (int)" + columns + " ) ) / " + columns + " ) % (int)" + rows + " ) ) * fbrowsoffset" + m_uniqueId + " ) );";
  176. string vcomment15 = "// Flipbook UV";
  177. string vfbuv = "half2 fbuv" + OutputId + " = " + uv + " * fbtiling" + OutputId + " + fboffset" + OutputId + ";";
  178. string vcomment16 = "// *** END Flipbook UV Animation vars ***";
  179. string result = "fbuv" + OutputId;
  180. dataCollector.AddLocalVariable( UniqueId, vcomment1 );
  181. dataCollector.AddLocalVariable( UniqueId, vcomment2 );
  182. dataCollector.AddLocalVariable( UniqueId, vtotaltiles );
  183. dataCollector.AddLocalVariable( UniqueId, vcomment3 );
  184. dataCollector.AddLocalVariable( UniqueId, vcolsoffset );
  185. dataCollector.AddLocalVariable( UniqueId, vrowssoffset );
  186. dataCollector.AddLocalVariable( UniqueId, vcomment4 );
  187. dataCollector.AddLocalVariable( UniqueId, vspeed );
  188. dataCollector.AddLocalVariable( UniqueId, vcomment5 );
  189. dataCollector.AddLocalVariable( UniqueId, vtiling );
  190. dataCollector.AddLocalVariable( UniqueId, vcomment6 );
  191. dataCollector.AddLocalVariable( UniqueId, vcomment7 );
  192. dataCollector.AddLocalVariable( UniqueId, vcurrenttileindex );
  193. dataCollector.AddLocalVariable( UniqueId, vcurrenttileindex1 );
  194. dataCollector.AddLocalVariable( UniqueId, vcomment8 );
  195. dataCollector.AddLocalVariable( UniqueId, voffsetx1 );
  196. if ( m_negativeSpeedBehavior != 0 )
  197. {
  198. dataCollector.AddLocalVariable( UniqueId, vcomment9 );
  199. dataCollector.AddLocalVariable( UniqueId, voffsetx2 );
  200. }
  201. dataCollector.AddLocalVariable( UniqueId, vcomment10 );
  202. dataCollector.AddLocalVariable( UniqueId, voffsetx3 );
  203. dataCollector.AddLocalVariable( UniqueId, vcomment11 );
  204. dataCollector.AddLocalVariable( UniqueId, voffsety1 );
  205. if ( m_selectedTextureVerticalDirection == 0 || m_negativeSpeedBehavior != 0 )
  206. {
  207. dataCollector.AddLocalVariable( UniqueId, vcomment12 );
  208. dataCollector.AddLocalVariable( UniqueId, voffsety2 );
  209. }
  210. dataCollector.AddLocalVariable( UniqueId, vcomment13 );
  211. dataCollector.AddLocalVariable( UniqueId, voffsety3 );
  212. dataCollector.AddLocalVariable( UniqueId, vcomment14 );
  213. dataCollector.AddLocalVariable( UniqueId, voffset );
  214. dataCollector.AddLocalVariable( UniqueId, vcomment15 );
  215. dataCollector.AddLocalVariable( UniqueId, vfbuv );
  216. dataCollector.AddLocalVariable( UniqueId, vcomment16 );
  217. string frame = "int flipbookFrame" + OutputId + " = ( ( int )fbcurrenttileindex" + OutputId + ");";
  218. dataCollector.AddLocalVariable( UniqueId, frame );
  219. m_outputPorts[ 0 ].SetLocalValue( result, dataCollector.PortCategory );
  220. m_outputPorts[ 3 ].SetLocalValue( "flipbookFrame" + OutputId, dataCollector.PortCategory );
  221. return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory );
  222. }
  223. }
  224. }