You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
11 KiB

  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using System;
  4. using System.Text.RegularExpressions;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. namespace AmplifyShaderEditor
  8. {
  9. /*ase_pass_options OLDEST
  10. DefineOnConnected:portId:definevalue
  11. DefineOnUnconnected:portId:definevalue
  12. Options:name:defaultOption:opt0:opt1:opt2
  13. SetVisible:PortId:OptionName:OptionValue
  14. */
  15. /*ase_pass_options OLD
  16. Option:Option Name:UI Type:Default:Item0,Item1,Item3...ItemN
  17. Action:Action Type:Action Data:ConditionA && ConditionB || ConditionC:
  18. */
  19. /*ase_pass_options:UniqueId:PropagateDataToHiddenPasses
  20. Option:Color Offset:A,B,C:A
  21. A:ShowPort:My Port Name
  22. B,C:HidePort:My Port Name
  23. B:SetDefine:MY_DEFINE
  24. C:SetDefine:MY_COLOR_DEFINE
  25. Option:My Other Option:True,False
  26. True:ShowOption:Color Offset
  27. False:HideOption:Color Offset
  28. Port:My Port Name
  29. On:SetDefine:MY_COLOR_DEFINE
  30. Off:UnsetDefine:MY_COLOR_DEFINE
  31. */
  32. public enum AseOptionsUIWidget
  33. {
  34. Dropdown,
  35. Toggle
  36. }
  37. public enum AseOptionsType
  38. {
  39. Option,
  40. Port
  41. }
  42. public enum AseOptionsActionType
  43. {
  44. ShowOption,
  45. HideOption,
  46. HidePort,
  47. ShowPort,
  48. SetDefine,
  49. UnsetDefine,
  50. ExcludePass
  51. }
  52. public enum AseOptionsSetup
  53. {
  54. CopyOptionsFromMainPass,
  55. Id,
  56. Name
  57. }
  58. [Serializable]
  59. public class TemplateActionItem
  60. {
  61. public AseOptionsActionType ActionType;
  62. public string ActionData = string.Empty;
  63. public int ActionDataIdx = -1;
  64. public override string ToString()
  65. {
  66. return ActionType + " " + ActionData + " " + ActionDataIdx;
  67. }
  68. }
  69. [Serializable]
  70. public class TemplateActionItemGrid
  71. {
  72. [Serializable]
  73. public class TemplateActionItemRow
  74. {
  75. public TemplateActionItem[] Columns;
  76. }
  77. public TemplateActionItemRow[] Rows;
  78. public TemplateActionItemGrid( int rowsCount )
  79. {
  80. Rows = new TemplateActionItemRow[ rowsCount ];
  81. }
  82. public TemplateActionItem this[ int row, int column ]
  83. {
  84. get { return Rows[ row ].Columns[ column ]; }
  85. set { Rows[ row ].Columns[ column ] = value; }
  86. }
  87. public TemplateActionItem[] this[ int row ]
  88. {
  89. get { return Rows[ row ].Columns; }
  90. set
  91. {
  92. if( Rows[ row ] == null )
  93. Rows[ row ] = new TemplateActionItemRow();
  94. Rows[ row ].Columns = value;
  95. }
  96. }
  97. }
  98. [Serializable]
  99. public class TemplateOptionsItem
  100. {
  101. public AseOptionsType Type;
  102. public AseOptionsUIWidget UIWidget;
  103. public string Id = string.Empty;
  104. public string Name = string.Empty;
  105. public string DefaultOption = string.Empty;
  106. public string[] Options = null;
  107. public TemplateActionItemGrid ActionsPerOption = null;
  108. [SerializeField]
  109. private int m_defaultOptionIndex = -1;
  110. public int OptionIndexFor( string option )
  111. {
  112. for( int i = 0; i < Options.Length; i++ )
  113. {
  114. if( Options[ i ].Equals( option ) )
  115. {
  116. return i;
  117. }
  118. }
  119. Debug.LogWarning( "Couldn't find index for option: " + option );
  120. return 0;
  121. }
  122. public int DefaultOptionIndex
  123. {
  124. get
  125. {
  126. if( m_defaultOptionIndex > -1 )
  127. return m_defaultOptionIndex;
  128. for( int i = 0; i < Options.Length; i++ )
  129. {
  130. if( Options[ i ].Equals( DefaultOption ) )
  131. {
  132. m_defaultOptionIndex = i;
  133. return i;
  134. }
  135. }
  136. Debug.LogWarning( "Couldn't find index for default option: " + DefaultOption );
  137. return 0;
  138. }
  139. }
  140. }
  141. [Serializable]
  142. public class TemplateOptionsContainer
  143. {
  144. public bool Enabled = false;
  145. public string Body = string.Empty;
  146. public int Index = -1;
  147. public int Id = -1;
  148. public string Name = string.Empty;
  149. public bool CopyOptionsFromMainPass = false;
  150. public TemplateOptionsItem[] Options = null;
  151. }
  152. public class TemplateOptionsToolsHelper
  153. {
  154. public const string PassOptionsMainPattern = @"\/\*ase_pass_options:([\w:= ]*)[\n]([\w: \t;\n&|,_]*)\*\/";
  155. public static Dictionary<string, AseOptionsSetup> AseOptionsSetupDict = new Dictionary<string, AseOptionsSetup>()
  156. {
  157. { "CopyOptionsFromMainPass",AseOptionsSetup.CopyOptionsFromMainPass},
  158. { "Id",AseOptionsSetup.Id},
  159. { "Name",AseOptionsSetup.Name},
  160. };
  161. public static Dictionary<string, AseOptionsUIWidget> AseOptionsUITypeDict = new Dictionary<string, AseOptionsUIWidget>()
  162. {
  163. { "Dropdown",AseOptionsUIWidget.Dropdown },
  164. { "Toggle", AseOptionsUIWidget.Toggle }
  165. };
  166. public static Dictionary<string, AseOptionsActionType> AseOptionsActionTypeDict = new Dictionary<string, AseOptionsActionType>()
  167. {
  168. {"ShowOption", AseOptionsActionType.ShowOption },
  169. {"HideOption", AseOptionsActionType.HideOption },
  170. {"HidePort", AseOptionsActionType.HidePort },
  171. {"ShowPort", AseOptionsActionType.ShowPort },
  172. {"SetDefine", AseOptionsActionType.SetDefine },
  173. {"UnsetDefine", AseOptionsActionType.UnsetDefine },
  174. {"ExcludePass", AseOptionsActionType.ExcludePass }
  175. };
  176. public static TemplateOptionsContainer GenerateOptionsContainer( string data )
  177. {
  178. TemplateOptionsContainer optionsContainer = new TemplateOptionsContainer();
  179. Match match = Regex.Match( data, PassOptionsMainPattern );
  180. optionsContainer.Enabled = match.Success;
  181. if( match.Success )
  182. {
  183. optionsContainer.Body = match.Value;
  184. optionsContainer.Index = match.Index;
  185. List<TemplateOptionsItem> optionItemsList = new List<TemplateOptionsItem>();
  186. List<List<TemplateActionItem>> actionItemsList = new List<List<TemplateActionItem>>();
  187. Dictionary<string, int> optionItemToIndex = new Dictionary<string, int>();
  188. TemplateOptionsItem currentOption = null;
  189. //OPTIONS OVERALL SETUP
  190. string[] setupLines = match.Groups[ 1 ].Value.Split( ':' );
  191. for( int i = 0; i < setupLines.Length; i++ )
  192. {
  193. if( AseOptionsSetupDict.ContainsKey( setupLines[ i ] ) )
  194. {
  195. AseOptionsSetup setup = AseOptionsSetupDict[ setupLines[ i ] ];
  196. switch( setup )
  197. {
  198. case AseOptionsSetup.CopyOptionsFromMainPass: optionsContainer.CopyOptionsFromMainPass = true; break;
  199. }
  200. }
  201. else
  202. {
  203. string[] args = setupLines[ i ].Split( '=' );
  204. if( args.Length > 1 && AseOptionsSetupDict.ContainsKey( args[ 0 ] ) )
  205. {
  206. AseOptionsSetup setup = AseOptionsSetupDict[ args[ 0 ] ];
  207. switch( setup )
  208. {
  209. case AseOptionsSetup.Id: int.TryParse(args[1], out optionsContainer.Id ) ; break;
  210. case AseOptionsSetup.Name: optionsContainer.Name = args[1]; break;
  211. }
  212. }
  213. }
  214. }
  215. //AVAILABLE OPTIONS
  216. string body = match.Groups[ 2 ].Value.Replace( "\t", string.Empty );
  217. string[] optionLines = body.Split( '\n' );
  218. for( int oL = 0; oL < optionLines.Length; oL++ )
  219. {
  220. string[] optionItems = optionLines[ oL ].Split( ':' );
  221. if( optionItems.Length > 0 )
  222. {
  223. string[] itemIds = optionItems[ 0 ].Split( ',' );
  224. switch( itemIds[0] )
  225. {
  226. case "Option":
  227. {
  228. //Fills previous option with its actions
  229. //actionItemsList is cleared over here
  230. FillOptionAction( currentOption, ref actionItemsList );
  231. optionItemToIndex.Clear();
  232. currentOption = new TemplateOptionsItem();
  233. currentOption.Type = AseOptionsType.Option;
  234. currentOption.Name = optionItems[ 1 ];
  235. currentOption.Id = itemIds.Length > 1? itemIds[1]:optionItems[ 1 ];
  236. currentOption.Options = optionItems[ 2 ].Split( ',' );
  237. for( int opIdx = 0; opIdx < currentOption.Options.Length; opIdx++ )
  238. {
  239. optionItemToIndex.Add( currentOption.Options[ opIdx ], opIdx );
  240. actionItemsList.Add( new List<TemplateActionItem>() );
  241. }
  242. if( optionItems.Length > 3 )
  243. {
  244. currentOption.DefaultOption = optionItems[ 3 ];
  245. }
  246. else
  247. {
  248. currentOption.DefaultOption = currentOption.Options[ 0 ];
  249. }
  250. if( currentOption.Options.Length > 2 )
  251. {
  252. currentOption.UIWidget = AseOptionsUIWidget.Dropdown;
  253. }
  254. else if( currentOption.Options.Length == 2 )
  255. {
  256. if( ( currentOption.Options[ 0 ].Equals( "true" ) && currentOption.Options[ 1 ].Equals( "false" ) ) ||
  257. ( currentOption.Options[ 0 ].Equals( "false" ) && currentOption.Options[ 1 ].Equals( "true" ) ) )
  258. {
  259. currentOption.UIWidget = AseOptionsUIWidget.Toggle;
  260. }
  261. }
  262. else
  263. {
  264. Debug.LogWarning( "Detected an option with less than two items:" + optionItems[ 1 ] );
  265. }
  266. optionItemsList.Add( currentOption );
  267. }
  268. break;
  269. case "Port":
  270. {
  271. //Fills previous option with its actions
  272. //actionItemsList is cleared over here
  273. FillOptionAction( currentOption, ref actionItemsList );
  274. optionItemToIndex.Clear();
  275. currentOption = new TemplateOptionsItem();
  276. currentOption.Type = AseOptionsType.Port;
  277. currentOption.Name = optionItems[ 1 ];
  278. currentOption.Options = new string[] { "On", "Off" };
  279. optionItemToIndex.Add( currentOption.Options[ 0 ], 0 );
  280. optionItemToIndex.Add( currentOption.Options[ 1 ], 1 );
  281. actionItemsList.Add( new List<TemplateActionItem>() );
  282. actionItemsList.Add( new List<TemplateActionItem>() );
  283. optionItemsList.Add( currentOption );
  284. }
  285. break;
  286. default:
  287. {
  288. if( optionItemToIndex.ContainsKey( optionItems[ 0 ] ) )
  289. {
  290. int idx = 0;
  291. if( currentOption != null && currentOption.UIWidget == AseOptionsUIWidget.Toggle )
  292. {
  293. idx = ( optionItems[ 0 ].Equals( "true" ) ) ? 1 : 0;
  294. }
  295. else
  296. {
  297. idx = optionItemToIndex[ optionItems[ 0 ] ];
  298. }
  299. actionItemsList[ idx ].Add( CreateActionItem( optionItems ) );
  300. }
  301. else
  302. {
  303. //string[] ids = optionItems[ 0 ].Split( ',' );
  304. if( itemIds.Length > 1 )
  305. {
  306. for( int i = 0; i < itemIds.Length; i++ )
  307. {
  308. if( optionItemToIndex.ContainsKey( itemIds[ i ] ) )
  309. {
  310. int idx = optionItemToIndex[ itemIds[ i ] ];
  311. actionItemsList[ idx ].Add( CreateActionItem( optionItems ) );
  312. }
  313. }
  314. }
  315. }
  316. }
  317. break;
  318. }
  319. }
  320. }
  321. //Fills last option with its actions
  322. FillOptionAction( currentOption, ref actionItemsList );
  323. actionItemsList.Clear();
  324. actionItemsList = null;
  325. optionsContainer.Options = optionItemsList.ToArray();
  326. optionItemsList.Clear();
  327. optionItemsList = null;
  328. optionItemToIndex.Clear();
  329. optionItemToIndex = null;
  330. }
  331. return optionsContainer;
  332. }
  333. static void FillOptionAction( TemplateOptionsItem currentOption, ref List<List<TemplateActionItem>> actionItemsList )
  334. {
  335. if( currentOption != null )
  336. {
  337. currentOption.ActionsPerOption = new TemplateActionItemGrid( actionItemsList.Count );
  338. for( int i = 0; i < actionItemsList.Count; i++ )
  339. {
  340. currentOption.ActionsPerOption[ i ] = actionItemsList[ i ].ToArray();
  341. actionItemsList[ i ].Clear();
  342. }
  343. actionItemsList.Clear();
  344. }
  345. }
  346. static TemplateActionItem CreateActionItem( string[] optionItems )
  347. {
  348. TemplateActionItem actionItem = new TemplateActionItem();
  349. actionItem.ActionType = AseOptionsActionTypeDict[ optionItems[ 1 ] ];
  350. actionItem.ActionData = optionItems[ 2 ];
  351. return actionItem;
  352. }
  353. }
  354. }