Assignment for RMIT Mixed Reality in 2020
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.

1183 lines
39 KiB

  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. // THIS FILE IS DEPRECATED AND SHOULD NOT BE USED
  4. using System;
  5. using UnityEngine;
  6. using UnityEditor;
  7. using System.Collections.Generic;
  8. using System.Text.RegularExpressions;
  9. namespace AmplifyShaderEditor
  10. {
  11. [Serializable]
  12. public class TemplateDataContainer
  13. {
  14. public int UNITY_VERSION = -1;
  15. public TemplateData TemplateDataRef;
  16. }
  17. [Serializable]
  18. public class VertexDataContainer
  19. {
  20. [SerializeField]
  21. private List<TemplateVertexData> m_vertexData;
  22. [SerializeField]
  23. private string m_vertexDataId = string.Empty;
  24. [SerializeField]
  25. private int m_vertexDataStartIdx = -1;
  26. public void Reload()
  27. {
  28. if( m_vertexData != null )
  29. {
  30. m_vertexData.Clear();
  31. }
  32. }
  33. public void Destroy()
  34. {
  35. if( m_vertexData != null )
  36. {
  37. m_vertexData.Clear();
  38. m_vertexData = null;
  39. }
  40. }
  41. public List<TemplateVertexData> VertexData { get { return m_vertexData; } set { m_vertexData = value; } }
  42. public string VertexDataId { get { return m_vertexDataId; } set { m_vertexDataId = value; } }
  43. public int VertexDataStartIdx { get { return m_vertexDataStartIdx; } set { m_vertexDataStartIdx = value; } }
  44. }
  45. [Serializable]
  46. public sealed class TemplateData : TemplateDataParent
  47. {
  48. [SerializeField]
  49. private string m_templateBody = string.Empty;
  50. [SerializeField]
  51. private string m_shaderNameId = string.Empty;
  52. [SerializeField]
  53. private List<TemplateProperty> m_propertyList = new List<TemplateProperty>();
  54. private Dictionary<string, TemplateProperty> m_propertyDict = new Dictionary<string, TemplateProperty>();
  55. [SerializeField]
  56. private List<TemplateInputData> m_inputDataList = new List<TemplateInputData>();
  57. private Dictionary<int, TemplateInputData> m_inputDataDict = new Dictionary<int, TemplateInputData>();
  58. //[SerializeField]
  59. //private List<TemplateCodeSnippetBase> m_snippetElementsList = new List<TemplateCodeSnippetBase>();
  60. //private Dictionary<string, TemplateCodeSnippetBase> m_snippetElementsDict = new Dictionary<string, TemplateCodeSnippetBase>();
  61. [SerializeField]
  62. private List<TemplateLocalVarData> m_localVarsList = new List<TemplateLocalVarData>();
  63. [SerializeField]
  64. private VertexDataContainer m_vertexDataContainer = new VertexDataContainer();
  65. [SerializeField]
  66. private TemplateInterpData m_interpolatorDataContainer;
  67. [SerializeField]
  68. private List<TemplateShaderPropertyData> m_availableShaderProperties = new List<TemplateShaderPropertyData>();
  69. [SerializeField]
  70. private TemplateFunctionData m_vertexFunctionData;
  71. [SerializeField]
  72. private TemplateFunctionData m_fragmentFunctionData;
  73. [SerializeField]
  74. private TemplateBlendData m_blendData = new TemplateBlendData();
  75. [SerializeField]
  76. private TemplateAlphaToMaskData m_alphaToMaskData = new TemplateAlphaToMaskData();
  77. [SerializeField]
  78. private TemplateCullModeData m_cullModeData = new TemplateCullModeData();
  79. [SerializeField]
  80. private TemplateColorMaskData m_colorMaskData = new TemplateColorMaskData();
  81. [SerializeField]
  82. private TemplateStencilData m_stencilData = new TemplateStencilData();
  83. [SerializeField]
  84. private TemplateDepthData m_depthData = new TemplateDepthData();
  85. [SerializeField]
  86. private TemplateTagsModuleData m_tagData = new TemplateTagsModuleData();
  87. public TemplateData()
  88. {
  89. m_templateType = TemplateDataType.LegacySinglePass;
  90. }
  91. public TemplateData( string name )
  92. {
  93. m_templateType = TemplateDataType.LegacySinglePass;
  94. Name = name;
  95. }
  96. public TemplateData( string name, string guid )
  97. {
  98. m_templateType = TemplateDataType.LegacySinglePass;
  99. m_communityTemplate = false;
  100. if( !string.IsNullOrEmpty( guid ) )
  101. {
  102. string datapath = AssetDatabase.GUIDToAssetPath( guid );
  103. if( string.IsNullOrEmpty( datapath ) )
  104. {
  105. m_isValid = false;
  106. return;
  107. }
  108. string body = string.Empty;
  109. try
  110. {
  111. body = IOUtils.LoadTextFileFromDisk( datapath );
  112. }
  113. catch( Exception e )
  114. {
  115. Debug.LogException( e );
  116. m_isValid = false;
  117. return;
  118. }
  119. if( !string.IsNullOrEmpty( body ) )
  120. {
  121. LoadTemplateBody( body );
  122. Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name;
  123. m_guid = guid;
  124. }
  125. }
  126. }
  127. public TemplateData( string name, string guid, string body )
  128. {
  129. m_templateType = TemplateDataType.LegacySinglePass;
  130. m_communityTemplate = true;
  131. if( !string.IsNullOrEmpty( body ) )
  132. {
  133. LoadTemplateBody( body );
  134. Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name;
  135. m_guid = guid;
  136. }
  137. }
  138. public override bool Reload()
  139. {
  140. if( m_vertexDataContainer != null )
  141. {
  142. m_vertexDataContainer.Reload();
  143. }
  144. if( m_interpolatorDataContainer != null )
  145. {
  146. m_interpolatorDataContainer.Destroy();
  147. }
  148. if( m_availableShaderProperties != null )
  149. {
  150. m_availableShaderProperties.Clear();
  151. }
  152. if( m_propertyDict != null )
  153. {
  154. m_propertyDict.Clear();
  155. }
  156. if( m_propertyList != null )
  157. {
  158. m_propertyList.Clear();
  159. }
  160. if( m_inputDataDict != null )
  161. {
  162. m_inputDataDict.Clear();
  163. }
  164. if( m_inputDataList != null )
  165. {
  166. m_inputDataList.Clear();
  167. }
  168. if( m_localVarsList != null )
  169. {
  170. m_localVarsList.Clear();
  171. }
  172. //if( m_snippetElementsDict != null )
  173. //{
  174. // m_snippetElementsDict.Clear();
  175. //}
  176. //if( m_snippetElementsList != null )
  177. //{
  178. // for( int i = 0; i < m_snippetElementsList.Count; i++ )
  179. // {
  180. // GameObject.DestroyImmediate( m_snippetElementsList[ i ] );
  181. // m_snippetElementsList[ i ] = null;
  182. // }
  183. // m_snippetElementsList.Clear();
  184. //}
  185. string datapath = AssetDatabase.GUIDToAssetPath( m_guid );
  186. string body = string.Empty;
  187. try
  188. {
  189. body = IOUtils.LoadTextFileFromDisk( datapath );
  190. body = body.Replace( "\r\n", "\n" );
  191. }
  192. catch( Exception e )
  193. {
  194. Debug.LogException( e );
  195. m_isValid = false;
  196. }
  197. LoadTemplateBody( body );
  198. if( m_communityTemplate )
  199. {
  200. Name = m_defaultShaderName;
  201. }
  202. return true;
  203. }
  204. void LoadTemplateBody( string body )
  205. {
  206. m_templateBody = body.Replace( "\r\n", "\n" ); ;
  207. if( m_templateBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) < 0 )
  208. {
  209. m_isValid = false;
  210. return;
  211. }
  212. //Fetching common tags
  213. FetchCommonTags();
  214. //Fetch function code areas
  215. FetchCodeAreas( TemplatesManager.TemplateVertexCodeBeginArea, MasterNodePortCategory.Vertex );
  216. FetchCodeAreas( TemplatesManager.TemplateFragmentCodeBeginArea, MasterNodePortCategory.Fragment );
  217. //Fetching inputs
  218. FetchInputs( MasterNodePortCategory.Fragment );
  219. FetchInputs( MasterNodePortCategory.Vertex );
  220. //Fetch local variables must be done after fetching code areas as it needs them to see is variable is on vertex or fragment
  221. TemplateHelperFunctions.FetchLocalVars( m_templateBody, ref m_localVarsList, m_vertexFunctionData, m_fragmentFunctionData );
  222. //Fetch snippets
  223. }
  224. void FetchSubShaderProperties()
  225. {
  226. Match match = Regex.Match( m_templateBody, @"Pass\s*{" );
  227. if( match.Groups.Count == 0 )
  228. {
  229. return;
  230. }
  231. int beginSubShader = m_templateBody.IndexOf( "SubShader" );
  232. int endSubShader = match.Groups[ 0 ].Index;
  233. if( beginSubShader > 0 && endSubShader > 0 && endSubShader > beginSubShader )
  234. {
  235. // ADD A PLACE TO INSERT GRAB PASSES
  236. int passIndex = m_templateBody.IndexOf( TemplatesManager.TemplatePassTag );
  237. if( passIndex < 0 )
  238. {
  239. int currIdx = endSubShader - 1;
  240. string identation = string.Empty;
  241. for( ; currIdx > 0; currIdx-- )
  242. {
  243. if( m_templateBody[ currIdx ] != '\n' )
  244. {
  245. identation = m_templateBody[ currIdx ] + identation;
  246. }
  247. else
  248. {
  249. identation = m_templateBody[ currIdx ] + identation;
  250. break;
  251. }
  252. }
  253. if( currIdx > 0 )
  254. {
  255. m_templateBody = m_templateBody.Insert( currIdx, identation + TemplatesManager.TemplatePassTag );
  256. }
  257. }
  258. // GET ALL THE MODULES
  259. string subBody = m_templateBody.Substring( beginSubShader, endSubShader - beginSubShader );
  260. //CULL MODE
  261. {
  262. int cullIdx = subBody.IndexOf( "Cull" );
  263. if( cullIdx > 0 )
  264. {
  265. int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, cullIdx );
  266. string cullParams = subBody.Substring( cullIdx, end - cullIdx );
  267. m_cullModeData.CullModeId = cullParams;
  268. TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData );
  269. if( m_cullModeData.DataCheck == TemplateDataCheck.Valid )
  270. AddId( cullParams, false, string.Empty );
  271. }
  272. }
  273. //COLOR MASK
  274. {
  275. int colorMaskIdx = subBody.IndexOf( "ColorMask" );
  276. if( colorMaskIdx > 0 )
  277. {
  278. int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx );
  279. string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx );
  280. m_colorMaskData.ColorMaskId = colorMaskParams;
  281. TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData, TemplateHelperFunctions.ColorMaskPattern );
  282. if( m_colorMaskData.DataCheck == TemplateDataCheck.Valid )
  283. AddId( colorMaskParams, false );
  284. }
  285. }
  286. //BlEND MODE
  287. {
  288. int blendModeIdx = subBody.IndexOf( "Blend" );
  289. if( blendModeIdx > 0 )
  290. {
  291. int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendModeIdx );
  292. string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx );
  293. m_blendData.BlendModeId = blendParams;
  294. TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData, TemplateHelperFunctions.BlendModePattern );
  295. if( m_blendData.ValidBlendMode )
  296. {
  297. AddId( blendParams, false );
  298. }
  299. }
  300. }
  301. //BLEND OP
  302. {
  303. int blendOpIdx = subBody.IndexOf( "BlendOp" );
  304. if( blendOpIdx > 0 )
  305. {
  306. int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendOpIdx );
  307. string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx );
  308. BlendData.BlendOpId = blendOpParams;
  309. TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData, TemplateHelperFunctions.BlendOpPattern );
  310. if( m_blendData.ValidBlendOp )
  311. {
  312. AddId( blendOpParams, false );
  313. }
  314. }
  315. m_blendData.DataCheck = ( m_blendData.ValidBlendMode || m_blendData.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid;
  316. }
  317. //STENCIL
  318. {
  319. int stencilIdx = subBody.IndexOf( "Stencil" );
  320. if( stencilIdx > -1 )
  321. {
  322. int stencilEndIdx = subBody.IndexOf( "}", stencilIdx );
  323. if( stencilEndIdx > 0 )
  324. {
  325. string stencilParams = subBody.Substring( stencilIdx, stencilEndIdx + 1 - stencilIdx );
  326. m_stencilData.StencilBufferId = stencilParams;
  327. TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData );
  328. if( m_stencilData.DataCheck == TemplateDataCheck.Valid )
  329. {
  330. AddId( stencilParams, true );
  331. }
  332. }
  333. }
  334. }
  335. //ZWRITE
  336. {
  337. int zWriteOpIdx = subBody.IndexOf( "ZWrite" );
  338. if( zWriteOpIdx > -1 )
  339. {
  340. int zWriteEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zWriteOpIdx );
  341. if( zWriteEndIdx > 0 )
  342. {
  343. m_depthData.ZWriteModeId = subBody.Substring( zWriteOpIdx, zWriteEndIdx + 1 - zWriteOpIdx );
  344. TemplateHelperFunctions.CreateZWriteMode( m_depthData.ZWriteModeId, ref m_depthData );
  345. if( m_depthData.DataCheck == TemplateDataCheck.Valid )
  346. {
  347. AddId( m_depthData.ZWriteModeId, true );
  348. }
  349. }
  350. }
  351. }
  352. //ZTEST
  353. {
  354. int zTestOpIdx = subBody.IndexOf( "ZTest" );
  355. if( zTestOpIdx > -1 )
  356. {
  357. int zTestEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zTestOpIdx );
  358. if( zTestEndIdx > 0 )
  359. {
  360. m_depthData.ZTestModeId = subBody.Substring( zTestOpIdx, zTestEndIdx + 1 - zTestOpIdx );
  361. TemplateHelperFunctions.CreateZTestMode( m_depthData.ZTestModeId, ref m_depthData );
  362. if( m_depthData.DataCheck == TemplateDataCheck.Valid )
  363. {
  364. AddId( m_depthData.ZTestModeId, true );
  365. }
  366. }
  367. }
  368. }
  369. //ZOFFSET
  370. {
  371. int zOffsetIdx = subBody.IndexOf( "Offset" );
  372. if( zOffsetIdx > -1 )
  373. {
  374. int zOffsetEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zOffsetIdx );
  375. if( zOffsetEndIdx > 0 )
  376. {
  377. m_depthData.OffsetId = subBody.Substring( zOffsetIdx, zOffsetEndIdx + 1 - zOffsetIdx );
  378. TemplateHelperFunctions.CreateZOffsetMode( m_depthData.OffsetId, ref m_depthData );
  379. if( m_depthData.DataCheck == TemplateDataCheck.Valid )
  380. {
  381. AddId( m_depthData.OffsetId, true );
  382. }
  383. }
  384. }
  385. m_depthData.SetDataCheck();
  386. }
  387. //TAGS
  388. {
  389. int tagsIdx = subBody.IndexOf( "Tags" );
  390. if( tagsIdx > -1 )
  391. {
  392. int tagsEndIdx = subBody.IndexOf( "}", tagsIdx );
  393. if( tagsEndIdx > -1 )
  394. {
  395. m_tagData.Reset();
  396. m_tagData.TagsId = subBody.Substring( tagsIdx, tagsEndIdx + 1 - tagsIdx );
  397. TemplateHelperFunctions.CreateTags( ref m_tagData, true );
  398. m_tagData.DataCheck = TemplateDataCheck.Valid;
  399. AddId( m_tagData.TagsId, false );
  400. }
  401. else
  402. {
  403. m_tagData.DataCheck = TemplateDataCheck.Invalid;
  404. }
  405. }
  406. else
  407. {
  408. m_tagData.DataCheck = TemplateDataCheck.Invalid;
  409. }
  410. }
  411. }
  412. }
  413. void FetchCommonTags()
  414. {
  415. // Name
  416. try
  417. {
  418. int nameBegin = m_templateBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag );
  419. if( nameBegin < 0 )
  420. {
  421. // Not a template
  422. return;
  423. }
  424. int nameEnd = m_templateBody.IndexOf( TemplatesManager.TemplateFullEndTag, nameBegin );
  425. int defaultBegin = nameBegin + TemplatesManager.TemplateShaderNameBeginTag.Length;
  426. int defaultLength = nameEnd - defaultBegin;
  427. m_defaultShaderName = m_templateBody.Substring( defaultBegin, defaultLength );
  428. int[] nameIdx = m_defaultShaderName.AllIndexesOf( "\"" );
  429. nameIdx[ 0 ] += 1; // Ignore the " character from the string
  430. m_defaultShaderName = m_defaultShaderName.Substring( nameIdx[ 0 ], nameIdx[ 1 ] - nameIdx[ 0 ] );
  431. m_shaderNameId = m_templateBody.Substring( nameBegin, nameEnd + TemplatesManager.TemplateFullEndTag.Length - nameBegin );
  432. AddId( m_shaderNameId, false );
  433. }
  434. catch( Exception e )
  435. {
  436. Debug.LogException( e );
  437. m_isValid = false;
  438. }
  439. FetchSubShaderProperties();
  440. // Vertex Data
  441. {
  442. int vertexDataTagBegin = m_templateBody.IndexOf( TemplatesManager.TemplateVertexDataTag );
  443. if( vertexDataTagBegin > -1 )
  444. {
  445. m_vertexDataContainer.VertexDataStartIdx = vertexDataTagBegin;
  446. int vertexDataTagEnd = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, vertexDataTagBegin );
  447. m_vertexDataContainer.VertexDataId = m_templateBody.Substring( vertexDataTagBegin, vertexDataTagEnd + TemplatesManager.TemplateEndOfLine.Length - vertexDataTagBegin );
  448. int dataBeginIdx = m_templateBody.LastIndexOf( '{', vertexDataTagBegin, vertexDataTagBegin );
  449. string vertexData = m_templateBody.Substring( dataBeginIdx + 1, vertexDataTagBegin - dataBeginIdx );
  450. int parametersBegin = vertexDataTagBegin + TemplatesManager.TemplateVertexDataTag.Length;
  451. string parameters = m_templateBody.Substring( parametersBegin, vertexDataTagEnd - parametersBegin );
  452. m_vertexDataContainer.VertexData = TemplateHelperFunctions.CreateVertexDataList( vertexData, parameters );
  453. AddId( m_vertexDataContainer.VertexDataId );
  454. }
  455. }
  456. // Available interpolators
  457. try
  458. {
  459. int interpDataBegin = m_templateBody.IndexOf( TemplatesManager.TemplateInterpolatorBeginTag );
  460. if( interpDataBegin > -1 )
  461. {
  462. int interpDataEnd = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, interpDataBegin );
  463. string interpDataId = m_templateBody.Substring( interpDataBegin, interpDataEnd + TemplatesManager.TemplateEndOfLine.Length - interpDataBegin );
  464. int dataBeginIdx = m_templateBody.LastIndexOf( '{', interpDataBegin, interpDataBegin );
  465. string interpData = m_templateBody.Substring( dataBeginIdx + 1, interpDataBegin - dataBeginIdx );
  466. m_interpolatorDataContainer = TemplateHelperFunctions.CreateInterpDataList( interpData, interpDataId, 8 );
  467. m_interpolatorDataContainer.InterpDataId = interpDataId;
  468. m_interpolatorDataContainer.InterpDataStartIdx = interpDataBegin;
  469. AddId( interpDataId );
  470. }
  471. }
  472. catch( Exception e )
  473. {
  474. Debug.LogException( e );
  475. m_isValid = false;
  476. }
  477. try
  478. {
  479. Dictionary<string, TemplateShaderPropertyData> duplicatesHelper = new Dictionary<string, TemplateShaderPropertyData>();
  480. m_availableShaderProperties = new List<TemplateShaderPropertyData>();
  481. // Common Tags
  482. for( int i = 0; i < TemplatesManager.CommonTags.Length; i++ )
  483. {
  484. int idx = m_templateBody.IndexOf( TemplatesManager.CommonTags[ i ].Id );
  485. if( idx > -1 )
  486. {
  487. string currentId = TemplatesManager.CommonTags[ i ].Id;
  488. TemplateCommonTagId commonTagId = (TemplateCommonTagId)i;
  489. switch( commonTagId )
  490. {
  491. // Properties
  492. case TemplateCommonTagId.Property:
  493. {
  494. TemplateHelperFunctions.CreateShaderPropertiesList( m_templateBody.Substring( 0, idx + TemplatesManager.CommonTags[ i ].Id.Length ), ref m_availableShaderProperties, ref duplicatesHelper );
  495. }
  496. break;
  497. // Globals
  498. case TemplateCommonTagId.Global:
  499. {
  500. TemplateHelperFunctions.CreateShaderGlobalsList( m_templateBody.Substring( 0, idx + TemplatesManager.CommonTags[ i ].Id.Length ), ref m_availableShaderProperties, ref duplicatesHelper );
  501. }
  502. break;
  503. //Tags
  504. //case TemplateCommonTagId.Tag:
  505. //{
  506. // m_propertyList[ m_propertyList.Count - 1 ].Indentation = " ";
  507. //}
  508. //break;
  509. //case TemplateCommonTagId.CullMode:
  510. //{
  511. // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
  512. // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
  513. // string cullParams = m_templateBody.Substring( newId, end - newId );
  514. // currentId = m_templateBody.Substring( idx, end - idx );
  515. // m_cullModeData.CullModeId = currentId;
  516. // TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData );
  517. //}
  518. //break;
  519. //Blend Mode
  520. //case TemplateCommonTagId.BlendMode:
  521. //{
  522. // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
  523. // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
  524. // string blendParams = m_templateBody.Substring( newId, end - newId );
  525. // currentId = m_templateBody.Substring( idx, end - idx );
  526. // m_blendData.BlendModeId = currentId;
  527. // TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData );
  528. //}break;
  529. //case TemplateCommonTagId.BlendOp:
  530. //{
  531. // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
  532. // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
  533. // currentId = m_templateBody.Substring( idx, end - idx );
  534. // BlendData.BlendOpId = currentId;
  535. // TemplateHelperFunctions.CreateBlendOp( m_templateBody.Substring( newId, end - newId ), ref m_blendData );
  536. //}break;
  537. //case TemplateCommonTagId.ColorMask:
  538. //{
  539. // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
  540. // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
  541. // string colorMaskParams = m_templateBody.Substring( newId, end - newId );
  542. // currentId = m_templateBody.Substring( idx, end - idx );
  543. // m_colorMaskData.ColorMaskId = currentId;
  544. // TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData );
  545. //}
  546. //break;
  547. //case TemplateCommonTagId.StencilOp:
  548. //{
  549. // int id = m_templateBody.LastIndexOf( "Stencil" );
  550. // if( id > -1 )
  551. // {
  552. // string stencilParams = m_templateBody.Substring( id, idx - id );
  553. // currentId = stencilParams + TemplatesManager.TemplateStencilOpTag;
  554. // m_stencilData.StencilBufferId = currentId;
  555. // TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData );
  556. // }
  557. //}
  558. //break;
  559. default:
  560. break;
  561. }
  562. //AddId( TemplatesManager.CommonTags[ i ] );
  563. AddId( currentId, TemplatesManager.CommonTags[ i ].SearchIndentation, TemplatesManager.CommonTags[ i ].CustomIndentation );
  564. }
  565. }
  566. duplicatesHelper.Clear();
  567. duplicatesHelper = null;
  568. }
  569. catch( Exception e )
  570. {
  571. Debug.LogException( e );
  572. m_isValid = false;
  573. }
  574. }
  575. void FetchCodeAreas( string begin, MasterNodePortCategory category )
  576. {
  577. int areaBeginIndexes = m_templateBody.IndexOf( begin );
  578. if( areaBeginIndexes > -1 )
  579. {
  580. int beginIdx = areaBeginIndexes + begin.Length;
  581. int endIdx = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx );
  582. int length = endIdx - beginIdx;
  583. string parameters = m_templateBody.Substring( beginIdx, length );
  584. string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR );
  585. string id = m_templateBody.Substring( areaBeginIndexes, endIdx + TemplatesManager.TemplateEndOfLine.Length - areaBeginIndexes );
  586. string inParameters = parametersArr[ 0 ];
  587. string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty;
  588. if( category == MasterNodePortCategory.Fragment )
  589. {
  590. m_fragmentFunctionData = new TemplateFunctionData(-1, string.Empty, id, areaBeginIndexes, inParameters, outParameters, category );
  591. }
  592. else
  593. {
  594. m_vertexFunctionData = new TemplateFunctionData( -1, string.Empty,id, areaBeginIndexes, inParameters, outParameters, category );
  595. }
  596. AddId( id, true );
  597. }
  598. }
  599. void FetchInputs( MasterNodePortCategory portCategory )
  600. {
  601. string beginTag = ( portCategory == MasterNodePortCategory.Fragment ) ? TemplatesManager.TemplateInputsFragBeginTag : TemplatesManager.TemplateInputsVertBeginTag;
  602. int[] inputBeginIndexes = m_templateBody.AllIndexesOf( beginTag );
  603. if( inputBeginIndexes != null && inputBeginIndexes.Length > 0 )
  604. {
  605. for( int i = 0; i < inputBeginIndexes.Length; i++ )
  606. {
  607. int inputEndIdx = m_templateBody.IndexOf( TemplatesManager.TemplateEndSectionTag, inputBeginIndexes[ i ] );
  608. int defaultValueBeginIdx = inputEndIdx + TemplatesManager.TemplateEndSectionTag.Length;
  609. int endLineIdx = m_templateBody.IndexOf( TemplatesManager.TemplateFullEndTag, defaultValueBeginIdx );
  610. string defaultValue = m_templateBody.Substring( defaultValueBeginIdx, endLineIdx - defaultValueBeginIdx );
  611. string tagId = m_templateBody.Substring( inputBeginIndexes[ i ], endLineIdx + TemplatesManager.TemplateFullEndTag.Length - inputBeginIndexes[ i ] );
  612. int beginIndex = inputBeginIndexes[ i ] + beginTag.Length;
  613. int length = inputEndIdx - beginIndex;
  614. string inputData = m_templateBody.Substring( beginIndex, length );
  615. string[] inputDataArray = inputData.Split( IOUtils.FIELD_SEPARATOR );
  616. if( inputDataArray != null && inputDataArray.Length > 0 )
  617. {
  618. try
  619. {
  620. string portName = inputDataArray[ (int)TemplatePortIds.Name ];
  621. WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), inputDataArray[ (int)TemplatePortIds.DataType ].ToUpper() );
  622. int portUniqueIDArrIdx = (int)TemplatePortIds.UniqueId;
  623. int portUniqueId = ( portUniqueIDArrIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portUniqueIDArrIdx ] ) : -1;
  624. if( portUniqueId < 0 )
  625. portUniqueId = m_inputDataList.Count;
  626. int portOrderArrayIdx = (int)TemplatePortIds.OrderId;
  627. int portOrderId = ( portOrderArrayIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portOrderArrayIdx ] ) : -1;
  628. if( portOrderId < 0 )
  629. portOrderId = m_inputDataList.Count;
  630. AddInput( inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId );
  631. }
  632. catch( Exception e )
  633. {
  634. Debug.LogException( e );
  635. }
  636. }
  637. }
  638. }
  639. }
  640. //void FetchSnippets()
  641. //{
  642. // int[] codeSnippetAttribBeginIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetAttribBegin );
  643. // int[] codeSnippetAttribEndIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetAttribEnd );
  644. // int[] codeSnippetEndIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetEnd );
  645. // if( codeSnippetAttribBeginIndexes != null && codeSnippetAttribBeginIndexes.Length > 0 &&
  646. // codeSnippetAttribEndIndexes != null && codeSnippetAttribEndIndexes.Length > 0 &&
  647. // codeSnippetEndIndexes != null && codeSnippetEndIndexes.Length > 0 &&
  648. // codeSnippetEndIndexes.Length == codeSnippetAttribBeginIndexes.Length &&
  649. // codeSnippetAttribBeginIndexes.Length == codeSnippetAttribEndIndexes.Length )
  650. // {
  651. // for( int i = 0; i < codeSnippetAttribBeginIndexes.Length; i++ )
  652. // {
  653. // // get attributes
  654. // int startAttribIndex = codeSnippetAttribBeginIndexes[ i ] + TemplatesManager.TemplateCodeSnippetAttribBegin.Length;
  655. // int lengthAttrib = codeSnippetAttribEndIndexes[ i ] - startAttribIndex;
  656. // string snippetAttribs = m_templateBody.Substring( startAttribIndex, lengthAttrib );
  657. // string[] snippetAttribsArr = snippetAttribs.Split( IOUtils.FIELD_SEPARATOR );
  658. // if( snippetAttribsArr != null && snippetAttribsArr.Length > 0 )
  659. // {
  660. // string attribName = snippetAttribsArr[ (int)TemplateCodeSnippetInfoIdx.Name ];
  661. // TemplateCodeSnippetType attribType = (TemplateCodeSnippetType)Enum.Parse( typeof( TemplateCodeSnippetType ), snippetAttribsArr[ (int)TemplateCodeSnippetInfoIdx.Type ] );
  662. // if( m_snippetElementsDict.ContainsKey( attribName ) )
  663. // {
  664. // if( m_snippetElementsDict[ attribName ].Type != attribType )
  665. // {
  666. // if( DebugConsoleWindow.DeveloperMode )
  667. // Debug.LogWarning( "Found incompatible types for snippet " + attribName );
  668. // }
  669. // }
  670. // else
  671. // {
  672. // switch( attribType )
  673. // {
  674. // case TemplateCodeSnippetType.Toggle:
  675. // {
  676. // //Register must be done by first instantiang the correct type and register it on both containers
  677. // //Overrides don't work if we use the container reference into the other
  678. // TemplateCodeSnippetToggle newSnippet = ScriptableObject.CreateInstance<TemplateCodeSnippetToggle>();
  679. // newSnippet.Init( attribName, attribType );
  680. // m_snippetElementsDict.Add( attribName, newSnippet );
  681. // m_snippetElementsList.Add( newSnippet );
  682. // }
  683. // break;
  684. // }
  685. // }
  686. // // Add initial tag indentation
  687. // int indentationIndex = codeSnippetAttribBeginIndexes[ i ];
  688. // int lengthAdjust = 0;
  689. // for( ; indentationIndex > 0; indentationIndex--, lengthAdjust++ )
  690. // {
  691. // if( m_templateBody[ indentationIndex ] == TemplatesManager.TemplateNewLine )
  692. // {
  693. // indentationIndex += 1;
  694. // lengthAdjust -= 1;
  695. // break;
  696. // }
  697. // }
  698. // if( indentationIndex > 0 )
  699. // {
  700. // string snippetId = m_templateBody.Substring( indentationIndex,
  701. // codeSnippetEndIndexes[ i ] + TemplatesManager.TemplateCodeSnippetEnd.Length - codeSnippetAttribBeginIndexes[ i ] + lengthAdjust );
  702. // int snippetCodeStart = codeSnippetAttribEndIndexes[ i ] + TemplatesManager.TemplateCodeSnippetAttribEnd.Length;
  703. // int snippetCodeLength = codeSnippetEndIndexes[ i ] - snippetCodeStart;
  704. // //Remove possible identation characters present between tag and last instruction
  705. // if( m_templateBody[ snippetCodeStart + snippetCodeLength - 1 ] != TemplatesManager.TemplateNewLine )
  706. // {
  707. // for( ; snippetCodeLength > 0; snippetCodeLength-- )
  708. // {
  709. // if( m_templateBody[ snippetCodeStart + snippetCodeLength - 1 ] == TemplatesManager.TemplateNewLine )
  710. // break;
  711. // }
  712. // }
  713. // if( snippetCodeLength > 0 )
  714. // {
  715. // string snippetCode = m_templateBody.Substring( snippetCodeStart, snippetCodeLength );
  716. // TemplateCodeSnippetElement element = new TemplateCodeSnippetElement( snippetId, snippetCode );
  717. // m_snippetElementsDict[ attribName ].AddSnippet( element );
  718. // }
  719. // }
  720. // }
  721. // }
  722. // }
  723. //}
  724. //void RefreshSnippetInfo()
  725. //{
  726. // if( m_snippetElementsDict == null )
  727. // {
  728. // m_snippetElementsDict = new Dictionary<string, TemplateCodeSnippetBase>();
  729. // }
  730. // if( m_snippetElementsDict.Count != m_snippetElementsList.Count )
  731. // {
  732. // m_snippetElementsDict.Clear();
  733. // for( int i = 0; i < m_snippetElementsList.Count; i++ )
  734. // {
  735. // m_snippetElementsDict.Add( m_snippetElementsList[ i ].NameId, m_snippetElementsList[ i ] );
  736. // }
  737. // }
  738. //}
  739. //public void DrawSnippetProperties( ParentNode owner )
  740. //{
  741. // for( int i = 0; i < m_snippetElementsList.Count; i++ )
  742. // {
  743. // m_snippetElementsList[ i ].DrawProperties( owner );
  744. // }
  745. //}
  746. //public void InsertSnippets( ref string shaderBody )
  747. //{
  748. // for( int i = 0; i < m_snippetElementsList.Count; i++ )
  749. // {
  750. // m_snippetElementsList[ i ].InsertSnippet( ref shaderBody );
  751. // }
  752. //}
  753. public void AddId( string ID, bool searchIndentation = true )
  754. {
  755. AddId( ID, searchIndentation, string.Empty );
  756. }
  757. public void AddId( string ID, bool searchIndentation, string customIndentation )
  758. {
  759. int propertyIndex = m_templateBody.IndexOf( ID );
  760. if( propertyIndex > -1 )
  761. {
  762. if( searchIndentation )
  763. {
  764. int indentationIndex = -1;
  765. for( int i = propertyIndex; i > 0; i-- )
  766. {
  767. if( m_templateBody[ i ] == TemplatesManager.TemplateNewLine )
  768. {
  769. indentationIndex = i + 1;
  770. break;
  771. }
  772. }
  773. if( indentationIndex > -1 )
  774. {
  775. int length = propertyIndex - indentationIndex;
  776. string indentation = ( length > 0 ) ? m_templateBody.Substring( indentationIndex, length ) : string.Empty;
  777. m_propertyList.Add( new TemplateProperty( ID, indentation, false ) );
  778. }
  779. }
  780. else
  781. {
  782. m_propertyList.Add( new TemplateProperty( ID, customIndentation, true ) );
  783. }
  784. }
  785. }
  786. void BuildInfo()
  787. {
  788. if( m_propertyDict == null )
  789. {
  790. m_propertyDict = new Dictionary<string, TemplateProperty>();
  791. }
  792. if( m_propertyList.Count != m_propertyDict.Count )
  793. {
  794. m_propertyDict.Clear();
  795. for( int i = 0; i < m_propertyList.Count; i++ )
  796. {
  797. m_propertyDict.Add( m_propertyList[ i ].Id, m_propertyList[ i ] );
  798. }
  799. }
  800. }
  801. public void ResetTemplateUsageData()
  802. {
  803. BuildInfo();
  804. for( int i = 0; i < m_propertyList.Count; i++ )
  805. {
  806. m_propertyList[ i ].Used = false;
  807. }
  808. }
  809. public void AddInput( int tagStartIdx, string tagId, string portName, string defaultValue, WirePortDataType dataType, MasterNodePortCategory portCategory, int portUniqueId, int portOrderId )
  810. {
  811. TemplateInputData inputData = new TemplateInputData( tagStartIdx, tagStartIdx, tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, string.Empty );
  812. m_inputDataList.Add( inputData );
  813. m_inputDataDict.Add( inputData.PortUniqueId, inputData );
  814. AddId( tagId, false );
  815. }
  816. public override void Destroy()
  817. {
  818. if( m_vertexDataContainer != null )
  819. {
  820. m_vertexDataContainer.Destroy();
  821. m_vertexDataContainer = null;
  822. }
  823. if( m_interpolatorDataContainer != null )
  824. {
  825. m_interpolatorDataContainer.Destroy();
  826. m_interpolatorDataContainer = null;
  827. }
  828. if( m_availableShaderProperties != null )
  829. {
  830. m_availableShaderProperties.Clear();
  831. m_availableShaderProperties = null;
  832. }
  833. if( m_propertyDict != null )
  834. {
  835. m_propertyDict.Clear();
  836. m_propertyDict = null;
  837. }
  838. if( m_propertyList != null )
  839. {
  840. m_propertyList.Clear();
  841. m_propertyList = null;
  842. }
  843. if( m_inputDataDict != null )
  844. {
  845. m_inputDataDict.Clear();
  846. m_inputDataDict = null;
  847. }
  848. if( m_inputDataList != null )
  849. {
  850. m_inputDataList.Clear();
  851. m_inputDataList = null;
  852. }
  853. if( m_localVarsList != null )
  854. {
  855. m_localVarsList.Clear();
  856. m_localVarsList = null;
  857. }
  858. //if( m_snippetElementsDict != null )
  859. //{
  860. // m_snippetElementsDict.Clear();
  861. // m_snippetElementsDict = null;
  862. //}
  863. //if( m_snippetElementsList != null )
  864. //{
  865. // for( int i = 0; i < m_snippetElementsList.Count; i++ )
  866. // {
  867. // GameObject.DestroyImmediate( m_snippetElementsList[ i ] );
  868. // m_snippetElementsList[ i ] = null;
  869. // }
  870. // m_snippetElementsList.Clear();
  871. // m_snippetElementsList = null;
  872. //}
  873. m_alphaToMaskData = null;
  874. m_cullModeData = null;
  875. m_blendData = null;
  876. m_colorMaskData = null;
  877. m_stencilData = null;
  878. if( m_tagData != null )
  879. {
  880. m_tagData.Destroy();
  881. m_tagData = null;
  882. }
  883. }
  884. public void FillEmptyTags( ref string body )
  885. {
  886. body = body.Replace( TemplatesManager.TemplateLocalVarTag, string.Empty );
  887. for( int i = 0; i < m_propertyList.Count; i++ )
  888. {
  889. if( !m_propertyList[ i ].Used )
  890. {
  891. if( m_propertyList[ i ].UseCustomIndentation )
  892. {
  893. body = body.Replace( m_propertyList[ i ].Id, string.Empty );
  894. }
  895. else
  896. {
  897. body = body.Replace( m_propertyList[ i ].Indentation + m_propertyList[ i ].Id, string.Empty );
  898. }
  899. }
  900. }
  901. }
  902. public bool FillVertexInstructions( ref string body, params string[] values )
  903. {
  904. if( m_vertexFunctionData != null && !string.IsNullOrEmpty( m_vertexFunctionData.Id ) )
  905. {
  906. return FillTemplateBody( m_vertexFunctionData.Id, ref body, values );
  907. }
  908. if( values.Length > 0 )
  909. {
  910. UIUtils.ShowMessage( "Attemping to add vertex instructions on a template with no assigned vertex code area", MessageSeverity.Error );
  911. return false;
  912. }
  913. return true;
  914. }
  915. public bool FillFragmentInstructions( ref string body, params string[] values )
  916. {
  917. if( m_fragmentFunctionData != null && !string.IsNullOrEmpty( m_fragmentFunctionData.Id ) )
  918. {
  919. return FillTemplateBody( m_fragmentFunctionData.Id, ref body, values );
  920. }
  921. if( values.Length > 0 )
  922. {
  923. UIUtils.ShowMessage( "Attemping to add fragment instructions on a template with no assigned vertex code area", MessageSeverity.Error );
  924. return false;
  925. }
  926. return true;
  927. }
  928. // values must be unindented an without line feed
  929. public bool FillTemplateBody( string id, ref string body, params string[] values )
  930. {
  931. if( values.Length == 0 )
  932. {
  933. return true;
  934. }
  935. BuildInfo();
  936. if( m_propertyDict.ContainsKey( id ) )
  937. {
  938. string finalValue = string.Empty;
  939. for( int i = 0; i < values.Length; i++ )
  940. {
  941. if( m_propertyDict[ id ].AutoLineFeed )
  942. {
  943. string[] valuesArr = values[ i ].Split( '\n' );
  944. for( int j = 0; j < valuesArr.Length; j++ )
  945. {
  946. //first value will be automatically indented by the string replace
  947. finalValue += ( ( i == 0 && j == 0 ) ? string.Empty : m_propertyDict[ id ].Indentation ) + valuesArr[ j ];
  948. finalValue += TemplatesManager.TemplateNewLine;
  949. }
  950. }
  951. else
  952. {
  953. //first value will be automatically indented by the string replace
  954. finalValue += ( i == 0 ? string.Empty : m_propertyDict[ id ].Indentation ) + values[ i ];
  955. }
  956. }
  957. body = body.Replace( id, finalValue );
  958. m_propertyDict[ id ].Used = true;
  959. return true;
  960. }
  961. if( values.Length > 1 || !string.IsNullOrEmpty( values[ 0 ] ) )
  962. {
  963. UIUtils.ShowMessage( string.Format( "Attempting to write data into inexistant tag {0}. Please review the template {1} body and consider adding the missing tag.", id, m_name ), MessageSeverity.Error );
  964. return false;
  965. }
  966. return true;
  967. }
  968. public bool FillTemplateBody( string id, ref string body, List<PropertyDataCollector> values )
  969. {
  970. if( values.Count == 0 )
  971. {
  972. return true;
  973. }
  974. string[] array = new string[ values.Count ];
  975. for( int i = 0; i < values.Count; i++ )
  976. {
  977. array[ i ] = values[ i ].PropertyName;
  978. }
  979. return FillTemplateBody( id, ref body, array );
  980. }
  981. public TemplateInputData InputDataFromId( int id )
  982. {
  983. if( m_inputDataDict == null )
  984. m_inputDataDict = new Dictionary<int, TemplateInputData>();
  985. if( m_inputDataDict.Count != m_inputDataList.Count )
  986. {
  987. m_inputDataDict.Clear();
  988. for( int i = 0; i < m_inputDataList.Count; i++ )
  989. {
  990. m_inputDataDict.Add( m_inputDataList[ i ].PortUniqueId, m_inputDataList[ i ] );
  991. }
  992. }
  993. if( m_inputDataDict.ContainsKey( id ) )
  994. return m_inputDataDict[ id ];
  995. return null;
  996. }
  997. public string GetVertexData( TemplateInfoOnSematics info )
  998. {
  999. int count = m_vertexDataContainer.VertexData.Count;
  1000. for( int i = 0; i < count; i++ )
  1001. {
  1002. if( m_vertexDataContainer.VertexData[ i ].DataInfo == info )
  1003. {
  1004. return string.Format( TemplateHelperFunctions.TemplateVarFormat, m_vertexFunctionData.InVarName, m_vertexDataContainer.VertexData[ i ].VarName );
  1005. }
  1006. }
  1007. return string.Empty;
  1008. }
  1009. public string GetInterpolatedData( TemplateInfoOnSematics info )
  1010. {
  1011. int count = m_interpolatorDataContainer.Interpolators.Count;
  1012. for( int i = 0; i < count; i++ )
  1013. {
  1014. if( m_interpolatorDataContainer.Interpolators[ i ].DataInfo == info )
  1015. {
  1016. return string.Format( TemplateHelperFunctions.TemplateVarFormat, m_fragmentFunctionData.InVarName, m_interpolatorDataContainer.Interpolators[ i ].VarName );
  1017. }
  1018. }
  1019. return string.Empty;
  1020. }
  1021. public string InterpDataId { get { return m_interpolatorDataContainer.InterpDataId; } }
  1022. public string VertexDataId { get { return m_vertexDataContainer.VertexDataId; } }
  1023. public string ShaderNameId { get { return m_shaderNameId; } set { m_shaderNameId = value; } }
  1024. public string TemplateBody { get { return m_templateBody; } set { m_templateBody = value; } }
  1025. public List<TemplateInputData> InputDataList { get { return m_inputDataList; } set { m_inputDataList = value; } }
  1026. public List<TemplateLocalVarData> LocalVarsList { get { return m_localVarsList; } }
  1027. public List<TemplateVertexData> VertexDataList { get { return m_vertexDataContainer.VertexData; } }
  1028. public TemplateInterpData InterpolatorData { get { return m_interpolatorDataContainer; } }
  1029. public TemplateFunctionData VertexFunctionData { get { return m_vertexFunctionData; } set { m_vertexFunctionData = value; } }
  1030. public TemplateFunctionData FragmentFunctionData { get { return m_fragmentFunctionData; } set { m_fragmentFunctionData = value; } }
  1031. public List<TemplateShaderPropertyData> AvailableShaderProperties { get { return m_availableShaderProperties; } set { m_availableShaderProperties = value; } }
  1032. public TemplateBlendData BlendData { get { return m_blendData; } set { m_blendData = value; } }
  1033. public TemplateAlphaToMaskData AlphaToMaskData { get { return m_alphaToMaskData; } set { m_alphaToMaskData = value; } }
  1034. public TemplateCullModeData CullModeData { get { return m_cullModeData; } set { m_cullModeData = value; } }
  1035. public TemplateColorMaskData ColorMaskData { get { return m_colorMaskData; } set { m_colorMaskData = value; } }
  1036. public TemplateStencilData StencilData { get { return m_stencilData; } set { m_stencilData = value; } }
  1037. public TemplateDepthData DepthData { get { return m_depthData; } set { m_depthData = value; } }
  1038. public TemplateTagsModuleData TagData { get { return m_tagData; } set { m_tagData = value; } }
  1039. private List<TemplateProperty> PropertyList { get { return m_propertyList; } set { m_propertyList = value; } }
  1040. public VertexDataContainer VertexDataContainer { get { return m_vertexDataContainer; } set { m_vertexDataContainer = value; } }
  1041. public TemplateInterpData InterpolatorDataContainer { get { return m_interpolatorDataContainer; } set { m_interpolatorDataContainer = value; } }
  1042. }
  1043. }